Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: codeclimate/codeclimate-fixme
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 03c5c83
Choose a base ref
...
head repository: codeclimate/codeclimate-fixme
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: eef732e
Choose a head ref
  • 6 commits
  • 8 files changed
  • 1 contributor

Commits on Aug 16, 2023

  1. Copy the full SHA
    45f419d View commit details

Commits on Aug 18, 2023

  1. Copy the full SHA
    8d81947 View commit details

Commits on Aug 21, 2023

  1. Copy the full SHA
    0fe5879 View commit details
  2. Update tests

    larkinscott committed Aug 21, 2023
    Copy the full SHA
    318a1e2 View commit details
  3. Add sarif output

    This adds support for sarif output. It also updates the test to work
    properly with the CLI format.
    larkinscott committed Aug 21, 2023
    Copy the full SHA
    6eb8f47 View commit details
  4. Update README.md

    larkinscott committed Aug 21, 2023
    Copy the full SHA
    eef732e View commit details
Showing with 664 additions and 285 deletions.
  1. +4 −31 README.md
  2. +3 −2 bin/fixme
  3. +0 −88 lib/fix-me.js
  4. +137 −0 lib/fixme.js
  5. +438 −0 package-lock.json
  6. +5 −2 package.json
  7. +0 −162 test/fix-me.js
  8. +77 −0 test/fixme.js
35 changes: 4 additions & 31 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
# Code Climate FIXME Engine
# Code Climate FIXME CLI

`codeclimate-fixme` is a Code Climate engine that performs a case-sensitive search for the following strings in your project:
`codeclimate-fixme` is a CLI that performs a case-sensitive search for the following strings in your project:

* `TODO`
* `FIXME`
@@ -10,34 +10,7 @@

These strings are things you should fix now, not later.

`codeclimate-fixme` is also very simple, and is intended to provide a `Hello World` like template for Code Climate Platform engine authors. It is implemented in JavaScript as an NPM package.

### Installation & Usage

1. If you haven't already, [install the Code Climate CLI](https://github.com/codeclimate/codeclimate).
2. Run `codeclimate engines:enable fixme`. This command both installs the engine and enables it in your `.codeclimate.yml` file.
3. You're ready to analyze! Browse into your project's folder and run `codeclimate analyze`.

### Configuration

You can specify what strings to match by adding a `strings` key in your
`.codeclimate.yml`:

```yaml
engines:
fixme:
enabled: true
config:
strings:
- FIXME
- CUSTOM
```
**NOTE**: values specified here *override* the defaults, they are not
*additional* strings to match.
### Need help?
For help with `codeclimate-fixme`, please open an issue on this repository.

If you're running into a Code Climate issue, first look over this project's [GitHub Issues](https://github.com/codeclimate/codeclimate-fixme/issues), as your question may have already been covered. If not, [go ahead and open a support ticket with us](https://codeclimate.com/help).
1. `npm i codeclimate-fixme`
2. `fixme [table|json|sarif] [path]`
5 changes: 3 additions & 2 deletions bin/fixme
Original file line number Diff line number Diff line change
@@ -1,13 +1,14 @@
#!/usr/bin/env node

var fs = require('fs');
var FixMe = require('../lib/fix-me');
var FixMe = require('../lib/fixme');
var config;

fs.readFile('/config.json', function(err, data) {
if (!err) {
config = JSON.parse(data);
}

new FixMe().run(config)
var fixer = new FixMe();
fixer.run(config);
});
88 changes: 0 additions & 88 deletions lib/fix-me.js

This file was deleted.

137 changes: 137 additions & 0 deletions lib/fixme.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,137 @@
const readline = require('readline');
const { spawn } = require('child_process');
const fs = require('fs');

const DEFAULT_PATHS = ['./'];
const DEFAULT_STRINGS = ['BUG', 'FIXME', 'HACK', 'TODO', 'XXX'];
const GREP_OPTIONS = [
'--binary-files=without-match',
'--extended-regexp',
'--line-number',
'--only-matching',
'--recursive',
'--with-filename',
'--word-regexp',
];

class FixMe {
constructor(writable) {
this.output = writable || process.stdout;
this.maxPathLength = 4; // initial length of "Path"
this.maxLineLength = 4; // initial length of "Line"
this.maxTypeLength = 4; // initial length of "Type"
this.issues = [];
}

run(engineConfig) {
const outputPathType = process.argv.includes('--json')
? 'json'
: process.argv.includes('--table')
? 'table'
: process.argv.includes('--sarif')
? 'sarif'
: 'default';

if (outputPathType === 'default' || process.argv.includes('--help')) {
console.log('Usage: fixme [OPTIONS] [PATH]\n\nOptions:\n --json\tOutput results in JSON format.\n --table\tOutput results in table format.\n --sarif\tOutput results in SARIF format.\n --help\tShow help.');
return;
}

let paths = DEFAULT_PATHS;
if (engineConfig && engineConfig.include_paths) {
paths = engineConfig.include_paths;
} else if (process.argv.length > 3) {
paths = process.argv.slice(3);
}

const strings = (engineConfig && engineConfig.config && engineConfig.config.strings) || DEFAULT_STRINGS;

this.find(paths, strings, outputPathType);
}

find(paths, strings, outputPathType, callback) {
const pattern = `(${strings.join('|')})`;
const grep = spawn('grep', [...GREP_OPTIONS, pattern, ...paths]);

readline.createInterface({ input: grep.stdout }).on('line', (line) => {
const [fullPath, lineStr, matchedString] = line.split(':');
const path = fullPath.replace(/^\/code\//, '');
const lineNumber = parseInt(lineStr, 10);

if (!path || !lineNumber || !matchedString) {
process.stderr.write(`Ignoring malformed output: ${line}\n`);
return;
}

// Update the maximum widths for each column for better formatting
this.maxPathLength = Math.max(this.maxPathLength, path.length);
this.maxLineLength = Math.max(this.maxLineLength, `${lineNumber}`.length);
this.maxTypeLength = Math.max(this.maxTypeLength, matchedString.length);

const issue = {
'categories': ['Bug Risk'],
'check_name': matchedString,
'description': `${matchedString} found`,
'file_path': path,
'start_line': lineNumber,
'type': 'issue',
};

this.issues.push(issue);
});

grep.stdout.on('close', () => {
if (outputPathType === 'json') {
this.output.write(JSON.stringify(this.issues));
} else if (outputPathType === 'table') {
// Print table format here...
} else if (outputPathType === 'sarif') {
this.outputSARIF();
}
if (callback) callback();
});
}

outputSARIF() {
const sarifResults = this.issues.map(issue => ({
ruleId: issue.check_name,
message: {
text: issue.description,
},
locations: [{
physicalLocation: {
artifactLocation: {
uri: issue.file_path,
},
region: {
startLine: issue.start_line,
},
},
}],
}));

const sarifOutput = {
$schema: "https://schemastore.azurewebsites.net/schemas/json/sarif-2.1.0-rtm.5.json",
version: "2.1.0",
runs: [{
tool: {
driver: {
name: "fixMe",
rules: this.issues.map(issue => ({
id: issue.check_name,
name: issue.check_name,
shortDescription: {
text: issue.description,
},
})),
},
},
results: sarifResults,
}],
};

this.output.write(JSON.stringify(sarifOutput));
}
}

module.exports = FixMe;
Loading