eslint 4.10.0 → 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 +36 -22
- package/conf/default-cli-options.js +5 -3
- package/lib/ast-utils.js +81 -41
- package/lib/cli-engine.js +27 -12
- package/lib/code-path-analysis/code-path-analyzer.js +8 -4
- package/lib/code-path-analysis/code-path-segment.js +4 -2
- package/lib/code-path-analysis/code-path-state.js +4 -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/junit.js +21 -15
- package/lib/formatters/tap.js +5 -3
- package/lib/ignored-paths.js +4 -2
- package/lib/linter.js +16 -10
- package/lib/rules/.eslintrc.yml +2 -2
- package/lib/rules/array-bracket-newline.js +20 -20
- 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/brace-style.js +14 -14
- 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 +5 -5
- package/lib/rules/func-call-spacing.js +4 -2
- package/lib/rules/getter-return.js +2 -1
- package/lib/rules/indent-legacy.js +20 -12
- package/lib/rules/indent.js +77 -73
- package/lib/rules/key-spacing.js +5 -3
- package/lib/rules/lines-around-directive.js +16 -12
- package/lib/rules/max-statements-per-line.js +5 -3
- package/lib/rules/newline-after-var.js +8 -6
- package/lib/rules/newline-before-return.js +9 -7
- 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-else-return.js +17 -11
- package/lib/rules/no-empty-character-class.js +11 -11
- package/lib/rules/no-extra-parens.js +16 -8
- 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-loop-func.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-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 +13 -7
- package/lib/rules/no-unreachable.js +4 -2
- package/lib/rules/no-use-before-define.js +13 -11
- package/lib/rules/no-useless-call.js +1 -25
- package/lib/rules/no-useless-escape.js +23 -22
- package/lib/rules/no-useless-return.js +14 -8
- 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 +41 -33
- package/lib/rules/operator-assignment.js +9 -9
- package/lib/rules/operator-linebreak.js +12 -10
- package/lib/rules/padding-line-between-statements.js +4 -2
- 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/semi-style.js +44 -19
- package/lib/rules/semi.js +5 -3
- package/lib/rules/sort-imports.js +5 -3
- package/lib/rules/space-unary-ops.js +61 -61
- package/lib/rules/strict.js +8 -8
- 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 +43 -34
- 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/glob.js +1 -1
- package/lib/util/naming.js +112 -0
- package/lib/util/node-event-generator.js +10 -10
- package/lib/util/safe-emitter.js +1 -1
- package/lib/util/source-code-fixer.js +4 -2
- package/lib/util/source-code.js +2 -1
- package/package.json +6 -5
package/lib/rules/semi-style.js
CHANGED
@@ -18,13 +18,51 @@ const astUtils = require("../ast-utils");
|
|
18
18
|
const SELECTOR = `:matches(${
|
19
19
|
[
|
20
20
|
"BreakStatement", "ContinueStatement", "DebuggerStatement",
|
21
|
-
"DoWhileStatement", "
|
21
|
+
"DoWhileStatement", "ExportAllDeclaration",
|
22
22
|
"ExportDefaultDeclaration", "ExportNamedDeclaration",
|
23
23
|
"ExpressionStatement", "ImportDeclaration", "ReturnStatement",
|
24
24
|
"ThrowStatement", "VariableDeclaration"
|
25
25
|
].join(",")
|
26
26
|
})`;
|
27
27
|
|
28
|
+
/**
|
29
|
+
* Get the child node list of a given node.
|
30
|
+
* This returns `Program#body`, `BlockStatement#body`, or `SwitchCase#consequent`.
|
31
|
+
* This is used to check whether a node is the first/last child.
|
32
|
+
* @param {Node} node A node to get child node list.
|
33
|
+
* @returns {Node[]|null} The child node list.
|
34
|
+
*/
|
35
|
+
function getChildren(node) {
|
36
|
+
const t = node.type;
|
37
|
+
|
38
|
+
if (t === "BlockStatement" || t === "Program") {
|
39
|
+
return node.body;
|
40
|
+
}
|
41
|
+
if (t === "SwitchCase") {
|
42
|
+
return node.consequent;
|
43
|
+
}
|
44
|
+
return null;
|
45
|
+
}
|
46
|
+
|
47
|
+
/**
|
48
|
+
* Check whether a given node is the last statement in the parent block.
|
49
|
+
* @param {Node} node A node to check.
|
50
|
+
* @returns {boolean} `true` if the node is the last statement in the parent block.
|
51
|
+
*/
|
52
|
+
function isLastChild(node) {
|
53
|
+
const t = node.parent.type;
|
54
|
+
|
55
|
+
if (t === "IfStatement" && node.parent.consequent === node && node.parent.alternate) { // before `else` keyword.
|
56
|
+
return true;
|
57
|
+
}
|
58
|
+
if (t === "DoWhileStatement") { // before `while` keyword.
|
59
|
+
return true;
|
60
|
+
}
|
61
|
+
const nodeList = getChildren(node.parent);
|
62
|
+
|
63
|
+
return nodeList !== null && nodeList[nodeList.length - 1] === node; // before `}` or etc.
|
64
|
+
}
|
65
|
+
|
28
66
|
module.exports = {
|
29
67
|
meta: {
|
30
68
|
docs: {
|
@@ -40,23 +78,6 @@ module.exports = {
|
|
40
78
|
const sourceCode = context.getSourceCode();
|
41
79
|
const option = context.options[0] || "last";
|
42
80
|
|
43
|
-
/**
|
44
|
-
* Check whether comments exist between the given 2 tokens.
|
45
|
-
* @param {Token} left The left token to check.
|
46
|
-
* @param {Token} right The right token to check.
|
47
|
-
* @returns {boolean} `true` if comments exist between the given 2 tokens.
|
48
|
-
*/
|
49
|
-
function commentsExistBetween(left, right) {
|
50
|
-
return sourceCode.getFirstTokenBetween(
|
51
|
-
left,
|
52
|
-
right,
|
53
|
-
{
|
54
|
-
includeComments: true,
|
55
|
-
filter: astUtils.isCommentToken
|
56
|
-
}
|
57
|
-
) !== null;
|
58
|
-
}
|
59
|
-
|
60
81
|
/**
|
61
82
|
* Check the given semicolon token.
|
62
83
|
* @param {Token} semiToken The semicolon token to check.
|
@@ -79,7 +100,7 @@ module.exports = {
|
|
79
100
|
: "the beginning of the next line"
|
80
101
|
},
|
81
102
|
fix(fixer) {
|
82
|
-
if (prevToken && nextToken && commentsExistBetween(prevToken, nextToken)) {
|
103
|
+
if (prevToken && nextToken && sourceCode.commentsExistBetween(prevToken, nextToken)) {
|
83
104
|
return null;
|
84
105
|
}
|
85
106
|
|
@@ -95,6 +116,10 @@ module.exports = {
|
|
95
116
|
|
96
117
|
return {
|
97
118
|
[SELECTOR](node) {
|
119
|
+
if (option === "first" && isLastChild(node)) {
|
120
|
+
return;
|
121
|
+
}
|
122
|
+
|
98
123
|
const lastToken = sourceCode.getLastToken(node);
|
99
124
|
|
100
125
|
if (astUtils.isSemicolonToken(lastToken)) {
|
package/lib/rules/semi.js
CHANGED
@@ -93,9 +93,11 @@ module.exports = {
|
|
93
93
|
loc = loc.start;
|
94
94
|
fix = function(fixer) {
|
95
95
|
|
96
|
-
|
97
|
-
|
98
|
-
|
96
|
+
/*
|
97
|
+
* Expand the replacement range to include the surrounding
|
98
|
+
* tokens to avoid conflicting with no-extra-semi.
|
99
|
+
* https://github.com/eslint/eslint/issues/7928
|
100
|
+
*/
|
99
101
|
return new FixTracker(fixer, sourceCode)
|
100
102
|
.retainSurroundingTokens(lastToken)
|
101
103
|
.remove(lastToken);
|
@@ -113,9 +113,11 @@ module.exports = {
|
|
113
113
|
currentLocalMemberName = currentLocalMemberName && currentLocalMemberName.toLowerCase();
|
114
114
|
}
|
115
115
|
|
116
|
-
|
117
|
-
|
118
|
-
|
116
|
+
/*
|
117
|
+
* When the current declaration uses a different member syntax,
|
118
|
+
* then check if the ordering is correct.
|
119
|
+
* Otherwise, make a default string compare (like rule sort-vars to be consistent) of the first used local member name.
|
120
|
+
*/
|
119
121
|
if (currentMemberSyntaxGroupIndex !== previousMemberSyntaxGroupIndex) {
|
120
122
|
if (currentMemberSyntaxGroupIndex < previousMemberSyntaxGroupIndex) {
|
121
123
|
context.report({
|
@@ -56,50 +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
|
-
|
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
82
|
function overrideExistsForOperator(operator) {
|
83
83
|
return options.overrides && options.overrides.hasOwnProperty(operator);
|
84
84
|
}
|
85
85
|
|
86
86
|
/**
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
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
91
|
function overrideEnforcesSpaces(operator) {
|
92
92
|
return options.overrides[operator];
|
93
93
|
}
|
94
94
|
|
95
95
|
/**
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
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
|
+
*/
|
103
103
|
function verifyWordHasSpaces(node, firstToken, secondToken, word) {
|
104
104
|
if (secondToken.range[0] === firstToken.range[1]) {
|
105
105
|
context.report({
|
@@ -116,13 +116,13 @@ module.exports = {
|
|
116
116
|
}
|
117
117
|
|
118
118
|
/**
|
119
|
-
|
120
|
-
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
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
|
+
*/
|
126
126
|
function verifyWordDoesntHaveSpaces(node, firstToken, secondToken, word) {
|
127
127
|
if (isArgumentObjectExpression(node)) {
|
128
128
|
if (secondToken.range[0] > firstToken.range[1]) {
|
@@ -141,13 +141,13 @@ module.exports = {
|
|
141
141
|
}
|
142
142
|
|
143
143
|
/**
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
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
|
+
*/
|
151
151
|
function checkUnaryWordOperatorForSpaces(node, firstToken, secondToken, word) {
|
152
152
|
word = word || firstToken.value;
|
153
153
|
|
@@ -165,10 +165,10 @@ module.exports = {
|
|
165
165
|
}
|
166
166
|
|
167
167
|
/**
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
168
|
+
* Verifies YieldExpressions satisfy spacing requirements
|
169
|
+
* @param {ASTnode} node AST node
|
170
|
+
* @returns {void}
|
171
|
+
*/
|
172
172
|
function checkForSpacesAfterYield(node) {
|
173
173
|
const tokens = sourceCode.getFirstTokens(node, 3),
|
174
174
|
word = "yield";
|
@@ -181,10 +181,10 @@ module.exports = {
|
|
181
181
|
}
|
182
182
|
|
183
183
|
/**
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
184
|
+
* Verifies AwaitExpressions satisfy spacing requirements
|
185
|
+
* @param {ASTNode} node AwaitExpression AST node
|
186
|
+
* @returns {void}
|
187
|
+
*/
|
188
188
|
function checkForSpacesAfterAwait(node) {
|
189
189
|
const tokens = sourceCode.getFirstTokens(node, 3);
|
190
190
|
|
@@ -192,12 +192,12 @@ module.exports = {
|
|
192
192
|
}
|
193
193
|
|
194
194
|
/**
|
195
|
-
|
196
|
-
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
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
|
+
*/
|
201
201
|
function verifyNonWordsHaveSpaces(node, firstToken, secondToken) {
|
202
202
|
if (node.prefix) {
|
203
203
|
if (isFirstBangInBangBangExpression(node)) {
|
@@ -232,12 +232,12 @@ module.exports = {
|
|
232
232
|
}
|
233
233
|
|
234
234
|
/**
|
235
|
-
|
236
|
-
|
237
|
-
|
238
|
-
|
239
|
-
|
240
|
-
|
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
|
+
*/
|
241
241
|
function verifyNonWordsDontHaveSpaces(node, firstToken, secondToken) {
|
242
242
|
if (node.prefix) {
|
243
243
|
if (secondToken.range[0] > firstToken.range[1]) {
|
@@ -272,10 +272,10 @@ module.exports = {
|
|
272
272
|
}
|
273
273
|
|
274
274
|
/**
|
275
|
-
|
276
|
-
|
277
|
-
|
278
|
-
|
275
|
+
* Verifies UnaryExpression, UpdateExpression and NewExpression satisfy spacing requirements
|
276
|
+
* @param {ASTnode} node AST node
|
277
|
+
* @returns {void}
|
278
|
+
*/
|
279
279
|
function checkForSpaces(node) {
|
280
280
|
const tokens = node.type === "UpdateExpression" && !node.prefix
|
281
281
|
? sourceCode.getLastTokens(node, 2)
|
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
|
}
|
@@ -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]);
|
@@ -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] ||
|
@@ -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),
|
@@ -526,7 +537,6 @@ class RuleTester {
|
|
526
537
|
RuleTester.describe("valid", () => {
|
527
538
|
test.valid.forEach(valid => {
|
528
539
|
RuleTester.it(typeof valid === "object" ? valid.code : valid, () => {
|
529
|
-
linter.defineRules(this.rules);
|
530
540
|
testValidTemplate(valid);
|
531
541
|
});
|
532
542
|
});
|
@@ -535,7 +545,6 @@ class RuleTester {
|
|
535
545
|
RuleTester.describe("invalid", () => {
|
536
546
|
test.invalid.forEach(invalid => {
|
537
547
|
RuleTester.it(invalid.code, () => {
|
538
|
-
linter.defineRules(this.rules);
|
539
548
|
testInvalidTemplate(invalid);
|
540
549
|
});
|
541
550
|
});
|
package/lib/token-store/utils.js
CHANGED
@@ -62,8 +62,10 @@ exports.getFirstIndex = function getFirstIndex(tokens, indexMap, startLoc) {
|
|
62
62
|
const index = indexMap[startLoc - 1];
|
63
63
|
const token = (index >= 0 && index < tokens.length) ? tokens[index] : null;
|
64
64
|
|
65
|
-
|
66
|
-
|
65
|
+
/*
|
66
|
+
* For the map of "comment's location -> token's index", it points the next token of a comment.
|
67
|
+
* In that case, +1 is unnecessary.
|
68
|
+
*/
|
67
69
|
if (token && token.range[0] >= startLoc) {
|
68
70
|
return index;
|
69
71
|
}
|
@@ -89,8 +91,10 @@ exports.getLastIndex = function getLastIndex(tokens, indexMap, endLoc) {
|
|
89
91
|
const index = indexMap[endLoc - 1];
|
90
92
|
const token = (index >= 0 && index < tokens.length) ? tokens[index] : null;
|
91
93
|
|
92
|
-
|
93
|
-
|
94
|
+
/*
|
95
|
+
* For the map of "comment's location -> token's index", it points the next token of a comment.
|
96
|
+
* In that case, -1 is necessary.
|
97
|
+
*/
|
94
98
|
if (token && token.range[1] > endLoc) {
|
95
99
|
return index - 1;
|
96
100
|
}
|
package/lib/util/glob.js
CHANGED
@@ -47,7 +47,7 @@ GlobSync.prototype._readdir = function(abs, inGlobStar) {
|
|
47
47
|
* `options.nodir` makes `options.mark` as `true`.
|
48
48
|
* Mark `abs` first
|
49
49
|
* to make sure `"node_modules"` will be ignored immediately with ignore pattern `"node_modules/"`.
|
50
|
-
|
50
|
+
*
|
51
51
|
* There is a built-in cache about marked `File.Stat` in `glob`, so that we could not worry about the extra invocation of `this._mark()`
|
52
52
|
*/
|
53
53
|
const marked = this._mark(abs);
|