New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

escomplex

Package Overview
Dependencies
Maintainers
1
Versions
16
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

escomplex - npm Package Compare versions

Comparing version 0.1.2 to 0.1.3

8

package.json
{
"name": "escomplex",
"version": "0.1.2",
"version": "0.1.3",
"description": "Software complexity analysis of Mozilla-format abstract syntax trees.",

@@ -30,3 +30,3 @@ "homepage": "https://github.com/philbooth/escomplex",

"dependencies": {
"check-types": "0.6.x"
"check-types": "0.7.x"
},

@@ -37,3 +37,5 @@ "devDependencies": {

"chai": "1.8.x",
"esprima": "1.0.x"
"escomplex-ast-moz": "0.1.0",
"esprima": "1.0.x",
"coffee-script-redux": "2.0.x"
},

@@ -40,0 +42,0 @@ "scripts": {

@@ -8,3 +8,3 @@ # escomplex

Software complexity analysis
of Mozilla-format abstract syntax trees.
of JavaScript-family abstract syntax trees.

@@ -33,23 +33,2 @@ * [Metrics][#metrics]

Mozilla's [Parser API][api]
has become a de-facto standard
for the in-memory data representation
of parsed JavaScript programs.
It defines an abstract syntax tree format
composed of objects that publish their type information,
allowing consuming programs to easily navigate those trees
using generic logic.
By accepting a syntax tree
in such a widely supported format,
escomplex is decoupled from
a specific input language.
Any language
that compiles to JavaScript
and has a conforming parser
can be the subject of
complexity analysis by this library.
Some examples of conforming parsers are:
* [Esprima][esprima];

@@ -60,2 +39,4 @@ * [Acorn][acorn];

## Abstract syntax tree walkers
## Installation

@@ -62,0 +43,0 @@

@@ -20,12 +20,13 @@ /**

* code complexity.
* @param walker {object} The AST walker to use against `ast`.
* @param [options] {object} Options to modify the complexity calculation.
*
*/
function analyse (ast, options) {
function analyse (ast, walker, options) {
if (check.isArray(ast)) {
return require('./project').analyse(ast, options);
return require('./project').analyse(ast, walker, options);
}
return require('./module').analyse(ast, options);
return require('./module').analyse(ast, walker, options);
}

@@ -5,16 +5,14 @@ /*globals exports, require */

var check, syntaxDefinitions, safeName, syntaxes, report, clearDependencies;
var check = require('check-types'), report;
exports.analyse = analyse;
check = require('check-types');
safeName = require('./safeName');
syntaxDefinitions = require('./syntax');
function analyse (ast, walker, options) {
// TODO: Asynchronise
function analyse (ast, options) {
// TODO: Asynchronize.
var settings, currentReport, clearDependencies = true, scopeStack = [];
var settings;
check.verifyObject(ast, 'Invalid syntax tree');
check.verifyObject(walker, 'Invalid walker');
check.verifyFunction(walker.walk, 'Invalid walker.walk method');

@@ -27,7 +25,10 @@ if (check.isObject(options)) {

syntaxes = syntaxDefinitions.get(settings);
// TODO: loc is moz-specific, move to walker?
report = createReport(ast.loc);
clearDependencies = true;
processTree(ast.body, undefined, undefined);
walker.walk(ast, settings, {
processNode: processNode,
createScope: createScope,
popScope: popScope
});

@@ -37,2 +38,34 @@ calculateMetrics(settings);

return report;
function processNode (node, syntax) {
processLloc(node, syntax, currentReport);
processComplexity(node, syntax, currentReport);
processOperators(node, syntax, currentReport);
processOperands(node, syntax, currentReport);
if (processDependencies(node, syntax, clearDependencies)) {
// HACK: This will fail with async or if other syntax than CallExpression introduces dependencies.
// TODO: Come up with a less crude approach.
clearDependencies = false;
}
}
function createScope (name, loc, parameterCount) {
currentReport = createFunctionReport(name, loc, parameterCount);
report.functions.push(currentReport);
report.aggregate.complexity.params += parameterCount;
scopeStack.push(currentReport);
}
function popScope () {
scopeStack.pop();
if (scopeStack.length > 0) {
currentReport = scopeStack[scopeStack.length - 1]
} else {
currentReport = undefined;
}
}
}

@@ -62,2 +95,5 @@

complexity: {
sloc: {
logical: 0
},
cyclomatic: 1,

@@ -71,6 +107,3 @@ halstead: createInitialHalsteadState(),

result.line = lines.start.line;
result.complexity.sloc = {
physical: lines.end.line - lines.start.line + 1,
logical: 0
};
result.complexity.sloc.physical = lines.end.line - lines.start.line + 1;
}

@@ -96,39 +129,9 @@

function processTree (tree, assignedName, currentReport) {
check.verifyArray(tree, 'Invalid syntax tree');
tree.forEach(function (node) {
processNode(node, assignedName, currentReport);
});
function processLloc (node, syntax, currentReport) {
incrementCounter(node, syntax, 'lloc', incrementLogicalSloc, currentReport);
}
function processNode (node, assignedName, currentReport) {
var syntax;
function incrementCounter (node, syntax, name, incrementFn, currentReport) {
var amount = syntax[name];
if (check.isObject(node)) {
syntax = syntaxes[node.type];
if (check.isObject(syntax)) {
processLloc(node, currentReport);
processComplexity(node, currentReport);
processOperators(node, currentReport);
processOperands(node, currentReport);
processDependencies(node);
if (syntax.newScope) {
processChildrenInNewScope(node, assignedName);
} else {
processChildren(node, currentReport);
}
}
}
}
function processLloc (node, currentReport) {
incrementCounter(node, 'lloc', incrementLogicalSloc, currentReport);
}
function incrementCounter (node, name, incrementFn, currentReport) {
var amount = syntaxes[node.type][name];
if (check.isNumber(amount)) {

@@ -142,13 +145,11 @@ incrementFn(currentReport, amount);

function incrementLogicalSloc (currentReport, amount) {
if (check.isObject(report.aggregate.complexity.sloc)) {
report.aggregate.complexity.sloc.logical += amount;
report.aggregate.complexity.sloc.logical += amount;
if (currentReport) {
currentReport.complexity.sloc.logical += amount;
}
if (currentReport) {
currentReport.complexity.sloc.logical += amount;
}
}
function processComplexity (node, currentReport) {
incrementCounter(node, 'complexity', incrementComplexity, currentReport);
function processComplexity (node, syntax, currentReport) {
incrementCounter(node, syntax, 'complexity', incrementComplexity, currentReport);
}

@@ -164,13 +165,11 @@

function processOperators (node, currentReport) {
processHalsteadMetric(node, 'operators', currentReport);
function processOperators (node, syntax, currentReport) {
processHalsteadMetric(node, syntax, 'operators', currentReport);
}
function processOperands (node, currentReport) {
processHalsteadMetric(node, 'operands', currentReport);
function processOperands (node, syntax, currentReport) {
processHalsteadMetric(node, syntax, 'operands', currentReport);
}
function processHalsteadMetric (node, metric, currentReport) {
var syntax = syntaxes[node.type];
function processHalsteadMetric (node, syntax, metric, currentReport) {
if (check.isArray(syntax[metric])) {

@@ -234,4 +233,4 @@ syntax[metric].forEach(function (s) {

function processDependencies (node) {
var syntax = syntaxes[node.type], dependencies;
function processDependencies (node, syntax, clearDependencies) {
var dependencies;

@@ -244,36 +243,8 @@ if (check.isFunction(syntax.dependencies)) {

// HACK: This will fail with async or if other syntax than CallExpression introduces dependencies.
// TODO: Come up with a less crude approach.
clearDependencies = false;
return true;
}
}
function processChildrenInNewScope (node, assignedName) {
var newReport = createFunctionReport(safeName(node.id, assignedName), node.loc, node.params.length);
report.functions.push(newReport);
report.aggregate.complexity.params += node.params.length;
processChildren(node, newReport);
return false;
}
function processChildren (node, currentReport) {
var syntax = syntaxes[node.type];
if (check.isArray(syntax.children)) {
syntax.children.forEach(function (child) {
processChild(
node[child],
check.isFunction(syntax.assignableName) ? syntax.assignableName(node) : '',
currentReport
);
});
}
}
function processChild (child, assignedName, currentReport) {
var fn = check.isArray(child) ? processTree : processNode;
fn(child, assignedName, currentReport);
}
function calculateMetrics (settings) {

@@ -344,5 +315,3 @@ var i, data, averages,

function sumMaintainabilityMetrics (sums, indices, data) {
if (check.isObject(data.sloc)) {
sums[indices.loc] += data.sloc.logical;
}
sums[indices.loc] += data.sloc.logical;
sums[indices.complexity] += data.cyclomatic;

@@ -354,7 +323,2 @@ sums[indices.effort] += data.halstead.effort;

function calculateMaintainabilityIndex (averageEffort, averageComplexity, averageLoc, settings) {
if (check.isObject(report.aggregate.complexity.sloc) === false) {
// Can't calculate maintainability index if caller didn't provide SLOC data.
return;
}
if (averageComplexity === 0) {

@@ -361,0 +325,0 @@ throw new Error('Encountered function with cyclomatic complexity zero!');

@@ -13,3 +13,3 @@ /*globals exports, require */

function analyse (modules, options) {
function analyse (modules, walker, options) {
// TODO: Asynchronize.

@@ -26,3 +26,3 @@

report = moduleAnalyser.analyse(m.ast, options);
report = moduleAnalyser.analyse(m.ast, walker, options);
report.path = m.path;

@@ -29,0 +29,0 @@

@@ -5,5 +5,6 @@ /*globals require, suite, test, setup, teardown */

var assert, mockery, esprima, modulePath,
var assert, mozWalker, esprima, modulePath,
assert = require('chai').assert;
mozWalker = require('escomplex-ast-moz');
esprima = require('esprima');

@@ -51,3 +52,3 @@

}
});
}, mozWalker);
});

@@ -58,3 +59,3 @@ });

assert.doesNotThrow(function () {
cr.analyse([]);
cr.analyse([], mozWalker);
});

@@ -67,3 +68,3 @@ });

setup(function () {
result = cr.analyse([]);
result = cr.analyse([], mozWalker);
});

@@ -115,3 +116,3 @@

{ ast: esprima.parse('if (true) { "foo"; } else { "bar"; }', { loc: true }), path: 'a' }
]);
], mozWalker);
});

@@ -239,3 +240,3 @@

{ ast: esprima.parse('require("./a/b");require("./a/c");"a";', { loc: true }), path: '/a.js' }
]);
], mozWalker);
});

@@ -242,0 +243,0 @@

Sorry, the diff of this file is too big to display

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc