eslint 5.6.0 → 5.9.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 +65 -0
- package/bin/eslint.js +0 -1
- package/lib/cli-engine.js +128 -31
- package/lib/cli.js +6 -1
- package/lib/linter.js +9 -0
- package/lib/options.js +5 -0
- package/lib/rules/accessor-pairs.js +4 -0
- package/lib/rules/array-bracket-newline.js +5 -0
- package/lib/rules/array-bracket-spacing.js +5 -0
- package/lib/rules/array-callback-return.js +2 -0
- package/lib/rules/array-element-newline.js +4 -0
- package/lib/rules/arrow-body-style.js +2 -0
- package/lib/rules/arrow-parens.js +2 -0
- package/lib/rules/arrow-spacing.js +2 -0
- package/lib/rules/block-scoped-var.js +2 -0
- package/lib/rules/block-spacing.js +2 -0
- package/lib/rules/brace-style.js +2 -0
- package/lib/rules/callback-return.js +2 -0
- package/lib/rules/camelcase.js +38 -8
- package/lib/rules/capitalized-comments.js +4 -0
- package/lib/rules/class-methods-use-this.js +3 -0
- package/lib/rules/comma-dangle.js +4 -0
- package/lib/rules/comma-spacing.js +2 -0
- package/lib/rules/comma-style.js +5 -0
- package/lib/rules/complexity.js +2 -0
- package/lib/rules/computed-property-spacing.js +2 -0
- package/lib/rules/consistent-return.js +2 -0
- package/lib/rules/consistent-this.js +2 -0
- package/lib/rules/constructor-super.js +2 -0
- package/lib/rules/curly.js +2 -0
- package/lib/rules/default-case.js +2 -0
- package/lib/rules/dot-location.js +2 -0
- package/lib/rules/dot-notation.js +2 -0
- package/lib/rules/eol-last.js +5 -0
- package/lib/rules/eqeqeq.js +2 -0
- package/lib/rules/for-direction.js +4 -0
- package/lib/rules/func-call-spacing.js +4 -0
- package/lib/rules/func-name-matching.js +3 -0
- package/lib/rules/func-names.js +3 -0
- package/lib/rules/func-style.js +3 -0
- package/lib/rules/function-paren-newline.js +5 -0
- package/lib/rules/generator-star-spacing.js +3 -0
- package/lib/rules/getter-return.js +5 -0
- package/lib/rules/global-require.js +2 -0
- package/lib/rules/guard-for-in.js +2 -0
- package/lib/rules/handle-callback-err.js +2 -0
- package/lib/rules/id-blacklist.js +2 -0
- package/lib/rules/id-length.js +2 -0
- package/lib/rules/id-match.js +101 -27
- package/lib/rules/implicit-arrow-linebreak.js +4 -0
- package/lib/rules/indent-legacy.js +4 -1
- package/lib/rules/indent.js +2 -0
- package/lib/rules/init-declarations.js +2 -0
- package/lib/rules/jsx-quotes.js +2 -0
- package/lib/rules/key-spacing.js +4 -3
- package/lib/rules/keyword-spacing.js +2 -0
- package/lib/rules/line-comment-position.js +2 -0
- package/lib/rules/linebreak-style.js +2 -0
- package/lib/rules/lines-around-comment.js +2 -0
- package/lib/rules/lines-around-directive.js +6 -2
- package/lib/rules/lines-between-class-members.js +2 -0
- package/lib/rules/max-classes-per-file.js +4 -0
- package/lib/rules/max-depth.js +2 -0
- package/lib/rules/max-len.js +2 -0
- package/lib/rules/max-lines-per-function.js +2 -0
- package/lib/rules/max-lines.js +2 -0
- package/lib/rules/max-nested-callbacks.js +2 -0
- package/lib/rules/max-params.js +2 -0
- package/lib/rules/max-statements-per-line.js +2 -0
- package/lib/rules/max-statements.js +2 -0
- package/lib/rules/multiline-comment-style.js +3 -0
- package/lib/rules/multiline-ternary.js +3 -0
- package/lib/rules/new-cap.js +2 -0
- package/lib/rules/new-parens.js +2 -1
- package/lib/rules/newline-after-var.js +5 -2
- package/lib/rules/newline-before-return.js +5 -2
- package/lib/rules/newline-per-chained-call.js +4 -0
- package/lib/rules/no-alert.js +2 -0
- package/lib/rules/no-array-constructor.js +2 -0
- package/lib/rules/no-async-promise-executor.js +3 -0
- package/lib/rules/no-await-in-loop.js +4 -0
- package/lib/rules/no-bitwise.js +2 -0
- package/lib/rules/no-buffer-constructor.js +4 -0
- package/lib/rules/no-caller.js +2 -0
- package/lib/rules/no-case-declarations.js +2 -0
- package/lib/rules/no-catch-shadow.js +6 -3
- package/lib/rules/no-class-assign.js +2 -0
- package/lib/rules/no-compare-neg-zero.js +4 -0
- package/lib/rules/no-cond-assign.js +2 -0
- package/lib/rules/no-confusing-arrow.js +2 -0
- package/lib/rules/no-console.js +2 -0
- package/lib/rules/no-const-assign.js +2 -0
- package/lib/rules/no-constant-condition.js +2 -0
- package/lib/rules/no-continue.js +2 -0
- package/lib/rules/no-control-regex.js +4 -2
- package/lib/rules/no-debugger.js +4 -0
- package/lib/rules/no-delete-var.js +2 -0
- package/lib/rules/no-div-regex.js +2 -0
- package/lib/rules/no-dupe-args.js +2 -0
- package/lib/rules/no-dupe-class-members.js +2 -0
- package/lib/rules/no-dupe-keys.js +2 -0
- package/lib/rules/no-duplicate-case.js +2 -0
- package/lib/rules/no-duplicate-imports.js +2 -0
- package/lib/rules/no-else-return.js +2 -0
- package/lib/rules/no-empty-character-class.js +2 -0
- package/lib/rules/no-empty-function.js +2 -0
- package/lib/rules/no-empty-pattern.js +2 -0
- package/lib/rules/no-empty.js +2 -0
- package/lib/rules/no-eq-null.js +2 -0
- package/lib/rules/no-eval.js +2 -0
- package/lib/rules/no-ex-assign.js +2 -0
- package/lib/rules/no-extend-native.js +2 -0
- package/lib/rules/no-extra-bind.js +24 -1
- package/lib/rules/no-extra-boolean-cast.js +2 -1
- package/lib/rules/no-extra-label.js +2 -1
- package/lib/rules/no-extra-parens.js +5 -6
- package/lib/rules/no-extra-semi.js +2 -0
- package/lib/rules/no-fallthrough.js +2 -0
- package/lib/rules/no-floating-decimal.js +2 -1
- package/lib/rules/no-func-assign.js +2 -0
- package/lib/rules/no-global-assign.js +2 -0
- package/lib/rules/no-implicit-coercion.js +3 -0
- package/lib/rules/no-implicit-globals.js +2 -0
- package/lib/rules/no-implied-eval.js +2 -0
- package/lib/rules/no-inline-comments.js +2 -0
- package/lib/rules/no-inner-declarations.js +2 -0
- package/lib/rules/no-invalid-regexp.js +2 -0
- package/lib/rules/no-invalid-this.js +2 -0
- package/lib/rules/no-irregular-whitespace.js +6 -8
- package/lib/rules/no-iterator.js +2 -0
- package/lib/rules/no-label-var.js +2 -0
- package/lib/rules/no-labels.js +2 -0
- package/lib/rules/no-lone-blocks.js +2 -0
- package/lib/rules/no-lonely-if.js +2 -1
- package/lib/rules/no-loop-func.js +2 -0
- package/lib/rules/no-magic-numbers.js +3 -0
- package/lib/rules/no-misleading-character-class.js +4 -0
- package/lib/rules/no-mixed-operators.js +3 -0
- package/lib/rules/no-mixed-requires.js +2 -0
- package/lib/rules/no-mixed-spaces-and-tabs.js +2 -0
- package/lib/rules/no-multi-assign.js +3 -0
- package/lib/rules/no-multi-spaces.js +2 -0
- package/lib/rules/no-multi-str.js +2 -0
- package/lib/rules/no-multiple-empty-lines.js +2 -0
- package/lib/rules/no-native-reassign.js +4 -1
- package/lib/rules/no-negated-condition.js +2 -0
- package/lib/rules/no-negated-in-lhs.js +5 -2
- package/lib/rules/no-nested-ternary.js +2 -0
- package/lib/rules/no-new-func.js +2 -0
- package/lib/rules/no-new-object.js +2 -0
- package/lib/rules/no-new-require.js +2 -0
- package/lib/rules/no-new-symbol.js +2 -0
- package/lib/rules/no-new-wrappers.js +2 -0
- package/lib/rules/no-new.js +2 -0
- package/lib/rules/no-obj-calls.js +2 -0
- package/lib/rules/no-octal-escape.js +2 -0
- package/lib/rules/no-octal.js +2 -0
- package/lib/rules/no-param-reassign.js +2 -0
- package/lib/rules/no-path-concat.js +2 -0
- package/lib/rules/no-plusplus.js +2 -0
- package/lib/rules/no-process-env.js +2 -0
- package/lib/rules/no-process-exit.js +2 -0
- package/lib/rules/no-proto.js +2 -0
- package/lib/rules/no-prototype-builtins.js +2 -0
- package/lib/rules/no-redeclare.js +2 -0
- package/lib/rules/no-regex-spaces.js +2 -1
- package/lib/rules/no-restricted-globals.js +2 -0
- package/lib/rules/no-restricted-imports.js +40 -22
- package/lib/rules/no-restricted-modules.js +2 -0
- package/lib/rules/no-restricted-properties.js +2 -0
- package/lib/rules/no-restricted-syntax.js +2 -0
- package/lib/rules/no-return-assign.js +2 -0
- package/lib/rules/no-return-await.js +4 -0
- package/lib/rules/no-script-url.js +2 -0
- package/lib/rules/no-self-assign.js +2 -0
- package/lib/rules/no-self-compare.js +2 -0
- package/lib/rules/no-sequences.js +2 -0
- package/lib/rules/no-shadow-restricted-names.js +2 -0
- package/lib/rules/no-shadow.js +2 -0
- package/lib/rules/no-spaced-func.js +4 -1
- package/lib/rules/no-sparse-arrays.js +2 -0
- package/lib/rules/no-sync.js +2 -0
- package/lib/rules/no-tabs.js +25 -6
- package/lib/rules/no-template-curly-in-string.js +2 -0
- package/lib/rules/no-ternary.js +2 -0
- package/lib/rules/no-this-before-super.js +2 -0
- package/lib/rules/no-throw-literal.js +2 -0
- package/lib/rules/no-trailing-spaces.js +2 -0
- package/lib/rules/no-undef-init.js +2 -1
- package/lib/rules/no-undef.js +2 -0
- package/lib/rules/no-undefined.js +2 -0
- package/lib/rules/no-underscore-dangle.js +2 -0
- package/lib/rules/no-unexpected-multiline.js +2 -0
- package/lib/rules/no-unmodified-loop-condition.js +2 -0
- package/lib/rules/no-unneeded-ternary.js +2 -0
- package/lib/rules/no-unreachable.js +2 -1
- package/lib/rules/no-unsafe-finally.js +2 -0
- package/lib/rules/no-unsafe-negation.js +3 -0
- package/lib/rules/no-unused-expressions.js +2 -0
- package/lib/rules/no-unused-labels.js +2 -1
- package/lib/rules/no-unused-vars.js +37 -13
- package/lib/rules/no-use-before-define.js +2 -0
- package/lib/rules/no-useless-call.js +2 -0
- package/lib/rules/no-useless-computed-key.js +2 -1
- package/lib/rules/no-useless-concat.js +2 -0
- package/lib/rules/no-useless-constructor.js +2 -0
- package/lib/rules/no-useless-escape.js +2 -0
- package/lib/rules/no-useless-rename.js +4 -0
- package/lib/rules/no-useless-return.js +3 -0
- package/lib/rules/no-var.js +2 -0
- package/lib/rules/no-void.js +2 -0
- package/lib/rules/no-warning-comments.js +2 -0
- package/lib/rules/no-whitespace-before-property.js +2 -0
- package/lib/rules/no-with.js +2 -0
- package/lib/rules/nonblock-statement-body-position.js +4 -0
- package/lib/rules/object-curly-newline.js +4 -0
- package/lib/rules/object-curly-spacing.js +2 -0
- package/lib/rules/object-property-newline.js +3 -2
- package/lib/rules/object-shorthand.js +2 -0
- package/lib/rules/one-var-declaration-per-line.js +2 -0
- package/lib/rules/one-var.js +13 -1
- package/lib/rules/operator-assignment.js +2 -0
- package/lib/rules/operator-linebreak.js +2 -0
- package/lib/rules/padded-blocks.js +2 -0
- package/lib/rules/padding-line-between-statements.js +7 -0
- package/lib/rules/prefer-arrow-callback.js +2 -0
- package/lib/rules/prefer-const.js +116 -11
- package/lib/rules/prefer-destructuring.js +3 -0
- package/lib/rules/prefer-numeric-literals.js +2 -1
- package/lib/rules/prefer-object-spread.js +4 -0
- package/lib/rules/prefer-promise-reject-errors.js +4 -0
- package/lib/rules/prefer-reflect.js +4 -1
- package/lib/rules/prefer-rest-params.js +2 -0
- package/lib/rules/prefer-spread.js +2 -1
- package/lib/rules/prefer-template.js +2 -1
- package/lib/rules/quote-props.js +2 -0
- package/lib/rules/quotes.js +2 -0
- package/lib/rules/radix.js +2 -0
- package/lib/rules/require-atomic-updates.js +91 -30
- package/lib/rules/require-await.js +3 -0
- package/lib/rules/require-jsdoc.js +2 -0
- package/lib/rules/require-unicode-regexp.js +4 -0
- package/lib/rules/require-yield.js +2 -0
- package/lib/rules/rest-spread-spacing.js +4 -0
- package/lib/rules/semi-spacing.js +2 -0
- package/lib/rules/semi-style.js +3 -0
- package/lib/rules/semi.js +2 -0
- package/lib/rules/sort-imports.js +2 -0
- package/lib/rules/sort-keys.js +3 -0
- package/lib/rules/sort-vars.js +2 -0
- package/lib/rules/space-before-blocks.js +46 -35
- package/lib/rules/space-before-function-paren.js +2 -0
- package/lib/rules/space-in-parens.js +2 -0
- package/lib/rules/space-infix-ops.js +18 -25
- package/lib/rules/space-unary-ops.js +2 -0
- package/lib/rules/spaced-comment.js +2 -0
- package/lib/rules/strict.js +2 -0
- package/lib/rules/switch-colon-spacing.js +4 -0
- package/lib/rules/symbol-description.js +2 -0
- package/lib/rules/template-curly-spacing.js +2 -0
- package/lib/rules/template-tag-spacing.js +2 -0
- package/lib/rules/unicode-bom.js +2 -0
- package/lib/rules/use-isnan.js +2 -0
- package/lib/rules/valid-jsdoc.js +2 -0
- package/lib/rules/valid-typeof.js +2 -0
- package/lib/rules/vars-on-top.js +2 -0
- package/lib/rules/wrap-iife.js +2 -0
- package/lib/rules/wrap-regex.js +3 -1
- package/lib/rules/yield-star-spacing.js +2 -0
- package/lib/rules/yoda.js +2 -0
- package/lib/testers/rule-tester.js +2 -2
- package/lib/util/source-code-fixer.js +1 -1
- package/package.json +12 -12
@@ -12,14 +12,18 @@ const astUtils = require("../util/ast-utils");
|
|
12
12
|
|
13
13
|
module.exports = {
|
14
14
|
meta: {
|
15
|
+
type: "problem",
|
16
|
+
|
15
17
|
docs: {
|
16
18
|
description: "disallow assignments that can lead to race conditions due to usage of `await` or `yield`",
|
17
19
|
category: "Possible Errors",
|
18
20
|
recommended: false,
|
19
21
|
url: "https://eslint.org/docs/rules/require-atomic-updates"
|
20
22
|
},
|
23
|
+
|
21
24
|
fixable: null,
|
22
25
|
schema: [],
|
26
|
+
|
23
27
|
messages: {
|
24
28
|
nonAtomicUpdate: "Possible race condition: `{{value}}` might be reassigned based on an outdated value of `{{value}}`."
|
25
29
|
}
|
@@ -119,6 +123,66 @@ module.exports = {
|
|
119
123
|
});
|
120
124
|
}
|
121
125
|
|
126
|
+
const alreadyReportedAssignments = new WeakSet();
|
127
|
+
|
128
|
+
class AssignmentTrackerState {
|
129
|
+
constructor({ openAssignmentsWithoutReads = new Set(), openAssignmentsWithReads = new Set() } = {}) {
|
130
|
+
this.openAssignmentsWithoutReads = openAssignmentsWithoutReads;
|
131
|
+
this.openAssignmentsWithReads = openAssignmentsWithReads;
|
132
|
+
}
|
133
|
+
|
134
|
+
copy() {
|
135
|
+
return new AssignmentTrackerState({
|
136
|
+
openAssignmentsWithoutReads: new Set(this.openAssignmentsWithoutReads),
|
137
|
+
openAssignmentsWithReads: new Set(this.openAssignmentsWithReads)
|
138
|
+
});
|
139
|
+
}
|
140
|
+
|
141
|
+
merge(other) {
|
142
|
+
const initialAssignmentsWithoutReadsCount = this.openAssignmentsWithoutReads.size;
|
143
|
+
const initialAssignmentsWithReadsCount = this.openAssignmentsWithReads.size;
|
144
|
+
|
145
|
+
other.openAssignmentsWithoutReads.forEach(assignment => this.openAssignmentsWithoutReads.add(assignment));
|
146
|
+
other.openAssignmentsWithReads.forEach(assignment => this.openAssignmentsWithReads.add(assignment));
|
147
|
+
|
148
|
+
return this.openAssignmentsWithoutReads.size > initialAssignmentsWithoutReadsCount ||
|
149
|
+
this.openAssignmentsWithReads.size > initialAssignmentsWithReadsCount;
|
150
|
+
}
|
151
|
+
|
152
|
+
enterAssignment(assignmentExpression) {
|
153
|
+
(assignmentExpression.operator === "=" ? this.openAssignmentsWithoutReads : this.openAssignmentsWithReads).add(assignmentExpression);
|
154
|
+
}
|
155
|
+
|
156
|
+
exitAssignment(assignmentExpression) {
|
157
|
+
this.openAssignmentsWithoutReads.delete(assignmentExpression);
|
158
|
+
this.openAssignmentsWithReads.delete(assignmentExpression);
|
159
|
+
}
|
160
|
+
|
161
|
+
exitAwaitOrYield(node, surroundingFunction) {
|
162
|
+
return [...this.openAssignmentsWithReads]
|
163
|
+
.filter(assignment => !isLocalVariableWithoutEscape(assignment.left, surroundingFunction))
|
164
|
+
.forEach(assignment => {
|
165
|
+
if (!alreadyReportedAssignments.has(assignment)) {
|
166
|
+
reportAssignment(assignment);
|
167
|
+
alreadyReportedAssignments.add(assignment);
|
168
|
+
}
|
169
|
+
});
|
170
|
+
}
|
171
|
+
|
172
|
+
exitIdentifierOrMemberExpression(node) {
|
173
|
+
[...this.openAssignmentsWithoutReads]
|
174
|
+
.filter(assignment => (
|
175
|
+
assignment.left !== node &&
|
176
|
+
assignment.left.type === node.type &&
|
177
|
+
astUtils.equalTokens(assignment.left, node, sourceCode)
|
178
|
+
))
|
179
|
+
.forEach(assignment => {
|
180
|
+
this.openAssignmentsWithoutReads.delete(assignment);
|
181
|
+
this.openAssignmentsWithReads.add(assignment);
|
182
|
+
});
|
183
|
+
}
|
184
|
+
}
|
185
|
+
|
122
186
|
/**
|
123
187
|
* If the control flow graph of a function enters an assignment expression, then does the
|
124
188
|
* both of the following steps in order (possibly with other steps in between) before exiting the
|
@@ -135,54 +199,51 @@ module.exports = {
|
|
135
199
|
codePathSegment,
|
136
200
|
surroundingFunction,
|
137
201
|
{
|
138
|
-
|
139
|
-
|
140
|
-
openAssignmentsWithReads = new Set()
|
202
|
+
stateBySegmentStart = new WeakMap(),
|
203
|
+
stateBySegmentEnd = new WeakMap()
|
141
204
|
} = {}
|
142
205
|
) {
|
143
|
-
if (
|
144
|
-
|
145
|
-
// An AssignmentExpression can't contain loops, so it's not necessary to reenter them with new state.
|
146
|
-
return;
|
206
|
+
if (!stateBySegmentStart.has(codePathSegment)) {
|
207
|
+
stateBySegmentStart.set(codePathSegment, new AssignmentTrackerState());
|
147
208
|
}
|
148
209
|
|
210
|
+
const currentState = stateBySegmentStart.get(codePathSegment).copy();
|
211
|
+
|
149
212
|
expressionsByCodePathSegment.get(codePathSegment).forEach(({ entering, node }) => {
|
150
213
|
if (node.type === "AssignmentExpression") {
|
151
214
|
if (entering) {
|
152
|
-
|
215
|
+
currentState.enterAssignment(node);
|
153
216
|
} else {
|
154
|
-
|
155
|
-
openAssignmentsWithReads.delete(node);
|
217
|
+
currentState.exitAssignment(node);
|
156
218
|
}
|
157
219
|
} else if (!entering && (node.type === "AwaitExpression" || node.type === "YieldExpression")) {
|
158
|
-
|
159
|
-
.filter(assignment => !isLocalVariableWithoutEscape(assignment.left, surroundingFunction))
|
160
|
-
.forEach(reportAssignment);
|
161
|
-
|
162
|
-
openAssignmentsWithReads.clear();
|
220
|
+
currentState.exitAwaitOrYield(node, surroundingFunction);
|
163
221
|
} else if (!entering && (node.type === "Identifier" || node.type === "MemberExpression")) {
|
164
|
-
|
165
|
-
.filter(assignment => (
|
166
|
-
assignment.left !== node &&
|
167
|
-
assignment.left.type === node.type &&
|
168
|
-
astUtils.equalTokens(assignment.left, node, sourceCode)
|
169
|
-
))
|
170
|
-
.forEach(assignment => {
|
171
|
-
openAssignmentsWithoutReads.delete(assignment);
|
172
|
-
openAssignmentsWithReads.add(assignment);
|
173
|
-
});
|
222
|
+
currentState.exitIdentifierOrMemberExpression(node);
|
174
223
|
}
|
175
224
|
});
|
176
225
|
|
226
|
+
stateBySegmentEnd.set(codePathSegment, currentState);
|
227
|
+
|
177
228
|
codePathSegment.nextSegments.forEach(nextSegment => {
|
229
|
+
if (stateBySegmentStart.has(nextSegment)) {
|
230
|
+
if (!stateBySegmentStart.get(nextSegment).merge(currentState)) {
|
231
|
+
|
232
|
+
/*
|
233
|
+
* This segment has already been processed with the given set of inputs;
|
234
|
+
* no need to do it again. After no new state is available to process
|
235
|
+
* for any control flow segment in the graph, the analysis reaches a fixpoint and
|
236
|
+
* traversal stops.
|
237
|
+
*/
|
238
|
+
return;
|
239
|
+
}
|
240
|
+
} else {
|
241
|
+
stateBySegmentStart.set(nextSegment, currentState.copy());
|
242
|
+
}
|
178
243
|
findOutdatedReads(
|
179
244
|
nextSegment,
|
180
245
|
surroundingFunction,
|
181
|
-
{
|
182
|
-
seenSegments: new Set(seenSegments).add(codePathSegment),
|
183
|
-
openAssignmentsWithoutReads: new Set(openAssignmentsWithoutReads),
|
184
|
-
openAssignmentsWithReads: new Set(openAssignmentsWithReads)
|
185
|
-
}
|
246
|
+
{ stateBySegmentStart, stateBySegmentEnd }
|
186
247
|
);
|
187
248
|
});
|
188
249
|
}
|
@@ -31,12 +31,15 @@ function capitalizeFirstLetter(text) {
|
|
31
31
|
|
32
32
|
module.exports = {
|
33
33
|
meta: {
|
34
|
+
type: "suggestion",
|
35
|
+
|
34
36
|
docs: {
|
35
37
|
description: "disallow async functions which have no `await` expression",
|
36
38
|
category: "Best Practices",
|
37
39
|
recommended: false,
|
38
40
|
url: "https://eslint.org/docs/rules/require-await"
|
39
41
|
},
|
42
|
+
|
40
43
|
schema: []
|
41
44
|
},
|
42
45
|
|
@@ -22,15 +22,19 @@ const {
|
|
22
22
|
|
23
23
|
module.exports = {
|
24
24
|
meta: {
|
25
|
+
type: "suggestion",
|
26
|
+
|
25
27
|
docs: {
|
26
28
|
description: "enforce the use of `u` flag on RegExp",
|
27
29
|
category: "Best Practices",
|
28
30
|
recommended: false,
|
29
31
|
url: "https://eslint.org/docs/rules/require-unicode-regexp"
|
30
32
|
},
|
33
|
+
|
31
34
|
messages: {
|
32
35
|
requireUFlag: "Use the 'u' flag."
|
33
36
|
},
|
37
|
+
|
34
38
|
schema: []
|
35
39
|
},
|
36
40
|
|
@@ -11,13 +11,17 @@
|
|
11
11
|
|
12
12
|
module.exports = {
|
13
13
|
meta: {
|
14
|
+
type: "layout",
|
15
|
+
|
14
16
|
docs: {
|
15
17
|
description: "enforce spacing between rest and spread operators and their expressions",
|
16
18
|
category: "ECMAScript 6",
|
17
19
|
recommended: false,
|
18
20
|
url: "https://eslint.org/docs/rules/rest-spread-spacing"
|
19
21
|
},
|
22
|
+
|
20
23
|
fixable: "whitespace",
|
24
|
+
|
21
25
|
schema: [
|
22
26
|
{
|
23
27
|
enum: ["always", "never"]
|
package/lib/rules/semi-style.js
CHANGED
@@ -65,12 +65,15 @@ function isLastChild(node) {
|
|
65
65
|
|
66
66
|
module.exports = {
|
67
67
|
meta: {
|
68
|
+
type: "layout",
|
69
|
+
|
68
70
|
docs: {
|
69
71
|
description: "enforce location of semicolons",
|
70
72
|
category: "Stylistic Issues",
|
71
73
|
recommended: false,
|
72
74
|
url: "https://eslint.org/docs/rules/semi-style"
|
73
75
|
},
|
76
|
+
|
74
77
|
schema: [{ enum: ["last", "first"] }],
|
75
78
|
fixable: "whitespace"
|
76
79
|
},
|
package/lib/rules/semi.js
CHANGED
package/lib/rules/sort-keys.js
CHANGED
@@ -73,12 +73,15 @@ const isValidOrders = {
|
|
73
73
|
|
74
74
|
module.exports = {
|
75
75
|
meta: {
|
76
|
+
type: "suggestion",
|
77
|
+
|
76
78
|
docs: {
|
77
79
|
description: "require object keys to be sorted",
|
78
80
|
category: "Stylistic Issues",
|
79
81
|
recommended: false,
|
80
82
|
url: "https://eslint.org/docs/rules/sort-keys"
|
81
83
|
},
|
84
|
+
|
82
85
|
schema: [
|
83
86
|
{
|
84
87
|
enum: ["asc", "desc"]
|
package/lib/rules/sort-vars.js
CHANGED
@@ -13,6 +13,8 @@ const astUtils = require("../util/ast-utils");
|
|
13
13
|
|
14
14
|
module.exports = {
|
15
15
|
meta: {
|
16
|
+
type: "layout",
|
17
|
+
|
16
18
|
docs: {
|
17
19
|
description: "enforce consistent spacing before blocks",
|
18
20
|
category: "Stylistic Issues",
|
@@ -32,13 +34,13 @@ module.exports = {
|
|
32
34
|
type: "object",
|
33
35
|
properties: {
|
34
36
|
keywords: {
|
35
|
-
enum: ["always", "never"]
|
37
|
+
enum: ["always", "never", "off"]
|
36
38
|
},
|
37
39
|
functions: {
|
38
|
-
enum: ["always", "never"]
|
40
|
+
enum: ["always", "never", "off"]
|
39
41
|
},
|
40
42
|
classes: {
|
41
|
-
enum: ["always", "never"]
|
43
|
+
enum: ["always", "never", "off"]
|
42
44
|
}
|
43
45
|
},
|
44
46
|
additionalProperties: false
|
@@ -51,18 +53,27 @@ module.exports = {
|
|
51
53
|
create(context) {
|
52
54
|
const config = context.options[0],
|
53
55
|
sourceCode = context.getSourceCode();
|
54
|
-
let
|
55
|
-
|
56
|
-
|
56
|
+
let alwaysFunctions = true,
|
57
|
+
alwaysKeywords = true,
|
58
|
+
alwaysClasses = true,
|
59
|
+
neverFunctions = false,
|
60
|
+
neverKeywords = false,
|
61
|
+
neverClasses = false;
|
57
62
|
|
58
63
|
if (typeof config === "object") {
|
59
|
-
|
60
|
-
|
61
|
-
|
64
|
+
alwaysFunctions = config.functions === "always";
|
65
|
+
alwaysKeywords = config.keywords === "always";
|
66
|
+
alwaysClasses = config.classes === "always";
|
67
|
+
neverFunctions = config.functions === "never";
|
68
|
+
neverKeywords = config.keywords === "never";
|
69
|
+
neverClasses = config.classes === "never";
|
62
70
|
} else if (config === "never") {
|
63
|
-
|
64
|
-
|
65
|
-
|
71
|
+
alwaysFunctions = false;
|
72
|
+
alwaysKeywords = false;
|
73
|
+
alwaysClasses = false;
|
74
|
+
neverFunctions = true;
|
75
|
+
neverKeywords = true;
|
76
|
+
neverClasses = true;
|
66
77
|
}
|
67
78
|
|
68
79
|
/**
|
@@ -88,35 +99,35 @@ module.exports = {
|
|
88
99
|
const hasSpace = sourceCode.isSpaceBetweenTokens(precedingToken, node);
|
89
100
|
const parent = context.getAncestors().pop();
|
90
101
|
let requireSpace;
|
102
|
+
let requireNoSpace;
|
91
103
|
|
92
104
|
if (parent.type === "FunctionExpression" || parent.type === "FunctionDeclaration") {
|
93
|
-
requireSpace =
|
105
|
+
requireSpace = alwaysFunctions;
|
106
|
+
requireNoSpace = neverFunctions;
|
94
107
|
} else if (node.type === "ClassBody") {
|
95
|
-
requireSpace =
|
108
|
+
requireSpace = alwaysClasses;
|
109
|
+
requireNoSpace = neverClasses;
|
96
110
|
} else {
|
97
|
-
requireSpace =
|
111
|
+
requireSpace = alwaysKeywords;
|
112
|
+
requireNoSpace = neverKeywords;
|
98
113
|
}
|
99
114
|
|
100
|
-
if (requireSpace) {
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
node
|
114
|
-
|
115
|
-
|
116
|
-
return fixer.removeRange([precedingToken.range[1], node.range[0]]);
|
117
|
-
}
|
118
|
-
});
|
119
|
-
}
|
115
|
+
if (requireSpace && !hasSpace) {
|
116
|
+
context.report({
|
117
|
+
node,
|
118
|
+
message: "Missing space before opening brace.",
|
119
|
+
fix(fixer) {
|
120
|
+
return fixer.insertTextBefore(node, " ");
|
121
|
+
}
|
122
|
+
});
|
123
|
+
} else if (requireNoSpace && hasSpace) {
|
124
|
+
context.report({
|
125
|
+
node,
|
126
|
+
message: "Unexpected space before opening brace.",
|
127
|
+
fix(fixer) {
|
128
|
+
return fixer.removeRange([precedingToken.range[1], node.range[0]]);
|
129
|
+
}
|
130
|
+
});
|
120
131
|
}
|
121
132
|
}
|
122
133
|
}
|
@@ -10,6 +10,8 @@
|
|
10
10
|
|
11
11
|
module.exports = {
|
12
12
|
meta: {
|
13
|
+
type: "layout",
|
14
|
+
|
13
15
|
docs: {
|
14
16
|
description: "require spacing around infix operators",
|
15
17
|
category: "Stylistic Issues",
|
@@ -34,37 +36,25 @@ module.exports = {
|
|
34
36
|
|
35
37
|
create(context) {
|
36
38
|
const int32Hint = context.options[0] ? context.options[0].int32Hint === true : false;
|
37
|
-
|
38
|
-
const OPERATORS = [
|
39
|
-
"*", "/", "%", "+", "-", "<<", ">>", ">>>", "<", "<=", ">", ">=", "in",
|
40
|
-
"instanceof", "==", "!=", "===", "!==", "&", "^", "|", "&&", "||", "=",
|
41
|
-
"+=", "-=", "*=", "/=", "%=", "<<=", ">>=", ">>>=", "&=", "^=", "|=",
|
42
|
-
"?", ":", ",", "**"
|
43
|
-
];
|
44
|
-
|
45
39
|
const sourceCode = context.getSourceCode();
|
46
40
|
|
47
41
|
/**
|
48
42
|
* Returns the first token which violates the rule
|
49
43
|
* @param {ASTNode} left - The left node of the main node
|
50
44
|
* @param {ASTNode} right - The right node of the main node
|
45
|
+
* @param {string} op - The operator of the main node
|
51
46
|
* @returns {Object} The violator token or null
|
52
47
|
* @private
|
53
48
|
*/
|
54
|
-
function getFirstNonSpacedToken(left, right) {
|
55
|
-
const
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
(op.type === "Punctuator" || op.type === "Keyword") &&
|
62
|
-
OPERATORS.indexOf(op.value) >= 0 &&
|
63
|
-
(tokens[i - 1].range[1] >= op.range[0] || op.range[1] >= tokens[i + 1].range[0])
|
64
|
-
) {
|
65
|
-
return op;
|
66
|
-
}
|
49
|
+
function getFirstNonSpacedToken(left, right, op) {
|
50
|
+
const operator = sourceCode.getFirstTokenBetween(left, right, token => token.value === op);
|
51
|
+
const prev = sourceCode.getTokenBefore(operator);
|
52
|
+
const next = sourceCode.getTokenAfter(operator);
|
53
|
+
|
54
|
+
if (!sourceCode.isSpaceBetweenTokens(prev, operator) || !sourceCode.isSpaceBetweenTokens(operator, next)) {
|
55
|
+
return operator;
|
67
56
|
}
|
57
|
+
|
68
58
|
return null;
|
69
59
|
}
|
70
60
|
|
@@ -110,7 +100,10 @@ module.exports = {
|
|
110
100
|
const leftNode = (node.left.typeAnnotation) ? node.left.typeAnnotation : node.left;
|
111
101
|
const rightNode = node.right;
|
112
102
|
|
113
|
-
|
103
|
+
// search for = in AssignmentPattern nodes
|
104
|
+
const operator = node.operator || "=";
|
105
|
+
|
106
|
+
const nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode, operator);
|
114
107
|
|
115
108
|
if (nonSpacedNode) {
|
116
109
|
if (!(int32Hint && sourceCode.getText(node).endsWith("|0"))) {
|
@@ -126,8 +119,8 @@ module.exports = {
|
|
126
119
|
* @private
|
127
120
|
*/
|
128
121
|
function checkConditional(node) {
|
129
|
-
const nonSpacedConsequesntNode = getFirstNonSpacedToken(node.test, node.consequent);
|
130
|
-
const nonSpacedAlternateNode = getFirstNonSpacedToken(node.consequent, node.alternate);
|
122
|
+
const nonSpacedConsequesntNode = getFirstNonSpacedToken(node.test, node.consequent, "?");
|
123
|
+
const nonSpacedAlternateNode = getFirstNonSpacedToken(node.consequent, node.alternate, ":");
|
131
124
|
|
132
125
|
if (nonSpacedConsequesntNode) {
|
133
126
|
report(node, nonSpacedConsequesntNode);
|
@@ -147,7 +140,7 @@ module.exports = {
|
|
147
140
|
const rightNode = node.init;
|
148
141
|
|
149
142
|
if (rightNode) {
|
150
|
-
const nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode);
|
143
|
+
const nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode, "=");
|
151
144
|
|
152
145
|
if (nonSpacedNode) {
|
153
146
|
report(node, nonSpacedNode);
|
package/lib/rules/strict.js
CHANGED
@@ -17,12 +17,15 @@ const astUtils = require("../util/ast-utils");
|
|
17
17
|
|
18
18
|
module.exports = {
|
19
19
|
meta: {
|
20
|
+
type: "layout",
|
21
|
+
|
20
22
|
docs: {
|
21
23
|
description: "enforce spacing around colons of switch statements",
|
22
24
|
category: "Stylistic Issues",
|
23
25
|
recommended: false,
|
24
26
|
url: "https://eslint.org/docs/rules/switch-colon-spacing"
|
25
27
|
},
|
28
|
+
|
26
29
|
schema: [
|
27
30
|
{
|
28
31
|
type: "object",
|
@@ -33,6 +36,7 @@ module.exports = {
|
|
33
36
|
additionalProperties: false
|
34
37
|
}
|
35
38
|
],
|
39
|
+
|
36
40
|
fixable: "whitespace"
|
37
41
|
},
|
38
42
|
|
package/lib/rules/unicode-bom.js
CHANGED
package/lib/rules/use-isnan.js
CHANGED