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

Commit

Permalink
New rule: requireCapitalizedConstructorsNew
Browse files Browse the repository at this point in the history
Valid
var a = new B();

Invalid
var d = E();

Added a new rule that behaves closer to the behavior of "newcap" in jshint

Fixes #2046
Closes gh-2047
  • Loading branch information
AlexanderOMara authored and markelog committed Jan 25, 2016
1 parent 63db340 commit ef9ed5e
Show file tree
Hide file tree
Showing 3 changed files with 129 additions and 0 deletions.
1 change: 1 addition & 0 deletions lib/config/configuration.js
Original file line number Diff line number Diff line change
Expand Up @@ -1077,6 +1077,7 @@ Configuration.prototype.registerDefaultRules = function() {
this.registerRule(require('../rules/disallow-space-between-arguments'));

this.registerRule(require('../rules/require-capitalized-constructors'));
this.registerRule(require('../rules/require-capitalized-constructors-new'));

this.registerRule(require('../rules/safe-context-keyword'));

Expand Down
74 changes: 74 additions & 0 deletions lib/rules/require-capitalized-constructors-new.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,74 @@
/**
* Requires capitalized constructors to to use the `new` keyword
*
* Types: `Boolean` or `Object`
*
* Values: `true` or Object with `allExcept` Array of quoted identifiers which are exempted
*
* JSHint: [`newcap`](http://jshint.com/docs/options/#newcap)
*
* #### Example
*
* ```js
* "requireCapitalizedConstructors": true
* "requireCapitalizedConstructors": {
* "allExcept": ["SomethingNative"]
* }
* ```
*
* ##### Valid
*
* ```js
* var a = new B();
* var c = SomethingNative();
* ```
*
* ##### Invalid
*
* ```js
* var d = E();
* ```
*/

var assert = require('assert');

module.exports = function() {};

module.exports.prototype = {
configure: function(options) {
assert(
options === true || Array.isArray(options.allExcept),
this.getOptionName() + ' option requires a true value or an object of exceptions'
);
this._allowedConstructors = {};

var allExcept = options.allExcept;
if (allExcept) {
for (var i = 0, l = allExcept.length; i < l; i++) {
this._allowedConstructors[allExcept[i]] = true;
}
}
},

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

check: function(file, errors) {
var allowedConstructors = this._allowedConstructors;

file.iterateNodesByType('CallExpression', function(node) {
if (node.callee.type === 'Identifier' &&
!allowedConstructors[node.callee.name] &&
node.callee.name[0].toLowerCase() !== node.callee.name[0]
) {
errors.add(
'Constructor functions should use the "new" keyword',
node.callee.loc.start.line,
node.callee.loc.start.column
);
}
});
}

};
54 changes: 54 additions & 0 deletions test/specs/rules/require-capitalized-constructors-new.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,54 @@
var Checker = require('../../../lib/checker');
var expect = require('chai').expect;

describe('rules/require-capitalized-constructors-new', function() {
var checker;

function baseCases() {
it('should report capitalized constructors without the "new" keyword', function() {
expect(checker.checkString('var x = Y();'))
.to.have.one.validation.error.from('requireCapitalizedConstructorsNew');
});

it('should not report capitalized construction', function() {
expect(checker.checkString('var x = new Y();')).to.have.no.errors();
});

it('should not report member expression construction', function() {
expect(checker.checkString('var x = ns.Y();')).to.have.no.errors();
});

it('should not report lowercase function calls', function() {
expect(checker.checkString('var x = y();')).to.have.no.errors();
});
}

beforeEach(function() {
checker = new Checker();
checker.registerDefaultRules();
});

describe('with `true` value', function() {
beforeEach(function() {
checker.configure({ requireCapitalizedConstructorsNew: true });
});

baseCases();
});

describe('with `allExcept` value', function() {
beforeEach(function() {
checker.configure({
requireCapitalizedConstructorsNew: {
allExcept: ['SomethingNative']
}
});
});

baseCases();

it('should not report exempted construction', function() {
expect(checker.checkString('var x = SomethingNative();')).to.have.no.errors();
});
});
});

0 comments on commit ef9ed5e

Please sign in to comment.