Git Product home page Git Product logo

complexity-report's Introduction

escomplex

Greenkeeper badge Build Status Known Vulnerabilities Dependencies Dev Dependencies

Software complexity analysis of JavaScript abstract syntax trees. The back-end for complexity-report.

Installation

The library is published on npm under the name escomplex. To install, you can add it to the dependencies in your package.json file or simply run:

npm i escomplex --save

Usage

You can use escomplex by including it as an Node.js module:

const escomplex = require('escomplex');

The module exports the analyse function.

analyse

The analyse function is used to convert the source code of one or more modules into one or more corresponding report objects containing metrics.

const result = escomplex.analyse(source, options);

Arguments

source

The first argument, source, must be either a string or an array of objects. If it is an array, each object should include a path property that is either a relative or full path to the equivalent module on disk and a code with the contents of the module. As well as identifying each of the result objects, the path property is also used during dependency analysis.

options

The third argument, options, is an optional object containing properties that modify some of the complexity calculations:

  • options.logicalor: Boolean indicating whether operator || should be considered a source of cyclomatic complexity, defaults to true.
  • options.switchcase: Boolean indicating whether switch statements should be considered a source of cyclomatic complexity, defaults to true.
  • options.forin: Boolean indicating whether for...in loops should be considered a source of cyclomatic complexity, defaults to false.
  • options.trycatch: Boolean indicating whether catch clauses should be considered a source of cyclomatic complexity, defaults to false.
  • options.newmi: Boolean indicating whether the maintainability index should be rebased on a scale from 0 to 100, defaults to false.
  • options.skipCalculation: only valid for when source is an array of files Boolean indicating if we should skip processing of certain values, such as the adjacency and visibility matrixes, core sizes, and average values loc, etc.
  • options.noCoreSize: Skips creating the visibility matrix and calculating the coreSize, which can be very expensive for large projects

Result Format

The analyze function returns a report of the following format, with some variation depending on the given options.

For a single module

If a single source string is passed in the source argument, the result will be a report object that looks like the following:

{
    maintainability: 171,
    dependencies: [],
    aggregate: {
        sloc: {
            logical: 0,
            physical: 0
        },
        params: 0,
        cyclomatic: 1,
        cyclomaticDensity: 1,
        halstead: {
            vocabulary: 0,
            difficulty: 0,
            volume: 0,
            effort: 0,
            bugs: 0,
            time: 0
        }
    },
    functions: [
        {
            name: '',
            line: 0,
            sloc: {
                logical: 0,
                physical: 0
            },
            params: 0,
            cyclomatic: 1,
            cyclomaticDensity: 1,
            halstead: {
                vocabulary: 0,
                difficulty: 0,
                volume: 0,
                effort: 0,
                bugs: 0,
                time: 0
            }
        },
        ...
    ]
}

The meaning of those values, briefly, is as follows (see metrics for more information on each one):

  • report.maintainability: The maintainability index for the module.
  • report.dependencies: The array of CommonJS/AMD dependencies for the module.
  • report.aggregate.sloc.physical: Physical lines of code for the module. Will be undefined if the syntax tree is not annotated with line number data.
  • report.aggregate.sloc.logical: Logical lines of code for the module.
  • report.aggregate.params: Parameter count for the module.
  • report.aggregate.cyclomatic: Cyclomatic complexity for the module.
  • report.aggregate.cyclomaticDensity: Cyclomatic complexity density for the module.
  • report.aggregate.halstead.vocabulary: Halstead vocabulary size for the module.
  • report.aggregate.halstead.difficulty: Halstead difficulty for the module.
  • report.aggregate.halstead.volume: Halstead volume for the module.
  • report.aggregate.halstead.effort: Halstead effort for the module.
  • report.aggregate.halstead.bugs: Halstead bugs for the module.
  • report.aggregate.halstead.time: Halstead time for the module.
  • report.functions[n].name: Function name.
  • report.functions[n].line: Line number that the function starts on. Will be undefined if the syntax tree is not annotated with line number data.
  • report.functions[n].sloc.physical: Physical lines of code for the function. Will be undefined if the syntax tree is not annotated with line number data.
  • report.functions[n].sloc.logical: Logical lines of code for the function.
  • report.functions[n].params: Parameter count for the function.
  • report.functions[n].cyclomatic: Cyclomatic complexity for the function.
  • report.functions[n].cyclomaticDensity: Cyclomatic complexity density for the function.
  • report.functions[n].halstead.vocabulary: Halstead vocabulary size for the function.
  • report.functions[n].halstead.difficulty: Halstead difficulty for the function.
  • report.functions[n].halstead.volume: Halstead volume for the function.
  • report.functions[n].halstead.effort: Halstead effort for the function.
  • report.functions[n].halstead.bugs: Halstead bugs for the function.
  • report.functions[n].halstead.time: Halstead time for the function.

For multiple modules

If an array of sources is passed in the source argument, the result will be an object that looks like the following:

{
    reports: [
        ...
    ],
    adjacencyMatrix: [
        [ 0 ]
    ],
    firstOrderDensity: 0,
    visibilityMatrix: [
        [ 0 ]
    ],
    changeCost: 100,
    coreSize: 100,
    loc: 0,
    cyclomatic: 1,
    effort: 0,
    params: 0,
    maintainability: 171
}

Those properties are defined as follows:

  • result.reports: An array of report objects, each one in the same format described above but with an extra property path that matches the path property from its corresponding syntax tree. This path property is required because the reports array gets sorted during dependency analysis.
  • result.adjacencyMatrix: The adjacency design structure matrix (DSM) for the project. This is a two-dimensional array, each dimension with the same order and length as the reports array. Each row and column represents its equivalent indexed module from the reports array, with values along the horizontal being 1 when that module directly depends on another and values along the vertical being 1 when that module is directly depended on by another. All other values are 0.
  • result.firstOrderDensity: The first-order density for the project.
  • result.visibilityMatrix: The visibility DSM for the project. Like the adjacency matrix, but expanded to incorporate indirect dependencies. Will be missing if noCoreSize is passed as an option.
  • result.changeCost: The change cost for the project. Will be missing if noCoreSize is passed as an option.
  • result.coreSize: The core size for the project.
  • result.loc: The average per-function count of logical lines of code.
  • result.cyclomatic: The average per-function cyclomatic complexity.
  • result.effort: The average per-function Halstead effort.
  • result.params: The average per-function parameter count.
  • result.maintainability: The average per-module maintainability index.

Refer to a more in-depth description of the metrics used for more details.

Related projects

  • plato: JavaScript source code visualization, static analysis, and complexity tool.
  • jsc: JavaScript source code complexity tool.
  • bob: Minimalist-omakase build tool for node.js projects.
  • cardio: A web application health tool.
  • grunt-complexity: A JavaScript complexity analysis grunt task.
  • atom-linter-escomplex: Lining code complexity in Atom editor.
  • brackets-crjs: Brackets extension.
  • jscomplexity: JS cyclomatic complexity report generator.
  • karma-complexity-processor: A preprocessor for karma runner to give some metrics about code complexity.
  • crlint: JS linter based on complexity report results.

Contributing

All changes should be submitted in the form of a pull request. Please refer to the contribution guidelines before submitting a pull request.

Source code is in /src. Unit tests are in /test. You can run the tests with npm test. You can run the linter with npm run lint. Make sure you've installed all the dependencies with npm install first.

License

MIT

complexity-report's People

Contributors

addisonj avatar barboni avatar dkavassy avatar geek avatar greenkeeper[bot] avatar jared-stilwell avatar juzerali avatar ludofischer avatar mattfield avatar mcandre avatar nilos avatar philbooth avatar rowanmanning avatar zzo avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

complexity-report's Issues

Update authorship

  • Add to AUTHORS
  • Update COPYING
  • Update CONTRIBUTING.md
  • Update package.json

Support for STDIN chaining (pipes)

I'm trying to do something like this:

cat ${file} | sed 's,# REMOVE THESE LINES.*,,g' | cr --format plain

cr doesn't appear to read from STDIN, so cannot be chained like this. While I can create a temporary file, I'd rather not so as to keep the file system clean in the event of a script failure.

Unknown command 'cr'

~/frontend   master $  npm install complexity-report      Mon Jun 18 10:31:07 2018
npm WARN [email protected] requires a peer of sinon@>=2.1.0 <5 but none is installed. You must install peer dependencies yourself.
npm WARN [email protected] requires a peer of sinon@^4.0.0 but none is installed. You must install peer dependencies yourself.
npm WARN The package es6-promise is included as both a dev and production dependency.
npm WARN The package oauth-signature is included as both a dev and production dependency.

+ [email protected]
added 5 packages from 26 contributors in 26.249s
 ~/frontend   master *$  cr ./                     29.7s  Mon Jun 18 10:31:39 2018
fish: Unknown command 'cr'
 !  ~/frontend   master *$  cr                            Mon Jun 18 10:31:58 2018
fish: Unknown command 'cr'
 ~/frontend   master *$  node -v                   16.5s  Mon Jun 18 10:33:56 2018
v9.5.0

Add test suite

Add a test suite so the test build test doesn't fail when mocha is upgraded.

JSON Formatter

I have just added CR to my project and the project is quite large. For the moment I will have to allow some files to exceed the complexity threshold. Unfortunately the JSON formatter outputs messages after "Warning: Complexity threshold breached!" as text instead of in JSON format which makes it difficult to parse the file as plain JSON - could you add these notifications to the JSON itself?

functions within es6 classes are skipped

See attached complexity report and test inputs. It looks like complexity report (and likely the underlying escomplex) doesn't see code within ES6 classes. The sample (es6classtest3.js) has a class containing one function, and that doesn't show up in the complexity report (cr.txt). A control sample without a class (es6classtest2.js) is analyzed correctly.

I tested with complexity-report 2.0.0-alpha.

Exclude patterns for files ...

Hi,

I needed exclude patterns at the file level.

I modified cr and wrapped the queue.push(p); on line 163 with the same check as done for the directory. ie -checked for !(cli.excludepattern && cli.excludepattern.test(p)) before adding the file to the queue.

complexity-report as a library

Great job on putting up together this module. I find it quite helpful but wonder if it can be supported as a library as well. ( I saw this was discussed before and the suggestion was to move to escomplex).

Will it work if I send a PR to support it as a library too ? Or can I fork this project, make the changes and publish a new module with library support ?

Problems with running

Hello all! Great job!
I just discovered this tool and trying to test my JS files... But the problem is this tool is not running. When I go to the node_modules folder and type cr --help it says SyntaxError: Unexpected identifier.

Maybe I`m not doing correctly something. Please help!

Call for maintainers

This repository is now unmaintained. If you are interested in assuming maintainership, please comment on this issue or email me directly.

Support per-module maximum cyclomatic complexity

It'd be nice to limit the cyclomatic complexity of a module rather than just on a per-function basis.

Would you accept a PR adding this as a --maxmodcyc or --maxcycmod option?

Rationale

Consider the following contrived example:

function x() {
    if (false) {
        for (; ;) {
            foo(function (bar) {
                bar.baz(function (bam) {
                    if (bam) {
                        switch (x) {
                            case 1:
                                return 42;
                        }
                    }

                    if (1) {

                    } else if (2) {
                        while (true) {
                            42
                        }
                    }
                })
            });
            foo(function (bar) {
                bar.baz(function (bam) {
                    if (bam) {
                        switch (x) {
                            case 1:
                                while (false) {

                                }
                                return 42;
                        }
                    }

                    if (1) {

                    } else if (2) {
                        while (true) {
                            42
                        }
                    }
                })
            });
        }
    }
}

CR gives the following report:

Mean per-function logical LOC: 5
Mean per-function parameter count: 0.8
Mean per-function cyclomatic complexity: 3.4
Mean per-function Halstead effort: 150.17728967464953
Mean per-module maintainability index: 74.56445903264705
First-order density: 0%
Change cost: 100%
Core size: 0%

src/cli/index.js

  Physical LOC: 45
  Logical LOC: 26
  Mean parameter count: 0.8
  Cyclomatic complexity: 13
  Cyclomatic complexity density: 50%
  Maintainability index: 74.56445903264705
  Dependency count: 0

  Function: x
    Line No.: 1
    Physical LOC: 45
    Logical LOC: 4
    Parameter count: 0
    Cyclomatic complexity: 2
    Cyclomatic complexity density: 50%
    Halstead difficulty: 3.3333333333333335
    Halstead volume: 30.880904142633646
    Halstead effort: 102.93634714211215

  Function: <anonymous>
    Line No.: 4
    Physical LOC: 18
    Logical LOC: 1
    Parameter count: 1
    Cyclomatic complexity: 1
    Cyclomatic complexity density: 100%
    Halstead difficulty: 2
    Halstead volume: 18.094737505048094
    Halstead effort: 36.18947501009619

  Function: <anonymous>
    Line No.: 5
    Physical LOC: 16
    Logical LOC: 9
    Parameter count: 1
    Cyclomatic complexity: 6
    Cyclomatic complexity density: 66.66666666666666%
    Halstead difficulty: 4.5
    Halstead volume: 60.94436251225966
    Halstead effort: 274.24963130516846

  Function: <anonymous>
    Line No.: 22
    Physical LOC: 21
    Logical LOC: 1
    Parameter count: 1
    Cyclomatic complexity: 1
    Cyclomatic complexity density: 100%
    Halstead difficulty: 2
    Halstead volume: 18.094737505048094
    Halstead effort: 36.18947501009619

  Function: <anonymous>
    Line No.: 23
    Physical LOC: 19
    Logical LOC: 10
    Parameter count: 1
    Cyclomatic complexity: 7
    Cyclomatic complexity density: 70%
    Halstead difficulty: 4.285714285714286
    Halstead volume: 70.30835464468075
    Halstead effort: 301.3215199057746

As you can see, the per-function CC is not too bad (it peaks at 7), but the overall CC for the module is 13.

cr doesn't return any output

I an trying to run this cr tool on commandline after installing it via npm package and adding node_modules.bin package to the classpath .. I don't get any error but also I don't see any output

Command: cr -o CR_out.json -f json typescript/main.ts

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.