Home Manual Reference Source Test Repository

src/ESComplex.js

import path             from 'path';

import ESComplexModule  from 'typhonjs-escomplex-module/src/ESComplexModule';
import ESComplexProject from 'typhonjs-escomplex-project/src/ESComplexProject';

import Parser           from './Parser';

/**
 * Next generation code complexity reporting for Javascript abstract syntax trees (AST). ESComplex exposes all methods
 * available via ESComplexModule & ESComplexProject modules which process AST. Several methods available below accept
 * source code which is translated via Babylon w/ all plugins enabled allowing any ES6/ES7/edge JS to be parsed.
 * Asynchronous versions with the `Async` suffix of all methods are available as well.
 *
 * @see https://www.npmjs.com/package/typhonjs-escomplex-module
 * @see https://www.npmjs.com/package/typhonjs-escomplex-project
 * @see https://www.npmjs.com/package/babylon
 */
export default class ESComplex
{
   /**
    * Initializes ESComplex.
    *
    * @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 ESComplexProject 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.
    * ```
    */
   constructor(options = {})
   {
      /* istanbul ignore if */
      if (typeof options !== 'object') { throw new TypeError(`ctor error: 'options' is not an 'object'.`); }

      /**
       * An instance of ESComplexModule.
       * @type {ESComplexModule}
       * @private
       */
      this._escomplexModule = new ESComplexModule(options.module);

      /**
       * An instance of ESComplexProject.
       * @type {ESComplexProject}
       * @private
       */
      this._escomplexProject = new ESComplexProject(path, options);
   }

   /**
    * Parses the given source code then processes the generated AST and calculates metrics via plugins.
    *
    * @param {string}   source - Javascript source code.
    * @param {object}   options - (Optional) module analyze options.
    * @param {object}   parserOptions - (Optional) overrides default babylon parser options.
    *
    * @returns {object} - A single module report.
    */
   analyzeModule(source, options = {}, parserOptions = undefined)
   {
      /* istanbul ignore if */
      if (typeof source !== 'string') { throw new TypeError(`analyze error: 'source' is not a 'string'.`); }

      return this._escomplexModule.analyze(Parser.parse(source, parserOptions), options);
   }

   /**
    * Processes the given ast and calculates metrics via plugins.
    *
    * @param {object|Array}   ast - Javascript AST.
    * @param {object}         options - (Optional) module analyze options.
    *
    * @returns {object} - A single module report.
    */
   analyzeModuleAST(ast, options = {})
   {
      return this._escomplexModule.analyze(ast, options);
   }

   /**
    * Processes the given sources and calculates project metrics via plugins.
    *
    * @param {Array<object>}  sources - Array of object hashes containing `code` and `srcPath` entries with optional
    *                                   entries include `filePath` and `srcPathAlias`.
    *
    * @param {object}         options - (Optional) project processing options.
    *
    * @param {object}         parserOptions - (Optional) overrides default babylon parser options.
    *
    * @returns {{reports: Array<{}>}} - An object hash with a `reports` entry that is an Array of module results.
    */
   analyzeProject(sources, options = {}, parserOptions = undefined)
   {
      // Parse sources and map entries to include `ast` entry from `code`.
      const modules = sources.map((source) =>
      {
         try
         {
            return {
               ast: Parser.parse(source.code, parserOptions),
               filePath: source.filePath,
               srcPath: source.srcPath,
               srcPathAlias: source.srcPathAlias
            };
         }
         catch (error)
         {
            /* istanbul ignore if */
            if (options.ignoreErrors) { return null; }

            /* istanbul ignore next */
            error.message = `${source.path}: ${error.message}`;

            /* istanbul ignore next */
            throw error;
         }
      })
      .filter((source) => !!source);

      return this._escomplexProject.analyze(modules, options);
   }

   /**
    * Processes the given modules and calculates project metrics via plugins.
    *
    * @param {Array<object>}  modules - Array of object hashes containing `ast` and `srcPath` entries with optional
    *                                   entries include `filePath` and `srcPathAlias`.
    *
    * @param {object}         options - (Optional) project processing options.
    *
    * @returns {{reports: Array<{}>}} - An object hash with a `reports` entry that is an Array of module results.
    */
   analyzeProjectAST(modules, options = {})
   {
      return this._escomplexProject.analyze(modules, options);
   }

   /**
    * Provides a convenience method to parse the given source code and return the babylon AST.
    *
    * @param {string}   source - Javascript source code.
    * @param {object}   parserOptions - (Optional) overrides default babylon parser options.
    *
    * @returns {object} - babylon generated AST.
    */
   parse(source, parserOptions = undefined)
   {
      return Parser.parse(source, parserOptions);
   }

   /**
    * Processes existing project results and calculates metrics via plugins.
    *
    * @param {object}   results - An object hash with a `reports` entry that is an Array of module results.
    * @param {object}   options - (Optional) project processing options.
    *
    * @returns {{reports: Array<{}>}} - An object hash with a `reports` entry that is an Array of module results.
    */
   processProject(results, options = {})
   {
      return this._escomplexProject.process(results, options);
   }

   // Asynchronous Promise based methods ----------------------------------------------------------------------------

   /**
    * Wraps in a Promise parsing of the given source code then processes the generated AST and calculates metrics via
    * plugins.
    *
    * @param {string}   source - Javascript source code.
    * @param {object}   options - (Optional) module analyze options.
    * @param {object}   parserOptions - (Optional) overrides default babylon parser options.
    *
    * @returns {object} - A single module report.
    */
   analyzeModuleAsync(source, options = {}, parserOptions = undefined)
   {
      return new Promise((resolve, reject) =>
      {
         try { resolve(this.analyzeModule(source, options, parserOptions)); }
         catch (err) { /* istanbul ignore next */ reject(err); }
      });
   }

   /**
    * Wraps in a Promise processing the given ast and calculates metrics via plugins.
    *
    * @param {object|Array}   ast - Javascript AST.
    * @param {object}         options - (Optional) module analyze options.
    *
    * @returns {Promise<object>} - A single module report.
    */
   analyzeModuleASTAsync(ast, options = {})
   {
      return new Promise((resolve, reject) =>
      {
         try { resolve(this.analyzeModuleAST(ast, options)); }
         catch (err) { /* istanbul ignore next */ reject(err); }
      });
   }

   /**
    * Wraps in a Promise processing the given sources and calculates project metrics via plugins.
    *
    * @param {Array<object>}  sources - Array of object hashes containing `code` and `path` entries.
    * @param {object}         options - (Optional) project processing options.
    * @param {object}         parserOptions - (Optional) overrides default babylon parser options.
    *
    * @returns {Promise<{reports: Array<{}>}>} - An object hash with a `reports` entry that is an Array of module
    *                                            results.
    */
   analyzeProjectAsync(sources, options = {}, parserOptions = undefined)
   {
      return new Promise((resolve, reject) =>
      {
         try { resolve(this.analyzeProject(sources, options, parserOptions)); }
         catch (err) { /* istanbul ignore next */ reject(err); }
      });
   }

   /**
    * Wraps in a Promise processing the given modules and calculates project metrics via plugins.
    *
    * @param {Array}    modules - Array of object hashes containing `ast` and `path` entries.
    * @param {object}   options - (Optional) project processing options.
    *
    * @returns {Promise<{reports: Array<{}>}>} - An object hash with a `reports` entry that is an Array of module
    *                                            results.
    */
   analyzeProjectASTAsync(modules, options = {})
   {
      return new Promise((resolve, reject) =>
      {
         try { resolve(this.analyzeProjectAST(modules, options)); }
         catch (err) { /* istanbul ignore next */ reject(err); }
      });
   }

   /**
    * Wraps in a Promise a convenience method to parse the given source code and return the babylon AST.
    *
    * @param {string}   source - Javascript source code.
    * @param {object}   parserOptions - (Optional) overrides default babylon parser options.
    *
    * @returns {Promise<object>} - babylon generated AST.
    */
   parseAsync(source, parserOptions = undefined)
   {
      return new Promise((resolve, reject) =>
      {
         try { resolve(this.parse(source, parserOptions)); }
         catch (err) { /* istanbul ignore next */ reject(err); }
      });
   }

   /**
    * Wraps in a Promise processing existing project results and calculates metrics via plugins.
    *
    * @param {object}   results - An object hash with a `reports` entry that is an Array of module results.
    * @param {object}   options - (Optional) project processing options.
    *
    * @returns {Promise<{reports: Array<{}>}>} - An object hash with a `reports` entry that is an Array of module
    *                                            results.
    */
   processProjectAsync(results, options = {})
   {
      return new Promise((resolve, reject) =>
      {
         try { resolve(this.processProject(results, options)); }
         catch (err) { /* istanbul ignore next */ reject(err); }
      });
   }
}