UNPKG

typhonjs-escomplex-project

Version:

Provides project oriented AST processing for typhonjs-escomplex complexity reports.

329 lines (255 loc) 12.7 kB
'use strict'; Object.defineProperty(exports, "__esModule", { value: true }); var _promise = require('babel-runtime/core-js/promise'); var _promise2 = _interopRequireDefault(_promise); var _typeof2 = require('babel-runtime/helpers/typeof'); var _typeof3 = _interopRequireDefault(_typeof2); var _classCallCheck2 = require('babel-runtime/helpers/classCallCheck'); var _classCallCheck3 = _interopRequireDefault(_classCallCheck2); var _createClass2 = require('babel-runtime/helpers/createClass'); var _createClass3 = _interopRequireDefault(_createClass2); var _ESComplexModule = require('typhonjs-escomplex-module/dist/ESComplexModule'); var _ESComplexModule2 = _interopRequireDefault(_ESComplexModule); var _ModuleReport = require('typhonjs-escomplex-commons/dist/module/report/ModuleReport'); var _ModuleReport2 = _interopRequireDefault(_ModuleReport); var _ProjectReport = require('typhonjs-escomplex-commons/dist/project/report/ProjectReport'); var _ProjectReport2 = _interopRequireDefault(_ProjectReport); var _Plugins = require('./Plugins'); var _Plugins2 = _interopRequireDefault(_Plugins); function _interopRequireDefault(obj) { return obj && obj.__esModule ? obj : { default: obj }; } /** * Provides a runtime to invoke ESComplexProject plugins for processing / metrics calculations of projects. */ var ESComplexProject = function () { /** * Initializes ESComplexProject. * * @param {object} pathModule - Provides an object which matches the Node path module. In particular the following * entries must be provided: * ``` * (string) sep - Provides the platform-specific path segment separator: `/` on POSIX & `\` on Windows. * * (function) dirname - Returns the directory name of a path, similar to the Unix dirname command. * * (function) extname - Returns the extension of the path, from the last occurance of the . (period) character to * end of string in the last portion of the path. * * (function) relative - Returns the relative path from from to to. * * (function) resolve - Resolves a sequence of paths or path segments into an absolute path. * ``` * * @param {object} options - module and project options including user plugins to load including: * ``` * (object) module - Provides an object hash of the following options for the module runtime: * (boolean) loadDefaultPlugins - When false ESComplexModule will not load any default plugins. * (Array<Object>) plugins - A list of ESComplexModule plugins that have already been instantiated. * * (object) project - Provides an object hash of the following options for the project runtime: * (boolean) loadDefaultPlugins - When false ESComplexProject will not load any default plugins. * (Array<Object>) plugins - A list of ESComplexProject plugins that have already been instantiated. * ``` * * @see https://nodejs.org/api/path.html */ function ESComplexProject(pathModule) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; (0, _classCallCheck3.default)(this, ESComplexProject); // Verify essential Node path module API. /* istanbul ignore if */ if ((typeof pathModule === 'undefined' ? 'undefined' : (0, _typeof3.default)(pathModule)) !== 'object') { throw new TypeError('ctor error: `pathModule` is not an `object`.'); } /* istanbul ignore if */ if (typeof pathModule.sep !== 'string') { throw new TypeError('ctor error: `pathModule.sep` is not a `string`.'); } /* istanbul ignore if */ if (typeof pathModule.dirname !== 'function') { throw new TypeError('ctor error: `pathModule.dirname` is not a `function`.'); } /* istanbul ignore if */ if (typeof pathModule.extname !== 'function') { throw new TypeError('ctor error: `pathModule.extname` is not a `function`.'); } /* istanbul ignore if */ if (typeof pathModule.relative !== 'function') { throw new TypeError('ctor error: `pathModule.relative` is not a `function`.'); } /* istanbul ignore if */ if (typeof pathModule.resolve !== 'function') { throw new TypeError('ctor error: `pathModule.resolve` is not a `function`.'); } /* istanbul ignore if */ if ((typeof options === 'undefined' ? 'undefined' : (0, _typeof3.default)(options)) !== 'object') { throw new TypeError('ctor error: `options` is not an `object`.'); } /** * Stores a module which matches the NodeJS path module API. * @type {Object} * @private */ this._pathModule = pathModule; /** * Provides dispatch methods to all module plugins. * @type {Plugins} * @private */ this._plugins = new _Plugins2.default(options.project); /** * Stores the ESComplexModule instance used for generating module reports. * @type {ESComplexModule} * @private */ this._escomplexModule = new _ESComplexModule2.default(options.module); } /** * Processes the given modules and calculates project metrics via plugins. * * @param {Array<object>} modules - Array of object hashes containing `ast` and `srcPath` entries. Optionally * `srcPathAlias` and `filePath` entries may also be provided. * * @param {object} options - (Optional) project processing options. * * @returns {ProjectReport} */ (0, _createClass3.default)(ESComplexProject, [{ key: 'analyze', value: function analyze(modules) { var _this = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; if (!Array.isArray(modules)) { throw new TypeError('analyze error: `modules` is not an `array`.'); } /* istanbul ignore if */ if ((typeof options === 'undefined' ? 'undefined' : (0, _typeof3.default)(options)) !== 'object') { throw new TypeError('analyze error: `options` is not an `object`.'); } var settings = this._plugins.onConfigure(options); this._plugins.onProjectStart(this._pathModule, settings); var moduleReports = modules.map(function (m) { var moduleReport = void 0; if (typeof m.srcPath !== 'string' || m.srcPath === '') { throw new Error('analyze error: Invalid `srcPath`'); } try { moduleReport = _this._escomplexModule.analyze(m.ast, options); // Set any supplied filePath / srcPath / srcPathAlias data. moduleReport.filePath = m.filePath; moduleReport.srcPath = m.srcPath; moduleReport.srcPathAlias = m.srcPathAlias; return moduleReport; } catch (error) { // Include the module srcPath to distinguish the actual offending entry. /* istanbul ignore next */ error.message = m.srcPath + ': ' + error.message; /* istanbul ignore next */ throw error; } }, []); var projectReport = new _ProjectReport2.default(moduleReports, settings); if (settings.skipCalculation) { return projectReport; } // Allow all plugins to have a calculation pass at the project report. this._plugins.onProjectCalculate(projectReport, this._pathModule, settings); // Allow all plugins to have a pass at the project report to calculate any averaged data. this._plugins.onProjectAverage(projectReport, this._pathModule, settings); // Allow all plugins to have a pass at the project report to calculate any metrics that depend on averaged data. this._plugins.onProjectPostAverage(projectReport, this._pathModule, settings); // Allow all plugins to clean up any resources as necessary. this._plugins.onProjectEnd(projectReport, this._pathModule, settings); return projectReport.finalize(); } /** * Processes an existing ProjectReport instance and calculates metrics via plugins. * * @param {ProjectReport} projectReport - An instance of ProjectReport with a `modules` entry that is an Array of * ModuleReports. * * @param {object} options - (Optional) project processing options. * * @returns {ProjectReport} */ }, { key: 'process', value: function process(projectReport) { var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; /* istanbul ignore if */ if (!(projectReport instanceof _ProjectReport2.default)) { throw new TypeError('process error: `projectReport` is not an instance of ProjectReport.'); } /* istanbul ignore if */ if ((typeof options === 'undefined' ? 'undefined' : (0, _typeof3.default)(options)) !== 'object') { throw new TypeError('process error: `options` is not an `object`.'); } /* istanbul ignore if */ if (projectReport.modules.length > 0 && !(projectReport.modules[0] instanceof _ModuleReport2.default)) { throw new TypeError('process error: `projectReport.modules` does not appear to contain `ModuleReport` entries.'); } var settings = this._plugins.onConfigure(options); // Override any stored settings given new options / settings set during processing reports. projectReport.settings = settings; this._plugins.onProjectStart(this._pathModule, settings); // Allow all plugins to have a calculation pass at the project report. this._plugins.onProjectCalculate(projectReport, this._pathModule, settings); // Allow all plugins to have a pass at the project report to calculate any averaged data. this._plugins.onProjectAverage(projectReport, this._pathModule, settings); // Allow all plugins to have a pass at the project report to calculate any metrics that depend on averaged data. this._plugins.onProjectPostAverage(projectReport, this._pathModule, settings); // Allow all plugins to clean up any resources as necessary. this._plugins.onProjectEnd(projectReport, this._pathModule, settings); return projectReport.finalize(); } // Asynchronous Promise based methods ---------------------------------------------------------------------------- /** * Wraps in a Promise processing the given modules and calculates metrics via plugins. * * @param {Array<object>} modules - Array of object hashes containing `ast` and `srcPath` entries. Optionally * `srcPathAlias` and `filePath` entries may also be provided. * * @param {object} options - project processing options * * @returns {Promise<ProjectReport>} */ }, { key: 'analyzeAsync', value: function analyzeAsync(modules) { var _this2 = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return new _promise2.default(function (resolve, reject) { try { resolve(_this2.analyze(modules, options)); } catch (err) { /* istanbul ignore next */reject(err); } }); } /** * Wraps in a Promise processing of existing ProjectReport instance and calculates metrics via plugins. * * @param {ProjectReport} projectReport - An instance of ProjectReport. * @param {object} options - (Optional) project processing options. * * @returns {Promise<ProjectReport>} */ }, { key: 'processAsync', value: function processAsync(projectReport) { var _this3 = this; var options = arguments.length > 1 && arguments[1] !== undefined ? arguments[1] : {}; return new _promise2.default(function (resolve, reject) { try { resolve(_this3.process(projectReport, options)); } catch (err) { /* istanbul ignore next */reject(err); } }); } }]); return ESComplexProject; }(); exports.default = ESComplexProject; module.exports = exports['default'];