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

Commit babc117

Browse files
janpieterzmarkelog
authored andcommitted
requireCamelCaseOrUpperCaseIdentifiers: add strict option
Added a strict mode, rendering capitals as a first character invalid for an identifier Closes gh-1974
1 parent 712798a commit babc117

2 files changed

Lines changed: 226 additions & 7 deletions

File tree

lib/rules/require-camelcase-or-uppercase-identifiers.js

Lines changed: 47 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,24 @@
11
/**
22
* Requires identifiers to be camelCased or UPPERCASE_WITH_UNDERSCORES
33
*
4-
* Types: `Boolean` or `String`
4+
* Types: `Boolean` or `String` or `Object`
55
*
66
* Values:
77
*
88
* - `true`
9-
* - `"ignoreProperties"` allows an exception for object property names.
9+
* - `"ignoreProperties"` allows an exception for object property names. Deprecated, Please use the `Object` value
10+
* - `Object`:
11+
* - `ignoreProperties`: boolean that allows an exception for object property names
12+
* - `strict`: boolean that forces the first character to not be capitalized
1013
*
1114
* JSHint: [`camelcase`](http://jshint.com/docs/options/#camelcase)
1215
*
1316
* #### Example
1417
*
1518
* ```js
1619
* "requireCamelCaseOrUpperCaseIdentifiers": true
20+
*
21+
* "requireCamelCaseOrUpperCaseIdentifiers": {ignoreProperties: true, strict: true}
1722
* ```
1823
*
1924
* ##### Valid for mode `true`
@@ -54,6 +59,26 @@
5459
* var mixed_Case = 3;
5560
* var snake_case = { snake_case: 6 };
5661
* ```
62+
*
63+
* ##### Valid for mode `strict`
64+
*
65+
* ```js
66+
* var camelCase = 0;
67+
* var _camelCase = 2;
68+
* var camelCase_ = 3;
69+
* var UPPER_CASE = 4;
70+
* var obj.snake_case = 5;
71+
* var camelCase = { snake_case: 6 };
72+
* ```
73+
*
74+
* ##### Invalid for mode `strict`
75+
*
76+
* ```js
77+
* var Mixed_case = 2;
78+
* var Snake_case = { snake_case: 6 };
79+
* var snake_case = { SnakeCase: 6 };
80+
* ```
81+
*
5782
*/
5883

5984
var assert = require('assert');
@@ -63,12 +88,24 @@ module.exports = function() {};
6388
module.exports.prototype = {
6489

6590
configure: function(options) {
91+
if (typeof options !== 'object') {
92+
assert(
93+
options === true || options === 'ignoreProperties',
94+
this.getOptionName() + ' option requires a true value or `ignoreProperties`'
95+
);
96+
var _options = {
97+
ignoreProperties: options === 'ignoreProperties' ? true : false,
98+
strict: false
99+
};
100+
return this.configure(_options);
101+
}
102+
66103
assert(
67-
options === true || options === 'ignoreProperties',
68-
this.getOptionName() + ' option requires a true value or `ignoreProperties`'
104+
typeof options.ignoreProperties === 'boolean' || typeof options.strict === 'boolean',
105+
this.getOptionName() + ' option should have boolean values for ignoreProperties and/or strict'
69106
);
70-
71-
this._ignoreProperties = (options === 'ignoreProperties');
107+
this._ignoreProperties = options.ignoreProperties;
108+
this._strict = options.strict;
72109
},
73110

74111
getOptionName: function() {
@@ -79,7 +116,10 @@ module.exports.prototype = {
79116
file.iterateTokensByType('Identifier', function(token) {
80117
var value = token.value;
81118
if (value.replace(/^_+|_+$/g, '').indexOf('_') === -1 || value.toUpperCase() === value) {
82-
return;
119+
if (!this._strict) {return;}
120+
if (value[0].toUpperCase() !== value[0] || value[0] === '_') {
121+
return;
122+
}
83123
}
84124
if (this._ignoreProperties) {
85125
var nextToken = file.getNextToken(token);

test/specs/rules/require-camelcase-or-uppercase-identifiers.js

Lines changed: 179 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -100,4 +100,183 @@ describe('rules/require-camelcase-or-uppercase-identifiers', function() {
100100
expect(checker.checkString('var extend = { set c_d(v) { } };')).to.have.no.errors();
101101
});
102102
});
103+
104+
describe('option object value `"ignoreProperties"`', function() {
105+
beforeEach(function() {
106+
checker.configure({ requireCamelCaseOrUpperCaseIdentifiers: {ignoreProperties: true} });
107+
});
108+
109+
it('should not report object keys', function() {
110+
expect(checker.checkString('var extend = { snake_case: a };')).to.have.no.errors();
111+
});
112+
113+
it('should not report object properties', function() {
114+
expect(checker.checkString('var extend = a.snake_case;')).to.have.no.errors();
115+
});
116+
117+
it('should report identifiers that are the last token', function() {
118+
expect(checker.checkString('var a = snake_case'))
119+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
120+
});
121+
122+
it('should report identifiers that are the first token', function() {
123+
expect(checker.checkString('snake_case = a;'))
124+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
125+
});
126+
127+
it('should not report es5 getters', function() {
128+
expect(checker.checkString('var extend = { get a_b() { } };')).to.have.no.errors();
129+
});
130+
131+
it('should not report es5 setters', function() {
132+
expect(checker.checkString('var extend = { set c_d(v) { } };')).to.have.no.errors();
133+
});
134+
});
135+
136+
describe('option object value `"strict"`', function() {
137+
beforeEach(function() {
138+
checker.configure({ requireCamelCaseOrUpperCaseIdentifiers: {strict: true} });
139+
});
140+
141+
it('should report capital', function() {
142+
expect(checker.checkString('var X = "x";'))
143+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
144+
});
145+
146+
it('should report capital word', function() {
147+
expect(checker.checkString('var Xoe = "x";'))
148+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
149+
});
150+
151+
it('should report capital used even with second one lower cased', function() {
152+
expect(checker.checkString('var Xy = "x";'))
153+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
154+
});
155+
156+
it('should not report no capital used', function() {
157+
expect(checker.checkString('var xy = "x";')).to.have.no.errors();
158+
});
159+
160+
it('should not report leading underscores', function() {
161+
expect(checker.checkString('var _x = "x", __y = "y";')).to.have.no.errors();
162+
});
163+
164+
it('should report trailing underscores', function() {
165+
expect(checker.checkString('var x_ = "x", y__ = "y";')).to.have.no.errors();
166+
});
167+
168+
it('should not report underscore.js', function() {
169+
expect(checker.checkString('var extend = _.extend;')).to.have.no.errors();
170+
});
171+
172+
it('should not report node globals', function() {
173+
expect(checker.checkString('var a = __dirname + __filename;')).to.have.no.errors();
174+
});
175+
176+
it('should report object keys', function() {
177+
expect(checker.checkString('var extend = { snake_case: a };'))
178+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
179+
});
180+
181+
it('should report object properties', function() {
182+
expect(checker.checkString('var extend = a.snake_case;'))
183+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
184+
});
185+
186+
it('should not report object properties without capital', function() {
187+
expect(checker.checkString('var extend = a.snakeCase;')).to.have.no.errors();
188+
});
189+
190+
it('should report object properties with capital', function() {
191+
expect(checker.checkString('var extend = a.SnakeCase;'))
192+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
193+
});
194+
195+
it('should report identifiers that are the last token', function() {
196+
expect(checker.checkString('var a = snake_case'))
197+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
198+
});
199+
200+
it('should report identifiers that are the first token', function() {
201+
expect(checker.checkString('snake_case = a;'))
202+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
203+
});
204+
205+
it('should report identifiers that start with a capital', function() {
206+
expect(checker.checkString('E'))
207+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
208+
});
209+
});
210+
211+
describe('option object value `"strict"` and `"ignoreProperties"`', function() {
212+
beforeEach(function() {
213+
checker.configure({ requireCamelCaseOrUpperCaseIdentifiers: {strict: true, ignoreProperties: true} });
214+
});
215+
216+
it('should report capital', function() {
217+
expect(checker.checkString('var X = "x";'))
218+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
219+
});
220+
221+
it('should report capital word', function() {
222+
expect(checker.checkString('var Xoe = "x";'))
223+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
224+
});
225+
226+
it('should report capital used even with second one lower cased', function() {
227+
expect(checker.checkString('var Xy = "x";'))
228+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
229+
});
230+
231+
it('should not report no capital used', function() {
232+
expect(checker.checkString('var xy = "x";')).to.have.no.errors();
233+
});
234+
235+
it('should not report leading underscores', function() {
236+
expect(checker.checkString('var _x = "x", __y = "y";')).to.have.no.errors();
237+
});
238+
239+
it('should report trailing underscores', function() {
240+
expect(checker.checkString('var x_ = "x", y__ = "y";')).to.have.no.errors();
241+
});
242+
243+
it('should not report underscore.js', function() {
244+
expect(checker.checkString('var extend = _.extend;')).to.have.no.errors();
245+
});
246+
247+
it('should not report node globals', function() {
248+
expect(checker.checkString('var a = __dirname + __filename;')).to.have.no.errors();
249+
});
250+
251+
it('should not report object keys', function() {
252+
expect(checker.checkString('var extend = { snake_case: a };')).to.have.no.errors();
253+
});
254+
255+
it('should not report object properties', function() {
256+
expect(checker.checkString('var extend = a.snake_case;')).to.have.no.errors();
257+
});
258+
259+
it('should not report object properties without capital', function() {
260+
expect(checker.checkString('var extend = a.snakeCase;')).to.have.no.errors();
261+
});
262+
263+
it('should report object properties with capital', function() {
264+
expect(checker.checkString('var extend = a.SnakeCase;')).to.have.no.errors();
265+
});
266+
267+
it('should report identifiers that are the last token', function() {
268+
expect(checker.checkString('var a = snake_case'))
269+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
270+
});
271+
272+
it('should report identifiers that are the first token', function() {
273+
expect(checker.checkString('snake_case = a;'))
274+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
275+
});
276+
277+
it('should report identifiers that start with a capital', function() {
278+
expect(checker.checkString('E'))
279+
.to.have.one.validation.error.from('requireCamelCaseOrUpperCaseIdentifiers');
280+
});
281+
});
103282
});

0 commit comments

Comments
 (0)