UNPKG

analyze-es6-modules

Version:

Performs static analysis of ES6 modules in your codebase.

255 lines (216 loc) 8.84 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _createClass = function () { function defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } } return function (Constructor, protoProps, staticProps) { if (protoProps) defineProperties(Constructor.prototype, protoProps); if (staticProps) defineProperties(Constructor, staticProps); return Constructor; }; }(); exports.readModules = readModules; var _module = require('./module'); var _module2 = _interopRequireDefault(_module); var _utility = require('./utility'); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } } var pathModule = require('path'); var babel = require('babel-core'); var Promise = require('bluebird'); var ModuleParser = function () { function ModuleParser(_ref) { var cwd = _ref.cwd; var aliases = _ref.aliases; var filePath = _ref.filePath; var resolveModulePath = _ref.resolveModulePath; var ast = _ref.ast; _classCallCheck(this, ModuleParser); this.cwd = cwd; this.aliases = aliases; this.filePath = filePath; this.resolveModulePath = resolveModulePath; this.ast = ast; } _createClass(ModuleParser, [{ key: 'parseModule', value: function parseModule() { var _this = this; // Get the relative path, remove the leading dot and slash, then remove the file extension var modulePath = pathModule.relative(this.cwd, this.filePath).replace(/^\.\//g, '').replace(/\.[^/.]+$/g, ''); var module = new _module2.default(modulePath); this.ast.program.body.forEach(function (declaration) { switch (declaration.type) { case 'ImportDeclaration': _this.handleImportDeclaration(module, declaration); break; case 'ExportAllDeclaration': _this.handleExportAllDeclaration(module, declaration); break; case 'ExportNamedDeclaration': _this.handleExportNamedDeclaration(module, declaration); break; case 'ExportDefaultDeclaration': _this.handleExportDefaultDeclaration(module, declaration); break; } }); return module; } }, { key: 'handleImportDeclaration', value: function handleImportDeclaration(module, declaration) { var rawSourcePath = declaration.source.value; var sourcePath = this.resolveImportModulePath(module.path, rawSourcePath); if (declaration.specifiers.length === 0) { module.addSideEffectImport({ sourcePath: sourcePath, rawSourcePath: rawSourcePath, lineNumber: declaration.loc.start.line }); return; } declaration.specifiers.forEach(function (specifier) { // Ignore Flow type imports (for now) if (specifier.importKind === 'type') { return; } var lineNumber = specifier.loc.start.line; switch (specifier.type) { case 'ImportSpecifier': var exportName = specifier.imported.name; if (exportName === 'default') { module.addDefaultImport({ sourcePath: sourcePath, rawSourcePath: rawSourcePath, lineNumber: lineNumber }); } else { module.addNamedImport({ exportName: exportName, sourcePath: sourcePath, rawSourcePath: rawSourcePath, lineNumber: lineNumber }); } break; case 'ImportDefaultSpecifier': module.addDefaultImport({ sourcePath: sourcePath, rawSourcePath: rawSourcePath, lineNumber: lineNumber }); break; case 'ImportNamespaceSpecifier': module.addBatchImport({ sourcePath: sourcePath, rawSourcePath: rawSourcePath, lineNumber: lineNumber }); break; } }); } }, { key: 'handleExportAllDeclaration', value: function handleExportAllDeclaration(module, declaration) { var rawSourcePath = declaration.source.value; var sourcePath = this.resolveImportModulePath(module.path, rawSourcePath); var lineNumber = declaration.loc.start.line; module.addBatchExport({ sourcePath: sourcePath, rawSourcePath: rawSourcePath, lineNumber: lineNumber }); } }, { key: 'handleExportNamedDeclaration', value: function handleExportNamedDeclaration(module, declaration) { var _this2 = this; if (declaration.source) { declaration.specifiers.forEach(function (specifier) { var rawSourcePath = declaration.source.value; var sourcePath = _this2.resolveImportModulePath(module.path, rawSourcePath); module.addReExport({ exportedName: specifier.exported.name, importedName: specifier.local.name, source: source, rawSourcePath: rawSourcePath, sourcePath: sourcePath, lineNumber: specifier.loc.start.line }); }); } else if (declaration.declaration) { if (declaration.declaration.type === 'FunctionDeclaration') { module.addNamedExport({ exportName: declaration.declaration.id.name, lineNumber: declaration.declaration.loc.start.line }); } else if (declaration.declaration.type === 'VariableDeclaration') { declaration.declaration.declarations.forEach(function (d) { module.addNamedExport({ exportName: d.id.name, lineNumber: d.loc.start.line }); }); } } else if (declaration.specifiers) { declaration.specifiers.forEach(function (specifier) { var exportName = specifier.exported.name; var lineNumber = specifier.loc.start.line; if (exportName === 'default') { module.addDefaultExport({ lineNumber: lineNumber }); } else { module.addNamedExport({ exportName: exportName, lineNumber: lineNumber }); } }); } } }, { key: 'handleExportDefaultDeclaration', value: function handleExportDefaultDeclaration(module, declaration) { var lineNumber = declaration.loc.start.line; module.addDefaultExport({ lineNumber: lineNumber }); } }, { key: 'resolveImportModulePath', value: function resolveImportModulePath(importingModulePath, exportingModuleRelativePath) { var resolveOptions = { cwd: this.cwd, path: exportingModuleRelativePath, importingModulePath: importingModulePath }; var userResolvedPath = this.resolveModulePath(resolveOptions); if (userResolvedPath !== undefined) { return userResolvedPath; } if (exportingModuleRelativePath[0] === '.') { var fullImportModulePath = pathModule.join(this.cwd, importingModulePath); var importingModuleDirectory = fullImportModulePath.replace(/\/[^/]+$/g, ''); var exportingModulePath = pathModule.resolve(importingModuleDirectory, exportingModuleRelativePath); // Get the relative path and remove the leading dot and slash return pathModule.relative(this.cwd, exportingModulePath).replace(/^\.\//g, ''); } var aliased = this.applyAliases(exportingModuleRelativePath); if (exportingModuleRelativePath !== aliased) { return aliased; } return exportingModuleRelativePath; } }, { key: 'applyAliases', value: function applyAliases(modulePath) { if (this.aliases.module[modulePath]) { return this.aliases.module[modulePath]; } for (var prefix in this.aliases.path) { if (this.aliases.path.hasOwnProperty(prefix)) { if (modulePath.indexOf(prefix) === 0) { var rest = modulePath.slice(prefix.length); var fullPath = pathModule.join(this.cwd, this.aliases.path[prefix], rest); var absolutePath = pathModule.resolve(fullPath); return pathModule.relative(this.cwd, absolutePath); } } } return modulePath; } }]); return ModuleParser; }(); function readModules(_ref2) { var cwd = _ref2.cwd; var sources = _ref2.sources; var aliases = _ref2.aliases; var resolveModulePath = _ref2.resolveModulePath; var fileReader = _ref2.fileReader; var userBabelOptions = _ref2.babel; var babelOptions = { compact: false, plugins: userBabelOptions.plugins || [] }; return (0, _utility.expandFilePatterns)(cwd, sources).then(function (filePaths) { var modulePromises = filePaths.map(function (filePath) { return fileReader(filePath).then(function (fileContents) { try { var ast = babel.transform(fileContents, babelOptions).ast; var moduleParser = new ModuleParser({ cwd: cwd, filePath: filePath, aliases: aliases, resolveModulePath: resolveModulePath, ast: ast }); return moduleParser.parseModule(); } catch (error) { throw generateParsingErrorMessage(filePath, error); } }); }); return Promise.all(modulePromises); }); } function generateParsingErrorMessage(filePath, error) { return 'Parsing error: ' + filePath + '\n' + (error ? error.stack || error.message : ''); }