Skip to content

MaibornWolff/metric-gardener

Repository files navigation

metric-gardener - static source code parser

One parser for all languages! No need to build your source code. This static source code parser calculates simple software quality metrics for quite a few languages (more will be added).

An experimental approach is implemented to approximate couplings metrics for C# and PHP without you having to build the source code. This is quite slow and can take up to one or two hours but can provide good results.

It is based on grammars from tree-sitter.

Usage

Install required build tools:

  • This project is based upon Node.js. Therefore, there has to be a recent version of Node.js installed on your machine (see engines entry of package.json for version requirements).
  • Ensure that you have installed all build tools necessary to compile the native C/C++ parts of the required tree-sitter package:
    • Ensure that a supported version of python is installed.
    • For Linux: ensure that make and a C/C++ compiler toolchain is installed, e.g. GCC including the g++ command.
    • For macOS: ensure that the "Xcode Command Line Tools" are installed. These include make as well as the clang and clang++ compiler.
    • For Windows: ensure that you have installed Visual Studio 2019 or later with the "Desktop development with C++" workload.
    • Further information about the required build tools can be found here: https://github.com/nodejs/node-gyp#installation

Install project and parse your sources:

  • npm install
  • npm run build
  • npm run start -- parse /path/to/sources -o /output/file/path.json specify the path to a folder or a file to be parsed and specify output file path.

Global installation via npm

  • npm install -g metric-gardener
  • metric-gardener parse /path/to/sources -o /output/file/path.json

Local as a npm dependency

  • npm install metric-gardener
  • npm exec metric-gardener /path/to/sources -o /output/file/path.json

Supported Languages

Basic support with missing or incomplete unit tests:

Supported File Metrics

complexity
Counts expressions that branch the control flow, like if-statements, loops, switch case labels, catch-blocks etc. - but no else/default/finally statements. Also counts the following other expressions that are considered to increase the complexity of the code inside a file:

  • function declarations (see functions metric below)
  • binary logical operations (like AND and OR)

functions
The number of function declarations inside a file. Includes all kinds of functions, like constructors, lambda functions, member functions, abstract functions, init blocks, closures, etc.

classes
The number of class definitions inside a file, also counting for enums, interfaces, structs, unions, traits and records.

lines_of_code
The total number of lines of a file, including empty lines, comments, etc.

Note: lines_of_code metric will be calculated for all input files with utf-8 encoding, regardless of the languages they are written in.

comment_lines
The number of comment lines inside a file. Does count for any kind of comment (except for python's special block comments).

real_lines_of_code
The number of lines inside a file that contain actual code of the programming language, not counting for comments, empty lines, etc.

max_nesting_level
The maximum nesting level of structured text files, like JSON and YAML.

keywords_in_comments
There is the saying that wtf's per minute is the most precise code metric. Sometimes they can even be found in the code. This metric counts the occurrence of the keywords hack, todo, bug and wtf within comments.

Note: Please click on the languages listed in the section above to access language-specific details.

Command line options for the parse command

--help
Shows an overview over all options and their usage

--output-path, -o
Specifies the location on which the .json-file with the results should be stored, e.g. ./metrics.json. This is required.

--relative-paths, -r
Write paths to the analyzed files in the output .json-file relative to the source directory instead of writing the absolute paths to the files. E.g. writes src/package1/file1.java instead of /home/user.name/programming/project1/src/package1/file1.java (works also for Windows-style paths).

--exclusions, -e
Excludes the specified folders from being scanned for files to be analyzed. Can be an arbitrarily nested subdirectory, so something like --exclusions "folder1" does exclude src/package1/folder1. Does exclude all files in the folder itself as well as in all subdirectories of the folder.

--parse-h-as-c, --hc
Parse all files with the file extension .h as files written in the C programming language instead of C++. Defaults to C++, as the C++ grammar is mostly a superset of the C grammar.

--parse-some-h-as-c, --shc
Parse all files inside the specified folders that have the file extension .h as files written in the C programming language instead of C++. Defaults to C++. Can be also used for file names, e.g. --shc header-file.h. Similar to --exclusions, the folder/file can lie in an arbitrary subdirectory and the option applies to all files in all subdirectories of the specified folder(s).

--compress, -c
Compresses the output .json-file into an zip-archive.

--parse-dependencies
EXPERIMENTAL - VERY SLOW AND NOT READY FOR PRODUCTIVE USE YET
Performs a dependency analysis and appends the results to the output .json-file ( see below).

Updating tree-sitter grammars and adding support for more languages

Take a look at UPDATE_GRAMMARS.md for further information on what to do if you have updated the tree-sitter grammars installed as dependency of this project. You also find information about adding support for an additional programming language there.

For contributors

Check out our contribution guidelines in the file CONTRIBUTING.md.

Enable debug prints

There are additional outputs about the metric calculation process that can be enabled by setting the environment variable NODE_DEBUG to metric-gardener.

Experimental Coupling Metrics

EXPERIMENTAL - VERY SLOW AND NOT READY FOR PRODUCTIVE USE YET

Supported for C# and PHP
Activate dependency analysis by passing --parseDependencies

  • Coupling Between Objects (CBO)
  • Incoming Dependencies and Outgoing Dependencies on file level
  • Instability: Outgoing Dependencies / (Outgoing Dependencies + Incoming Dependencies)

Limitations:

  • Multiple, nested Namespace Declarations within one .cs file are not covered so far and are ignored during the calculation of coupling.

TODOs

  • Rename callExpression Resolver to accessor Resolver
  • Refactor Abstract Usage Collector (small resolver classes?)
  • Add more Unit Tests (Helpers, QueryResolver, TreeParser, etc.)
  • Separate Infrastructure from Domain Code
  • Checkout sample project(s) per language and parse them as an automatic test