Codehawk is a static analysis tool for JavaScript projects.
Codehawk is a static analysis tool for JavaScript projects. It is intended as a warning system, to identify complex areas of code that need special attention by developers.
FTA is a direct replacement for the Codehawk CLI project. It's much more robust and dramatically faster, with low level static analysis carried out in Rust.
It's recommended to use FTA over Codehawk CLI. FTA is in active development whereas Codehawk CLI is in maintenance mode.
JavaScript (including TypeScript and Flow) projects are supported for analysis. The CLI tool supports unix and windows filesystems (there is a reasonable amount of Windows compatibility code).
It works by traversing a directory and discovering all supported filetypes, runs a static analysis routine on each file, then performs project-wide analysis such as inter-dependency counting and test coverage mapping.
The CLI runs as a Node.js process. Node.js >=14 is required, but >=16 is recommended. Node v12 and under is not supported.
The simplest way to use codehawk-cli is to use it against a directory in your project:
npm install --save-dev codehawk-cli
or yarn add --dev codehawk-cli
Add a codehawk.json
to the root of your project, for example:
{
"skipDirectories": ["/node_modules", "coverage"]
}
Add a new script to package.json
, for example: "codehawk": "codehawk src"
Run npm run codehawk
and get output to stdout
Also see an example using Next.js.
Codehawk Static Analysis Results
Top 14 files
| File | # of Lines | Times Used/Depended On | Maintainability (higher is better) |
| -------------------------------------------------- | ---------- | ---------------------- | ---------------------------------- |
| /test/codehawk.test.js | 149 | 1 | 45.3 (Needs improvement) |
| /src/util.ts | 143 | 4 | 47.26 (Needs improvement) |
| /src/codehawk.ts | 122 | 2 | 47.94 (Needs improvement) |
| /src/options.ts | 72 | 2 | 52.64 (Could be better) |
| /src/analyze.ts | 67 | 3 | 54.04 (Could be better) |
| /src/cli-util.ts | 63 | 2 | 54.68 (Could be better) |
| /src/traverseProject.ts | 51 | 2 | 56.91 (Could be better) |
| /src/reporters/escomplex.ts | 43 | 2 | 57.44 (Could be better) |
| /src/badge.ts | 45 | 2 | 58.09 (Could be better) |
| /test/options.test.js | 47 | 1 | 58.55 (Could be better) |
| /src/dependencies.ts | 40 | 2 | 58.7 (Could be better) |
| /src/coverage.ts | 21 | 2 | 60.75 OK |
| /src/index.ts | 20 | 1 | 60.97 OK |
To customise your analysis, use the following options, placed in a codehawk.json
file in the root directory.
Option | Description | Default |
---|---|---|
badgesDirectory |
Directory where the two maintainbility badges will be created (when enabled) | ['/generated'] |
enableFlow |
Enable Flow support | false |
extensions |
File extensions that should be analyzed. The default is always used, but you can add more extensions. You can use the exclude[...] options to exclude specific files. |
['.js', '.jsx', '.ts', '.tsx'] |
excludeFilenames |
Filename matches that should be excluded from static analysis (but still show in the data). The default is always used, but you can add more matches to be excluded. Note that the matching is exact. The exclude list is taken into consideration after the extension list. | ['.d.ts', '.min.js', '.bundle.js'] |
excludeDirectories |
Directory matches that should be excluded from static analysis (but still show in the data). Relative to the root. E.g. ['/fixtures', '/test'] |
['/dist', '/bin', '/build'] |
excludeExact |
Exact file matches that should be excluded from static analysis (but still show in the data). Relative to the root. E.g. ['/src/foo/bar.ts'] |
[] |
skipDirectories |
Directories that should be excluded completely, i.e. not visible in the resulting data at all. The defaults will always be skipped. | ['/node_modules', '/flow-typed', '/coverage'] |
minimumThreshold |
Minimum acceptable maintainability score. If a file violates this score, the CLI will exit with code 1 (used to ensure a minimum level of maintainability in CI). It is recommended to set this to at least 30. | 10 |
cliOutputLimit |
Number of files to list in the CLI output (from worst scoring to best scoring). | 25 |
Analyze an entire directory:
const { analyzeProject } = require('codehawk-cli')
const output = analyzeProject('/path/to/project') // returns a Results object
// Get summary maintainability scores
const {
average,
median,
worst,
} = output.summary
Analyze a single piece of code:
const { calculateComplexity } = require('codehawk-cli')
const STATIC_SAMPLE = `
import lodash from 'lodash';
const chunkIntoFives = (myArr) => {
return _.chunk(myArr, 5);
}
export default chunkIntoFives;
`
const metrics = calculateComplexity(STATIC_SAMPLE)
console.log(metrics) // Inspect the full metrics
Codehawk depends on typhonjs-escomplex
for low level complexity metrics.
Flow is supported via flow-remove-types
and typescript is supported via @babel/plugin-transform-typescript
. In other words, it transforms any flow or TypeScript code into JavaScript code before static analysis is carried out.
Each analyzed file in your project ends up with:
codehawkScore
- A Codehawk score which represents it's estimated level of maintainability (0-100, higher is better)dependencies
- a map of this file's dependeciestimesDependedOn
- number of times this file is imported by other filescomplexityReport
- various detailed complexity metrics such as halstead metrics and cyclomatic complexityBy default, codehawk-cli generates 2 badges (in generated/*.svg
) when called via the main CLI interface:
A higher score is better (simpler, more maintainable code).
To avoid generating badges, use the --no-badge
option.
Codehawk gathers various complexity metrics, including:
codehawk.json
configuration files are currently required. However, they can be empty."Samples" contains 4 fake and 1 real project for the purposes of testing the cli tool.
Sweetalert in this directory is a static export (carried out in 2019) of that library.
Each sample contains an empty codehawk.json
configuration file (at present, this config)
Non-latin (or certain unicode?) characters such as \u2019 confuse flow-remove-types
, see https://github.com/facebook/flow/issues/8060