escomplex-plugin-metrics-module
Advanced tools
Comparing version 0.0.11 to 0.0.12
@@ -29,5 +29,95 @@ 'use strict'; | ||
_createClass(ModuleMetricCalculate, null, [{ | ||
key: 'calculateCyclomaticDensity', | ||
key: 'calculate', | ||
/** | ||
* Coordinates calculating all metrics. All module and class methods are traversed. If there are no module or class | ||
* methods respectively the aggregate MethodReport is used for calculations. | ||
* | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {object} settings - Settings for module processing. | ||
* | ||
* @private | ||
*/ | ||
value: function calculate(moduleReport, settings) { | ||
var moduleMethodCount = moduleReport.methods.length; | ||
var moduleMethodAverages = moduleReport.methodAverage; | ||
var moduleMethodAverageKeys = _ObjectUtil2.default.getAccessorList(moduleMethodAverages); | ||
// Handle module methods. | ||
moduleReport.methods.forEach(function (methodReport) { | ||
moduleMethodAverageKeys.forEach(function (averageKey) { | ||
ModuleMetricCalculate.calculateCyclomaticDensity(methodReport); | ||
ModuleMetricCalculate.calculateHalsteadMetrics(methodReport.halstead); | ||
var targetValue = _ObjectUtil2.default.safeAccess(methodReport, averageKey, 0); | ||
_ObjectUtil2.default.safeSet(moduleMethodAverages, averageKey, targetValue, 'add'); | ||
}); | ||
}); | ||
// Handle module class reports. | ||
moduleReport.classes.forEach(function (classReport) { | ||
var classMethodAverages = classReport.methodAverage; | ||
var classMethodCount = classReport.methods.length; | ||
moduleMethodCount += classMethodCount; | ||
// Process all class methods. | ||
classReport.methods.forEach(function (methodReport) { | ||
ModuleMetricCalculate.calculateCyclomaticDensity(methodReport); | ||
ModuleMetricCalculate.calculateHalsteadMetrics(methodReport.halstead); | ||
moduleMethodAverageKeys.forEach(function (averageKey) { | ||
var targetValue = _ObjectUtil2.default.safeAccess(methodReport, averageKey, 0); | ||
_ObjectUtil2.default.safeSet(moduleMethodAverages, averageKey, targetValue, 'add'); | ||
_ObjectUtil2.default.safeSet(classMethodAverages, averageKey, targetValue, 'add'); | ||
}); | ||
}); | ||
ModuleMetricCalculate.calculateCyclomaticDensity(classReport.aggregateMethodReport); | ||
ModuleMetricCalculate.calculateHalsteadMetrics(classReport.aggregateMethodReport.halstead); | ||
// If there are no class methods use the class aggregate MethodReport. | ||
if (classMethodCount === 0) { | ||
// Sane handling of classes that contain no methods. | ||
moduleMethodAverageKeys.forEach(function (averageKey) { | ||
var targetValue = _ObjectUtil2.default.safeAccess(classReport.aggregateMethodReport, averageKey, 0); | ||
_ObjectUtil2.default.safeSet(classMethodAverages, averageKey, targetValue, 'add'); | ||
}); | ||
classMethodCount = 1; | ||
} | ||
moduleMethodAverageKeys.forEach(function (averageKey) { | ||
_ObjectUtil2.default.safeSet(classMethodAverages, averageKey, classMethodCount, 'div'); | ||
}); | ||
ModuleMetricCalculate.calculateMaintainabilityIndex(classReport, settings, classMethodAverages.cyclomatic, classMethodAverages.halstead.effort, classMethodAverages.sloc.logical); | ||
}); | ||
ModuleMetricCalculate.calculateCyclomaticDensity(moduleReport.aggregateMethodReport); | ||
ModuleMetricCalculate.calculateHalsteadMetrics(moduleReport.aggregateMethodReport.halstead); | ||
// If there are no module methods use the module aggregate MethodReport. | ||
if (moduleMethodCount === 0) { | ||
// Sane handling of classes that contain no methods. | ||
moduleMethodAverageKeys.forEach(function (averageKey) { | ||
var targetValue = _ObjectUtil2.default.safeAccess(moduleReport.aggregateMethodReport, averageKey, 0); | ||
_ObjectUtil2.default.safeSet(moduleMethodAverages, averageKey, targetValue, 'add'); | ||
}); | ||
// Sane handling of modules that contain no methods. | ||
moduleMethodCount = 1; | ||
} | ||
moduleMethodAverageKeys.forEach(function (averageKey) { | ||
_ObjectUtil2.default.safeSet(moduleMethodAverages, averageKey, moduleMethodCount, 'div'); | ||
}); | ||
ModuleMetricCalculate.calculateMaintainabilityIndex(moduleReport, settings, moduleMethodAverages.cyclomatic, moduleMethodAverages.halstead.effort, moduleMethodAverages.sloc.logical); | ||
} | ||
/** | ||
* Calculates cyclomatic density - Proposed as a modification to cyclomatic complexity by Geoffrey K. Gill and | ||
@@ -37,6 +127,9 @@ * Chris F. Kemerer in 1991, this metric simply re-expresses it as a percentage of the logical lines of code. Lower | ||
* | ||
* @param {MethodReport} report - A MethodReport to perform calculations on. | ||
* @param {AggregateMethodReport} report - An AggregateMethodReport to perform calculations on. | ||
* | ||
* @private | ||
*/ | ||
}, { | ||
key: 'calculateCyclomaticDensity', | ||
value: function calculateCyclomaticDensity(report) { | ||
@@ -119,95 +212,2 @@ report.cyclomaticDensity = report.sloc.logical === 0 ? 0 : report.cyclomatic / report.sloc.logical * 100; | ||
} | ||
/** | ||
* Coordinates calculating all metrics. All module and class methods are traversed. If there are no module or class | ||
* methods respectively the aggregate MethodReport is used for calculations. | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {object} settings - Settings for module processing. | ||
* | ||
* @private | ||
*/ | ||
}, { | ||
key: 'calculateMetrics', | ||
value: function calculateMetrics(report, settings) { | ||
var moduleMethodCount = report.methods.length; | ||
var moduleMethodAverages = report.methodAverage; | ||
var moduleMethodAverageKeys = _ObjectUtil2.default.getAccessorList(moduleMethodAverages); | ||
// Handle module methods. | ||
report.methods.forEach(function (methodReport) { | ||
moduleMethodAverageKeys.forEach(function (averageKey) { | ||
ModuleMetricCalculate.calculateCyclomaticDensity(methodReport); | ||
ModuleMetricCalculate.calculateHalsteadMetrics(methodReport.halstead); | ||
var targetValue = _ObjectUtil2.default.safeAccess(methodReport, averageKey, 0); | ||
_ObjectUtil2.default.safeSet(moduleMethodAverages, averageKey, targetValue, 'add'); | ||
}); | ||
}); | ||
// Handle module class reports. | ||
report.classes.forEach(function (classReport) { | ||
var classMethodAverages = classReport.methodAverage; | ||
var classMethodCount = classReport.methods.length; | ||
moduleMethodCount += classMethodCount; | ||
// Process all class methods. | ||
classReport.methods.forEach(function (methodReport) { | ||
ModuleMetricCalculate.calculateCyclomaticDensity(methodReport); | ||
ModuleMetricCalculate.calculateHalsteadMetrics(methodReport.halstead); | ||
moduleMethodAverageKeys.forEach(function (averageKey) { | ||
var targetValue = _ObjectUtil2.default.safeAccess(methodReport, averageKey, 0); | ||
_ObjectUtil2.default.safeSet(moduleMethodAverages, averageKey, targetValue, 'add'); | ||
_ObjectUtil2.default.safeSet(classMethodAverages, averageKey, targetValue, 'add'); | ||
}); | ||
}); | ||
ModuleMetricCalculate.calculateCyclomaticDensity(classReport.aggregateMethodReport); | ||
ModuleMetricCalculate.calculateHalsteadMetrics(classReport.aggregateMethodReport.halstead); | ||
// If there are no class methods use the class aggregate MethodReport. | ||
if (classMethodCount === 0) { | ||
// Sane handling of classes that contain no methods. | ||
moduleMethodAverageKeys.forEach(function (averageKey) { | ||
var targetValue = _ObjectUtil2.default.safeAccess(classReport.aggregateMethodReport, averageKey, 0); | ||
_ObjectUtil2.default.safeSet(classMethodAverages, averageKey, targetValue, 'add'); | ||
}); | ||
classMethodCount = 1; | ||
} | ||
moduleMethodAverageKeys.forEach(function (averageKey) { | ||
_ObjectUtil2.default.safeSet(classMethodAverages, averageKey, classMethodCount, 'div'); | ||
}); | ||
ModuleMetricCalculate.calculateMaintainabilityIndex(classReport, settings, classMethodAverages.cyclomatic, classMethodAverages.halstead.effort, classMethodAverages.sloc.logical); | ||
}); | ||
ModuleMetricCalculate.calculateCyclomaticDensity(report.aggregateMethodReport); | ||
ModuleMetricCalculate.calculateHalsteadMetrics(report.aggregateMethodReport.halstead); | ||
// If there are no module methods use the module aggregate MethodReport. | ||
if (moduleMethodCount === 0) { | ||
// Sane handling of classes that contain no methods. | ||
moduleMethodAverageKeys.forEach(function (averageKey) { | ||
var targetValue = _ObjectUtil2.default.safeAccess(report.aggregateMethodReport, averageKey, 0); | ||
_ObjectUtil2.default.safeSet(moduleMethodAverages, averageKey, targetValue, 'add'); | ||
}); | ||
// Sane handling of modules that contain no methods. | ||
moduleMethodCount = 1; | ||
} | ||
moduleMethodAverageKeys.forEach(function (averageKey) { | ||
_ObjectUtil2.default.safeSet(moduleMethodAverages, averageKey, moduleMethodCount, 'div'); | ||
}); | ||
ModuleMetricCalculate.calculateMaintainabilityIndex(report, settings, moduleMethodAverages.cyclomatic, moduleMethodAverages.halstead.effort, moduleMethodAverages.sloc.logical); | ||
} | ||
}]); | ||
@@ -214,0 +214,0 @@ |
@@ -30,8 +30,8 @@ 'use strict'; | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {object|Array<object>} dependencies - Dependencies to add. | ||
*/ | ||
value: function addDependencies(report, dependencies) { | ||
value: function addDependencies(moduleReport, dependencies) { | ||
if ((typeof dependencies === 'undefined' ? 'undefined' : _typeof(dependencies)) === 'object' || Array.isArray(dependencies)) { | ||
report.dependencies = report.dependencies.concat(dependencies); | ||
moduleReport.dependencies = moduleReport.dependencies.concat(dependencies); | ||
} | ||
@@ -41,5 +41,5 @@ } | ||
/** | ||
* Creates a report scope when a class or method is entered. | ||
* Creates a moduleReport scope when a class or method is entered. | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {ModuleScopeControl} scopeControl - The associated module report scope control. | ||
@@ -58,3 +58,3 @@ * @param {object} newScope - An object hash defining the new scope including: | ||
key: 'createScope', | ||
value: function createScope(report, scopeControl) { | ||
value: function createScope(moduleReport, scopeControl) { | ||
var newScope = arguments.length <= 2 || arguments[2] === undefined ? {} : arguments[2]; | ||
@@ -92,4 +92,4 @@ | ||
// Increments the associated aggregate report parameter count. | ||
report.aggregateMethodReport.params += newScope.paramCount; | ||
// Increments the associated aggregate moduleReport parameter count. | ||
moduleReport.aggregateMethodReport.params += newScope.paramCount; | ||
@@ -112,3 +112,3 @@ var classReport = scopeControl.getCurrentClassReport(); | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {ModuleScopeControl} scopeControl - The associated module report scope control. | ||
@@ -121,14 +121,14 @@ * @param {string} metric - A Halstead metric name. | ||
key: 'halsteadItemEncountered', | ||
value: function halsteadItemEncountered(report, scopeControl, metric, identifier) { | ||
value: function halsteadItemEncountered(moduleReport, scopeControl, metric, identifier) { | ||
var currentClassReport = scopeControl.getCurrentClassReport(); | ||
var currentMethodReport = scopeControl.getCurrentMethodReport(); | ||
this.incrementHalsteadItems(report, metric, identifier); | ||
ModuleMetricControl.incrementHalsteadItems(moduleReport, metric, identifier); | ||
if (currentClassReport) { | ||
this.incrementHalsteadItems(currentClassReport, metric, identifier); | ||
ModuleMetricControl.incrementHalsteadItems(currentClassReport, metric, identifier); | ||
} | ||
if (currentMethodReport) { | ||
this.incrementHalsteadItems(currentMethodReport, metric, identifier); | ||
ModuleMetricControl.incrementHalsteadItems(currentMethodReport, metric, identifier); | ||
} | ||
@@ -140,3 +140,3 @@ } | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {ModuleScopeControl} scopeControl - The associated module report scope control. | ||
@@ -148,7 +148,7 @@ * @param {number} amount - Amount to increment. | ||
key: 'incrementCyclomatic', | ||
value: function incrementCyclomatic(report, scopeControl, amount) { | ||
value: function incrementCyclomatic(moduleReport, scopeControl, amount) { | ||
var currentClassReport = scopeControl.getCurrentClassReport(); | ||
var currentMethodReport = scopeControl.getCurrentMethodReport(); | ||
report.methodAggregate.cyclomatic += amount; | ||
moduleReport.methodAggregate.cyclomatic += amount; | ||
@@ -167,3 +167,3 @@ if (currentClassReport) { | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {ModuleScopeControl} scopeControl - The associated module report scope control. | ||
@@ -175,7 +175,7 @@ * @param {number} amount - Amount to increment. | ||
key: 'incrementLogicalSloc', | ||
value: function incrementLogicalSloc(report, scopeControl, amount) { | ||
value: function incrementLogicalSloc(moduleReport, scopeControl, amount) { | ||
var currentClassReport = scopeControl.getCurrentClassReport(); | ||
var currentMethodReport = scopeControl.getCurrentMethodReport(); | ||
report.methodAggregate.sloc.logical += amount; | ||
moduleReport.methodAggregate.sloc.logical += amount; | ||
@@ -193,3 +193,3 @@ if (currentClassReport) { | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {string} metric - A Halstead metric name. | ||
@@ -201,11 +201,11 @@ * @param {string} identifier - A Halstead identifier name. | ||
key: 'incrementHalsteadItems', | ||
value: function incrementHalsteadItems(report, metric, identifier) { | ||
value: function incrementHalsteadItems(moduleReport, metric, identifier) { | ||
// Increments the associated aggregate report HalsteadData for distinct identifiers. | ||
if (report.aggregateMethodReport.halstead[metric].identifiers.indexOf(identifier) === -1) { | ||
report.aggregateMethodReport.halstead[metric].identifiers.push(identifier); | ||
report.aggregateMethodReport.halstead[metric]['distinct'] += 1; | ||
if (moduleReport.aggregateMethodReport.halstead[metric].identifiers.indexOf(identifier) === -1) { | ||
moduleReport.aggregateMethodReport.halstead[metric].identifiers.push(identifier); | ||
moduleReport.aggregateMethodReport.halstead[metric]['distinct'] += 1; | ||
} | ||
// Increment total halstead items | ||
report.aggregateMethodReport.halstead[metric]['total'] += 1; | ||
moduleReport.aggregateMethodReport.halstead[metric]['total'] += 1; | ||
} | ||
@@ -216,3 +216,3 @@ | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {ModuleScopeControl} scopeControl - The associated module report scope control. | ||
@@ -226,17 +226,15 @@ * @param {object} syntax - The associated syntax being processed for current node. | ||
key: 'processSyntax', | ||
value: function processSyntax(report, scopeControl, syntax, node, parent) { | ||
var _this = this; | ||
value: function processSyntax(moduleReport, scopeControl, syntax, node, parent) { | ||
var _loop = function _loop(key) { | ||
switch (syntax[key].metric) { | ||
case 'cyclomatic': | ||
_this.incrementCyclomatic(report, scopeControl, syntax[key].valueOf(node, parent)); | ||
ModuleMetricControl.incrementCyclomatic(moduleReport, scopeControl, syntax[key].valueOf(node, parent)); | ||
break; | ||
case 'dependencies': | ||
_this.addDependencies(report, syntax[key].valueOf(node, parent)); | ||
ModuleMetricControl.addDependencies(moduleReport, syntax[key].valueOf(node, parent)); | ||
break; | ||
case 'lloc': | ||
_this.incrementLogicalSloc(report, scopeControl, syntax[key].valueOf(node, parent)); | ||
ModuleMetricControl.incrementLogicalSloc(moduleReport, scopeControl, syntax[key].valueOf(node, parent)); | ||
break; | ||
@@ -250,3 +248,3 @@ } | ||
identifiers.forEach(function (identifier) { | ||
_this.halsteadItemEncountered(report, scopeControl, syntax[key].metric, identifier); | ||
ModuleMetricControl.halsteadItemEncountered(moduleReport, scopeControl, syntax[key].metric, identifier); | ||
}); | ||
@@ -253,0 +251,0 @@ } |
'use strict'; | ||
Object.defineProperty(exports, "__esModule", { | ||
value: true | ||
value: true | ||
}); | ||
@@ -30,78 +30,76 @@ | ||
var PluginMetricsModule = function () { | ||
function PluginMetricsModule() { | ||
_classCallCheck(this, PluginMetricsModule); | ||
} | ||
function PluginMetricsModule() { | ||
_classCallCheck(this, PluginMetricsModule); | ||
} | ||
_createClass(PluginMetricsModule, [{ | ||
key: 'onConfigure', | ||
_createClass(PluginMetricsModule, [{ | ||
key: 'onConfigure', | ||
// ESComplexModule plugin callbacks ------------------------------------------------------------------------------ | ||
/** | ||
* Loads any default settings that are not already provided by any user options. | ||
* | ||
* @param {object} ev - escomplex plugin event data. | ||
* | ||
* The following options are: | ||
* ``` | ||
* (boolean) newmi - Boolean indicating whether the maintainability index should be rebased on a scale from | ||
* 0 to 100; defaults to false. | ||
* ``` | ||
*/ | ||
value: function onConfigure(ev) { | ||
ev.data.settings.newmi = typeof ev.data.options.newmi === 'boolean' ? ev.data.options.newmi : false; | ||
} | ||
/** | ||
* Loads any default settings that are not already provided by any user options. | ||
* | ||
* @param {object} ev - escomplex plugin event data. | ||
* | ||
* The following options are: | ||
* ``` | ||
* (boolean) newmi - Boolean indicating whether the maintainability index should be rebased on a scale from | ||
* 0 to 100; defaults to false. | ||
* ``` | ||
*/ | ||
value: function onConfigure(ev) { | ||
ev.data.settings.newmi = typeof ev.data.options.newmi === 'boolean' ? ev.data.options.newmi : false; | ||
} | ||
/** | ||
* During AST traversal when a node is entered it is processed immediately if the node type corresponds to a | ||
* loaded trait syntax. | ||
* | ||
* @param {object} ev - escomplex plugin event data. | ||
*/ | ||
/** | ||
* During AST traversal when a node is entered it is processed immediately if the node type corresponds to a | ||
* loaded trait syntax. | ||
* | ||
* @param {object} ev - escomplex plugin event data. | ||
*/ | ||
}, { | ||
key: 'onEnterNode', | ||
value: function onEnterNode(ev) { | ||
var moduleReport = ev.data.moduleReport; | ||
var scopeControl = ev.data.scopeControl; | ||
var node = ev.data.node; | ||
var parent = ev.data.parent; | ||
var syntax = ev.data.syntaxes[node.type]; | ||
}, { | ||
key: 'onEnterNode', | ||
value: function onEnterNode(ev) { | ||
var report = ev.data.report; | ||
var scopeControl = ev.data.scopeControl; | ||
var node = ev.data.node; | ||
var parent = ev.data.parent; | ||
var syntax = ev.data.syntaxes[node.type]; | ||
// Process node syntax. | ||
if ((typeof syntax === 'undefined' ? 'undefined' : _typeof(syntax)) === 'object') { | ||
_ModuleMetricControl2.default.processSyntax(report, scopeControl, syntax, node, parent); | ||
// Process node syntax. | ||
if ((typeof syntax === 'undefined' ? 'undefined' : _typeof(syntax)) === 'object') { | ||
_ModuleMetricControl2.default.processSyntax(moduleReport, scopeControl, syntax, node, parent); | ||
} | ||
} | ||
} | ||
/** | ||
* Performs final calculations based on collected report data. | ||
* | ||
* @param {object} ev - escomplex plugin event data. | ||
*/ | ||
/** | ||
* Performs final calculations based on collected report data. | ||
* | ||
* @param {object} ev - escomplex plugin event data. | ||
*/ | ||
}, { | ||
key: 'onModuleEnd', | ||
value: function onModuleEnd(ev) { | ||
_ModuleMetricCalculate2.default.calculateMetrics(ev.data.report, ev.data.settings); | ||
} | ||
}, { | ||
key: 'onModuleEnd', | ||
value: function onModuleEnd(ev) { | ||
_ModuleMetricCalculate2.default.calculate(ev.data.moduleReport, ev.data.settings); | ||
} | ||
/** | ||
* A new module report scope has been created. Update any associated metrics regarding the new scope. | ||
* | ||
* @param {object} ev - escomplex plugin event data. | ||
*/ | ||
/** | ||
* A new module report scope has been created. Update any associated metrics regarding the new scope. | ||
* | ||
* @param {object} ev - escomplex plugin event data. | ||
*/ | ||
}, { | ||
key: 'onScopeCreated', | ||
value: function onScopeCreated(ev) { | ||
var report = ev.data.report; | ||
var scopeControl = ev.data.scopeControl; | ||
var newScope = ev.data.newScope; | ||
}, { | ||
key: 'onScopeCreated', | ||
value: function onScopeCreated(ev) { | ||
var moduleReport = ev.data.moduleReport; | ||
var scopeControl = ev.data.scopeControl; | ||
var newScope = ev.data.newScope; | ||
_ModuleMetricControl2.default.createScope(report, scopeControl, newScope); | ||
} | ||
}]); | ||
_ModuleMetricControl2.default.createScope(moduleReport, scopeControl, newScope); | ||
} | ||
}]); | ||
return PluginMetricsModule; | ||
return PluginMetricsModule; | ||
}(); | ||
@@ -108,0 +106,0 @@ |
{ | ||
"name": "escomplex-plugin-metrics-module", | ||
"version": "0.0.11", | ||
"version": "0.0.12", | ||
"homepage": "https://github.com/typhonjs-node-escomplex/escomplex-plugin-metrics-module/", | ||
@@ -23,6 +23,6 @@ "description": "Provides the core module metric / report generation plugin for typhonjs-escomplex module processing.", | ||
"dependencies": { | ||
"typhonjs-escomplex-commons": "^0.0.15" | ||
"typhonjs-escomplex-commons": "^0.0.16" | ||
}, | ||
"devDependencies": { | ||
"escomplex-plugin-syntax-babylon": "^0.0.11", | ||
"escomplex-plugin-syntax-babylon": "^0.0.12", | ||
"typhonjs-ast-walker": "^0.1.0", | ||
@@ -29,0 +29,0 @@ "typhonjs-config-eslint": "^0.4.0", |
@@ -1,2 +0,2 @@ | ||
import ObjectUtil from 'typhonjs-escomplex-commons/src/utils/ObjectUtil'; | ||
import ObjectUtil from 'typhonjs-escomplex-commons/src/utils/ObjectUtil'; | ||
@@ -12,92 +12,6 @@ /** | ||
/** | ||
* Calculates cyclomatic density - Proposed as a modification to cyclomatic complexity by Geoffrey K. Gill and | ||
* Chris F. Kemerer in 1991, this metric simply re-expresses it as a percentage of the logical lines of code. Lower | ||
* is better. | ||
* | ||
* @param {MethodReport} report - A MethodReport to perform calculations on. | ||
* | ||
* @private | ||
*/ | ||
static calculateCyclomaticDensity(report) | ||
{ | ||
report.cyclomaticDensity = report.sloc.logical === 0 ? 0 : (report.cyclomatic / report.sloc.logical) * 100; | ||
} | ||
/** | ||
* Calculates Halstead metrics. In 1977, Maurice Halstead developed a set of metrics which are calculated based on | ||
* the number of distinct operators, the number of distinct operands, the total number of operators and the total | ||
* number of operands in each function. This site picks out three Halstead measures in particular: difficulty, | ||
* volume and effort. | ||
* | ||
* @param {HalsteadData} halstead - A HalsteadData instance to perform calculations on. | ||
* | ||
* @see https://en.wikipedia.org/wiki/Halstead_complexity_measures | ||
* | ||
* @private | ||
*/ | ||
static calculateHalsteadMetrics(halstead) | ||
{ | ||
halstead.length = halstead.operators.total + halstead.operands.total; | ||
/* istanbul ignore if */ | ||
if (halstead.length === 0) | ||
{ | ||
halstead.reset(); | ||
} | ||
else | ||
{ | ||
halstead.vocabulary = halstead.operators.distinct + halstead.operands.distinct; | ||
halstead.difficulty = (halstead.operators.distinct / 2) | ||
* (halstead.operands.distinct === 0 ? 1 : halstead.operands.total / halstead.operands.distinct); | ||
halstead.volume = halstead.length * (Math.log(halstead.vocabulary) / Math.log(2)); | ||
halstead.effort = halstead.difficulty * halstead.volume; | ||
halstead.bugs = halstead.volume / 3000; | ||
halstead.time = halstead.effort / 18; | ||
} | ||
} | ||
/** | ||
* Designed in 1991 by Paul Oman and Jack Hagemeister at the University of Idaho, this metric is calculated at the | ||
* whole program or module level from averages of the other 3 metrics, using the following formula: | ||
* ``` | ||
* 171 - | ||
* (3.42 * ln(mean effort)) - | ||
* (0.23 * ln(mean cyclomatic complexity)) - | ||
* (16.2 * ln(mean logical LOC)) | ||
* ``` | ||
* Values are on a logarithmic scale ranging from negative infinity up to 171, with greater numbers indicating a | ||
* higher level of maintainability. In their original paper, Oman and Hagemeister identified 65 as the threshold | ||
* value below which a program should be considered difficult to maintain. | ||
* | ||
* @param {ClassReport|ModuleReport} report - A ClassReport or ModuleReport to perform calculations on. | ||
* @param {object} settings - Settings for module processing. | ||
* @param {number} averageCyclomatic - Average cyclomatic metric across a ClassReport / ModuleReport. | ||
* @param {number} averageEffort - Average Halstead effort across a ClassReport / ModuleReport. | ||
* @param {number} averageLoc - Average SLOC metric across a ClassReport / ModuleReport. | ||
* | ||
* @private | ||
*/ | ||
static calculateMaintainabilityIndex(report, settings, averageCyclomatic, averageEffort, averageLoc) | ||
{ | ||
/* istanbul ignore if */ | ||
if (averageCyclomatic === 0) { throw new Error('Encountered function with cyclomatic complexity zero!'); } | ||
report.maintainability = | ||
171 | ||
- (3.42 * Math.log(averageEffort)) | ||
- (0.23 * Math.log(averageCyclomatic)) | ||
- (16.2 * Math.log(averageLoc)); | ||
/* istanbul ignore if */ | ||
if (report.maintainability > 171) { report.maintainability = 171; } | ||
/* istanbul ignore if */ | ||
if (settings.newmi) { report.maintainability = Math.max(0, (report.maintainability * 100) / 171); } | ||
} | ||
/** | ||
* Coordinates calculating all metrics. All module and class methods are traversed. If there are no module or class | ||
* methods respectively the aggregate MethodReport is used for calculations. | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {object} settings - Settings for module processing. | ||
@@ -107,10 +21,10 @@ * | ||
*/ | ||
static calculateMetrics(report, settings) | ||
static calculate(moduleReport, settings) | ||
{ | ||
let moduleMethodCount = report.methods.length; | ||
const moduleMethodAverages = report.methodAverage; | ||
let moduleMethodCount = moduleReport.methods.length; | ||
const moduleMethodAverages = moduleReport.methodAverage; | ||
const moduleMethodAverageKeys = ObjectUtil.getAccessorList(moduleMethodAverages); | ||
// Handle module methods. | ||
report.methods.forEach((methodReport) => | ||
moduleReport.methods.forEach((methodReport) => | ||
{ | ||
@@ -128,3 +42,3 @@ moduleMethodAverageKeys.forEach((averageKey) => | ||
// Handle module class reports. | ||
report.classes.forEach((classReport) => | ||
moduleReport.classes.forEach((classReport) => | ||
{ | ||
@@ -177,4 +91,4 @@ const classMethodAverages = classReport.methodAverage; | ||
ModuleMetricCalculate.calculateCyclomaticDensity(report.aggregateMethodReport); | ||
ModuleMetricCalculate.calculateHalsteadMetrics(report.aggregateMethodReport.halstead); | ||
ModuleMetricCalculate.calculateCyclomaticDensity(moduleReport.aggregateMethodReport); | ||
ModuleMetricCalculate.calculateHalsteadMetrics(moduleReport.aggregateMethodReport.halstead); | ||
@@ -187,3 +101,3 @@ // If there are no module methods use the module aggregate MethodReport. | ||
{ | ||
const targetValue = ObjectUtil.safeAccess(report.aggregateMethodReport, averageKey, 0); | ||
const targetValue = ObjectUtil.safeAccess(moduleReport.aggregateMethodReport, averageKey, 0); | ||
@@ -202,5 +116,91 @@ ObjectUtil.safeSet(moduleMethodAverages, averageKey, targetValue, 'add'); | ||
ModuleMetricCalculate.calculateMaintainabilityIndex(report, settings, moduleMethodAverages.cyclomatic, | ||
ModuleMetricCalculate.calculateMaintainabilityIndex(moduleReport, settings, moduleMethodAverages.cyclomatic, | ||
moduleMethodAverages.halstead.effort, moduleMethodAverages.sloc.logical); | ||
} | ||
/** | ||
* Calculates cyclomatic density - Proposed as a modification to cyclomatic complexity by Geoffrey K. Gill and | ||
* Chris F. Kemerer in 1991, this metric simply re-expresses it as a percentage of the logical lines of code. Lower | ||
* is better. | ||
* | ||
* @param {AggregateMethodReport} report - An AggregateMethodReport to perform calculations on. | ||
* | ||
* @private | ||
*/ | ||
static calculateCyclomaticDensity(report) | ||
{ | ||
report.cyclomaticDensity = report.sloc.logical === 0 ? 0 : (report.cyclomatic / report.sloc.logical) * 100; | ||
} | ||
/** | ||
* Calculates Halstead metrics. In 1977, Maurice Halstead developed a set of metrics which are calculated based on | ||
* the number of distinct operators, the number of distinct operands, the total number of operators and the total | ||
* number of operands in each function. This site picks out three Halstead measures in particular: difficulty, | ||
* volume and effort. | ||
* | ||
* @param {HalsteadData} halstead - A HalsteadData instance to perform calculations on. | ||
* | ||
* @see https://en.wikipedia.org/wiki/Halstead_complexity_measures | ||
* | ||
* @private | ||
*/ | ||
static calculateHalsteadMetrics(halstead) | ||
{ | ||
halstead.length = halstead.operators.total + halstead.operands.total; | ||
/* istanbul ignore if */ | ||
if (halstead.length === 0) | ||
{ | ||
halstead.reset(); | ||
} | ||
else | ||
{ | ||
halstead.vocabulary = halstead.operators.distinct + halstead.operands.distinct; | ||
halstead.difficulty = (halstead.operators.distinct / 2) | ||
* (halstead.operands.distinct === 0 ? 1 : halstead.operands.total / halstead.operands.distinct); | ||
halstead.volume = halstead.length * (Math.log(halstead.vocabulary) / Math.log(2)); | ||
halstead.effort = halstead.difficulty * halstead.volume; | ||
halstead.bugs = halstead.volume / 3000; | ||
halstead.time = halstead.effort / 18; | ||
} | ||
} | ||
/** | ||
* Designed in 1991 by Paul Oman and Jack Hagemeister at the University of Idaho, this metric is calculated at the | ||
* whole program or module level from averages of the other 3 metrics, using the following formula: | ||
* ``` | ||
* 171 - | ||
* (3.42 * ln(mean effort)) - | ||
* (0.23 * ln(mean cyclomatic complexity)) - | ||
* (16.2 * ln(mean logical LOC)) | ||
* ``` | ||
* Values are on a logarithmic scale ranging from negative infinity up to 171, with greater numbers indicating a | ||
* higher level of maintainability. In their original paper, Oman and Hagemeister identified 65 as the threshold | ||
* value below which a program should be considered difficult to maintain. | ||
* | ||
* @param {ClassReport|ModuleReport} report - A ClassReport or ModuleReport to perform calculations on. | ||
* @param {object} settings - Settings for module processing. | ||
* @param {number} averageCyclomatic - Average cyclomatic metric across a ClassReport / ModuleReport. | ||
* @param {number} averageEffort - Average Halstead effort across a ClassReport / ModuleReport. | ||
* @param {number} averageLoc - Average SLOC metric across a ClassReport / ModuleReport. | ||
* | ||
* @private | ||
*/ | ||
static calculateMaintainabilityIndex(report, settings, averageCyclomatic, averageEffort, averageLoc) | ||
{ | ||
/* istanbul ignore if */ | ||
if (averageCyclomatic === 0) { throw new Error('Encountered function with cyclomatic complexity zero!'); } | ||
report.maintainability = | ||
171 | ||
- (3.42 * Math.log(averageEffort)) | ||
- (0.23 * Math.log(averageCyclomatic)) | ||
- (16.2 * Math.log(averageLoc)); | ||
/* istanbul ignore if */ | ||
if (report.maintainability > 171) { report.maintainability = 171; } | ||
/* istanbul ignore if */ | ||
if (settings.newmi) { report.maintainability = Math.max(0, (report.maintainability * 100) / 171); } | ||
} | ||
} |
@@ -8,10 +8,10 @@ import HalsteadArray from 'typhonjs-escomplex-commons/src/module/traits/HalsteadArray'; | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {object|Array<object>} dependencies - Dependencies to add. | ||
*/ | ||
static addDependencies(report, dependencies) | ||
static addDependencies(moduleReport, dependencies) | ||
{ | ||
if (typeof dependencies === 'object' || Array.isArray(dependencies)) | ||
{ | ||
report.dependencies = report.dependencies.concat(dependencies); | ||
moduleReport.dependencies = moduleReport.dependencies.concat(dependencies); | ||
} | ||
@@ -21,5 +21,5 @@ } | ||
/** | ||
* Creates a report scope when a class or method is entered. | ||
* Creates a moduleReport scope when a class or method is entered. | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {ModuleScopeControl} scopeControl - The associated module report scope control. | ||
@@ -35,3 +35,3 @@ * @param {object} newScope - An object hash defining the new scope including: | ||
*/ | ||
static createScope(report, scopeControl, newScope = {}) | ||
static createScope(moduleReport, scopeControl, newScope = {}) | ||
{ | ||
@@ -72,4 +72,4 @@ if (typeof newScope !== 'object') { throw new TypeError(`createScope error: 'newScope' is not an 'object'.`); } | ||
// Increments the associated aggregate report parameter count. | ||
report.aggregateMethodReport.params += newScope.paramCount; | ||
// Increments the associated aggregate moduleReport parameter count. | ||
moduleReport.aggregateMethodReport.params += newScope.paramCount; | ||
@@ -90,3 +90,3 @@ const classReport = scopeControl.getCurrentClassReport(); | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {ModuleScopeControl} scopeControl - The associated module report scope control. | ||
@@ -96,3 +96,3 @@ * @param {string} metric - A Halstead metric name. | ||
*/ | ||
static halsteadItemEncountered(report, scopeControl, metric, identifier) | ||
static halsteadItemEncountered(moduleReport, scopeControl, metric, identifier) | ||
{ | ||
@@ -102,7 +102,7 @@ const currentClassReport = scopeControl.getCurrentClassReport(); | ||
this.incrementHalsteadItems(report, metric, identifier); | ||
ModuleMetricControl.incrementHalsteadItems(moduleReport, metric, identifier); | ||
if (currentClassReport) { this.incrementHalsteadItems(currentClassReport, metric, identifier); } | ||
if (currentClassReport) { ModuleMetricControl.incrementHalsteadItems(currentClassReport, metric, identifier); } | ||
if (currentMethodReport) { this.incrementHalsteadItems(currentMethodReport, metric, identifier); } | ||
if (currentMethodReport) { ModuleMetricControl.incrementHalsteadItems(currentMethodReport, metric, identifier); } | ||
} | ||
@@ -114,7 +114,7 @@ | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {ModuleScopeControl} scopeControl - The associated module report scope control. | ||
* @param {number} amount - Amount to increment. | ||
*/ | ||
static incrementCyclomatic(report, scopeControl, amount) | ||
static incrementCyclomatic(moduleReport, scopeControl, amount) | ||
{ | ||
@@ -124,3 +124,3 @@ const currentClassReport = scopeControl.getCurrentClassReport(); | ||
report.methodAggregate.cyclomatic += amount; | ||
moduleReport.methodAggregate.cyclomatic += amount; | ||
@@ -135,7 +135,7 @@ if (currentClassReport) { currentClassReport.methodAggregate.cyclomatic += amount; } | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {ModuleScopeControl} scopeControl - The associated module report scope control. | ||
* @param {number} amount - Amount to increment. | ||
*/ | ||
static incrementLogicalSloc(report, scopeControl, amount) | ||
static incrementLogicalSloc(moduleReport, scopeControl, amount) | ||
{ | ||
@@ -145,3 +145,3 @@ const currentClassReport = scopeControl.getCurrentClassReport(); | ||
report.methodAggregate.sloc.logical += amount; | ||
moduleReport.methodAggregate.sloc.logical += amount; | ||
@@ -155,17 +155,17 @@ if (currentClassReport) { currentClassReport.methodAggregate.sloc.logical += amount; } | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {string} metric - A Halstead metric name. | ||
* @param {string} identifier - A Halstead identifier name. | ||
*/ | ||
static incrementHalsteadItems(report, metric, identifier) | ||
static incrementHalsteadItems(moduleReport, metric, identifier) | ||
{ | ||
// Increments the associated aggregate report HalsteadData for distinct identifiers. | ||
if (report.aggregateMethodReport.halstead[metric].identifiers.indexOf(identifier) === -1) | ||
if (moduleReport.aggregateMethodReport.halstead[metric].identifiers.indexOf(identifier) === -1) | ||
{ | ||
report.aggregateMethodReport.halstead[metric].identifiers.push(identifier); | ||
report.aggregateMethodReport.halstead[metric]['distinct'] += 1; | ||
moduleReport.aggregateMethodReport.halstead[metric].identifiers.push(identifier); | ||
moduleReport.aggregateMethodReport.halstead[metric]['distinct'] += 1; | ||
} | ||
// Increment total halstead items | ||
report.aggregateMethodReport.halstead[metric]['total'] += 1; | ||
moduleReport.aggregateMethodReport.halstead[metric]['total'] += 1; | ||
} | ||
@@ -176,3 +176,3 @@ | ||
* | ||
* @param {ModuleReport} report - The ModuleReport being processed. | ||
* @param {ModuleReport} moduleReport - The ModuleReport being processed. | ||
* @param {ModuleScopeControl} scopeControl - The associated module report scope control. | ||
@@ -183,3 +183,3 @@ * @param {object} syntax - The associated syntax being processed for current node. | ||
*/ | ||
static processSyntax(report, scopeControl, syntax, node, parent) | ||
static processSyntax(moduleReport, scopeControl, syntax, node, parent) | ||
{ | ||
@@ -191,11 +191,11 @@ for (const key in syntax) | ||
case 'cyclomatic': | ||
this.incrementCyclomatic(report, scopeControl, syntax[key].valueOf(node, parent)); | ||
ModuleMetricControl.incrementCyclomatic(moduleReport, scopeControl, syntax[key].valueOf(node, parent)); | ||
break; | ||
case 'dependencies': | ||
this.addDependencies(report, syntax[key].valueOf(node, parent)); | ||
ModuleMetricControl.addDependencies(moduleReport, syntax[key].valueOf(node, parent)); | ||
break; | ||
case 'lloc': | ||
this.incrementLogicalSloc(report, scopeControl, syntax[key].valueOf(node, parent)); | ||
ModuleMetricControl.incrementLogicalSloc(moduleReport, scopeControl, syntax[key].valueOf(node, parent)); | ||
break; | ||
@@ -211,3 +211,3 @@ } | ||
{ | ||
this.halsteadItemEncountered(report, scopeControl, syntax[key].metric, identifier); | ||
ModuleMetricControl.halsteadItemEncountered(moduleReport, scopeControl, syntax[key].metric, identifier); | ||
}); | ||
@@ -214,0 +214,0 @@ } |
@@ -12,4 +12,2 @@ import ModuleMetricCalculate from './ModuleMetricCalculate'; | ||
{ | ||
// ESComplexModule plugin callbacks ------------------------------------------------------------------------------ | ||
/** | ||
@@ -39,3 +37,3 @@ * Loads any default settings that are not already provided by any user options. | ||
{ | ||
const report = ev.data.report; | ||
const moduleReport = ev.data.moduleReport; | ||
const scopeControl = ev.data.scopeControl; | ||
@@ -47,3 +45,6 @@ const node = ev.data.node; | ||
// Process node syntax. | ||
if (typeof syntax === 'object') { ModuleMetricControl.processSyntax(report, scopeControl, syntax, node, parent); } | ||
if (typeof syntax === 'object') | ||
{ | ||
ModuleMetricControl.processSyntax(moduleReport, scopeControl, syntax, node, parent); | ||
} | ||
} | ||
@@ -58,3 +59,3 @@ | ||
{ | ||
ModuleMetricCalculate.calculateMetrics(ev.data.report, ev.data.settings); | ||
ModuleMetricCalculate.calculate(ev.data.moduleReport, ev.data.settings); | ||
} | ||
@@ -69,8 +70,8 @@ | ||
{ | ||
const report = ev.data.report; | ||
const moduleReport = ev.data.moduleReport; | ||
const scopeControl = ev.data.scopeControl; | ||
const newScope = ev.data.newScope; | ||
ModuleMetricControl.createScope(report, scopeControl, newScope); | ||
ModuleMetricControl.createScope(moduleReport, scopeControl, newScope); | ||
} | ||
} |
Major refactor
Supply chain riskPackage has recently undergone a major refactor. It may be unstable or indicate significant internal changes. Use caution when updating to versions that include significant changes.
Found 1 instance in 1 package
66016
0
+ Addedtyphonjs-escomplex-commons@0.0.16(transitive)
- Removedtyphonjs-escomplex-commons@0.0.15(transitive)