Skip to content

Commit

Permalink
CLI: Support a maxErrors option to limit the number of reported errors
Browse files Browse the repository at this point in the history
  • Loading branch information
mrjoelkemp committed Oct 8, 2014
1 parent a16a694 commit b7e77dc
Show file tree
Hide file tree
Showing 11 changed files with 147 additions and 2 deletions.
17 changes: 17 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,9 @@ jscs path[ path[...]] --reporter=./some-dir/my-reporter.js
### `--no-colors`
Clean output without colors.

### '--max-errors'
Set the maximum number of errors to report

### `--help`
Outputs usage information.

Expand Down Expand Up @@ -166,6 +169,20 @@ Values: A single file extension or an Array of file extensions, beginning with a
"fileExtensions": [".js"]
```

### maxErrors

Set the maximum number of errors to report

Type: `Number`

Default: Infinity

#### Example

```js
"maxErrors": 10
```

## Error Suppression

### Inline Comments
Expand Down
1 change: 1 addition & 0 deletions bin/jscs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ program
.option('-p, --preset <preset>', 'preset config')
.option('-r, --reporter <reporter>', 'error reporter, console - default, text, checkstyle, junit, inline')
.option('-v, --verbose', 'adds rule names to the error output')
.option('-m, --max-errors <number>', 'maximum number of errors to report')
.option('', 'Also accepts relative or absolute path to custom reporter')
.option('', 'For instance:')
.option('', '\t ../some-dir/my-reporter.js\t(relative path with extension)')
Expand Down
2 changes: 2 additions & 0 deletions lib/checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ var path = require('path');
var additionalRules = require('./options/additional-rules');
var excludeFiles = require('./options/exclude-files');
var fileExtensions = require('./options/file-extensions');
var maxErrors = require('./options/max-errors');

/**
* Starts Code Style checking process.
Expand All @@ -30,6 +31,7 @@ Checker.prototype.configure = function(config) {
fileExtensions(config, this);
excludeFiles(config, this, cwd);
additionalRules(config, this, cwd);
maxErrors(config, this);

StringChecker.prototype.configure.apply(this, arguments);
};
Expand Down
8 changes: 8 additions & 0 deletions lib/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,10 @@ module.exports = function(program) {
config.preset = program.preset;
}

if (program.maxErrors) {
config.maxErrors = Number(program.maxErrors);
}

if (program.reporter) {
reporterPath = path.resolve(process.cwd(), program.reporter);
returnArgs.reporter = reporterPath;
Expand Down Expand Up @@ -135,6 +139,10 @@ module.exports = function(program) {

reporter(errorsCollection);

if (checker.maxErrorsHit) {
console.log('Too many errors... Set the `maxErrors` configuration option to see more.');
}

errorsCollection.forEach(function(errors) {
if (!errors.isEmpty()) {
defer.reject(2);
Expand Down
32 changes: 31 additions & 1 deletion lib/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -6,21 +6,34 @@ var colors = require('colors');
* @name Errors
* @param {JsFile} file
* @param {Boolean} verbose
* @param {Number} [maxErrors=Infinity]
*/
var Errors = function(file, verbose) {
var Errors = function(file, verbose, maxErrors) {
this._errorList = [];
this._file = file;
this._currentRule = '';
this._verbose = verbose || false;

this._maxErrors = maxErrors || Infinity;
};

/**
* Tracks the number of errors found across all instances
*
* @type {Number}
*/
var _errorCount = 0;

Errors.prototype = {
/**
* Adds style error to the list
*
* @param {String} message
* @param {Number|Object} line
* @param {Number} [column]
* @returns {Boolean|undefined} true if the addition was successful,
* false if the add limit was hit
* undefined if the rule is not enabled
*/
add: function(message, line, column) {
if (typeof line === 'object') {
Expand All @@ -32,12 +45,29 @@ Errors.prototype = {
return;
}

// We're trying to add more than the max number of errors
if (_errorCount === this._maxErrors) {
this.maxErrorsHit = true;
return false;
}

this._errorList.push({
rule: this._currentRule,
message: this._verbose ? this._currentRule + ': ' + message : message,
line: line,
column: column || 0
});

_errorCount++;

return true;
},

/**
* Sets the current error count back to zero
*/
resetErrorCount: function() {
_errorCount = 0;
},

/**
Expand Down
12 changes: 12 additions & 0 deletions lib/options/max-errors.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
/**
* Limits the total number of errors reported
*
* @param {Object} config
* @param {lib/checker} instance
*/
module.exports = function(config, instance) {
Object.defineProperty(config, 'maxErrors', {
value: Number(config.maxErrors),
enumerable: false
});
};
4 changes: 3 additions & 1 deletion lib/string-checker.js
Original file line number Diff line number Diff line change
Expand Up @@ -248,7 +248,7 @@ StringChecker.prototype = {
parseError = e;
}
var file = new JsFile(filename, str, tree);
var errors = new Errors(file, this._verbose);
var errors = new Errors(file, this._verbose, this._config.maxErrors);

if (parseError) {
errors.setCurrentRule('parseError');
Expand All @@ -267,6 +267,8 @@ StringChecker.prototype = {

}, this);

this.maxErrorsHit = errors.maxErrorsHit;

// sort errors list to show errors as they appear in source
errors.getErrorList().sort(function(a, b) {
return (a.line - b.line) || (a.column - b.column);
Expand Down
39 changes: 39 additions & 0 deletions test/cli.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ var exec = require('child_process').exec;

var cli = rewire('../lib/cli');
var startingDir = process.cwd();
var Errors = require('../lib/errors');

describe('modules/cli', function() {
before(function() {
Expand Down Expand Up @@ -524,4 +525,42 @@ describe('modules/cli', function() {
});
});
});

describe('maxErrors option', function() {
var errors = new Errors();
beforeEach(function() {
sinon.spy(console, 'log');
errors.resetErrorCount();
});

afterEach(function() {
console.log.restore();
});

it('should limit the number of errors reported to the provided amount', function(done) {
return cli({
maxErrors: 1,
args: ['test/data/cli/error.js'],
config: 'test/data/cli/maxErrors.json'
})
.promise.always(function() {
assert(console.log.getCall(1).args[0].indexOf('1 code style error found.') !== -1);
rAfter();
done();
});
});

it('should display a message indicating that there were more errors', function(done) {
return cli({
maxErrors: 1,
args: ['test/data/cli/error.js'],
config: 'test/data/cli/maxErrors.json'
})
.promise.always(function() {
assert(console.log.getCall(2).args[0].indexOf('Set the `maxErrors` configuration') !== -1);
rAfter();
done();
});
});
});
});
4 changes: 4 additions & 0 deletions test/data/cli/maxErrors.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@
{
"disallowKeywords": ["with"],
"requireSpaceBeforePostfixUnaryOperators": ["++"]
}
5 changes: 5 additions & 0 deletions test/errors.js
Original file line number Diff line number Diff line change
Expand Up @@ -88,4 +88,9 @@ describe('modules/errors', function() {

assert.ok(errors.isEmpty());
});

it('should report all errors, by default', function() {
checker.configure({ requireSpaceBeforeBinaryOperators: ['='] });
assert(checker.checkString('var foo=1;\n var bar=2;').getErrorCount() === 2);
});
});
25 changes: 25 additions & 0 deletions test/string-checker.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
var Checker = require('../lib/checker');
var Errors = require('../lib/errors');
var assert = require('assert');

describe('modules/string-checker', function() {
Expand Down Expand Up @@ -70,6 +71,30 @@ describe('modules/string-checker', function() {
}
});

describe('maxErrors', function() {
beforeEach(function() {
var errors = new Errors();
errors.resetErrorCount();

checker.configure({
requireSpaceBeforeBinaryOperators: ['='],
maxErrors: 1
});
});

it('should allow a maximum number of reported errors to be set', function() {
var errors = checker.checkString('var foo=1;\n var bar=2;').getErrorList();
assert(errors.length === 1);
});

it('should not report more than the maximum errors across multiple checks', function() {
var errors = checker.checkString('var foo=1;\n var bar=2;').getErrorList();
var errors2 = checker.checkString('var baz=1;\n var qux=2;').getErrorList();
assert(errors.length === 1);
assert(errors2.length === 0);
});
});

describe('rules registration', function() {
it('should report rules in config which don\'t match any registered rules', function() {
var error;
Expand Down

0 comments on commit b7e77dc

Please sign in to comment.