From d4807c119b9ec1156c320efd95c2c3a675835c7b Mon Sep 17 00:00:00 2001 From: David First Date: Wed, 5 Jun 2019 21:01:44 -0400 Subject: [PATCH] support require statements with apostrophes (#103) * fix https://github.com/teambit/bit/issues/1708, support require statements with apostrophes * bump version --- CHANGELOG.md | 4 ++ package.json | 2 +- src/cli/commands/get-dependencies.js | 3 +- .../detectives/detective-es6/index.js | 30 +++---------- .../detectives/detective-es6/index.spec.js | 12 +++++ .../detectives/detective-typescript/index.js | 28 +++--------- .../detective-typescript/index.spec.js | 9 ++++ .../detectives/parser-helper.js | 44 +++++++++++++++++++ 8 files changed, 86 insertions(+), 46 deletions(-) create mode 100644 src/dependency-builder/detectives/parser-helper.js diff --git a/CHANGELOG.md b/CHANGELOG.md index b190983..84918e0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -7,6 +7,10 @@ and this project adheres to [Semantic Versioning](http://semver.org/). ## [unreleased] +## [2.0.11] - 2019-06-05 + +- [#1708](https://github.com/teambit/bit/issues/1708) support `require` with apostrophes + ## [2.0.10] - 2019-05-31 - [#1690](https://github.com/teambit/bit/issues/1690) fix error "Cannot read property 'find' of undefined" with typescript files diff --git a/package.json b/package.json index 23a736e..fa827a1 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "bit-javascript", - "version": "2.0.10", + "version": "2.0.11", "scripts": { "flow": "flow; test $? -eq 0 -o $? -eq 2", "lint": "eslint src && flow check || true", diff --git a/src/cli/commands/get-dependencies.js b/src/cli/commands/get-dependencies.js index cad4417..5360a96 100644 --- a/src/cli/commands/get-dependencies.js +++ b/src/cli/commands/get-dependencies.js @@ -4,7 +4,8 @@ import { getDependenciesAction } from '../../actions'; import { DEFAULT_BINDINGS_PREFIX } from '../../constants'; const report = (data) => { - console.log('dependencies', JSON.stringify(data, null, ' ')); + if (!data) return 'No dependencies found!'; + return JSON.stringify(data, null, ' '); }; const resolveConfig = undefined; // @todo: figure out how to get the data from the command line, maybe as a file diff --git a/src/dependency-builder/detectives/detective-es6/index.js b/src/dependency-builder/detectives/detective-es6/index.js index fdf32e9..b59cba3 100644 --- a/src/dependency-builder/detectives/detective-es6/index.js +++ b/src/dependency-builder/detectives/detective-es6/index.js @@ -1,3 +1,4 @@ +import { getDependenciesFromMemberExpression, getDependenciesFromCallExpression } from '../parser-helper'; /** * this file had been forked (and changed since then) from https://github.com/dependents/node-detective-es6 */ @@ -83,32 +84,15 @@ module.exports = function (src) { addExportedToImportSpecifier(node.declaration.name); break; case 'CallExpression': - if (node.callee.type === 'Import' && node.arguments.length && node.arguments[0].value) { - addDependency(node.arguments[0].value); - } - if ( - node.callee.type === 'Identifier' && // taken from detective-cjs - node.callee.name === 'require' && - node.arguments[0].value && - node.arguments && - node.arguments.length && - (node.arguments[0].type === 'Literal' || node.arguments[0].type === 'StringLiteral') - ) { - addDependency(node.arguments[0].value); + { + const value = getDependenciesFromCallExpression(node); + if (value) addDependency(value); } break; case 'MemberExpression': - if ( - node.object.type === 'CallExpression' && - node.object.callee.type === 'Identifier' && - node.object.callee.name === 'require' && - node.object.arguments && - node.object.arguments.length && - node.object.arguments[0].value && - (node.object.arguments[0].type === 'Literal' || node.object.arguments[0].type === 'StringLiteral') - ) { - const depValue = node.object.arguments[0].value; - addDependency(depValue); + { + const value = getDependenciesFromMemberExpression(node); + if (value) addDependency(value); } break; default: diff --git a/src/dependency-builder/detectives/detective-es6/index.spec.js b/src/dependency-builder/detectives/detective-es6/index.spec.js index c23afde..8190702 100644 --- a/src/dependency-builder/detectives/detective-es6/index.spec.js +++ b/src/dependency-builder/detectives/detective-es6/index.spec.js @@ -116,6 +116,18 @@ describe('detective-es6', () => { }); }); + describe('string in apostrophes', () => { + it('should recognize when using require statement', () => { + const deps = detective('const foo = require(`foo`);'); // eslint-disable-line + const depsKeys = Object.keys(deps); + assert.equal(depsKeys.length, 1); + assert.equal(depsKeys[0], 'foo'); + }); + it('should throw when using import syntax', () => { + expect(() => detective('import foo from `foo`;')).to.throw(); // eslint-disable-line + }); + }); + describe('import-specifiers detection (for tree shaking)', () => { it('should recognize default imports as default', () => { const deps = detective('import foo from "foo";'); diff --git a/src/dependency-builder/detectives/detective-typescript/index.js b/src/dependency-builder/detectives/detective-typescript/index.js index 496bebe..cd36400 100644 --- a/src/dependency-builder/detectives/detective-typescript/index.js +++ b/src/dependency-builder/detectives/detective-typescript/index.js @@ -1,6 +1,7 @@ /** * this file had been forked from https://github.com/pahen/detective-typescript */ +import { getDependenciesFromMemberExpression, getDependenciesFromCallExpression } from '../parser-helper'; const Parser = require('@typescript-eslint/typescript-estree'); const Walker = require('node-source-walk'); @@ -81,30 +82,15 @@ module.exports = function (src, options = {}) { } break; case 'CallExpression': - if (node.callee.type === 'Import' && node.arguments.length) { - addDependency(node.arguments[0].value); - } - if ( - node.callee.type === 'Identifier' && // taken from detective-cjs - node.callee.name === 'require' && - node.arguments && - node.arguments.length && - (node.arguments[0].type === 'Literal' || node.arguments[0].type === 'StringLiteral') - ) { - addDependency(node.arguments[0].value); + { + const value = getDependenciesFromCallExpression(node); + if (value) addDependency(value); } break; case 'MemberExpression': - if ( - node.object.type === 'CallExpression' && - node.object.callee.type === 'Identifier' && - node.object.callee.name === 'require' && - node.object.arguments && - node.object.arguments.length && - (node.object.arguments[0].type === 'Literal' || node.object.arguments[0].type === 'StringLiteral') - ) { - const depValue = node.object.arguments[0].value; - addDependency(depValue); + { + const value = getDependenciesFromMemberExpression(node); + if (value) addDependency(value); } break; default: diff --git a/src/dependency-builder/detectives/detective-typescript/index.spec.js b/src/dependency-builder/detectives/detective-typescript/index.spec.js index 0d13ba1..17bda68 100644 --- a/src/dependency-builder/detectives/detective-typescript/index.spec.js +++ b/src/dependency-builder/detectives/detective-typescript/index.spec.js @@ -119,4 +119,13 @@ describe('detective-typescript', () => { detective("import './layout.scss'; export default something;"); }); }); + + describe('string in apostrophes', () => { + it('should recognize when using require statement', () => { + const deps = detective('const foo = require(`foo`);'); // eslint-disable-line + const depsKeys = Object.keys(deps); + assert.equal(depsKeys.length, 1); + assert.equal(depsKeys[0], 'foo'); + }); + }); }); diff --git a/src/dependency-builder/detectives/parser-helper.js b/src/dependency-builder/detectives/parser-helper.js new file mode 100644 index 0000000..f7f52c4 --- /dev/null +++ b/src/dependency-builder/detectives/parser-helper.js @@ -0,0 +1,44 @@ +export function getDependenciesFromMemberExpression(node) { + if ( + node.object.type === 'CallExpression' && + node.object.callee.type === 'Identifier' && + node.object.callee.name === 'require' && + node.object.arguments && + node.object.arguments.length + ) { + return getStringValue(node.object.arguments[0]); + } + return null; +} + +export function getDependenciesFromCallExpression(node) { + if (node.callee.type === 'Import' && node.arguments.length && node.arguments[0].value) { + return node.arguments[0].value; + } + if ( + node.callee.type === 'Identifier' && // taken from detective-cjs + node.callee.name === 'require' && + node.arguments && + node.arguments.length + ) { + return getStringValue(node.arguments[0]); + } + return null; +} + +function getStringValue(node) { + // using single or double quotes (', ") + if (node.type === 'Literal' || node.type === 'StringLiteral') { + return node.value; + } + // using apostrophe (`) + if ( + node.type === 'TemplateLiteral' && + node.quasis && + node.quasis.length && + node.quasis[0].type === 'TemplateElement' + ) { + return node.quasis[0].value.raw; + } + return null; +}