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

Commit bc6f960

Browse files
seanpdoylemarkelog
authored andcommitted
New rule: requireObjectDestructuring
When { requireObjectDestructuring: true }, assert that variable declarations use object destructuring when assigning via object access Closes gh-1986
1 parent ec8c0b0 commit bc6f960

3 files changed

Lines changed: 131 additions & 0 deletions

File tree

lib/config/configuration.js

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -948,6 +948,7 @@ Configuration.prototype.registerDefaultRules = function() {
948948
this.registerRule(require('../rules/disallow-shorthand-arrow-functions'));
949949
this.registerRule(require('../rules/disallow-identical-destructuring-names'));
950950
this.registerRule(require('../rules/require-spaces-in-generator'));
951+
this.registerRule(require('../rules/require-object-destructuring'));
951952

952953
/* ES6 only (end) */
953954

Lines changed: 77 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,77 @@
1+
/**
2+
* Requires variable declarations from objects via destructuring
3+
*
4+
* Type: `Boolean`
5+
*
6+
* Value: `true`
7+
*
8+
* Version: `ES6`
9+
*
10+
* #### Example
11+
*
12+
* ```js
13+
* "requireObjectDestructuring": true
14+
* ```
15+
*
16+
* ##### Valid
17+
*
18+
* ```js
19+
* var { foo } = SomeThing;
20+
* var { bar } = SomeThing.foo;
21+
* var { val } = SomeThing['some.key'];
22+
* ```
23+
*
24+
* ##### Invalid
25+
*
26+
* ```js
27+
* var foo = SomeThing.foo;
28+
* var bar = SomeThing.foo.bar;
29+
* var val = SomeThing['some.key'].val;
30+
* ```
31+
*/
32+
33+
var assert = require('assert');
34+
35+
module.exports = function() {};
36+
37+
module.exports.prototype = {
38+
configure: function(option) {
39+
var isTrue = option === true;
40+
41+
assert(
42+
isTrue || (typeof option === 'object' && Array.isArray(option.allExcept)),
43+
this.getOptionName() + ' requires the value `true` ' +
44+
'or an object with an `allExcept` array property'
45+
);
46+
47+
this._propertyExceptions = !isTrue && option.allExcept || [];
48+
},
49+
50+
getOptionName: function() {
51+
return 'requireObjectDestructuring';
52+
},
53+
54+
check: function(file, errors) {
55+
var propertyExceptions = this._propertyExceptions;
56+
57+
file.iterateNodesByType('VariableDeclaration', function(node) {
58+
59+
node.declarations.forEach(function(declaration) {
60+
var declarationId = declaration.id || {};
61+
var declarationInit = declaration.init || {};
62+
63+
if (declarationId.type !== 'Identifier' || declarationInit.type !== 'MemberExpression') {
64+
return;
65+
}
66+
67+
var propertyName = declarationInit.property && declarationInit.property.name;
68+
69+
if (declarationId.name === propertyName &&
70+
propertyExceptions.indexOf(propertyName) < 0) {
71+
72+
errors.add('Property assignments should use destructuring', node.loc.start);
73+
}
74+
});
75+
});
76+
}
77+
};
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
var Checker = require('../../../lib/checker');
2+
var expect = require('chai').expect;
3+
4+
describe('rules/require-object-destructuring', function() {
5+
describe('when { requireObjectDestructuring: true }', function() {
6+
it('disallows direct property access/assignment', function() {
7+
var checker = buildChecker({ requireObjectDestructuring: true });
8+
9+
expect(checker.checkString('var foo = SomeThing.foo;')).
10+
to.have.one.validation.error.from('requireObjectDestructuring');
11+
});
12+
13+
it('disallows nested property access/assignment', function() {
14+
var checker = buildChecker({ requireObjectDestructuring: true });
15+
16+
expect(checker.checkString('var bar = SomeThing.foo.bar;')).
17+
to.have.one.validation.error.from('requireObjectDestructuring');
18+
});
19+
20+
it('disallows access/assignment with a string literal', function() {
21+
var checker = buildChecker({ requireObjectDestructuring: true });
22+
23+
expect(checker.checkString('var val = SomeThing["some.key"].val;')).
24+
to.have.one.validation.error.from('requireObjectDestructuring');
25+
});
26+
27+
it('allows destructuring direct property access/assignment', function() {
28+
var checker = buildChecker({ requireObjectDestructuring: true });
29+
30+
expect(checker.checkString('var { foo } = SomeThing;')).to.have.no.errors();
31+
});
32+
33+
it('allows destructuring nested property access/assignment', function() {
34+
var checker = buildChecker({ requireObjectDestructuring: true });
35+
36+
expect(checker.checkString('var { bar } = SomeThing.foo;')).to.have.no.errors();
37+
});
38+
39+
it('allows destructuring access/assignment with a string literal', function() {
40+
var checker = buildChecker({ requireObjectDestructuring: true });
41+
42+
expect(checker.checkString('var { val } = SomeThing["some.key"];')).to.have.no.errors();
43+
});
44+
});
45+
46+
function buildChecker(rules) {
47+
var checker = new Checker();
48+
checker.registerDefaultRules();
49+
checker.configure(rules);
50+
51+
return checker;
52+
}
53+
});

0 commit comments

Comments
 (0)