UNPKG

4.21 kBJavaScriptView Raw
1/**
2 * Requires member expressions to use dot notation when possible
3 *
4 * Types: `Boolean` or `Object`
5 *
6 * Values:
7 * - `true`
8 * - `"except_snake_case"` (*deprecated* use `"allExcept": ["snake_case"]`) allow quoted snake cased identifiers
9 * - `Object`:
10 * - `'allExcept'` array of exceptions:
11 * - `'keywords'` allow quoted identifiers made of reserved words
12 * - `'snake_case'` allow quoted snake cased identifiers
13 *
14 * N.B.: keywords are always allowed with es3 enabled (http://jscs.info/overview.html#es3)
15 *
16 * JSHint: [`sub`](http://www.jshint.com/docs/options/#sub)
17 *
18 * #### Example
19 *
20 * ```js
21 * "requireDotNotation": true
22 * ```
23 *
24 * ##### Valid
25 *
26 * ```js
27 * var a = b[c];
28 * var a = b.c;
29 * var a = b[c.d];
30 * var a = b[1];
31 * var a = b.while; // reserved words can be property names in ES5
32 * ```
33 *
34 * ##### Invalid
35 *
36 * ```js
37 * var a = b['c'];
38 * var a = b['snake_cased'];
39 * var a = b['_camelCased'];
40 * var a = b['camelCased_'];
41 * ```
42 *
43 * #### Example for allExcept snake_case
44 *
45 * ```js
46 * "requireDotNotation": { "allExcept": [ "snake_case" ] }
47 * ```
48 *
49 * ##### Valid
50 * ```js
51 * var a = b[c];
52 * var a = b.c;
53 * var a = b['snake_cased'];
54 * var a = b['camelCased_butWithSnakes'];
55 * ```
56 *
57 * #### Example for allExcept keywords
58 *
59 * ```js
60 * "requireDotNotation": { "allExcept": [ "keywords" ] }
61 * ```
62 *
63 * ##### Valid
64 *
65 * ```js
66 * var a = b['await']; // reserved word in ES6
67 * var a = b['yield']; // reserved word in ES5
68 * var a = b['let'];
69 * ```
70 *
71 * ##### Invalid
72 *
73 * ```js
74 * var a = b['c'];
75 * ```
76 *
77 * #### Example for `"es3": true`
78 *
79 * ```js
80 * "requireDotNotation": true,
81 * "es3": true
82 * ```
83 *
84 * ##### Valid
85 *
86 * ```js
87 * var a = b[c];
88 * var a = b.c;
89 * var a = b[c.d];
90 * var a = b[1];
91 * var a = b['while']; // reserved word in ES3
92 * ```
93 *
94 * ##### Invalid
95 *
96 * ```js
97 * var a = b['c'];
98 * ```
99 */
100
101var assert = require('assert');
102var utils = require('../utils');
103var reservedWords = require('reserved-words');
104
105module.exports = function() {};
106
107module.exports.prototype = {
108
109 configure: function(options) {
110 if (typeof options !== 'object') {
111 assert(
112 options === true || options === 'except_snake_case',
113 this.getOptionName() + ' option requires either a true value or an object'
114 );
115
116 var _options = {};
117 if (options === 'except_snake_case') {
118 _options.allExcept = ['snake_case'];
119 }
120
121 return this.configure(_options);
122 }
123
124 assert(
125 !options.allExcept || Array.isArray(options.allExcept),
126 'allExcept value of ' + this.getOptionName() + ' option requires an array with exceptions'
127 );
128
129 if (Array.isArray(options.allExcept)) {
130 this._exceptSnakeCase = options.allExcept.indexOf('snake_case') > -1;
131 this._exceptKeywords = options.allExcept.indexOf('keywords') > -1;
132 }
133 },
134
135 getOptionName: function() {
136 return 'requireDotNotation';
137 },
138
139 check: function(file, errors) {
140 var exceptSnakeCase = this._exceptSnakeCase;
141 var exceptKeywords = this._exceptKeywords;
142
143 var dialect = file.getDialect();
144 file.iterateNodesByType('MemberExpression', function(node) {
145 if (!node.computed || node.property.type !== 'StringLiteral') {
146 return;
147 }
148
149 var value = node.property.value;
150 if (// allow numbers, nulls, and anything else
151 typeof value !== 'string' ||
152 // allow invalid identifiers
153 !utils.isValidIdentifierName(value, file.getDialect()) ||
154 // allow quoted snake cased identifiers if allExcept: ['snake_case']
155 (exceptSnakeCase && utils.isSnakeCased(utils.trimUnderscores(value))) ||
156 // allow quoted reserved words if allExcept: ['keywords']
157 ((dialect === 'es3' || exceptKeywords) && reservedWords.check(value, dialect, true))
158 ) {
159 return;
160 }
161
162 errors.add('Use dot notation instead of brackets for member expressions', node.property);
163 });
164 }
165
166};