├── .eslintignore ├── .gitattributes ├── .gitignore ├── .travis.yml ├── .eslintrc ├── src ├── formats │ ├── json.js │ ├── modules.js │ ├── minimal.js │ ├── plain.js │ ├── markdown.js │ ├── checkstyle.js │ └── xml.js ├── config.js └── index.js ├── .editorconfig ├── .complexrc.example ├── AUTHORS ├── CONTRIBUTING.md ├── COPYING ├── package.json ├── test └── config-test.js ├── README.md └── EXAMPLE.md /.eslintignore: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /.gitattributes: -------------------------------------------------------------------------------- 1 | * text 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | npm-debug.log 3 | .DS_Store 4 | 5 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: node_js 2 | sudo: false 3 | node_js: 4 | - "stable" 5 | - "0.12" 6 | - "0.11" 7 | - "0.10" 8 | -------------------------------------------------------------------------------- /.eslintrc: -------------------------------------------------------------------------------- 1 | extends: "eslint:recommended" 2 | parser: "esprima" 3 | env: 4 | node: true 5 | mocha: true 6 | rules: 7 | comma-dangle: [2, "never"] 8 | 9 | -------------------------------------------------------------------------------- /src/formats/json.js: -------------------------------------------------------------------------------- 1 | /*globals exports, JSON */ 2 | 3 | 'use strict'; 4 | 5 | exports.format = format; 6 | 7 | function format (result) { 8 | return JSON.stringify(result, undefined, 4); 9 | } 10 | 11 | -------------------------------------------------------------------------------- /.editorconfig: -------------------------------------------------------------------------------- 1 | [*] 2 | end_of_line = lf 3 | charset = utf-8 4 | insert_final_newline = true 5 | indent_style = space 6 | indent_size = 2 7 | trim_trailing_whitespace = true 8 | 9 | [*.js] 10 | indent_size = 4 11 | 12 | -------------------------------------------------------------------------------- /src/formats/modules.js: -------------------------------------------------------------------------------- 1 | /*globals exports */ 2 | 3 | 'use strict'; 4 | 5 | exports.format = format; 6 | 7 | function format (result) { 8 | return result.reports.reduce(function (formatted, report) { 9 | return formatted + report.path + '\n'; 10 | }, ''); 11 | } 12 | 13 | -------------------------------------------------------------------------------- /.complexrc.example: -------------------------------------------------------------------------------- 1 | { 2 | "output": "/Users/pbooth/complexity-report.md", 3 | "format": "markdown", 4 | "allfiles": false, 5 | "ignoreerrors": true, 6 | "filepattern": "\\.js$", 7 | "dirpattern": "(server)|(client)|(helpers)", 8 | "maxfiles": 256, 9 | "maxfod": 20, 10 | "maxcost": 50, 11 | "maxsize": 25, 12 | "minmi": 100, 13 | "maxcyc": 8, 14 | "maxcycden": 100, 15 | "maxhd": 20, 16 | "maxhv": 500, 17 | "maxhe": 2000, 18 | "silent": false, 19 | "logicalor": false, 20 | "switchcase": false, 21 | "forin": false, 22 | "trycatch": false, 23 | "newmi": false 24 | } 25 | -------------------------------------------------------------------------------- /AUTHORS: -------------------------------------------------------------------------------- 1 | Phil Booth (https://github.com/philbooth) 2 | Juzer Ali (https://github.com/juzerali) 3 | Mark Trostler (https://github.com/zzo) 4 | Wyatt Preul (https://github.com/wpreul) 5 | Rowan Manning (https://github.com/rowanmanning) 6 | Andrew Pennebaker (https://github.com/mcandre) 7 | Nils Kenneweg (https://github.com/nkenneweg) 8 | Eric Burin des Roziers (https://github.com/Ericbdr) 9 | Matt Field (https://github.com/mattfield) 10 | Addison Higham (https://github.com/addisonj) 11 | Daniel Kavassy (https://github.com/dkavassy) 12 | Jared Stilwell (https://github.com/jared-stilwell) 13 | Vlad Barboni (https://github.com/barboni) 14 | -------------------------------------------------------------------------------- /src/config.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var check = require('check-types'); 4 | 5 | module.exports = { 6 | isModuleComplexityThresholdSet: function isModuleComplexityThresholdSet (config) { 7 | return check.number(config.minmi); 8 | }, 9 | 10 | isFunctionComplexityThresholdSet: function isFunctionComplexityThresholdSet (config) { 11 | return check.number(config.maxcyc) || 12 | check.number(config.maxcycden) || 13 | check.number(config.maxhd) || 14 | check.number(config.maxhv) || 15 | check.number(config.maxhe); 16 | }, 17 | 18 | isProjectComplexityThresholdSet: function isProjectComplexityThresholdSet (config) { 19 | return check.number(config.maxfod) || 20 | check.number(config.maxcost) || 21 | check.number(config.maxsize); 22 | } 23 | }; 24 | -------------------------------------------------------------------------------- /src/formats/minimal.js: -------------------------------------------------------------------------------- 1 | /*globals exports */ 2 | 3 | 'use strict'; 4 | 5 | exports.format = format; 6 | 7 | function format (result) { 8 | return result.reports.reduce(function (formatted, report) { 9 | return formatted + formatModule(report) + '\n'; 10 | }, ''); 11 | } 12 | 13 | function formatModule (report) { 14 | return [ 15 | report.path, ': ', report.maintainability, 16 | formatFunctions(report.functions) 17 | ].join(''); 18 | } 19 | 20 | function formatFunctions (report) { 21 | return report.reduce(function (formatted, r) { 22 | return formatted + '\n' + formatFunction(r); 23 | }, ''); 24 | } 25 | 26 | function formatFunction (report) { 27 | return [ 28 | ' ', 29 | report.name, 30 | ' (', 31 | report.line, 32 | '): ', 33 | report.cyclomatic 34 | ].join(''); 35 | } 36 | 37 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # Contribution guidelines 2 | 3 | * Install/update the dependencies. 4 | `npm install` 5 | * Make sure the code lints. 6 | `npm run lint` 7 | * New features 8 | or changes to existing features 9 | must be documented in the [readme] file. 10 | * Adhere to the coding conventions 11 | that are used elsewhere in the codebase. 12 | * Add yourself to the [authors] file. 13 | * Feel free to [open an issue][newissue] first, 14 | if the change is one that you think 15 | needs some discussion. 16 | I'm not precious 17 | about the [issue list][issues]. 18 | 19 | [readme]: https://github.com/jared-stilwell/complexity-report/blob/master/README.md 20 | [authors]: https://github.com/jared-stilwell/complexity-report/blob/master/AUTHORS 21 | [newissue]: https://github.com/jared-stilwell/complexity-report/issues/new 22 | [issues]: https://github.com/jared-stilwell/complexity-report/issues 23 | -------------------------------------------------------------------------------- /COPYING: -------------------------------------------------------------------------------- 1 | Copyright © 2016 Jared Stilwell 2 | 3 | Permission is hereby granted, free of charge, to any person obtaining a copy of 4 | this software and associated documentation files (the "Software"), to deal in 5 | the Software without restriction, including without limitation the rights to 6 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies 7 | of the Software, and to permit persons to whom the Software is furnished to do 8 | so, subject to the following conditions: 9 | 10 | The above copyright notice and this permission notice shall be included in all 11 | copies or substantial portions of the Software. 12 | 13 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 14 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 15 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 16 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 17 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 18 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 19 | SOFTWARE. 20 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "complexity-report", 3 | "version": "2.0.0-alpha", 4 | "description": "Software complexity analysis for JavaScript projects", 5 | "homepage": "https://github.com/jared-stilwell/complexity-report", 6 | "bugs": "https://github.com/jared-stilwell/complexity-report/issues", 7 | "license": "MIT", 8 | "author": "Phil Booth ", 9 | "bin": { 10 | "cr": "./src/index.js" 11 | }, 12 | "repository": { 13 | "type": "git", 14 | "url": "https://github.com/jared-stilwell/complexity-report.git" 15 | }, 16 | "maintainers": [ 17 | { 18 | "name": "Jared Stilwell", 19 | "email": "jared.k.stilwell@gmail.com", 20 | "url": "https://github.com/jared-stilwell" 21 | } 22 | ], 23 | "keywords": [ 24 | "complexity", 25 | "simplicity", 26 | "cyclomatic", 27 | "halstead", 28 | "maintainability", 29 | "static", 30 | "analysis", 31 | "metrics", 32 | "escomplex" 33 | ], 34 | "dependencies": { 35 | "async": "^2.1.5", 36 | "check-types": "^7.1.5", 37 | "commander": "^2.9.0", 38 | "escomplex": "2.0.0-alpha", 39 | "esprima": "^3.1.3" 40 | }, 41 | "devDependencies": { 42 | "chai": "^3.4.0", 43 | "eslint": "^3.17.1", 44 | "mocha": "^3.2.0" 45 | }, 46 | "scripts": { 47 | "lint": "eslint test src", 48 | "test": "mocha --ui tdd --reporter spec --colors" 49 | }, 50 | "eslintConfig": { 51 | "extends": "eslint:recommended", 52 | "parser": "esprima", 53 | "env": { 54 | "node": true, 55 | "mocha": true 56 | } 57 | } 58 | } 59 | -------------------------------------------------------------------------------- /src/formats/plain.js: -------------------------------------------------------------------------------- 1 | /*globals exports */ 2 | 3 | 'use strict'; 4 | 5 | exports.format = format; 6 | 7 | function format (result) { 8 | return result.reports.reduce(function (formatted, report) { 9 | return formatted + formatModule(report) + '\n\n'; 10 | }, formatProject(result)); 11 | } 12 | 13 | function formatProject (result) { 14 | return [ 15 | 'Mean per-function logical LOC: ', result.loc, '\n', 16 | 'Mean per-function parameter count: ', result.params, '\n', 17 | 'Mean per-function cyclomatic complexity: ', result.cyclomatic, '\n', 18 | 'Mean per-function Halstead effort: ', result.effort, '\n', 19 | 'Mean per-module maintainability index: ', result.maintainability, '\n', 20 | 'First-order density: ', result.firstOrderDensity, '%\n', 21 | 'Change cost: ', result.changeCost, '%\n', 22 | 'Core size: ', result.coreSize, '%\n\n' 23 | ].join(''); 24 | } 25 | 26 | function formatModule (report) { 27 | return [ 28 | report.path, '\n\n', 29 | ' Physical LOC: ', report.aggregate.sloc.physical, '\n', 30 | ' Logical LOC: ', report.aggregate.sloc.logical, '\n', 31 | ' Mean parameter count: ', report.params, '\n', 32 | ' Cyclomatic complexity: ', report.aggregate.cyclomatic, '\n', 33 | ' Cyclomatic complexity density: ', report.aggregate.cyclomaticDensity, '%\n', 34 | ' Maintainability index: ', report.maintainability, '\n', 35 | ' Dependency count: ', report.dependencies.length, 36 | formatFunctions(report.functions) 37 | ].join(''); 38 | } 39 | 40 | function formatFunctions (report) { 41 | return report.reduce(function (formatted, r) { 42 | return formatted + '\n\n' + formatFunction(r); 43 | }, ''); 44 | } 45 | 46 | function formatFunction (report) { 47 | return [ 48 | ' Function: ', report.name, '\n', 49 | ' Line No.: ', report.line, '\n', 50 | ' Physical LOC: ', report.sloc.physical, '\n', 51 | ' Logical LOC: ', report.sloc.logical, '\n', 52 | ' Parameter count: ', report.params, '\n', 53 | ' Cyclomatic complexity: ', report.cyclomatic, '\n', 54 | ' Cyclomatic complexity density: ', report.cyclomaticDensity, '%\n', 55 | ' Halstead difficulty: ', report.halstead.difficulty, '\n', 56 | ' Halstead volume: ', report.halstead.volume, '\n', 57 | ' Halstead effort: ', report.halstead.effort 58 | ].join(''); 59 | } 60 | 61 | -------------------------------------------------------------------------------- /src/formats/markdown.js: -------------------------------------------------------------------------------- 1 | /*globals exports */ 2 | 3 | 'use strict'; 4 | 5 | exports.format = format; 6 | 7 | function format (result) { 8 | return result.reports.reduce(function (formatted, report) { 9 | return formatted + formatModule(report) + '\n\n'; 10 | }, formatProject(result)); 11 | } 12 | 13 | function formatProject (result) { 14 | return [ 15 | '# Complexity report, ', (new Date()).toLocaleDateString(), '\n\n', 16 | '* Mean per-function logical LOC: ', result.loc, '\n', 17 | '* Mean per-function parameter count: ', result.params, '\n', 18 | '* Mean per-function cyclomatic complexity: ', result.cyclomatic, '\n', 19 | '* Mean per-function Halstead effort: ', result.effort, '\n', 20 | '* Mean per-module maintainability index: ', result.maintainability, '\n', 21 | '* First-order density: ', result.firstOrderDensity, '%\n', 22 | '* Change cost: ', result.changeCost, '%\n', 23 | '* Core size: ', result.coreSize, '%\n\n' 24 | ].join(''); 25 | } 26 | 27 | function formatModule (report) { 28 | return [ 29 | '## ', report.path, '\n\n', 30 | '* Physical LOC: ', report.aggregate.sloc.physical, '\n', 31 | '* Logical LOC: ', report.aggregate.sloc.logical, '\n', 32 | '* Mean parameter count: ', report.params, '\n', 33 | '* Cyclomatic complexity: ', report.aggregate.cyclomatic, '\n', 34 | '* Cyclomatic complexity density: ', report.aggregate.cyclomaticDensity, '%\n', 35 | '* Maintainability index: ', report.maintainability, '\n', 36 | '* Dependency count: ', report.dependencies.length, 37 | formatFunctions(report.functions) 38 | ].join(''); 39 | } 40 | 41 | function formatFunctions (report) { 42 | return report.reduce(function (formatted, r) { 43 | return formatted + '\n' + formatFunction(r); 44 | }, ''); 45 | } 46 | 47 | function formatFunction (report) { 48 | return [ 49 | '* Function: **', report.name.replace('<', '<'), '**\n', 50 | ' * Line No.: ', report.line, '\n', 51 | ' * Physical LOC: ', report.sloc.physical, '\n', 52 | ' * Logical LOC: ', report.sloc.logical, '\n', 53 | ' * Parameter count: ', report.params, '\n', 54 | ' * Cyclomatic complexity: ', report.cyclomatic, '\n', 55 | ' * Cyclomatic complexity density: ', report.cyclomaticDensity, '%\n', 56 | ' * Halstead difficulty: ', report.halstead.difficulty, '\n', 57 | ' * Halstead volume: ', report.halstead.volume, '\n', 58 | ' * Halstead effort: ', report.halstead.effort 59 | ].join(''); 60 | } 61 | 62 | -------------------------------------------------------------------------------- /src/formats/checkstyle.js: -------------------------------------------------------------------------------- 1 | /*globals exports */ 2 | 3 | 'use strict'; 4 | 5 | var thresholds = { 6 | cyclomatic: [3, 7, 12], 7 | halstead: [8, 13, 20] 8 | }; 9 | 10 | exports.format = format; 11 | 12 | function format (result) { 13 | return createXMLDefinition() + createElement( 14 | 0, 15 | 'checkstyle', 16 | true, 17 | result.reports.reduce(function (formatted, report) { 18 | return formatted + formatModule(2, report); 19 | }, '') 20 | ); 21 | } 22 | 23 | function createXMLDefinition () { 24 | return '\n'; 25 | } 26 | 27 | function createElementWithAttributes (indentation, tag, attributes, linebreak, content) { 28 | return createElementWithTags(indentation, tag + ' ' + attributes, tag, linebreak, content); 29 | } 30 | 31 | function createElementWithTags (indentation, openingTag, closingTag, linebreak, content) { 32 | return indent('<', indentation) + openingTag + '>' + 33 | (linebreak ? '\n' : '') + content + 34 | (linebreak ? indent('\n'; 35 | } 36 | 37 | function createEmptyElementWithAttributes (indentation, tag, attributes) { 38 | var nextIndentation = incrementIndentation(indentation); 39 | 40 | return indent('<', indentation) + tag + '\n' + 41 | indent(attributes + '\n', nextIndentation)+ 42 | indent('/>', indentation) + '\n'; 43 | } 44 | 45 | function indent (string, indentation) { 46 | return (new Array(indentation + 1)).join(' ') + string; 47 | } 48 | 49 | function formatModule (indentation, report) { 50 | var i, functions = '', nextIndentation = incrementIndentation(indentation); 51 | 52 | for (i = 0; i < report.functions.length; i += 1) { 53 | functions += formatFunction(nextIndentation, report.functions[i]); 54 | } 55 | 56 | return createElementWithAttributes( 57 | indentation, 'file', 'name="' + report.path + '"', true, functions 58 | ); 59 | } 60 | 61 | function incrementIndentation (indentation) { 62 | return indentation + 2; 63 | } 64 | 65 | function formatFunction (indentation, data) { 66 | var nextIndentation = incrementIndentation(indentation); 67 | 68 | return createEmptyElementWithAttributes( 69 | indentation, 'error', 70 | [ 71 | 'line="' + data.line + '"', 72 | 'severity="' + assignSeverity(data) + '"', 73 | 'message="Cyclomatic: ' + data.cyclomatic + ',', 74 | 'Halstead: ' + data.halstead.difficulty.toPrecision(5), 75 | '| Effort: ' + data.halstead.effort.toPrecision(5), 76 | '| Volume: ' + data.halstead.volume.toPrecision(5), 77 | '| Vocabulary: ' + data.halstead.vocabulary + '"', 78 | 'source="' + data.name.replace('<', '<').replace('>', '>') + '"' 79 | ].join('\n' + indent('', nextIndentation)) 80 | ); 81 | } 82 | 83 | function createElement (indentation, tag, linebreak, content) { 84 | return createElementWithTags(indentation, tag, tag, linebreak, content); 85 | } 86 | 87 | function assignSeverity (data) { 88 | var levels = ['info', 'warning', 'error'], 89 | severity = levels[0]; 90 | 91 | levels.forEach(function(level, i) { 92 | if (data.cyclomatic > thresholds.cyclomatic[i] || 93 | data.halstead.difficulty > thresholds.halstead[i]) { 94 | severity = levels[i]; 95 | } 96 | }); 97 | 98 | return severity; 99 | } 100 | 101 | -------------------------------------------------------------------------------- /test/config-test.js: -------------------------------------------------------------------------------- 1 | 'use strict'; 2 | 3 | var assert = require('chai').assert; 4 | var config = require('../src/config'); 5 | 6 | suite('Configuration Checks', function () { 7 | suite('#isModuleComplexityThresholdSet', function () { 8 | test('null value', function () { 9 | assert.isFalse( 10 | config.isModuleComplexityThresholdSet({ 11 | minmi: null 12 | }) 13 | ); 14 | }); 15 | 16 | test('string value', function () { 17 | assert.isFalse( 18 | config.isModuleComplexityThresholdSet({ 19 | minmi: 'test' 20 | }) 21 | ); 22 | }); 23 | 24 | test('boolean value', function () { 25 | assert.isFalse( 26 | config.isModuleComplexityThresholdSet({ 27 | minmi: true 28 | }) 29 | ); 30 | }); 31 | 32 | test('object value', function () { 33 | assert.isFalse( 34 | config.isModuleComplexityThresholdSet({ 35 | minmi: {} 36 | }) 37 | ); 38 | }); 39 | 40 | test('number value', function () { 41 | assert.isTrue( 42 | config.isModuleComplexityThresholdSet({ 43 | minmi: 10 44 | }) 45 | ); 46 | }); 47 | }); 48 | 49 | suite('#isFunctionComplexityThresholdSet', function () { 50 | var fn = config.isFunctionComplexityThresholdSet; 51 | 52 | test('null value', function () { 53 | assert.isFalse(fn({ maxcyc: null })); 54 | assert.isFalse(fn({ maxcycden: null })); 55 | assert.isFalse(fn({ maxhd: null })); 56 | assert.isFalse(fn({ maxhv: null })); 57 | assert.isFalse(fn({ maxhe: null })); 58 | }); 59 | 60 | test('string value', function () { 61 | assert.isFalse(fn({ maxcyc: 'test' })); 62 | assert.isFalse(fn({ maxcycden: 'test' })); 63 | assert.isFalse(fn({ maxhd: 'test' })); 64 | assert.isFalse(fn({ maxhv: 'test' })); 65 | assert.isFalse(fn({ maxhe: 'test' })); 66 | }); 67 | 68 | test('boolean value', function () { 69 | assert.isFalse(fn({ maxcyc: true })); 70 | assert.isFalse(fn({ maxcycden: true })); 71 | assert.isFalse(fn({ maxhd: true })); 72 | assert.isFalse(fn({ maxhv: true })); 73 | assert.isFalse(fn({ maxhe: true })); 74 | }); 75 | 76 | test('object value', function () { 77 | assert.isFalse(fn({ maxcyc: {} })); 78 | assert.isFalse(fn({ maxcycden: {} })); 79 | assert.isFalse(fn({ maxhd: {} })); 80 | assert.isFalse(fn({ maxhv: {} })); 81 | assert.isFalse(fn({ maxhe: {} })); 82 | }); 83 | 84 | test('number value', function () { 85 | assert.isTrue(fn({ maxcyc: 10 })); 86 | assert.isTrue(fn({ maxcycden: 10 })); 87 | assert.isTrue(fn({ maxhd: 10 })); 88 | assert.isTrue(fn({ maxhv: 10 })); 89 | assert.isTrue(fn({ maxhe: 10 })); 90 | }); 91 | }); 92 | 93 | suite('#isProjectComplexityThresholdSet', function () { 94 | var fn = config.isProjectComplexityThresholdSet; 95 | 96 | test('null value', function () { 97 | assert.isFalse(fn({ maxfod: null })); 98 | assert.isFalse(fn({ maxcost: null })); 99 | assert.isFalse(fn({ maxsize: null })); 100 | }); 101 | 102 | test('string value', function () { 103 | assert.isFalse(fn({ maxfod: 'test' })); 104 | assert.isFalse(fn({ maxcost: 'test' })); 105 | assert.isFalse(fn({ maxsize: 'test' })); 106 | }); 107 | 108 | test('boolean value', function () { 109 | assert.isFalse(fn({ maxfod: true })); 110 | assert.isFalse(fn({ maxcost: true })); 111 | assert.isFalse(fn({ maxsize: true })); 112 | }); 113 | 114 | test('object value', function () { 115 | assert.isFalse(fn({ maxfod: {} })); 116 | assert.isFalse(fn({ maxcost: {} })); 117 | assert.isFalse(fn({ maxsize: {} })); 118 | }); 119 | 120 | test('number value', function () { 121 | assert.isTrue(fn({ maxfod: 10 })); 122 | assert.isTrue(fn({ maxcost: 10 })); 123 | assert.isTrue(fn({ maxsize: 10 })); 124 | }); 125 | }); 126 | }); 127 | -------------------------------------------------------------------------------- /src/formats/xml.js: -------------------------------------------------------------------------------- 1 | /*globals exports */ 2 | 3 | 'use strict'; 4 | 5 | exports.format = format; 6 | 7 | function format (result) { 8 | return createElementWithAttributes( 9 | 0, 10 | 'project', 11 | 'xmlns="" xml:lang="en" timestamp="' + 12 | Date.now() + 13 | '" first-order-denisty="' + 14 | result.firstOrderDensity + 15 | '" change-cost="' + 16 | result.changeCost + 17 | '" core-size="' + 18 | result.coreSize + '"', 19 | true, 20 | result.reports.reduce(function (formatted, report) { 21 | return formatted + formatModule(4, report); 22 | }, '') 23 | ); 24 | } 25 | 26 | function createElementWithAttributes (indentation, tag, attributes, linebreak, content) { 27 | return createElementWithTags(indentation, tag + ' ' + attributes, tag, linebreak, content); 28 | } 29 | 30 | function createElementWithTags (indentation, openingTag, closingTag, linebreak, content) { 31 | return indent('<', indentation) + openingTag + '>' + 32 | (linebreak ? '\n' : '') + content + 33 | (linebreak ? indent('\n'; 34 | } 35 | 36 | function indent (string, indentation) { 37 | return (new Array(indentation + 1)).join(' ') + string; 38 | } 39 | 40 | function formatModule (indentation, report) { 41 | var i, functions = '', nextIndentation = incrementIndentation(indentation); 42 | 43 | for (i = 0; i < report.functions.length; i += 1) { 44 | functions += formatFunction(nextIndentation, report.functions[i]); 45 | } 46 | 47 | return createElementWithAttributes( 48 | indentation, 'module', 'path="' + report.path + '"', true, 49 | createElement(nextIndentation, 'maintainability', false, report.maintainability) + 50 | formatAggregate(nextIndentation, report.aggregate) + functions 51 | ); 52 | } 53 | 54 | function incrementIndentation (indentation) { 55 | return indentation + 4; 56 | } 57 | 58 | function formatFunction (indentation, data) { 59 | var nextIndentation = incrementIndentation(indentation); 60 | 61 | return createElementWithAttributes( 62 | indentation, 'function', 'name="' + data.name.replace('<', '<').replace('>', '>') + '"', true, 63 | createElement(nextIndentation, 'line', false, data.line) + 64 | formatSlocComplexity(nextIndentation, data.sloc) + 65 | formatParameterComplexity(nextIndentation, data.params) + 66 | formatCyclomaticComplexity(nextIndentation, data.cyclomatic) + 67 | formatCyclomaticDensity(nextIndentation, data.cyclomaticDensity) + 68 | formatHalsteadComplexity(nextIndentation, data.halstead) 69 | ); 70 | } 71 | 72 | function createElement (indentation, tag, linebreak, content) { 73 | return createElementWithTags(indentation, tag, tag, linebreak, content); 74 | } 75 | 76 | function formatSlocComplexity (indentation, data) { 77 | return createElement( 78 | indentation, 'sloc', true, 79 | formatSlocMetrics(incrementIndentation(indentation), data) 80 | ); 81 | } 82 | 83 | function formatSlocMetrics (indentation, data) { 84 | return createElement(indentation, 'physical', false, data.physical) + 85 | createElement(indentation, 'logical', false, data.logical); 86 | } 87 | 88 | function formatParameterComplexity (indentation, data) { 89 | return createElement(indentation, 'parameters', false, data); 90 | } 91 | 92 | function formatCyclomaticComplexity (indentation, data) { 93 | return createElement(indentation, 'cyclomatic', false, data); 94 | } 95 | 96 | function formatCyclomaticDensity (indentation, data) { 97 | return createElement(indentation, 'cyclomatic-density', false, data); 98 | } 99 | 100 | function formatHalsteadComplexity (indentation, data) { 101 | return createElement( 102 | indentation, 'halstead', true, 103 | formatHalsteadMetrics(incrementIndentation(indentation), data) 104 | ); 105 | } 106 | 107 | function formatHalsteadMetrics (indentation, data) { 108 | return createElement(indentation, 'length', false, data.length) + 109 | createElement(indentation, 'vocabulary', false, data.vocabulary) + 110 | createElement(indentation, 'difficulty', false, data.difficulty) + 111 | createElement(indentation, 'volume', false, data.volume) + 112 | createElement(indentation, 'effort', false, data.effort) + 113 | createElement(indentation, 'bugs', false, data.bugs) + 114 | createElement(indentation, 'time', false, data.time); 115 | } 116 | 117 | function formatAggregate (indentation, data) { 118 | var nextIndentation = incrementIndentation(indentation); 119 | 120 | return createElement( 121 | indentation, 'aggregate', true, 122 | formatSlocComplexity(nextIndentation, data.sloc) + 123 | formatParameterComplexity(nextIndentation, data.params) + 124 | formatCyclomaticComplexity(nextIndentation, data.cyclomatic) + 125 | formatCyclomaticDensity(nextIndentation, data.cyclomaticDensity) + 126 | formatHalsteadComplexity(nextIndentation, data.halstead) 127 | ); 128 | } 129 | 130 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # complexity-report 2 | 3 | [![Greenkeeper badge](https://badges.greenkeeper.io/escomplex/complexity-report.svg)](https://greenkeeper.io/) 4 | 5 | [![Dependency Status](https://david-dm.org/jared-stilwell/complexity-report.svg)](https://david-dm.org/jared-stilwell/complexity-report) [![devDependency Status](https://david-dm.org/jared-stilwell/complexity-report/dev-status.svg)](https://david-dm.org/jared-stilwell/complexity-report#info=devDependencies) 6 | 7 | Software complexity analysis for JavaScript projects. 8 | Command-line front-end for [escomplex]. 9 | Less attractive elder brother of [JSComplexity.org][jscomplexity]. 10 | 11 | * [Software complexity analysis](#software-complexity-analysis) 12 | * [How it works](#how-it-works) 13 | * [Complexity metrics](#complexity-metrics) 14 | * [What not to do with the results](#what-not-to-do-with-the-results) 15 | * [What to do with the results](#what-to-do-with-the-results) 16 | * [Installation](#installation) 17 | * [Usage](#usage) 18 | * [Command-line options](#command-line-options) 19 | * [Output formats](#output-formats) 20 | * [License](#license) 21 | 22 | ## Software complexity analysis 23 | 24 | Complexity is the quality of 25 | consisting of many interrelated parts. 26 | When software consists of many interrelated parts, 27 | it becomes more difficult to reason about. 28 | Software that is difficult to reason about 29 | is a more fertile breeding ground for bugs 30 | than software that is simple. 31 | 32 | Every problem space contains some level of inherent complexity, 33 | which is shared by all possible solutions. 34 | However, as programmers, 35 | we can reduce the complexity of our chosen solutions 36 | by limiting the interrelatedness of their constituent components. 37 | This is commonly referred to as favouring cohesion over coupling, 38 | and forms the bedrock on which axioms 39 | such as the single responsibility principle are built. 40 | 41 | In codebases that are large and/or unfamiliar, 42 | it can be difficult to know 43 | whether regions of complexity exist 44 | and where they might be. 45 | By defining metrics of complexity, 46 | the search for offending components can be automated 47 | and brought into the existing build process 48 | alongside other forms of static analysis 49 | and unit tests. 50 | 51 | ## How it works 52 | 53 | complexity-report is just 54 | a [node.js][node]-based 55 | command-line wrapper around [escomplex], 56 | which is the library 57 | that performs the actual analysis work. 58 | Code is passed to escomplex 59 | in the form of syntax trees 60 | that have been generated 61 | with [esprima], 62 | the popular JavaScript parser. 63 | 64 | [Here is an example report][eg]. 65 | 66 | ## Complexity metrics 67 | 68 | The readme for escomplex contains 69 | a [brief overview of the metrics][metrics] 70 | it produces. 71 | 72 | ## What not to do with the results 73 | 74 | The numbers returned by this tool 75 | should not be interpreted 76 | as definitive indicators 77 | of whether a piece of software 78 | is "too complex", 79 | whatever that might mean. 80 | 81 | Software development is a varied field 82 | and every project is subject 83 | to a unique set of environmental factors. 84 | Attempts to set generic hard limits 85 | for these complexity metrics 86 | must essentially be arbitrary 87 | and fail to consider 88 | the specific requirements 89 | of a given project. 90 | Further, complexity itself 91 | is such an amorphous, multi-dimensional continuum, 92 | that attempting to pigeon-hole chunks of code 93 | at discrete points along a single axis 94 | is an intrinsically crude approach. 95 | 96 | ## What to do with the results 97 | 98 | It is better to use this tool 99 | as a fuzzy, high-level mechanism, 100 | which can identify regions of interest 101 | or concern 102 | and from which 103 | your own programming- and domain-expertise 104 | can take over 105 | for a more comprehensive analysis. 106 | 107 | Although the metrics themselves are not perfect, 108 | they can help to identify areas of code 109 | that warrant closer inspection. 110 | They can also be tracked over time, 111 | as an indicator of the direction 112 | that overall code quality may be moving in. 113 | 114 | The tool can be configured to fail 115 | when complexity metrics pass a specified threshold, 116 | to aid its usefulness in automated environments / CI. 117 | There are also options 118 | for controlling how metrics are calculated 119 | and the format of the report output. 120 | 121 | ## Installation 122 | 123 | You must have [node.js installed][nodeinstall]. 124 | 125 | Then, for a project-based install: 126 | 127 | ``` 128 | npm install complexity-report 129 | ``` 130 | 131 | Or globally for all projects: 132 | 133 | ``` 134 | sudo npm install -g complexity-report 135 | ``` 136 | 137 | ## Usage 138 | 139 | ``` 140 | cr [options] 141 | ``` 142 | 143 | The tool will recursively read files 144 | from any directories that it encounters 145 | automatically. 146 | 147 | ### Command-line options 148 | 149 | ``` 150 | -h, --help output usage information 151 | -c, --config specify a configuration JSON file 152 | -o, --output specify an output file for the report 153 | -f, --format specify the output format of the report 154 | -e, --ignoreerrors ignore parser errors 155 | -a, --allfiles include hidden files in the report 156 | -p, --filepattern specify the files to process using a regular expression to match against file names 157 | -P, --dirpattern specify the directories to process using a regular expression to match against directory names 158 | -x, --excludepattern specify the the directories to exclude using a regular expression to match against directory names 159 | -m, --maxfiles specify the maximum number of files to have open at any point 160 | -F, --maxfod specify the per-project first-order density threshold 161 | -O, --maxcost specify the per-project change cost threshold 162 | -S, --maxsize specify the per-project core size threshold 163 | -M, --minmi specify the per-module maintainability index threshold 164 | -C, --maxcyc specify the per-function cyclomatic complexity threshold 165 | -Y, --maxcycden specify the per-function cyclomatic complexity density threshold 166 | -D, --maxhd specify the per-function Halstead difficulty threshold 167 | -V, --maxhv specify the per-function Halstead volume threshold 168 | -E, --maxhe specify the per-function Halstead effort threshold 169 | -s, --silent don't write any output to the console 170 | -l, --logicalor disregard operator || as source of cyclomatic complexity 171 | -w, --switchcase disregard switch statements as source of cyclomatic complexity 172 | -i, --forin treat for...in statements as source of cyclomatic complexity 173 | -t, --trycatch treat catch clauses as source of cyclomatic complexity 174 | -n, --newmi use the Microsoft-variant maintainability index (scale of 0 to 100) 175 | ``` 176 | 177 | ### Configuration files 178 | 179 | By default, 180 | complexity-report will attempt 181 | to read configuration options 182 | from a JSON file 183 | called `.complexrc` 184 | in the current working directory. 185 | This file should contain 186 | a JSON object 187 | with property names 188 | matching the long-form 189 | option names 190 | from the command line 191 | (the ones that follow `--`). 192 | Options set in this file 193 | will be over-ridden 194 | by options specified 195 | on the command line. 196 | 197 | See an [example configuration file][egconfig]. 198 | 199 | You can also specify 200 | an alternative path 201 | to this file 202 | using the `-c` 203 | command-line option. 204 | 205 | ### Output formats 206 | 207 | Currently there are five output formats supported: 208 | `plain`, 209 | `markdown`, 210 | `minimal`, 211 | `json`, 212 | `xml` 213 | and `checkstyle`. 214 | These are loaded 215 | from the `src/formats` subdirectory. 216 | If the format file is not found 217 | in that directory, 218 | a second attempt will be made to load the module 219 | without the subdirectory prefix, 220 | more easily enabling the use of 221 | custom formats if so desired. 222 | 223 | Adding new formats is simple; 224 | each one must be a CommonJS module, 225 | which exports a function named `format`. 226 | The `format` function 227 | should take a report object, 228 | as [defined by escomplex][format], 229 | and return its string 230 | representation of the report. 231 | 232 | See [the plain formatter][plain] 233 | for an example. 234 | 235 | ## Development 236 | 237 | See the [contribution guidelines][contributions]. 238 | 239 | ## License 240 | 241 | [MIT][license] 242 | 243 | [ci-image]: https://secure.travis-ci.org/jared-stilwell/complexity-report.png?branch=master 244 | [ci-status]: http://travis-ci.org/#!/jared-stilwell/complexity-report 245 | [escomplex]: https://github.com/jared-stilwell/escomplex 246 | [jscomplexity]: http://jscomplexity.org/ 247 | [node]: http://nodejs.org/ 248 | [esprima]: http://esprima.org/ 249 | [eg]: https://github.com/jared-stilwell/complexity-report/blob/master/EXAMPLE.md 250 | [metrics]: https://github.com/jared-stilwell/escomplex/blob/master/README.md#metrics 251 | [nodeinstall]: http://nodejs.org/download 252 | [egconfig]: https://github.com/jared-stilwell/complexity-report/blob/master/.complexrc.example 253 | [format]: https://github.com/jared-stilwell/escomplex/blob/master/README.md#result 254 | [plain]: https://github.com/jared-stilwell/complexity-report/blob/master/src/formats/plain.js 255 | [contributions]: https://github.com/jared-stilwell/complexity-report/blob/master/CONTRIBUTING.md 256 | [license]: https://github.com/jared-stilwell/complexity-report/blob/master/COPYING 257 | -------------------------------------------------------------------------------- /src/index.js: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env node 2 | 3 | /*globals require, process, console */ 4 | 5 | 'use strict'; 6 | 7 | var options, formatter, state, queue, 8 | 9 | cli = require('commander'), 10 | config = require('./config'), 11 | fs = require('fs'), 12 | path = require('path'), 13 | escomplex = require('escomplex'), 14 | check = require('check-types'), 15 | async = require('async'); 16 | 17 | // Node v0.10 polyfill for process.exitCode 18 | process.on('exit', function(code) { 19 | process.exit(code || process.exitCode); 20 | }); 21 | 22 | parseCommandLine(); 23 | 24 | state = { 25 | sources: { 26 | js: [] 27 | } 28 | }; 29 | 30 | expectFiles(cli.args, cli.help.bind(cli)); 31 | queue = async.queue(readFile, cli.maxfiles); 32 | processPaths(cli.args, function() { 33 | }); 34 | 35 | function parseCommandLine () { 36 | var config; 37 | 38 | cli. 39 | usage('[options] '). 40 | option('-c, --config ', 'specify path to configuration JSON file'). 41 | option('-o, --output ', 'specify an output file for the report'). 42 | option('-f, --format ', 'specify the output format of the report'). 43 | option('-e, --ignoreerrors', 'ignore parser errors'). 44 | option('-a, --allfiles', 'include hidden files in the report'). 45 | option('-p, --filepattern ', 'specify the files to process using a regular expression to match against file names'). 46 | option('-P, --dirpattern ', 'specify the directories to process using a regular expression to match against directory names'). 47 | option('-x, --excludepattern ', 'specify the the directories to exclude using a regular expression to match against directory names'). 48 | option('-m, --maxfiles ', 'specify the maximum number of files to have open at any point', parseInt). 49 | option('-F, --maxfod ', 'specify the per-project first-order density threshold', parseFloat). 50 | option('-O, --maxcost ', 'specify the per-project change cost threshold', parseFloat). 51 | option('-S, --maxsize ', 'specify the per-project core size threshold', parseFloat). 52 | option('-M, --minmi ', 'specify the per-module maintainability index threshold', parseFloat). 53 | option('-C, --maxcyc ', 'specify the per-function cyclomatic complexity threshold', parseInt). 54 | option('-Y, --maxcycden ', 'specify the per-function cyclomatic complexity density threshold', parseInt). 55 | option('-D, --maxhd ', 'specify the per-function Halstead difficulty threshold', parseFloat). 56 | option('-V, --maxhv ', 'specify the per-function Halstead volume threshold', parseFloat). 57 | option('-E, --maxhe ', 'specify the per-function Halstead effort threshold', parseFloat). 58 | option('-s, --silent', 'don\'t write any output to the console'). 59 | option('-l, --logicalor', 'disregard operator || as source of cyclomatic complexity'). 60 | option('-w, --switchcase', 'disregard switch statements as source of cyclomatic complexity'). 61 | option('-i, --forin', 'treat for...in statements as source of cyclomatic complexity'). 62 | option('-t, --trycatch', 'treat catch clauses as source of cyclomatic complexity'). 63 | option('-n, --newmi', 'use the Microsoft-variant maintainability index (scale of 0 to 100)'). 64 | option('-Q, --nocoresize', 'don\'t calculate core size or visibility matrix'). 65 | parse(process.argv); 66 | 67 | config = readConfig(cli.config); 68 | 69 | Object.keys(config).forEach(function (key) { 70 | if (cli[key] === undefined) { 71 | cli[key] = config[key]; 72 | } 73 | }); 74 | 75 | options = { 76 | logicalor: !cli.logicalor, 77 | switchcase: !cli.switchcase, 78 | forin: cli.forin || false, 79 | trycatch: cli.trycatch || false, 80 | newmi: cli.newmi || false, 81 | ignoreErrors: cli.ignoreerrors || false, 82 | noCoreSize: cli.nocoresize || false 83 | }; 84 | 85 | if (check.nonEmptyString(cli.format) === false) { 86 | cli.format = 'plain'; 87 | } 88 | 89 | if (check.nonEmptyString(cli.filepattern) === false) { 90 | cli.filepattern = '\\.js$'; 91 | } 92 | cli.filepattern = new RegExp(cli.filepattern); 93 | 94 | if (check.nonEmptyString(cli.dirpattern)) { 95 | cli.dirpattern = new RegExp(cli.dirpattern); 96 | } 97 | 98 | if (check.nonEmptyString(cli.excludepattern)) { 99 | cli.excludepattern = new RegExp(cli.excludepattern); 100 | } 101 | 102 | if (check.number(cli.maxfiles) === false) { 103 | cli.maxfiles = 1024; 104 | } 105 | 106 | try { 107 | formatter = require('./formats/' + cli.format); 108 | } catch (err) { 109 | formatter = require(cli.format); 110 | } 111 | } 112 | 113 | function readConfig (configPath) { 114 | var configInfo; 115 | 116 | try { 117 | if (check.not.nonEmptyString(configPath)) { 118 | configPath = path.join(process.cwd(), '.complexrc'); 119 | } 120 | 121 | if (fs.existsSync(configPath)) { 122 | configInfo = fs.statSync(configPath); 123 | 124 | if (configInfo.isFile()) { 125 | return JSON.parse(fs.readFileSync(configPath), { encoding: 'utf8' }); 126 | } 127 | } 128 | 129 | return {}; 130 | } catch (err) { 131 | error('readConfig', err); 132 | } 133 | } 134 | 135 | function expectFiles (paths, noFilesFn) { 136 | if (paths.length === 0) { 137 | noFilesFn(); 138 | } 139 | } 140 | 141 | function processPaths (paths, cb) { 142 | async.each(paths, processPath, function(err) { 143 | if (err) { 144 | error('readFiles', err); 145 | } 146 | queue.drain = function() { 147 | getReports(); 148 | cb(); 149 | }; 150 | }); 151 | } 152 | 153 | function processPath(p, cb) { 154 | fs.stat(p, function(err, stat) { 155 | if (err) { 156 | return cb(err); 157 | } 158 | if (stat.isDirectory()) { 159 | if ((!cli.dirpattern || cli.dirpattern.test(p)) && (!cli.excludepattern || !cli.excludepattern.test(p))) { 160 | return readDirectory(p, cb); 161 | } 162 | } else if (cli.filepattern.test(p)) { 163 | queue.push(p); 164 | } 165 | cb(); 166 | }); 167 | } 168 | 169 | function readDirectory (directoryPath, cb) { 170 | fs.readdir(directoryPath, function(err, files) { 171 | if (err) { 172 | return cb(err); 173 | } 174 | files = files.filter(function (p) { 175 | return path.basename(p).charAt(0) !== '.' || cli.allfiles; 176 | }).map(function (p) { 177 | return path.resolve(directoryPath, p); 178 | }); 179 | if (!files.length) { 180 | return cb(); 181 | } 182 | async.each(files, processPath, cb); 183 | }); 184 | } 185 | 186 | function readFile(filePath, cb) { 187 | fs.readFile(filePath, 'utf8', function (err, source) { 188 | if (err) { 189 | error('readFile', err); 190 | } 191 | 192 | if (beginsWithShebang(source)) { 193 | source = commentFirstLine(source); 194 | } 195 | 196 | setSource(filePath, source); 197 | cb(); 198 | }); 199 | } 200 | 201 | function error (functionName, err) { 202 | fail('Fatal error [' + functionName + ']: ' + err.message); 203 | process.exit(1); 204 | } 205 | 206 | function fail (message) { 207 | console.log(message); // eslint-disable-line no-console 208 | process.exitCode = 2; 209 | } 210 | 211 | function beginsWithShebang (source) { 212 | return source[0] === '#' && source[1] === '!'; 213 | } 214 | 215 | function commentFirstLine (source) { 216 | return '//' + source; 217 | } 218 | 219 | function setSource (modulePath, source) { 220 | var type = getType(modulePath); 221 | state.sources[type].push({ 222 | path: modulePath, 223 | code: source 224 | }); 225 | } 226 | 227 | function getType(modulePath) { 228 | return path.extname(modulePath).replace('.', ''); 229 | } 230 | 231 | function getReports () { 232 | var result, failingModules; 233 | 234 | try { 235 | result = escomplex.analyse(state.sources.js, options); 236 | 237 | if (!cli.silent) { 238 | writeReports(result); 239 | } 240 | 241 | failingModules = getFailingModules(result.reports); 242 | if (failingModules.length > 0) { 243 | return fail('Warning: Complexity threshold breached!\nFailing modules:\n' + failingModules.join('\n')); 244 | } 245 | 246 | if (config.isProjectComplexityThresholdSet(cli) && isProjectTooComplex(result)) { 247 | fail('Warning: Project complexity threshold breached!'); 248 | } 249 | } catch (err) { 250 | error('getReports', err); 251 | } 252 | } 253 | 254 | function writeReports (result) { 255 | var formatted = formatter.format(result); 256 | 257 | if (check.nonEmptyString(cli.output)) { 258 | fs.writeFile(cli.output, formatted, 'utf8', function (err) { 259 | if (err) { 260 | error('writeReport', err); 261 | } 262 | }); 263 | } else { 264 | console.log(formatted); // eslint-disable-line no-console 265 | } 266 | } 267 | 268 | function getFailingModules (reports) { 269 | return reports.reduce(function (failingModules, report) { 270 | if ( 271 | (config.isModuleComplexityThresholdSet(cli) && isModuleTooComplex(report)) || 272 | (config.isFunctionComplexityThresholdSet(cli) && isFunctionTooComplex(report)) 273 | ) { 274 | return failingModules.concat(report.path); 275 | } 276 | 277 | return failingModules; 278 | }, []); 279 | } 280 | 281 | 282 | function isThresholdBreached (threshold, metric, inverse) { 283 | if (!inverse) { 284 | return check.number(threshold) && metric > threshold; 285 | } 286 | 287 | return check.number(threshold) && metric < threshold; 288 | } 289 | 290 | function isFunctionTooComplex (report) { 291 | var i; 292 | 293 | for (i = 0; i < report.functions.length; i += 1) { 294 | if (isThresholdBreached(cli.maxcyc, report.functions[i].cyclomatic)) { 295 | return true; 296 | } 297 | 298 | if (isThresholdBreached(cli.maxcycden, report.functions[i].cyclomaticDensity)) { 299 | return true; 300 | } 301 | 302 | if (isThresholdBreached(cli.maxhd, report.functions[i].halstead.difficulty)) { 303 | return true; 304 | } 305 | 306 | if (isThresholdBreached(cli.maxhv, report.functions[i].halstead.volume)) { 307 | return true; 308 | } 309 | 310 | if (isThresholdBreached(cli.maxhe, report.functions[i].halstead.effort)) { 311 | return true; 312 | } 313 | } 314 | 315 | return false; 316 | } 317 | 318 | function isModuleTooComplex (report) { 319 | if (isThresholdBreached(cli.minmi, report.maintainability, true)) { 320 | return true; 321 | } 322 | } 323 | 324 | function isProjectTooComplex (result) { 325 | if (isThresholdBreached(cli.maxfod, result.firstOrderDensity)) { 326 | return true; 327 | } 328 | 329 | if (isThresholdBreached(cli.maxcost, result.changeCost)) { 330 | return true; 331 | } 332 | 333 | if (isThresholdBreached(cli.maxsize, result.coreSize)) { 334 | return true; 335 | } 336 | 337 | return false; 338 | } 339 | -------------------------------------------------------------------------------- /EXAMPLE.md: -------------------------------------------------------------------------------- 1 | # Complexity report, Saturday, December 27, 2014 2 | 3 | * Mean per-function logical LOC: 4.191244239631336 4 | * Mean per-function parameter count: 2.2211981566820276 5 | * Mean per-function cyclomatic complexity: 2.1059907834101383 6 | * Mean per-function Halstead effort: 802.4973507353953 7 | * Mean per-module maintainability index: 125.24778532321781 8 | * First-order density: 18.75% 9 | * Change cost: 43.75% 10 | * Core size: 25% 11 | 12 | ## /Users/pbooth/code/escomplex/src/index.js 13 | 14 | * Physical LOC: 24 15 | * Logical LOC: 7 16 | * Mean parameter count: 3 17 | * Cyclomatic complexity: 2 18 | * Cyclomatic complexity density: 28.57142857142857% 19 | * Maintainability index: 132.31087395723623 20 | * Dependency count: 3 21 | * Function: **analyse** 22 | * Line No.: 24 23 | * Physical LOC: 7 24 | * Logical LOC: 3 25 | * Parameter count: 3 26 | * Cyclomatic complexity: 2 27 | * Cyclomatic complexity density: 66.66666666666666% 28 | * Halstead difficulty: 4 29 | * Halstead volume: 107.31275182609167 30 | * Halstead effort: 429.2510073043667 31 | 32 | ## /Users/pbooth/code/escomplex/src/module.js 33 | 34 | * Physical LOC: 331 35 | * Logical LOC: 192 36 | * Mean parameter count: 2.142857142857143 37 | * Cyclomatic complexity: 26 38 | * Cyclomatic complexity density: 13.541666666666666% 39 | * Maintainability index: 122.31078309873308 40 | * Dependency count: 1 41 | * Function: **analyse** 42 | * Line No.: 9 43 | * Physical LOC: 60 44 | * Logical LOC: 21 45 | * Parameter count: 3 46 | * Cyclomatic complexity: 2 47 | * Cyclomatic complexity density: 9.523809523809524% 48 | * Halstead difficulty: 11.66 49 | * Halstead volume: 454.9534001269235 50 | * Halstead effort: 5304.756645479928 51 | * Function: **processNode** 52 | * Line No.: 37 53 | * Physical LOC: 12 54 | * Logical LOC: 6 55 | * Parameter count: 2 56 | * Cyclomatic complexity: 2 57 | * Cyclomatic complexity density: 33.33333333333333% 58 | * Halstead difficulty: 3.5999999999999996 59 | * Halstead volume: 114.71363126237385 60 | * Halstead effort: 412.96907254454584 61 | * Function: **createScope** 62 | * Line No.: 50 63 | * Physical LOC: 8 64 | * Logical LOC: 4 65 | * Parameter count: 3 66 | * Cyclomatic complexity: 1 67 | * Cyclomatic complexity density: 25% 68 | * Halstead difficulty: 3.4545454545454546 69 | * Halstead volume: 113.29982727264704 70 | * Halstead effort: 391.399403305508 71 | * Function: **popScope** 72 | * Line No.: 59 73 | * Physical LOC: 9 74 | * Logical LOC: 5 75 | * Parameter count: 0 76 | * Cyclomatic complexity: 2 77 | * Cyclomatic complexity density: 40% 78 | * Halstead difficulty: 6 79 | * Halstead volume: 87.56916320732489 80 | * Halstead effort: 525.4149792439493 81 | * Function: **getDefaultSettings** 82 | * Line No.: 70 83 | * Physical LOC: 9 84 | * Logical LOC: 6 85 | * Parameter count: 0 86 | * Cyclomatic complexity: 1 87 | * Cyclomatic complexity density: 16.666666666666664% 88 | * Halstead difficulty: 2.0625 89 | * Halstead volume: 62.26976913547136 90 | * Halstead effort: 128.43139884190967 91 | * Function: **createReport** 92 | * Line No.: 80 93 | * Physical LOC: 7 94 | * Logical LOC: 4 95 | * Parameter count: 1 96 | * Cyclomatic complexity: 1 97 | * Cyclomatic complexity density: 25% 98 | * Halstead difficulty: 3.4375 99 | * Halstead volume: 70.30835464468075 100 | * Halstead effort: 241.68496909109007 101 | * Function: **createFunctionReport** 102 | * Line No.: 88 103 | * Physical LOC: 18 104 | * Logical LOC: 11 105 | * Parameter count: 3 106 | * Cyclomatic complexity: 2 107 | * Cyclomatic complexity density: 18.181818181818183% 108 | * Halstead difficulty: 10 109 | * Halstead volume: 307.67071501168664 110 | * Halstead effort: 3076.7071501168666 111 | * Function: **createInitialHalsteadState** 112 | * Line No.: 107 113 | * Physical LOC: 6 114 | * Logical LOC: 3 115 | * Parameter count: 0 116 | * Cyclomatic complexity: 1 117 | * Cyclomatic complexity density: 33.33333333333333% 118 | * Halstead difficulty: 2.5 119 | * Halstead volume: 33 120 | * Halstead effort: 82.5 121 | * Function: **createInitialHalsteadItemState** 122 | * Line No.: 114 123 | * Physical LOC: 7 124 | * Logical LOC: 4 125 | * Parameter count: 0 126 | * Cyclomatic complexity: 1 127 | * Cyclomatic complexity density: 25% 128 | * Halstead difficulty: 2.8 129 | * Halstead volume: 41.20902501875006 130 | * Halstead effort: 115.38527005250016 131 | * Function: **processLloc** 132 | * Line No.: 122 133 | * Physical LOC: 3 134 | * Logical LOC: 1 135 | * Parameter count: 3 136 | * Cyclomatic complexity: 1 137 | * Cyclomatic complexity density: 100% 138 | * Halstead difficulty: 0.75 139 | * Halstead volume: 28.07354922057604 140 | * Halstead effort: 21.05516191543203 141 | * Function: **incrementCounter** 142 | * Line No.: 126 143 | * Physical LOC: 9 144 | * Logical LOC: 6 145 | * Parameter count: 5 146 | * Cyclomatic complexity: 3 147 | * Cyclomatic complexity density: 50% 148 | * Halstead difficulty: 7 149 | * Halstead volume: 132.83428025068963 150 | * Halstead effort: 929.8399617548274 151 | * Function: **incrementLogicalSloc** 152 | * Line No.: 136 153 | * Physical LOC: 7 154 | * Logical LOC: 3 155 | * Parameter count: 2 156 | * Cyclomatic complexity: 2 157 | * Cyclomatic complexity density: 66.66666666666666% 158 | * Halstead difficulty: 3 159 | * Halstead volume: 63.39850002884625 160 | * Halstead effort: 190.19550008653874 161 | * Function: **processCyclomatic** 162 | * Line No.: 144 163 | * Physical LOC: 3 164 | * Logical LOC: 1 165 | * Parameter count: 3 166 | * Cyclomatic complexity: 1 167 | * Cyclomatic complexity density: 100% 168 | * Halstead difficulty: 0.75 169 | * Halstead volume: 28.07354922057604 170 | * Halstead effort: 21.05516191543203 171 | * Function: **incrementCyclomatic** 172 | * Line No.: 148 173 | * Physical LOC: 7 174 | * Logical LOC: 3 175 | * Parameter count: 2 176 | * Cyclomatic complexity: 2 177 | * Cyclomatic complexity density: 66.66666666666666% 178 | * Halstead difficulty: 3 179 | * Halstead volume: 48 180 | * Halstead effort: 144 181 | * Function: **processOperators** 182 | * Line No.: 156 183 | * Physical LOC: 3 184 | * Logical LOC: 1 185 | * Parameter count: 3 186 | * Cyclomatic complexity: 1 187 | * Cyclomatic complexity density: 100% 188 | * Halstead difficulty: 0.8 189 | * Halstead volume: 23.264662506490403 190 | * Halstead effort: 18.611730005192324 191 | * Function: **processOperands** 192 | * Line No.: 160 193 | * Physical LOC: 3 194 | * Logical LOC: 1 195 | * Parameter count: 3 196 | * Cyclomatic complexity: 1 197 | * Cyclomatic complexity density: 100% 198 | * Halstead difficulty: 0.8 199 | * Halstead volume: 23.264662506490403 200 | * Halstead effort: 18.611730005192324 201 | * Function: **processHalsteadMetric** 202 | * Line No.: 164 203 | * Physical LOC: 17 204 | * Logical LOC: 2 205 | * Parameter count: 4 206 | * Cyclomatic complexity: 2 207 | * Cyclomatic complexity density: 100% 208 | * Halstead difficulty: 3 209 | * Halstead volume: 71.69925001442313 210 | * Halstead effort: 215.0977500432694 211 | * Function: **<anonymous>** 212 | * Line No.: 166 213 | * Physical LOC: 13 214 | * Logical LOC: 7 215 | * Parameter count: 1 216 | * Cyclomatic complexity: 4 217 | * Cyclomatic complexity density: 57.14285714285714% 218 | * Halstead difficulty: 9.454545454545455 219 | * Halstead volume: 199.6525931318485 220 | * Halstead effort: 1887.6245168829314 221 | * Function: **halsteadItemEncountered** 222 | * Line No.: 182 223 | * Physical LOC: 7 224 | * Logical LOC: 3 225 | * Parameter count: 3 226 | * Cyclomatic complexity: 2 227 | * Cyclomatic complexity density: 66.66666666666666% 228 | * Halstead difficulty: 3.25 229 | * Halstead volume: 53.88872502451932 230 | * Halstead effort: 175.13835632968778 231 | * Function: **incrementHalsteadItems** 232 | * Line No.: 190 233 | * Physical LOC: 4 234 | * Logical LOC: 2 235 | * Parameter count: 3 236 | * Cyclomatic complexity: 1 237 | * Cyclomatic complexity density: 50% 238 | * Halstead difficulty: 1 239 | * Halstead volume: 31.019550008653873 240 | * Halstead effort: 31.019550008653873 241 | * Function: **incrementDistinctHalsteadItems** 242 | * Line No.: 195 243 | * Physical LOC: 9 244 | * Logical LOC: 6 245 | * Parameter count: 3 246 | * Cyclomatic complexity: 3 247 | * Cyclomatic complexity density: 50% 248 | * Halstead difficulty: 5 249 | * Halstead volume: 143.0611994437619 250 | * Halstead effort: 715.3059972188095 251 | * Function: **isHalsteadMetricDistinct** 252 | * Line No.: 205 253 | * Physical LOC: 3 254 | * Logical LOC: 1 255 | * Parameter count: 3 256 | * Cyclomatic complexity: 1 257 | * Cyclomatic complexity density: 100% 258 | * Halstead difficulty: 3.5714285714285716 259 | * Halstead volume: 64.52932501298082 260 | * Halstead effort: 230.4618750463601 261 | * Function: **recordDistinctHalsteadMetric** 262 | * Line No.: 209 263 | * Physical LOC: 3 264 | * Logical LOC: 1 265 | * Parameter count: 3 266 | * Cyclomatic complexity: 1 267 | * Cyclomatic complexity density: 100% 268 | * Halstead difficulty: 1.5 269 | * Halstead volume: 42 270 | * Halstead effort: 63 271 | * Function: **incrementHalsteadMetric** 272 | * Line No.: 213 273 | * Physical LOC: 5 274 | * Logical LOC: 2 275 | * Parameter count: 3 276 | * Cyclomatic complexity: 2 277 | * Cyclomatic complexity density: 100% 278 | * Halstead difficulty: 2.7 279 | * Halstead volume: 42 280 | * Halstead effort: 113.4 281 | * Function: **incrementTotalHalsteadItems** 282 | * Line No.: 219 283 | * Physical LOC: 3 284 | * Logical LOC: 1 285 | * Parameter count: 2 286 | * Cyclomatic complexity: 1 287 | * Cyclomatic complexity density: 100% 288 | * Halstead difficulty: 0.75 289 | * Halstead volume: 16.253496664211536 290 | * Halstead effort: 12.190122498158651 291 | * Function: **processDependencies** 292 | * Line No.: 223 293 | * Physical LOC: 14 294 | * Logical LOC: 7 295 | * Parameter count: 3 296 | * Cyclomatic complexity: 4 297 | * Cyclomatic complexity density: 57.14285714285714% 298 | * Halstead difficulty: 7.875 299 | * Halstead volume: 203.9005206452921 300 | * Halstead effort: 1605.716600081675 301 | * Function: **calculateMetrics** 302 | * Line No.: 238 303 | * Physical LOC: 39 304 | * Logical LOC: 20 305 | * Parameter count: 1 306 | * Cyclomatic complexity: 2 307 | * Cyclomatic complexity density: 10% 308 | * Halstead difficulty: 12.037037037037038 309 | * Halstead volume: 557.4115101222976 310 | * Halstead effort: 6709.582992212842 311 | * Function: **<anonymous>** 312 | * Line No.: 250 313 | * Physical LOC: 5 314 | * Logical LOC: 3 315 | * Parameter count: 1 316 | * Cyclomatic complexity: 1 317 | * Cyclomatic complexity density: 33.33333333333333% 318 | * Halstead difficulty: 1.4285714285714286 319 | * Halstead volume: 44.37895002019238 320 | * Halstead effort: 63.39850002884626 321 | * Function: **<anonymous>** 322 | * Line No.: 264 323 | * Physical LOC: 1 324 | * Logical LOC: 1 325 | * Parameter count: 1 326 | * Cyclomatic complexity: 1 327 | * Cyclomatic complexity density: 100% 328 | * Halstead difficulty: 1.5 329 | * Halstead volume: 10 330 | * Halstead effort: 15 331 | * Function: **<anonymous>** 332 | * Line No.: 273 333 | * Physical LOC: 3 334 | * Logical LOC: 1 335 | * Parameter count: 1 336 | * Cyclomatic complexity: 1 337 | * Cyclomatic complexity density: 100% 338 | * Halstead difficulty: 1.5 339 | * Halstead volume: 25.84962500721156 340 | * Halstead effort: 38.77443751081734 341 | * Function: **calculateCyclomaticDensity** 342 | * Line No.: 278 343 | * Physical LOC: 3 344 | * Logical LOC: 1 345 | * Parameter count: 1 346 | * Cyclomatic complexity: 1 347 | * Cyclomatic complexity density: 100% 348 | * Halstead difficulty: 3 349 | * Halstead volume: 53.1508495181978 350 | * Halstead effort: 159.45254855459342 351 | * Function: **calculateHalsteadMetrics** 352 | * Line No.: 282 353 | * Physical LOC: 15 354 | * Logical LOC: 10 355 | * Parameter count: 1 356 | * Cyclomatic complexity: 3 357 | * Cyclomatic complexity density: 30% 358 | * Halstead difficulty: 16.5 359 | * Halstead volume: 603.5475432598478 360 | * Halstead effort: 9958.534463787488 361 | * Function: **nilHalsteadMetrics** 362 | * Line No.: 298 363 | * Physical LOC: 9 364 | * Logical LOC: 1 365 | * Parameter count: 1 366 | * Cyclomatic complexity: 1 367 | * Cyclomatic complexity density: 100% 368 | * Halstead difficulty: 1.75 369 | * Halstead volume: 86.37013046707143 370 | * Halstead effort: 151.147728317375 371 | * Function: **sumMaintainabilityMetrics** 372 | * Line No.: 308 373 | * Physical LOC: 6 374 | * Logical LOC: 4 375 | * Parameter count: 3 376 | * Cyclomatic complexity: 1 377 | * Cyclomatic complexity density: 25% 378 | * Halstead difficulty: 2.5 379 | * Halstead volume: 154.15338753100974 380 | * Halstead effort: 385.3834688275243 381 | * Function: **calculateMaintainabilityIndex** 382 | * Line No.: 315 383 | * Physical LOC: 19 384 | * Logical LOC: 7 385 | * Parameter count: 4 386 | * Cyclomatic complexity: 4 387 | * Cyclomatic complexity density: 57.14285714285714% 388 | * Halstead difficulty: 12.222222222222223 389 | * Halstead volume: 349.77463164918527 390 | * Halstead effort: 4275.023275712265 391 | 392 | ## /Users/pbooth/code/escomplex/src/project.js 393 | 394 | * Physical LOC: 270 395 | * Logical LOC: 156 396 | * Mean parameter count: 1.7419354838709677 397 | * Cyclomatic complexity: 23 398 | * Cyclomatic complexity density: 14.743589743589745% 399 | * Maintainability index: 124.0598813563106 400 | * Dependency count: 4 401 | * Function: **analyse** 402 | * Line No.: 14 403 | * Physical LOC: 36 404 | * Logical LOC: 11 405 | * Parameter count: 3 406 | * Cyclomatic complexity: 1 407 | * Cyclomatic complexity density: 9.090909090909092% 408 | * Halstead difficulty: 8.4 409 | * Halstead volume: 206.32331253245206 410 | * Halstead effort: 1733.1158252725975 411 | * Function: **<anonymous>** 412 | * Line No.: 21 413 | * Physical LOC: 17 414 | * Logical LOC: 9 415 | * Parameter count: 1 416 | * Cyclomatic complexity: 1 417 | * Cyclomatic complexity density: 11.11111111111111% 418 | * Halstead difficulty: 7.733333333333333 419 | * Halstead volume: 226.17809780285066 420 | * Halstead effort: 1749.1106230087119 421 | * Function: **createAdjacencyMatrix** 422 | * Line No.: 51 423 | * Physical LOC: 18 424 | * Logical LOC: 5 425 | * Parameter count: 1 426 | * Cyclomatic complexity: 1 427 | * Cyclomatic complexity density: 20% 428 | * Halstead difficulty: 5.5 429 | * Halstead volume: 166.7970000576925 430 | * Halstead effort: 917.3835003173086 431 | * Function: **<anonymous>** 432 | * Line No.: 56 433 | * Physical LOC: 9 434 | * Logical LOC: 2 435 | * Parameter count: 2 436 | * Cyclomatic complexity: 1 437 | * Cyclomatic complexity density: 50% 438 | * Halstead difficulty: 3.333333333333333 439 | * Halstead volume: 79.95445336320968 440 | * Halstead effort: 266.51484454403226 441 | * Function: **<anonymous>** 442 | * Line No.: 58 443 | * Physical LOC: 6 444 | * Logical LOC: 3 445 | * Parameter count: 2 446 | * Cyclomatic complexity: 2 447 | * Cyclomatic complexity density: 66.66666666666666% 448 | * Halstead difficulty: 5.333333333333333 449 | * Halstead volume: 101.57915548582149 450 | * Halstead effort: 541.7554959243812 451 | * Function: **<anonymous>** 452 | * Line No.: 54 453 | * Physical LOC: 3 454 | * Logical LOC: 1 455 | * Parameter count: 2 456 | * Cyclomatic complexity: 1 457 | * Cyclomatic complexity density: 100% 458 | * Halstead difficulty: 2.625 459 | * Halstead volume: 30.880904142633646 460 | * Halstead effort: 81.06237337441333 461 | * Function: **comparePaths** 462 | * Line No.: 70 463 | * Physical LOC: 13 464 | * Logical LOC: 7 465 | * Parameter count: 2 466 | * Cyclomatic complexity: 5 467 | * Cyclomatic complexity density: 71.42857142857143% 468 | * Halstead difficulty: 21 469 | * Halstead volume: 303.2413500673362 470 | * Halstead effort: 6368.06835141406 471 | * Function: **getAdjacencyMatrixValue** 472 | * Line No.: 84 473 | * Physical LOC: 11 474 | * Logical LOC: 5 475 | * Parameter count: 3 476 | * Cyclomatic complexity: 3 477 | * Cyclomatic complexity density: 60% 478 | * Halstead difficulty: 5.416666666666666 479 | * Halstead volume: 76.10749561002055 480 | * Halstead effort: 412.2489345542779 481 | * Function: **doesDependencyExist** 482 | * Line No.: 96 483 | * Physical LOC: 9 484 | * Logical LOC: 1 485 | * Parameter count: 2 486 | * Cyclomatic complexity: 1 487 | * Cyclomatic complexity density: 100% 488 | * Halstead difficulty: 2.3333333333333335 489 | * Halstead volume: 39.863137138648355 490 | * Halstead effort: 93.01398665684617 491 | * Function: **<anonymous>** 492 | * Line No.: 97 493 | * Physical LOC: 7 494 | * Logical LOC: 3 495 | * Parameter count: 2 496 | * Cyclomatic complexity: 2 497 | * Cyclomatic complexity density: 66.66666666666666% 498 | * Halstead difficulty: 3.4375 499 | * Halstead volume: 66.60791492653966 500 | * Halstead effort: 228.9647075599801 501 | * Function: **checkDependency** 502 | * Line No.: 106 503 | * Physical LOC: 11 504 | * Logical LOC: 5 505 | * Parameter count: 3 506 | * Cyclomatic complexity: 3 507 | * Cyclomatic complexity density: 60% 508 | * Halstead difficulty: 3.4285714285714284 509 | * Halstead volume: 83.04820237218406 510 | * Halstead effort: 284.7366938474882 511 | * Function: **isCommonJSDependency** 512 | * Line No.: 118 513 | * Physical LOC: 3 514 | * Logical LOC: 1 515 | * Parameter count: 1 516 | * Cyclomatic complexity: 1 517 | * Cyclomatic complexity density: 100% 518 | * Halstead difficulty: 2 519 | * Halstead volume: 18.094737505048094 520 | * Halstead effort: 36.18947501009619 521 | * Function: **isInternalCommonJSDependency** 522 | * Line No.: 122 523 | * Physical LOC: 10 524 | * Logical LOC: 1 525 | * Parameter count: 1 526 | * Cyclomatic complexity: 2 527 | * Cyclomatic complexity density: 200% 528 | * Halstead difficulty: 6.7857142857142865 529 | * Halstead volume: 132.6436125266828 530 | * Halstead effort: 900.081656431062 531 | * Function: **isDependency** 532 | * Line No.: 133 533 | * Physical LOC: 9 534 | * Logical LOC: 4 535 | * Parameter count: 3 536 | * Cyclomatic complexity: 2 537 | * Cyclomatic complexity density: 50% 538 | * Halstead difficulty: 9.333333333333334 539 | * Halstead volume: 151.23612512626258 540 | * Halstead effort: 1411.5371678451174 541 | * Function: **percentifyDensity** 542 | * Line No.: 143 543 | * Physical LOC: 3 544 | * Logical LOC: 1 545 | * Parameter count: 2 546 | * Cyclomatic complexity: 1 547 | * Cyclomatic complexity density: 100% 548 | * Halstead difficulty: 4 549 | * Halstead volume: 39 550 | * Halstead effort: 156 551 | * Function: **percentify** 552 | * Line No.: 147 553 | * Physical LOC: 7 554 | * Logical LOC: 3 555 | * Parameter count: 2 556 | * Cyclomatic complexity: 2 557 | * Cyclomatic complexity density: 66.66666666666666% 558 | * Halstead difficulty: 5 559 | * Halstead volume: 44.37895002019238 560 | * Halstead effort: 221.8947501009619 561 | * Function: **createVisibilityMatrix** 562 | * Line No.: 155 563 | * Physical LOC: 29 564 | * Logical LOC: 9 565 | * Parameter count: 1 566 | * Cyclomatic complexity: 1 567 | * Cyclomatic complexity density: 11.11111111111111% 568 | * Halstead difficulty: 6.8181818181818175 569 | * Halstead volume: 212 570 | * Halstead effort: 1445.4545454545453 571 | * Function: **<anonymous>** 572 | * Line No.: 158 573 | * Physical LOC: 4 574 | * Logical LOC: 2 575 | * Parameter count: 0 576 | * Cyclomatic complexity: 1 577 | * Cyclomatic complexity density: 50% 578 | * Halstead difficulty: 2.357142857142857 579 | * Halstead volume: 59.794705707972525 580 | * Halstead effort: 140.94466345450667 581 | * Function: **<anonymous>** 582 | * Line No.: 163 583 | * Physical LOC: 3 584 | * Logical LOC: 1 585 | * Parameter count: 2 586 | * Cyclomatic complexity: 1 587 | * Cyclomatic complexity density: 100% 588 | * Halstead difficulty: 1.5 589 | * Halstead volume: 23.264662506490403 590 | * Halstead effort: 34.89699375973561 591 | * Function: **<anonymous>** 592 | * Line No.: 167 593 | * Physical LOC: 13 594 | * Logical LOC: 1 595 | * Parameter count: 2 596 | * Cyclomatic complexity: 1 597 | * Cyclomatic complexity density: 100% 598 | * Halstead difficulty: 2.5 599 | * Halstead volume: 27 600 | * Halstead effort: 67.5 601 | * Function: **<anonymous>** 602 | * Line No.: 168 603 | * Physical LOC: 11 604 | * Logical LOC: 5 605 | * Parameter count: 2 606 | * Cyclomatic complexity: 3 607 | * Cyclomatic complexity density: 60% 608 | * Halstead difficulty: 4.166666666666667 609 | * Halstead volume: 58.81033751683406 610 | * Halstead effort: 245.0430729868086 611 | * Function: **setCoreSize** 612 | * Line No.: 185 613 | * Physical LOC: 38 614 | * Logical LOC: 16 615 | * Parameter count: 1 616 | * Cyclomatic complexity: 2 617 | * Cyclomatic complexity density: 12.5% 618 | * Halstead difficulty: 16.666666666666668 619 | * Halstead volume: 422.59091326949994 620 | * Halstead effort: 7043.181887825 621 | * Function: **<anonymous>** 622 | * Line No.: 198 623 | * Physical LOC: 11 624 | * Logical LOC: 1 625 | * Parameter count: 2 626 | * Cyclomatic complexity: 1 627 | * Cyclomatic complexity density: 100% 628 | * Halstead difficulty: 2.6666666666666665 629 | * Halstead volume: 43.18506523353572 630 | * Halstead effort: 115.16017395609524 631 | * Function: **<anonymous>** 632 | * Line No.: 199 633 | * Physical LOC: 9 634 | * Logical LOC: 5 635 | * Parameter count: 3 636 | * Cyclomatic complexity: 2 637 | * Cyclomatic complexity density: 40% 638 | * Halstead difficulty: 8.666666666666666 639 | * Halstead volume: 83.76180828526728 640 | * Halstead effort: 725.9356718056497 641 | * Function: **<anonymous>** 642 | * Line No.: 215 643 | * Physical LOC: 5 644 | * Logical LOC: 2 645 | * Parameter count: 2 646 | * Cyclomatic complexity: 2 647 | * Cyclomatic complexity density: 100% 648 | * Halstead difficulty: 4.285714285714286 649 | * Halstead volume: 75.28421251514429 650 | * Halstead effort: 322.6466250649041 651 | * Function: **getMedian** 652 | * Line No.: 224 653 | * Physical LOC: 9 654 | * Logical LOC: 4 655 | * Parameter count: 1 656 | * Cyclomatic complexity: 2 657 | * Cyclomatic complexity density: 50% 658 | * Halstead difficulty: 10.0625 659 | * Halstead volume: 171.90318620677482 660 | * Halstead effort: 1729.7758112056715 661 | * Function: **compareNumbers** 662 | * Line No.: 234 663 | * Physical LOC: 11 664 | * Logical LOC: 5 665 | * Parameter count: 2 666 | * Cyclomatic complexity: 3 667 | * Cyclomatic complexity density: 60% 668 | * Halstead difficulty: 5.625 669 | * Halstead volume: 53.88872502451932 670 | * Halstead effort: 303.12407826292116 671 | * Function: **calculateAverages** 672 | * Line No.: 246 673 | * Physical LOC: 27 674 | * Logical LOC: 14 675 | * Parameter count: 1 676 | * Cyclomatic complexity: 2 677 | * Cyclomatic complexity density: 14.285714285714285% 678 | * Halstead difficulty: 10.625 679 | * Halstead volume: 282.02638308846554 680 | * Halstead effort: 2996.5303203149465 681 | * Function: **<anonymous>** 682 | * Line No.: 263 683 | * Physical LOC: 5 684 | * Logical LOC: 1 685 | * Parameter count: 1 686 | * Cyclomatic complexity: 1 687 | * Cyclomatic complexity density: 100% 688 | * Halstead difficulty: 1.5 689 | * Halstead volume: 34.86917501586544 690 | * Halstead effort: 52.303762523798156 691 | * Function: **<anonymous>** 692 | * Line No.: 264 693 | * Physical LOC: 3 694 | * Logical LOC: 1 695 | * Parameter count: 1 696 | * Cyclomatic complexity: 1 697 | * Cyclomatic complexity density: 100% 698 | * Halstead difficulty: 1.6666666666666667 699 | * Halstead volume: 18.575424759098897 700 | * Halstead effort: 30.95904126516483 701 | * Function: **<anonymous>** 702 | * Line No.: 269 703 | * Physical LOC: 3 704 | * Logical LOC: 1 705 | * Parameter count: 1 706 | * Cyclomatic complexity: 1 707 | * Cyclomatic complexity density: 100% 708 | * Halstead difficulty: 2.25 709 | * Halstead volume: 28.07354922057604 710 | * Halstead effort: 63.16548574629609 711 | 712 | ## /Users/pbooth/code/escomplex/src/safeName.js 713 | 714 | * Physical LOC: 15 715 | * Logical LOC: 8 716 | * Mean parameter count: 2 717 | * Cyclomatic complexity: 3 718 | * Cyclomatic complexity density: 37.5% 719 | * Maintainability index: 122.30960288059134 720 | * Dependency count: 1 721 | * Function: **module.exports** 722 | * Line No.: 7 723 | * Physical LOC: 11 724 | * Logical LOC: 5 725 | * Parameter count: 2 726 | * Cyclomatic complexity: 3 727 | * Cyclomatic complexity density: 60% 728 | * Halstead difficulty: 6.666666666666666 729 | * Halstead volume: 103.78294855911894 730 | * Halstead effort: 691.8863237274595 731 | 732 | --------------------------------------------------------------------------------