eslint 4.7.2 → 4.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +123 -0
- package/README.md +34 -19
- package/conf/default-cli-options.js +7 -4
- package/conf/eslint-recommended.js +2 -0
- package/lib/ast-utils.js +83 -42
- package/lib/cli-engine.js +53 -17
- package/lib/cli.js +17 -9
- package/lib/code-path-analysis/code-path-analyzer.js +8 -4
- package/lib/code-path-analysis/code-path-segment.js +43 -41
- package/lib/code-path-analysis/code-path-state.js +7 -2
- package/lib/config/autoconfig.js +14 -12
- package/lib/config/config-file.js +8 -51
- package/lib/config/config-initializer.js +10 -6
- package/lib/config/config-ops.js +21 -21
- package/lib/config/config-rule.js +24 -24
- package/lib/config/config-validator.js +38 -36
- package/lib/config/plugins.js +8 -35
- package/lib/config.js +12 -8
- package/lib/formatters/html-template-message.html +1 -1
- package/lib/formatters/html-template-page.html +3 -1
- package/lib/formatters/html.js +2 -1
- package/lib/formatters/junit.js +21 -15
- package/lib/formatters/tap.js +5 -3
- package/lib/ignored-paths.js +5 -3
- package/lib/linter.js +42 -42
- package/lib/logging.js +2 -2
- package/lib/options.js +12 -0
- package/lib/rules/.eslintrc.yml +2 -2
- package/lib/rules/array-bracket-newline.js +39 -25
- package/lib/rules/array-bracket-spacing.js +28 -28
- package/lib/rules/array-callback-return.js +13 -9
- package/lib/rules/array-element-newline.js +8 -8
- package/lib/rules/arrow-body-style.js +12 -6
- package/lib/rules/arrow-parens.js +4 -2
- package/lib/rules/block-spacing.js +1 -1
- package/lib/rules/brace-style.js +14 -14
- package/lib/rules/callback-return.js +2 -1
- package/lib/rules/capitalized-comments.js +2 -1
- package/lib/rules/comma-style.js +3 -1
- package/lib/rules/computed-property-spacing.js +22 -22
- package/lib/rules/consistent-return.js +4 -4
- package/lib/rules/consistent-this.js +4 -2
- package/lib/rules/curly.js +13 -9
- package/lib/rules/dot-notation.js +56 -35
- package/lib/rules/func-call-spacing.js +4 -2
- package/lib/rules/generator-star-spacing.js +3 -3
- package/lib/rules/getter-return.js +2 -1
- package/lib/rules/indent-legacy.js +25 -14
- package/lib/rules/indent.js +101 -91
- package/lib/rules/key-spacing.js +5 -3
- package/lib/rules/lines-around-comment.js +33 -4
- package/lib/rules/lines-around-directive.js +16 -12
- package/lib/rules/lines-between-class-members.js +91 -0
- package/lib/rules/max-len.js +2 -3
- package/lib/rules/max-statements-per-line.js +5 -3
- package/lib/rules/multiline-comment-style.js +294 -0
- package/lib/rules/new-cap.js +2 -1
- package/lib/rules/newline-after-var.js +8 -6
- package/lib/rules/newline-before-return.js +13 -9
- package/lib/rules/no-alert.js +7 -15
- package/lib/rules/no-await-in-loop.js +17 -9
- package/lib/rules/no-bitwise.js +5 -3
- package/lib/rules/no-catch-shadow.js +4 -2
- package/lib/rules/no-console.js +2 -1
- package/lib/rules/no-constant-condition.js +2 -2
- package/lib/rules/no-control-regex.js +2 -1
- package/lib/rules/no-else-return.js +60 -19
- package/lib/rules/no-empty-character-class.js +11 -11
- package/lib/rules/no-extra-parens.js +22 -11
- package/lib/rules/no-extra-semi.js +5 -3
- package/lib/rules/no-global-assign.js +4 -2
- package/lib/rules/no-implicit-coercion.js +6 -6
- package/lib/rules/no-implied-eval.js +2 -1
- package/lib/rules/no-label-var.js +4 -2
- package/lib/rules/no-lone-blocks.js +3 -3
- package/lib/rules/no-lonely-if.js +2 -1
- package/lib/rules/no-loop-func.js +10 -7
- package/lib/rules/no-mixed-requires.js +8 -4
- package/lib/rules/no-native-reassign.js +4 -2
- package/lib/rules/no-param-reassign.js +4 -2
- package/lib/rules/no-regex-spaces.js +1 -1
- package/lib/rules/no-restricted-imports.js +86 -17
- package/lib/rules/no-restricted-modules.js +84 -15
- package/lib/rules/no-restricted-properties.js +10 -10
- package/lib/rules/no-return-await.js +6 -6
- package/lib/rules/no-self-assign.js +4 -2
- package/lib/rules/no-sequences.js +6 -4
- package/lib/rules/no-trailing-spaces.js +14 -8
- package/lib/rules/no-unneeded-ternary.js +3 -1
- package/lib/rules/no-unreachable.js +4 -2
- package/lib/rules/no-unused-labels.js +2 -1
- package/lib/rules/no-use-before-define.js +13 -11
- package/lib/rules/no-useless-call.js +1 -25
- package/lib/rules/no-useless-computed-key.js +2 -1
- package/lib/rules/no-useless-escape.js +31 -23
- package/lib/rules/no-useless-return.js +14 -8
- package/lib/rules/no-var.js +11 -0
- package/lib/rules/no-whitespace-before-property.js +4 -2
- package/lib/rules/object-curly-newline.js +9 -2
- package/lib/rules/object-curly-spacing.js +20 -20
- package/lib/rules/object-shorthand.js +47 -35
- package/lib/rules/operator-assignment.js +9 -9
- package/lib/rules/operator-linebreak.js +15 -11
- package/lib/rules/padding-line-between-statements.js +6 -4
- package/lib/rules/prefer-arrow-callback.js +12 -10
- package/lib/rules/prefer-const.js +18 -10
- package/lib/rules/prefer-destructuring.js +4 -2
- package/lib/rules/prefer-numeric-literals.js +4 -2
- package/lib/rules/prefer-promise-reject-errors.js +16 -16
- package/lib/rules/prefer-rest-params.js +4 -2
- package/lib/rules/prefer-spread.js +1 -25
- package/lib/rules/prefer-template.js +33 -29
- package/lib/rules/quote-props.js +8 -8
- package/lib/rules/require-jsdoc.js +11 -18
- package/lib/rules/semi-style.js +44 -19
- package/lib/rules/semi.js +5 -3
- package/lib/rules/sort-imports.js +11 -6
- package/lib/rules/space-unary-ops.js +67 -69
- package/lib/rules/strict.js +8 -8
- package/lib/rules/valid-jsdoc.js +39 -33
- package/lib/rules/valid-typeof.js +4 -4
- package/lib/rules/wrap-iife.js +4 -4
- package/lib/rules/yoda.js +9 -7
- package/lib/testers/rule-tester.js +63 -40
- package/lib/token-store/backward-token-cursor.js +5 -3
- package/lib/token-store/forward-token-cursor.js +5 -3
- package/lib/token-store/utils.js +8 -4
- package/lib/util/apply-disable-directives.js +56 -27
- package/lib/util/glob.js +1 -1
- package/lib/util/naming.js +112 -0
- package/lib/util/node-event-generator.js +13 -27
- package/lib/util/safe-emitter.js +54 -0
- package/lib/util/source-code-fixer.js +4 -2
- package/lib/util/source-code.js +70 -65
- package/messages/no-config-found.txt +1 -1
- package/package.json +8 -8
- package/lib/internal-rules/.eslintrc.yml +0 -3
- package/lib/internal-rules/internal-consistent-docs-description.js +0 -130
- package/lib/internal-rules/internal-no-invalid-meta.js +0 -188
@@ -56,52 +56,50 @@ module.exports = {
|
|
56
56
|
//--------------------------------------------------------------------------
|
57
57
|
|
58
58
|
/**
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
59
|
+
* Check if the node is the first "!" in a "!!" convert to Boolean expression
|
60
|
+
* @param {ASTnode} node AST node
|
61
|
+
* @returns {boolean} Whether or not the node is first "!" in "!!"
|
62
|
+
*/
|
63
63
|
function isFirstBangInBangBangExpression(node) {
|
64
64
|
return node && node.type === "UnaryExpression" && node.argument.operator === "!" &&
|
65
65
|
node.argument && node.argument.type === "UnaryExpression" && node.argument.operator === "!";
|
66
66
|
}
|
67
67
|
|
68
68
|
/**
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
69
|
+
* Check if the node's child argument is an "ObjectExpression"
|
70
|
+
* @param {ASTnode} node AST node
|
71
|
+
* @returns {boolean} Whether or not the argument's type is "ObjectExpression"
|
72
|
+
*/
|
73
73
|
function isArgumentObjectExpression(node) {
|
74
74
|
return node.argument && node.argument.type && node.argument.type === "ObjectExpression";
|
75
75
|
}
|
76
76
|
|
77
77
|
/**
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
function overrideExistsForOperator(node, operator) {
|
78
|
+
* Checks if an override exists for a given operator.
|
79
|
+
* @param {string} operator Operator
|
80
|
+
* @returns {boolean} Whether or not an override has been provided for the operator
|
81
|
+
*/
|
82
|
+
function overrideExistsForOperator(operator) {
|
84
83
|
return options.overrides && options.overrides.hasOwnProperty(operator);
|
85
84
|
}
|
86
85
|
|
87
86
|
/**
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
function overrideEnforcesSpaces(node, operator) {
|
87
|
+
* Gets the value that the override was set to for this operator
|
88
|
+
* @param {string} operator Operator
|
89
|
+
* @returns {boolean} Whether or not an override enforces a space with this operator
|
90
|
+
*/
|
91
|
+
function overrideEnforcesSpaces(operator) {
|
94
92
|
return options.overrides[operator];
|
95
93
|
}
|
96
94
|
|
97
95
|
/**
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
96
|
+
* Verify Unary Word Operator has spaces after the word operator
|
97
|
+
* @param {ASTnode} node AST node
|
98
|
+
* @param {Object} firstToken first token from the AST node
|
99
|
+
* @param {Object} secondToken second token from the AST node
|
100
|
+
* @param {string} word The word to be used for reporting
|
101
|
+
* @returns {void}
|
102
|
+
*/
|
105
103
|
function verifyWordHasSpaces(node, firstToken, secondToken, word) {
|
106
104
|
if (secondToken.range[0] === firstToken.range[1]) {
|
107
105
|
context.report({
|
@@ -118,13 +116,13 @@ module.exports = {
|
|
118
116
|
}
|
119
117
|
|
120
118
|
/**
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
119
|
+
* Verify Unary Word Operator doesn't have spaces after the word operator
|
120
|
+
* @param {ASTnode} node AST node
|
121
|
+
* @param {Object} firstToken first token from the AST node
|
122
|
+
* @param {Object} secondToken second token from the AST node
|
123
|
+
* @param {string} word The word to be used for reporting
|
124
|
+
* @returns {void}
|
125
|
+
*/
|
128
126
|
function verifyWordDoesntHaveSpaces(node, firstToken, secondToken, word) {
|
129
127
|
if (isArgumentObjectExpression(node)) {
|
130
128
|
if (secondToken.range[0] > firstToken.range[1]) {
|
@@ -143,18 +141,18 @@ module.exports = {
|
|
143
141
|
}
|
144
142
|
|
145
143
|
/**
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
144
|
+
* Check Unary Word Operators for spaces after the word operator
|
145
|
+
* @param {ASTnode} node AST node
|
146
|
+
* @param {Object} firstToken first token from the AST node
|
147
|
+
* @param {Object} secondToken second token from the AST node
|
148
|
+
* @param {string} word The word to be used for reporting
|
149
|
+
* @returns {void}
|
150
|
+
*/
|
153
151
|
function checkUnaryWordOperatorForSpaces(node, firstToken, secondToken, word) {
|
154
152
|
word = word || firstToken.value;
|
155
153
|
|
156
|
-
if (overrideExistsForOperator(
|
157
|
-
if (overrideEnforcesSpaces(
|
154
|
+
if (overrideExistsForOperator(word)) {
|
155
|
+
if (overrideEnforcesSpaces(word)) {
|
158
156
|
verifyWordHasSpaces(node, firstToken, secondToken, word);
|
159
157
|
} else {
|
160
158
|
verifyWordDoesntHaveSpaces(node, firstToken, secondToken, word);
|
@@ -167,10 +165,10 @@ module.exports = {
|
|
167
165
|
}
|
168
166
|
|
169
167
|
/**
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
168
|
+
* Verifies YieldExpressions satisfy spacing requirements
|
169
|
+
* @param {ASTnode} node AST node
|
170
|
+
* @returns {void}
|
171
|
+
*/
|
174
172
|
function checkForSpacesAfterYield(node) {
|
175
173
|
const tokens = sourceCode.getFirstTokens(node, 3),
|
176
174
|
word = "yield";
|
@@ -183,10 +181,10 @@ module.exports = {
|
|
183
181
|
}
|
184
182
|
|
185
183
|
/**
|
186
|
-
|
187
|
-
|
188
|
-
|
189
|
-
|
184
|
+
* Verifies AwaitExpressions satisfy spacing requirements
|
185
|
+
* @param {ASTNode} node AwaitExpression AST node
|
186
|
+
* @returns {void}
|
187
|
+
*/
|
190
188
|
function checkForSpacesAfterAwait(node) {
|
191
189
|
const tokens = sourceCode.getFirstTokens(node, 3);
|
192
190
|
|
@@ -194,12 +192,12 @@ module.exports = {
|
|
194
192
|
}
|
195
193
|
|
196
194
|
/**
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
195
|
+
* Verifies UnaryExpression, UpdateExpression and NewExpression have spaces before or after the operator
|
196
|
+
* @param {ASTnode} node AST node
|
197
|
+
* @param {Object} firstToken First token in the expression
|
198
|
+
* @param {Object} secondToken Second token in the expression
|
199
|
+
* @returns {void}
|
200
|
+
*/
|
203
201
|
function verifyNonWordsHaveSpaces(node, firstToken, secondToken) {
|
204
202
|
if (node.prefix) {
|
205
203
|
if (isFirstBangInBangBangExpression(node)) {
|
@@ -234,12 +232,12 @@ module.exports = {
|
|
234
232
|
}
|
235
233
|
|
236
234
|
/**
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
241
|
-
|
242
|
-
|
235
|
+
* Verifies UnaryExpression, UpdateExpression and NewExpression don't have spaces before or after the operator
|
236
|
+
* @param {ASTnode} node AST node
|
237
|
+
* @param {Object} firstToken First token in the expression
|
238
|
+
* @param {Object} secondToken Second token in the expression
|
239
|
+
* @returns {void}
|
240
|
+
*/
|
243
241
|
function verifyNonWordsDontHaveSpaces(node, firstToken, secondToken) {
|
244
242
|
if (node.prefix) {
|
245
243
|
if (secondToken.range[0] > firstToken.range[1]) {
|
@@ -274,10 +272,10 @@ module.exports = {
|
|
274
272
|
}
|
275
273
|
|
276
274
|
/**
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
275
|
+
* Verifies UnaryExpression, UpdateExpression and NewExpression satisfy spacing requirements
|
276
|
+
* @param {ASTnode} node AST node
|
277
|
+
* @returns {void}
|
278
|
+
*/
|
281
279
|
function checkForSpaces(node) {
|
282
280
|
const tokens = node.type === "UpdateExpression" && !node.prefix
|
283
281
|
? sourceCode.getLastTokens(node, 2)
|
@@ -292,8 +290,8 @@ module.exports = {
|
|
292
290
|
|
293
291
|
const operator = node.prefix ? tokens[0].value : tokens[1].value;
|
294
292
|
|
295
|
-
if (overrideExistsForOperator(
|
296
|
-
if (overrideEnforcesSpaces(
|
293
|
+
if (overrideExistsForOperator(operator)) {
|
294
|
+
if (overrideEnforcesSpaces(operator)) {
|
297
295
|
verifyNonWordsHaveSpaces(node, firstToken, secondToken);
|
298
296
|
} else {
|
299
297
|
verifyNonWordsDontHaveSpaces(node, firstToken, secondToken);
|
package/lib/rules/strict.js
CHANGED
@@ -109,19 +109,19 @@ module.exports = {
|
|
109
109
|
}
|
110
110
|
|
111
111
|
/**
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
112
|
+
* Determines whether a reported error should be fixed, depending on the error type.
|
113
|
+
* @param {string} errorType The type of error
|
114
|
+
* @returns {boolean} `true` if the reported error should be fixed
|
115
|
+
*/
|
116
116
|
function shouldFix(errorType) {
|
117
117
|
return errorType === "multiple" || errorType === "unnecessary" || errorType === "module" || errorType === "implied" || errorType === "unnecessaryInClasses";
|
118
118
|
}
|
119
119
|
|
120
120
|
/**
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
121
|
+
* Gets a fixer function to remove a given 'use strict' directive.
|
122
|
+
* @param {ASTNode} node The directive that should be removed
|
123
|
+
* @returns {Function} A fixer function
|
124
|
+
*/
|
125
125
|
function getFixFunction(node) {
|
126
126
|
return fixer => fixer.remove(node);
|
127
127
|
}
|
package/lib/rules/valid-jsdoc.js
CHANGED
@@ -226,8 +226,10 @@ module.exports = {
|
|
226
226
|
function checkJSDoc(node) {
|
227
227
|
const jsdocNode = sourceCode.getJSDocComment(node),
|
228
228
|
functionData = fns.pop(),
|
229
|
-
params = Object.create(null)
|
229
|
+
params = Object.create(null),
|
230
|
+
paramsTags = [];
|
230
231
|
let hasReturns = false,
|
232
|
+
returnsTag,
|
231
233
|
hasConstructor = false,
|
232
234
|
isInterface = false,
|
233
235
|
isOverride = false,
|
@@ -261,43 +263,13 @@ module.exports = {
|
|
261
263
|
case "param":
|
262
264
|
case "arg":
|
263
265
|
case "argument":
|
264
|
-
|
265
|
-
context.report({ node: jsdocNode, message: "Missing JSDoc parameter type for '{{name}}'.", data: { name: tag.name } });
|
266
|
-
}
|
267
|
-
|
268
|
-
if (!tag.description && requireParamDescription) {
|
269
|
-
context.report({ node: jsdocNode, message: "Missing JSDoc parameter description for '{{name}}'.", data: { name: tag.name } });
|
270
|
-
}
|
271
|
-
|
272
|
-
if (params[tag.name]) {
|
273
|
-
context.report({ node: jsdocNode, message: "Duplicate JSDoc parameter '{{name}}'.", data: { name: tag.name } });
|
274
|
-
} else if (tag.name.indexOf(".") === -1) {
|
275
|
-
params[tag.name] = 1;
|
276
|
-
}
|
266
|
+
paramsTags.push(tag);
|
277
267
|
break;
|
278
268
|
|
279
269
|
case "return":
|
280
270
|
case "returns":
|
281
271
|
hasReturns = true;
|
282
|
-
|
283
|
-
if (!requireReturn && !functionData.returnPresent && (tag.type === null || !isValidReturnType(tag)) && !isAbstract) {
|
284
|
-
context.report({
|
285
|
-
node: jsdocNode,
|
286
|
-
message: "Unexpected @{{title}} tag; function has no return statement.",
|
287
|
-
data: {
|
288
|
-
title: tag.title
|
289
|
-
}
|
290
|
-
});
|
291
|
-
} else {
|
292
|
-
if (requireReturnType && !tag.type) {
|
293
|
-
context.report({ node: jsdocNode, message: "Missing JSDoc return type." });
|
294
|
-
}
|
295
|
-
|
296
|
-
if (!isValidReturnType(tag) && !tag.description && requireReturnDescription) {
|
297
|
-
context.report({ node: jsdocNode, message: "Missing JSDoc return description." });
|
298
|
-
}
|
299
|
-
}
|
300
|
-
|
272
|
+
returnsTag = tag;
|
301
273
|
break;
|
302
274
|
|
303
275
|
case "constructor":
|
@@ -333,6 +305,40 @@ module.exports = {
|
|
333
305
|
}
|
334
306
|
});
|
335
307
|
|
308
|
+
paramsTags.forEach(param => {
|
309
|
+
if (!param.type) {
|
310
|
+
context.report({ node: jsdocNode, message: "Missing JSDoc parameter type for '{{name}}'.", data: { name: param.name } });
|
311
|
+
}
|
312
|
+
if (!param.description && requireParamDescription) {
|
313
|
+
context.report({ node: jsdocNode, message: "Missing JSDoc parameter description for '{{name}}'.", data: { name: param.name } });
|
314
|
+
}
|
315
|
+
if (params[param.name]) {
|
316
|
+
context.report({ node: jsdocNode, message: "Duplicate JSDoc parameter '{{name}}'.", data: { name: param.name } });
|
317
|
+
} else if (param.name.indexOf(".") === -1) {
|
318
|
+
params[param.name] = 1;
|
319
|
+
}
|
320
|
+
});
|
321
|
+
|
322
|
+
if (hasReturns) {
|
323
|
+
if (!requireReturn && !functionData.returnPresent && (returnsTag.type === null || !isValidReturnType(returnsTag)) && !isAbstract) {
|
324
|
+
context.report({
|
325
|
+
node: jsdocNode,
|
326
|
+
message: "Unexpected @{{title}} tag; function has no return statement.",
|
327
|
+
data: {
|
328
|
+
title: returnsTag.title
|
329
|
+
}
|
330
|
+
});
|
331
|
+
} else {
|
332
|
+
if (requireReturnType && !returnsTag.type) {
|
333
|
+
context.report({ node: jsdocNode, message: "Missing JSDoc return type." });
|
334
|
+
}
|
335
|
+
|
336
|
+
if (!isValidReturnType(returnsTag) && !returnsTag.description && requireReturnDescription) {
|
337
|
+
context.report({ node: jsdocNode, message: "Missing JSDoc return description." });
|
338
|
+
}
|
339
|
+
}
|
340
|
+
}
|
341
|
+
|
336
342
|
// check for functions missing @returns
|
337
343
|
if (!isOverride && !hasReturns && !hasConstructor && !isInterface &&
|
338
344
|
node.parent.kind !== "get" && node.parent.kind !== "constructor" &&
|
@@ -37,10 +37,10 @@ module.exports = {
|
|
37
37
|
const requireStringLiterals = context.options[0] && context.options[0].requireStringLiterals;
|
38
38
|
|
39
39
|
/**
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
40
|
+
* Determines whether a node is a typeof expression.
|
41
|
+
* @param {ASTNode} node The node
|
42
|
+
* @returns {boolean} `true` if the node is a typeof expression
|
43
|
+
*/
|
44
44
|
function isTypeofExpression(node) {
|
45
45
|
return node.type === "UnaryExpression" && node.operator === "typeof";
|
46
46
|
}
|
package/lib/rules/wrap-iife.js
CHANGED
@@ -59,10 +59,10 @@ module.exports = {
|
|
59
59
|
}
|
60
60
|
|
61
61
|
/**
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
62
|
+
* Get the function node from an IIFE
|
63
|
+
* @param {ASTNode} node node to evaluate
|
64
|
+
* @returns {ASTNode} node that is the function expression of the given IIFE, or null if none exist
|
65
|
+
*/
|
66
66
|
function getFunctionNodeFromIIFE(node) {
|
67
67
|
const callee = node.callee;
|
68
68
|
|
package/lib/rules/yoda.js
CHANGED
@@ -126,9 +126,11 @@ function same(a, b) {
|
|
126
126
|
);
|
127
127
|
}
|
128
128
|
|
129
|
-
|
130
|
-
|
131
|
-
|
129
|
+
/*
|
130
|
+
* x[0] = x[0]
|
131
|
+
* x[y] = x[y]
|
132
|
+
* x.y = x.y
|
133
|
+
*/
|
132
134
|
return (
|
133
135
|
a.computed === b.computed &&
|
134
136
|
same(a.object, b.object) &&
|
@@ -259,10 +261,10 @@ module.exports = {
|
|
259
261
|
};
|
260
262
|
|
261
263
|
/**
|
262
|
-
|
263
|
-
|
264
|
-
|
265
|
-
|
264
|
+
* Returns a string representation of a BinaryExpression node with its sides/operator flipped around.
|
265
|
+
* @param {ASTNode} node The BinaryExpression node
|
266
|
+
* @returns {string} A string representation of the node with the sides and operator flipped
|
267
|
+
*/
|
266
268
|
function getFlippedString(node) {
|
267
269
|
const operatorToken = sourceCode.getFirstTokenBetween(node.left, node.right, token => token.value === node.operator);
|
268
270
|
const textBeforeOperator = sourceCode.getText().slice(sourceCode.getTokenBefore(operatorToken).range[1], operatorToken.range[0]);
|
@@ -178,7 +178,7 @@ class RuleTester {
|
|
178
178
|
*/
|
179
179
|
static setDefaultConfig(config) {
|
180
180
|
if (typeof config !== "object") {
|
181
|
-
throw new
|
181
|
+
throw new TypeError("RuleTester.setDefaultConfig: config must be an object");
|
182
182
|
}
|
183
183
|
defaultConfig = config;
|
184
184
|
|
@@ -204,9 +204,11 @@ class RuleTester {
|
|
204
204
|
}
|
205
205
|
|
206
206
|
|
207
|
-
|
208
|
-
|
209
|
-
|
207
|
+
/*
|
208
|
+
* If people use `mocha test.js --watch` command, `describe` and `it` function
|
209
|
+
* instances are different for each execution. So `describe` and `it` should get fresh instance
|
210
|
+
* always.
|
211
|
+
*/
|
210
212
|
static get describe() {
|
211
213
|
return (
|
212
214
|
this[DESCRIBE] ||
|
@@ -254,7 +256,7 @@ class RuleTester {
|
|
254
256
|
linter = this.linter;
|
255
257
|
|
256
258
|
if (lodash.isNil(test) || typeof test !== "object") {
|
257
|
-
throw new
|
259
|
+
throw new TypeError(`Test Scenarios for rule ${ruleName} : Could not find test scenario object`);
|
258
260
|
}
|
259
261
|
|
260
262
|
requiredScenarios.forEach(scenarioType => {
|
@@ -269,6 +271,23 @@ class RuleTester {
|
|
269
271
|
].concat(scenarioErrors).join("\n"));
|
270
272
|
}
|
271
273
|
|
274
|
+
|
275
|
+
linter.defineRule(ruleName, Object.assign({}, rule, {
|
276
|
+
|
277
|
+
// Create a wrapper rule that freezes the `context` properties.
|
278
|
+
create(context) {
|
279
|
+
freezeDeeply(context.options);
|
280
|
+
freezeDeeply(context.settings);
|
281
|
+
freezeDeeply(context.parserOptions);
|
282
|
+
|
283
|
+
return (typeof rule === "function" ? rule : rule.create)(context);
|
284
|
+
}
|
285
|
+
}));
|
286
|
+
|
287
|
+
linter.defineRules(this.rules);
|
288
|
+
|
289
|
+
const ruleMap = linter.getRules();
|
290
|
+
|
272
291
|
/**
|
273
292
|
* Run the rule for the given item
|
274
293
|
* @param {string|Object} item Item to run the rule against
|
@@ -284,12 +303,16 @@ class RuleTester {
|
|
284
303
|
} else {
|
285
304
|
code = item.code;
|
286
305
|
|
287
|
-
|
288
|
-
|
306
|
+
/*
|
307
|
+
* Assumes everything on the item is a config except for the
|
308
|
+
* parameters used by this tester
|
309
|
+
*/
|
289
310
|
const itemConfig = lodash.omit(item, RuleTesterParameters);
|
290
311
|
|
291
|
-
|
292
|
-
|
312
|
+
/*
|
313
|
+
* Create the config object from the tester config and this item
|
314
|
+
* specific configurations.
|
315
|
+
*/
|
293
316
|
config = lodash.merge(
|
294
317
|
config,
|
295
318
|
itemConfig
|
@@ -307,20 +330,22 @@ class RuleTester {
|
|
307
330
|
config.rules[ruleName] = 1;
|
308
331
|
}
|
309
332
|
|
310
|
-
|
311
|
-
|
312
|
-
// Create a wrapper rule that freezes the `context` properties.
|
313
|
-
create(context) {
|
314
|
-
freezeDeeply(context.options);
|
315
|
-
freezeDeeply(context.settings);
|
316
|
-
freezeDeeply(context.parserOptions);
|
333
|
+
const schema = validator.getRuleOptionsSchema(rule);
|
317
334
|
|
318
|
-
|
335
|
+
/*
|
336
|
+
* Setup AST getters.
|
337
|
+
* The goal is to check whether or not AST was modified when
|
338
|
+
* running the rule under test.
|
339
|
+
*/
|
340
|
+
linter.defineRule("rule-tester/validate-ast", () => ({
|
341
|
+
Program(node) {
|
342
|
+
beforeAST = cloneDeeplyExcludesParent(node);
|
343
|
+
},
|
344
|
+
"Program:exit"(node) {
|
345
|
+
afterAST = node;
|
319
346
|
}
|
320
347
|
}));
|
321
348
|
|
322
|
-
const schema = validator.getRuleOptionsSchema(ruleName, linter.rules);
|
323
|
-
|
324
349
|
if (schema) {
|
325
350
|
ajv.validateSchema(schema);
|
326
351
|
|
@@ -335,21 +360,7 @@ class RuleTester {
|
|
335
360
|
}
|
336
361
|
}
|
337
362
|
|
338
|
-
validator.validate(config, "rule-tester",
|
339
|
-
|
340
|
-
/*
|
341
|
-
* Setup AST getters.
|
342
|
-
* The goal is to check whether or not AST was modified when
|
343
|
-
* running the rule under test.
|
344
|
-
*/
|
345
|
-
linter.defineRule("rule-tester/validate-ast", () => ({
|
346
|
-
Program(node) {
|
347
|
-
beforeAST = cloneDeeplyExcludesParent(node);
|
348
|
-
},
|
349
|
-
"Program:exit"(node) {
|
350
|
-
afterAST = node;
|
351
|
-
}
|
352
|
-
}));
|
363
|
+
validator.validate(config, "rule-tester", ruleMap.get.bind(ruleMap), new Environments());
|
353
364
|
|
354
365
|
return {
|
355
366
|
messages: linter.verify(code, config, filename, true),
|
@@ -369,6 +380,7 @@ class RuleTester {
|
|
369
380
|
if (!lodash.isEqual(beforeAST, afterAST)) {
|
370
381
|
|
371
382
|
// Not using directly to avoid performance problem in node 6.1.0. See #6111
|
383
|
+
// eslint-disable-next-line no-restricted-properties
|
372
384
|
assert.deepEqual(beforeAST, afterAST, "Rule should not modify AST.");
|
373
385
|
}
|
374
386
|
}
|
@@ -384,7 +396,7 @@ class RuleTester {
|
|
384
396
|
const result = runRuleForItem(item);
|
385
397
|
const messages = result.messages;
|
386
398
|
|
387
|
-
assert.
|
399
|
+
assert.strictEqual(messages.length, 0, util.format("Should have no errors but had %d: %s",
|
388
400
|
messages.length, util.inspect(messages)));
|
389
401
|
|
390
402
|
assertASTDidntChange(result.beforeAST, result.afterAST);
|
@@ -408,7 +420,7 @@ class RuleTester {
|
|
408
420
|
`Expected '${actual}' to match ${expected}`
|
409
421
|
);
|
410
422
|
} else {
|
411
|
-
assert.
|
423
|
+
assert.strictEqual(actual, expected);
|
412
424
|
}
|
413
425
|
}
|
414
426
|
|
@@ -428,10 +440,10 @@ class RuleTester {
|
|
428
440
|
|
429
441
|
|
430
442
|
if (typeof item.errors === "number") {
|
431
|
-
assert.
|
443
|
+
assert.strictEqual(messages.length, item.errors, util.format("Should have %d error%s but had %d: %s",
|
432
444
|
item.errors, item.errors === 1 ? "" : "s", messages.length, util.inspect(messages)));
|
433
445
|
} else {
|
434
|
-
assert.
|
446
|
+
assert.strictEqual(
|
435
447
|
messages.length, item.errors.length,
|
436
448
|
util.format(
|
437
449
|
"Should have %d error%s but had %d: %s",
|
@@ -460,23 +472,35 @@ class RuleTester {
|
|
460
472
|
assertMessageMatches(messages[i].message, item.errors[i].message);
|
461
473
|
}
|
462
474
|
|
475
|
+
// The following checks use loose equality assertions for backwards compatibility.
|
476
|
+
|
463
477
|
if (item.errors[i].type) {
|
478
|
+
|
479
|
+
// eslint-disable-next-line no-restricted-properties
|
464
480
|
assert.equal(messages[i].nodeType, item.errors[i].type, `Error type should be ${item.errors[i].type}, found ${messages[i].nodeType}`);
|
465
481
|
}
|
466
482
|
|
467
483
|
if (item.errors[i].hasOwnProperty("line")) {
|
484
|
+
|
485
|
+
// eslint-disable-next-line no-restricted-properties
|
468
486
|
assert.equal(messages[i].line, item.errors[i].line, `Error line should be ${item.errors[i].line}`);
|
469
487
|
}
|
470
488
|
|
471
489
|
if (item.errors[i].hasOwnProperty("column")) {
|
490
|
+
|
491
|
+
// eslint-disable-next-line no-restricted-properties
|
472
492
|
assert.equal(messages[i].column, item.errors[i].column, `Error column should be ${item.errors[i].column}`);
|
473
493
|
}
|
474
494
|
|
475
495
|
if (item.errors[i].hasOwnProperty("endLine")) {
|
496
|
+
|
497
|
+
// eslint-disable-next-line no-restricted-properties
|
476
498
|
assert.equal(messages[i].endLine, item.errors[i].endLine, `Error endLine should be ${item.errors[i].endLine}`);
|
477
499
|
}
|
478
500
|
|
479
501
|
if (item.errors[i].hasOwnProperty("endColumn")) {
|
502
|
+
|
503
|
+
// eslint-disable-next-line no-restricted-properties
|
480
504
|
assert.equal(messages[i].endColumn, item.errors[i].endColumn, `Error endColumn should be ${item.errors[i].endColumn}`);
|
481
505
|
}
|
482
506
|
} else {
|
@@ -497,6 +521,7 @@ class RuleTester {
|
|
497
521
|
} else {
|
498
522
|
const fixResult = SourceCodeFixer.applyFixes(item.code, messages);
|
499
523
|
|
524
|
+
// eslint-disable-next-line no-restricted-properties
|
500
525
|
assert.equal(fixResult.output, item.output, "Output is incorrect.");
|
501
526
|
}
|
502
527
|
}
|
@@ -512,7 +537,6 @@ class RuleTester {
|
|
512
537
|
RuleTester.describe("valid", () => {
|
513
538
|
test.valid.forEach(valid => {
|
514
539
|
RuleTester.it(typeof valid === "object" ? valid.code : valid, () => {
|
515
|
-
linter.defineRules(this.rules);
|
516
540
|
testValidTemplate(valid);
|
517
541
|
});
|
518
542
|
});
|
@@ -521,7 +545,6 @@ class RuleTester {
|
|
521
545
|
RuleTester.describe("invalid", () => {
|
522
546
|
test.invalid.forEach(invalid => {
|
523
547
|
RuleTester.it(invalid.code, () => {
|
524
|
-
linter.defineRules(this.rules);
|
525
548
|
testInvalidTemplate(invalid);
|
526
549
|
});
|
527
550
|
});
|