Skip to content
This repository has been archived by the owner on Mar 23, 2024. It is now read-only.

Commit

Permalink
New rule: requireAlignedMultilineParams:
Browse files Browse the repository at this point in the history
Enforce indentation of parameters in multiline functions -
var test = function(one, two,
   three, four, five) {
...
};

Closes gh-1901
Fixes #1894
  • Loading branch information
JGulbronson authored and markelog committed Oct 22, 2015
1 parent 077c2f6 commit 2c8d58e
Show file tree
Hide file tree
Showing 3 changed files with 326 additions and 0 deletions.
2 changes: 2 additions & 0 deletions lib/config/configuration.js
Expand Up @@ -1119,6 +1119,8 @@ Configuration.prototype.registerDefaultRules = function() {
this.registerRule(require('../rules/validate-order-in-object-keys'));

this.registerRule(require('../rules/disallow-tabs'));

this.registerRule(require('../rules/require-aligned-multiline-params'));
};

/**
Expand Down
127 changes: 127 additions & 0 deletions lib/rules/require-aligned-multiline-params.js
@@ -0,0 +1,127 @@
/**
* Enforces indentation of parameters in multiline functions
*
* Types: `Boolean`, `String`, `Number`
*
* Values:
* - `true` to require parameters are aligned with the body of the function
* - `'firstParam'` to require parameters to be aligned with the first parameter
* - `Number` for the number of columns the parameters should be indented past the function body
*
* #### Example
*
* ```js
* "disallowSpaceBeforeComma": true
* ```
*
* ##### Valid for `true`
*
* ```js
* var test = function(one, two,
* three, four, five,
* six, seven, eight) {
* console.log(a);
* };
* ```
*
* ##### Valid for `2`
*
* ```js
* var test = function(one, two,
* three, four, five,
* six, seven, eight) {
* console.log(a);
* };
* ```
*
* ##### Valid for `'firstParam'`
*
* ```js
* var test = function(one, two,
* three, four, five,
* six, seven, eight) {
* console.log(a);
* };
* ```
*
* ##### Invalid for `0`
*
* ```js
* var test = function(one, two,
* three, four, five,
* six, seven, eight) {
* console.log(a);
* };
* ```
*
*/

var assert = require('assert');

module.exports = function() {
};

module.exports.prototype = {

configure: function(option) {
if (typeof option === 'number') {
this._indentationLevel = option;
} else if (typeof option === 'string') {
assert(
option === 'firstParam',
this.getOptionName() + ' option requires string value to be "firstParam"'
);

this._alignWithFirstParam = true;
} else if (option === true) {
this._indentationLevel = 0;
} else {
assert(
false,
this.getOptionName() + ' option requires a valid option'
);
}
},

getOptionName: function() {
return 'requireAlignedMultilineParams';
},

check: function(file, errors) {
var _this = this;
file.iterateNodesByType(['FunctionDeclaration', 'FunctionExpression'], function(node) {
var params = node.params;

// We can pass the check if there's no params
if (params.length === 0) {
return;
}

var currentLine = params[0].loc.start.line;
var referenceColumn;
if (_this._alignWithFirstParam) {
referenceColumn = params[0].loc.start.column;
} else {
referenceColumn = node.body.body[0].loc.start.column + _this._indentationLevel;
}

params.forEach(function(param) {
if (param.loc.start.line !== currentLine) {
if (param.loc.start.column !== referenceColumn) {
errors.assert.indentation({
lineNumber: param.loc.start.line,
actual: param.loc.start.column,
expected: referenceColumn,
indentChar: ' ',
silent: false
});
}

currentLine = param.loc.start.line;
}
});

});
}

};
197 changes: 197 additions & 0 deletions test/specs/rules/require-aligned-multiline-params.js
@@ -0,0 +1,197 @@
var Checker = require('../../../lib/checker');
var expect = require('chai').expect;

describe('rules/require-aligned-multiline-params', function() {
var checker;
var option;
function rules() {
return { 'requireAlignedMultilineParams': option };
}

describe('when we pass invalid config options', function() {
beforeEach(function() {
checker = new Checker();
checker.registerDefaultRules();
});

it('should error when an invalid string is passed as the config option', function() {
expect(function() {
checker.configure({ 'requireAlignedMultilineParams': 'invalid' });
}).to.throw();
});

it('should error when an object is passed as the config option', function() {
expect(function() {
checker.configure({ 'requireAlignedMultilineParams': {} });
}).to.throw();
});
});

describe('when we pass true as the config option', function() {
beforeEach(function() {
checker = new Checker();
checker.registerDefaultRules();
option = true;
checker.configure(rules());
});

it('should validate a function with no params properly', function() {
var noParamFunction = 'var noParamFunction = function() { \n' +
' return;\n' +
'};';

expect(checker.checkString(noParamFunction)).to.have.no.errors();
});

it('should validate a function with a single line of params properly', function() {
var singleLineFunction = 'var singleLineFunction = function(a, b, c) { \n' +
' console.log(a + b + c);\n' +
'};';

expect(checker.checkString(singleLineFunction)).to.have.no.errors();
});

it('should validate a function with aligned params properly', function() {
var unalignedFunction = 'var alignedFunction = function(a,\n' +
' b, c,\n' +
' d, e) {\n' +
' console.log(a + b + c + d + e);\n' +
'};';

expect(checker.checkString(unalignedFunction)).to.have.no.errors();
});

it('should validate a function with one unaligned param properly', function() {
var unalignedFunction = 'var unalignedFunction = function(a,\n' +
' b, c,\n' +
' d, e) {\n' +
' console.log(a + b + c + d + e);\n' +
'};';

expect(checker.checkString(unalignedFunction)).to.have.one.validation.error.from(
'requireAlignedMultilineParams');
});

it('should validate a function with two unaligned params properly', function() {
var unalignedFunction = 'var unalignedFunction = function(a,\n' +
' b, c,\n' +
' d, e) {\n' +
' console.log(a + b + c + d + e);\n' +
'};';

expect(checker.checkString(unalignedFunction)).to.have.error.count.equal(2);
});
});

describe('when we pass a number as the config option', function() {
beforeEach(function() {
checker = new Checker();
checker.registerDefaultRules();
option = 2;
checker.configure(rules());
});

it('should validate a function with no params properly', function() {
var noParamFunction = 'var noParamFunction = function() { \n' +
' return;\n' +
'};';

expect(checker.checkString(noParamFunction)).to.have.no.errors();
});

it('should validate a function with a single line of params properly', function() {
var singleLineFunction = 'var singleLineFunction = function(a, b, c) { \n' +
' console.log(a + b + c);\n' +
'};';

expect(checker.checkString(singleLineFunction)).to.have.no.errors();
});

it('should validate a function with aligned params properly', function() {
var unalignedFunction = 'var alignedFunction = function(a,\n' +
' b, c,\n' +
' d, e) {\n' +
' console.log(a + b + c + d + e);\n' +
'};';

expect(checker.checkString(unalignedFunction)).to.have.no.errors();
});

it('should validate a function with one unaligned param properly', function() {
var unalignedFunction = 'var unalignedFunction = function(a,\n' +
' b, c,\n' +
' d, e) {\n' +
' console.log(a + b + c + d + e);\n' +
'};';

expect(checker.checkString(unalignedFunction)).to.have.one.validation.error.from(
'requireAlignedMultilineParams');
});

it('should validate a function with two unaligned params properly', function() {
var unalignedFunction = 'var unalignedFunction = function(a,\n' +
' b, c,\n' +
' d, e) {\n' +
' console.log(a + b + c + d + e);\n' +
'};';

expect(checker.checkString(unalignedFunction)).to.have.error.count.equal(2);
});
});

describe('when we pass "firstParam" as the config option', function() {
beforeEach(function() {
checker = new Checker();
checker.registerDefaultRules();
option = 'firstParam';
checker.configure(rules());
});

it('should validate a function with no params properly', function() {
var noParamFunction = 'var noParamFunction = function() { \n' +
' return;\n' +
'};';

expect(checker.checkString(noParamFunction)).to.have.no.errors();
});

it('should validate a function with a single line of params properly', function() {
var singleLineFunction = 'var singleLineFunction = function(a, b, c) { \n' +
' console.log(a + b + c);\n' +
'};';

expect(checker.checkString(singleLineFunction)).to.have.no.errors();
});

it('should validate a function with aligned params properly', function() {
var unalignedFunction = 'var alignedFunction = function(a,\n' +
' b, c,\n' +
' d, e) {\n' +
' console.log(a + b + c + d + e);\n' +
'};';

expect(checker.checkString(unalignedFunction)).to.have.no.errors();
});

it('should validate a function with one unaligned param properly', function() {
var unalignedFunction = 'var unalignedFunction = function(a,\n' +
' b, c,\n' +
' d, e) {\n' +
' console.log(a + b + c + d + e);\n' +
'};';

expect(checker.checkString(unalignedFunction)).to.have.one.validation.error.from(
'requireAlignedMultilineParams');
});

it('should validate a function with two unaligned params properly', function() {
var unalignedFunction = 'var unalignedFunction = function(a,\n' +
' b, c,\n' +
' d, e) {\n' +
' console.log(a + b + c + d + e);\n' +
'};';

expect(checker.checkString(unalignedFunction)).to.have.error.count.equal(2);
});
});
});

0 comments on commit 2c8d58e

Please sign in to comment.