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.
- 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 theg++
command. - For macOS: ensure that the "Xcode Command Line Tools" are installed. These include
make
as well as theclang
andclang++
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
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.
npm install -g metric-gardener
metric-gardener parse /path/to/sources -o /output/file/path.json
npm install metric-gardener
npm exec metric-gardener /path/to/sources -o /output/file/path.json
- C (take a look at the CLI
option
parse-h-as-c
orparse-some-h-as-c
for parsing.h
C headers as C) - Ruby
- Rust
- Bash
- Flow-annotated JavaScript
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.
--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).
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.
Check out our contribution guidelines in the file CONTRIBUTING.md.
There are additional outputs about the metric calculation process that can be enabled by setting the
environment variable NODE_DEBUG
to metric-gardener
.
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.
- 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