eslint 7.0.0-alpha.1 → 7.0.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 +329 -0
- package/README.md +7 -7
- package/bin/eslint.js +115 -77
- package/conf/category-list.json +2 -3
- package/conf/environments.js +2 -1
- package/conf/eslint-recommended.js +3 -0
- package/lib/api.js +2 -0
- package/lib/cli-engine/cascading-config-array-factory.js +16 -2
- package/lib/cli-engine/cli-engine.js +53 -47
- package/lib/cli-engine/config-array/config-array.js +30 -1
- package/lib/cli-engine/config-array/ignore-pattern.js +7 -1
- package/lib/cli-engine/config-array-factory.js +244 -235
- package/lib/cli.js +181 -95
- package/lib/eslint/eslint.js +656 -0
- package/lib/eslint/index.js +7 -0
- package/lib/init/autoconfig.js +4 -4
- package/lib/init/config-file.js +2 -2
- package/lib/init/config-initializer.js +2 -4
- package/lib/init/source-code-utils.js +2 -2
- package/lib/linter/node-event-generator.js +2 -2
- package/lib/options.js +0 -1
- package/lib/rule-tester/rule-tester.js +178 -23
- package/lib/rules/accessor-pairs.js +2 -2
- package/lib/rules/array-callback-return.js +3 -18
- package/lib/rules/arrow-body-style.js +26 -15
- package/lib/rules/callback-return.js +4 -0
- package/lib/rules/camelcase.js +38 -1
- package/lib/rules/comma-style.js +3 -8
- package/lib/rules/computed-property-spacing.js +2 -2
- package/lib/rules/curly.js +124 -40
- package/lib/rules/func-call-spacing.js +4 -3
- package/lib/rules/func-names.js +31 -24
- package/lib/rules/getter-return.js +2 -12
- package/lib/rules/global-require.js +4 -0
- package/lib/rules/handle-callback-err.js +4 -0
- package/lib/rules/id-blacklist.js +140 -64
- package/lib/rules/id-length.js +14 -4
- package/lib/rules/indent-legacy.js +0 -16
- package/lib/rules/key-spacing.js +1 -1
- package/lib/rules/new-cap.js +1 -1
- package/lib/rules/newline-per-chained-call.js +6 -3
- package/lib/rules/no-alert.js +5 -3
- package/lib/rules/no-buffer-constructor.js +4 -0
- package/lib/rules/no-dupe-else-if.js +1 -1
- package/lib/rules/no-empty-function.js +4 -2
- package/lib/rules/no-eval.js +3 -2
- package/lib/rules/no-extra-bind.js +1 -1
- package/lib/rules/no-extra-boolean-cast.js +168 -38
- package/lib/rules/no-extra-parens.js +9 -5
- package/lib/rules/no-implied-eval.js +83 -101
- package/lib/rules/no-import-assign.js +1 -1
- package/lib/rules/no-inner-declarations.js +31 -39
- package/lib/rules/no-lone-blocks.js +1 -1
- package/lib/rules/no-magic-numbers.js +72 -37
- package/lib/rules/no-mixed-requires.js +4 -0
- package/lib/rules/no-new-object.js +15 -3
- package/lib/rules/no-new-require.js +4 -0
- package/lib/rules/no-new-wrappers.js +1 -1
- package/lib/rules/no-obj-calls.js +24 -5
- package/lib/rules/no-path-concat.js +4 -0
- package/lib/rules/no-plusplus.js +39 -3
- package/lib/rules/no-process-env.js +4 -0
- package/lib/rules/no-process-exit.js +4 -0
- package/lib/rules/no-prototype-builtins.js +1 -1
- package/lib/rules/no-restricted-modules.js +52 -18
- package/lib/rules/no-setter-return.js +1 -1
- package/lib/rules/no-sync.js +4 -0
- package/lib/rules/no-underscore-dangle.js +1 -1
- package/lib/rules/no-unexpected-multiline.js +22 -12
- package/lib/rules/no-useless-concat.js +1 -1
- package/lib/rules/operator-assignment.js +3 -3
- package/lib/rules/operator-linebreak.js +4 -16
- package/lib/rules/prefer-numeric-literals.js +3 -3
- package/lib/rules/prefer-object-spread.js +2 -2
- package/lib/rules/require-await.js +1 -1
- package/lib/rules/space-before-function-paren.js +5 -2
- package/lib/rules/template-curly-spacing.js +59 -42
- package/lib/rules/utils/ast-utils.js +65 -4
- package/lib/rules/wrap-iife.js +54 -17
- package/lib/rules/yoda.js +101 -51
- package/lib/shared/relative-module-resolver.js +1 -0
- package/lib/shared/types.js +9 -2
- package/messages/plugin-conflict.txt +7 -0
- package/package.json +27 -26
package/lib/rules/no-plusplus.js
CHANGED
@@ -6,6 +6,41 @@
|
|
6
6
|
|
7
7
|
"use strict";
|
8
8
|
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
// Helpers
|
11
|
+
//------------------------------------------------------------------------------
|
12
|
+
|
13
|
+
/**
|
14
|
+
* Determines whether the given node is the update node of a `ForStatement`.
|
15
|
+
* @param {ASTNode} node The node to check.
|
16
|
+
* @returns {boolean} `true` if the node is `ForStatement` update.
|
17
|
+
*/
|
18
|
+
function isForStatementUpdate(node) {
|
19
|
+
const parent = node.parent;
|
20
|
+
|
21
|
+
return parent.type === "ForStatement" && parent.update === node;
|
22
|
+
}
|
23
|
+
|
24
|
+
/**
|
25
|
+
* Determines whether the given node is considered to be a for loop "afterthought" by the logic of this rule.
|
26
|
+
* In particular, it returns `true` if the given node is either:
|
27
|
+
* - The update node of a `ForStatement`: for (;; i++) {}
|
28
|
+
* - An operand of a sequence expression that is the update node: for (;; foo(), i++) {}
|
29
|
+
* - An operand of a sequence expression that is child of another sequence expression, etc.,
|
30
|
+
* up to the sequence expression that is the update node: for (;; foo(), (bar(), (baz(), i++))) {}
|
31
|
+
* @param {ASTNode} node The node to check.
|
32
|
+
* @returns {boolean} `true` if the node is a for loop afterthought.
|
33
|
+
*/
|
34
|
+
function isForLoopAfterthought(node) {
|
35
|
+
const parent = node.parent;
|
36
|
+
|
37
|
+
if (parent.type === "SequenceExpression") {
|
38
|
+
return isForLoopAfterthought(parent);
|
39
|
+
}
|
40
|
+
|
41
|
+
return isForStatementUpdate(node);
|
42
|
+
}
|
43
|
+
|
9
44
|
//------------------------------------------------------------------------------
|
10
45
|
// Rule Definition
|
11
46
|
//------------------------------------------------------------------------------
|
@@ -42,18 +77,19 @@ module.exports = {
|
|
42
77
|
create(context) {
|
43
78
|
|
44
79
|
const config = context.options[0];
|
45
|
-
let
|
80
|
+
let allowForLoopAfterthoughts = false;
|
46
81
|
|
47
82
|
if (typeof config === "object") {
|
48
|
-
|
83
|
+
allowForLoopAfterthoughts = config.allowForLoopAfterthoughts === true;
|
49
84
|
}
|
50
85
|
|
51
86
|
return {
|
52
87
|
|
53
88
|
UpdateExpression(node) {
|
54
|
-
if (
|
89
|
+
if (allowForLoopAfterthoughts && isForLoopAfterthought(node)) {
|
55
90
|
return;
|
56
91
|
}
|
92
|
+
|
57
93
|
context.report({
|
58
94
|
node,
|
59
95
|
messageId: "unexpectedUnaryOp",
|
@@ -40,6 +40,10 @@ const arrayOfStringsOrObjects = {
|
|
40
40
|
|
41
41
|
module.exports = {
|
42
42
|
meta: {
|
43
|
+
deprecated: true,
|
44
|
+
|
45
|
+
replacedBy: ["node/no-restricted-require"],
|
46
|
+
|
43
47
|
type: "suggestion",
|
44
48
|
|
45
49
|
docs: {
|
@@ -106,10 +110,19 @@ module.exports = {
|
|
106
110
|
* @param {ASTNode} node The node to check.
|
107
111
|
* @returns {boolean} If the node is a string literal.
|
108
112
|
*/
|
109
|
-
function
|
113
|
+
function isStringLiteral(node) {
|
110
114
|
return node && node.type === "Literal" && typeof node.value === "string";
|
111
115
|
}
|
112
116
|
|
117
|
+
/**
|
118
|
+
* Function to check if a node is a static string template literal.
|
119
|
+
* @param {ASTNode} node The node to check.
|
120
|
+
* @returns {boolean} If the node is a string template literal.
|
121
|
+
*/
|
122
|
+
function isStaticTemplateLiteral(node) {
|
123
|
+
return node && node.type === "TemplateLiteral" && node.expressions.length === 0;
|
124
|
+
}
|
125
|
+
|
113
126
|
/**
|
114
127
|
* Function to check if a node is a require call.
|
115
128
|
* @param {ASTNode} node The node to check.
|
@@ -119,14 +132,31 @@ module.exports = {
|
|
119
132
|
return node.callee.type === "Identifier" && node.callee.name === "require";
|
120
133
|
}
|
121
134
|
|
135
|
+
/**
|
136
|
+
* Extract string from Literal or TemplateLiteral node
|
137
|
+
* @param {ASTNode} node The node to extract from
|
138
|
+
* @returns {string|null} Extracted string or null if node doesn't represent a string
|
139
|
+
*/
|
140
|
+
function getFirstArgumentString(node) {
|
141
|
+
if (isStringLiteral(node)) {
|
142
|
+
return node.value.trim();
|
143
|
+
}
|
144
|
+
|
145
|
+
if (isStaticTemplateLiteral(node)) {
|
146
|
+
return node.quasis[0].value.cooked.trim();
|
147
|
+
}
|
148
|
+
|
149
|
+
return null;
|
150
|
+
}
|
151
|
+
|
122
152
|
/**
|
123
153
|
* Report a restricted path.
|
124
154
|
* @param {node} node representing the restricted path reference
|
155
|
+
* @param {string} name restricted path
|
125
156
|
* @returns {void}
|
126
157
|
* @private
|
127
158
|
*/
|
128
|
-
function reportPath(node) {
|
129
|
-
const name = node.arguments[0].value.trim();
|
159
|
+
function reportPath(node, name) {
|
130
160
|
const customMessage = restrictedPathMessages[name];
|
131
161
|
const messageId = customMessage
|
132
162
|
? "customMessage"
|
@@ -156,21 +186,25 @@ module.exports = {
|
|
156
186
|
CallExpression(node) {
|
157
187
|
if (isRequireCall(node)) {
|
158
188
|
|
159
|
-
// node has arguments
|
160
|
-
if (node.arguments.length
|
161
|
-
const name = node.arguments[0]
|
162
|
-
|
163
|
-
//
|
164
|
-
if (
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
|
171
|
-
|
172
|
-
|
173
|
-
|
189
|
+
// node has arguments
|
190
|
+
if (node.arguments.length) {
|
191
|
+
const name = getFirstArgumentString(node.arguments[0]);
|
192
|
+
|
193
|
+
// if first argument is a string literal or a static string template literal
|
194
|
+
if (name) {
|
195
|
+
|
196
|
+
// check if argument value is in restricted modules array
|
197
|
+
if (isRestrictedPath(name)) {
|
198
|
+
reportPath(node, name);
|
199
|
+
}
|
200
|
+
|
201
|
+
if (restrictedPatterns.length > 0 && ig.ignores(name)) {
|
202
|
+
context.report({
|
203
|
+
node,
|
204
|
+
messageId: "patternMessage",
|
205
|
+
data: { name }
|
206
|
+
});
|
207
|
+
}
|
174
208
|
}
|
175
209
|
}
|
176
210
|
}
|
package/lib/rules/no-sync.js
CHANGED
@@ -205,7 +205,7 @@ module.exports = {
|
|
205
205
|
const identifier = node.key.name;
|
206
206
|
const isMethod = node.type === "MethodDefinition" || node.type === "Property" && node.method;
|
207
207
|
|
208
|
-
if (typeof identifier !== "undefined" && enforceInMethodNames && isMethod && hasTrailingUnderscore(identifier)) {
|
208
|
+
if (typeof identifier !== "undefined" && enforceInMethodNames && isMethod && hasTrailingUnderscore(identifier) && !isAllowed(identifier)) {
|
209
209
|
context.report({
|
210
210
|
node,
|
211
211
|
messageId: "unexpectedUnderscore",
|
@@ -53,7 +53,11 @@ module.exports = {
|
|
53
53
|
const nodeExpressionEnd = sourceCode.getTokenBefore(openParen);
|
54
54
|
|
55
55
|
if (openParen.loc.start.line !== nodeExpressionEnd.loc.end.line) {
|
56
|
-
context.report({
|
56
|
+
context.report({
|
57
|
+
node,
|
58
|
+
loc: openParen.loc,
|
59
|
+
messageId
|
60
|
+
});
|
57
61
|
}
|
58
62
|
}
|
59
63
|
|
@@ -71,18 +75,24 @@ module.exports = {
|
|
71
75
|
},
|
72
76
|
|
73
77
|
TaggedTemplateExpression(node) {
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
78
|
+
const { quasi } = node;
|
79
|
+
|
80
|
+
// handles common tags, parenthesized tags, and typescript's generic type arguments
|
81
|
+
const tokenBefore = sourceCode.getTokenBefore(quasi);
|
82
|
+
|
83
|
+
if (tokenBefore.loc.end.line !== quasi.loc.start.line) {
|
84
|
+
context.report({
|
85
|
+
node,
|
86
|
+
loc: {
|
87
|
+
start: quasi.loc.start,
|
88
|
+
end: {
|
89
|
+
line: quasi.loc.start.line,
|
90
|
+
column: quasi.loc.start.column + 1
|
91
|
+
}
|
92
|
+
},
|
93
|
+
messageId: "taggedTemplate"
|
94
|
+
});
|
83
95
|
}
|
84
|
-
|
85
|
-
context.report({ node, loc: node.loc.start, messageId: "taggedTemplate" });
|
86
96
|
},
|
87
97
|
|
88
98
|
CallExpression(node) {
|
@@ -214,12 +214,12 @@ module.exports = {
|
|
214
214
|
) {
|
215
215
|
rightText = `${sourceCode.text.slice(operatorToken.range[1], node.right.range[0])}(${sourceCode.getText(node.right)})`;
|
216
216
|
} else {
|
217
|
-
const
|
217
|
+
const tokenAfterOperator = sourceCode.getTokenAfter(operatorToken, { includeComments: true });
|
218
218
|
let rightTextPrefix = "";
|
219
219
|
|
220
220
|
if (
|
221
|
-
operatorToken.range[1] ===
|
222
|
-
!astUtils.canTokensBeAdjacent({ type: "Punctuator", value: newOperator },
|
221
|
+
operatorToken.range[1] === tokenAfterOperator.range[0] &&
|
222
|
+
!astUtils.canTokensBeAdjacent({ type: "Punctuator", value: newOperator }, tokenAfterOperator)
|
223
223
|
) {
|
224
224
|
rightTextPrefix = " "; // foo+=+bar -> foo= foo+ +bar
|
225
225
|
}
|
@@ -172,10 +172,7 @@ module.exports = {
|
|
172
172
|
// lone operator
|
173
173
|
context.report({
|
174
174
|
node,
|
175
|
-
loc:
|
176
|
-
line: operatorToken.loc.end.line,
|
177
|
-
column: operatorToken.loc.end.column
|
178
|
-
},
|
175
|
+
loc: operatorToken.loc,
|
179
176
|
messageId: "badLinebreak",
|
180
177
|
data: {
|
181
178
|
operator
|
@@ -187,10 +184,7 @@ module.exports = {
|
|
187
184
|
|
188
185
|
context.report({
|
189
186
|
node,
|
190
|
-
loc:
|
191
|
-
line: operatorToken.loc.end.line,
|
192
|
-
column: operatorToken.loc.end.column
|
193
|
-
},
|
187
|
+
loc: operatorToken.loc,
|
194
188
|
messageId: "operatorAtBeginning",
|
195
189
|
data: {
|
196
190
|
operator
|
@@ -202,10 +196,7 @@ module.exports = {
|
|
202
196
|
|
203
197
|
context.report({
|
204
198
|
node,
|
205
|
-
loc:
|
206
|
-
line: operatorToken.loc.end.line,
|
207
|
-
column: operatorToken.loc.end.column
|
208
|
-
},
|
199
|
+
loc: operatorToken.loc,
|
209
200
|
messageId: "operatorAtEnd",
|
210
201
|
data: {
|
211
202
|
operator
|
@@ -217,10 +208,7 @@ module.exports = {
|
|
217
208
|
|
218
209
|
context.report({
|
219
210
|
node,
|
220
|
-
loc:
|
221
|
-
line: operatorToken.loc.end.line,
|
222
|
-
column: operatorToken.loc.end.column
|
223
|
-
},
|
211
|
+
loc: operatorToken.loc,
|
224
212
|
messageId: "noLinebreak",
|
225
213
|
data: {
|
226
214
|
operator
|
@@ -79,13 +79,13 @@ module.exports = {
|
|
79
79
|
|
80
80
|
"CallExpression[arguments.length=2]"(node) {
|
81
81
|
const [strNode, radixNode] = node.arguments,
|
82
|
-
str = strNode
|
82
|
+
str = astUtils.getStaticStringValue(strNode),
|
83
83
|
radix = radixNode.value;
|
84
84
|
|
85
85
|
if (
|
86
|
-
|
86
|
+
str !== null &&
|
87
|
+
astUtils.isStringLiteral(strNode) &&
|
87
88
|
radixNode.type === "Literal" &&
|
88
|
-
typeof str === "string" &&
|
89
89
|
typeof radix === "number" &&
|
90
90
|
radixMap.has(radix) &&
|
91
91
|
isParseInt(node.callee)
|
@@ -181,8 +181,8 @@ function defineFixer(node, sourceCode) {
|
|
181
181
|
const leftParen = sourceCode.getTokenAfter(node.callee, isOpeningParenToken);
|
182
182
|
const rightParen = sourceCode.getLastToken(node);
|
183
183
|
|
184
|
-
// Remove the callee `Object.assign
|
185
|
-
yield fixer.
|
184
|
+
// Remove everything before the opening paren: callee `Object.assign`, type arguments, and whitespace between the callee and the paren.
|
185
|
+
yield fixer.removeRange([node.range[0], leftParen.range[0]]);
|
186
186
|
|
187
187
|
// Replace the parens of argument list to braces.
|
188
188
|
if (needsParens(node, sourceCode)) {
|
@@ -68,7 +68,7 @@ module.exports = {
|
|
68
68
|
* @returns {void}
|
69
69
|
*/
|
70
70
|
function exitFunction(node) {
|
71
|
-
if (node.async && !scopeInfo.hasAwait && !astUtils.isEmptyFunction(node)) {
|
71
|
+
if (!node.generator && node.async && !scopeInfo.hasAwait && !astUtils.isEmptyFunction(node)) {
|
72
72
|
context.report({
|
73
73
|
node,
|
74
74
|
loc: astUtils.getFunctionHeadLoc(node, sourceCode),
|
@@ -127,7 +127,10 @@ module.exports = {
|
|
127
127
|
if (hasSpacing && functionConfig === "never") {
|
128
128
|
context.report({
|
129
129
|
node,
|
130
|
-
loc:
|
130
|
+
loc: {
|
131
|
+
start: leftToken.loc.end,
|
132
|
+
end: rightToken.loc.start
|
133
|
+
},
|
131
134
|
messageId: "unexpectedSpace",
|
132
135
|
fix(fixer) {
|
133
136
|
const comments = sourceCode.getCommentsBefore(rightToken);
|
@@ -145,7 +148,7 @@ module.exports = {
|
|
145
148
|
} else if (!hasSpacing && functionConfig === "always") {
|
146
149
|
context.report({
|
147
150
|
node,
|
148
|
-
loc:
|
151
|
+
loc: rightToken.loc,
|
149
152
|
messageId: "missingSpace",
|
150
153
|
fix: fixer => fixer.insertTextAfter(leftToken, " ")
|
151
154
|
});
|
@@ -11,13 +11,6 @@
|
|
11
11
|
|
12
12
|
const astUtils = require("./utils/ast-utils");
|
13
13
|
|
14
|
-
//------------------------------------------------------------------------------
|
15
|
-
// Helpers
|
16
|
-
//------------------------------------------------------------------------------
|
17
|
-
|
18
|
-
const OPEN_PAREN = /\$\{$/u;
|
19
|
-
const CLOSE_PAREN = /^\}/u;
|
20
|
-
|
21
14
|
//------------------------------------------------------------------------------
|
22
15
|
// Rule Definition
|
23
16
|
//------------------------------------------------------------------------------
|
@@ -49,7 +42,6 @@ module.exports = {
|
|
49
42
|
create(context) {
|
50
43
|
const sourceCode = context.getSourceCode();
|
51
44
|
const always = context.options[0] === "always";
|
52
|
-
const prefix = always ? "expected" : "unexpected";
|
53
45
|
|
54
46
|
/**
|
55
47
|
* Checks spacing before `}` of a given token.
|
@@ -57,25 +49,39 @@ module.exports = {
|
|
57
49
|
* @returns {void}
|
58
50
|
*/
|
59
51
|
function checkSpacingBefore(token) {
|
60
|
-
|
52
|
+
if (!token.value.startsWith("}")) {
|
53
|
+
return; // starts with a backtick, this is the first template element in the template literal
|
54
|
+
}
|
55
|
+
|
56
|
+
const prevToken = sourceCode.getTokenBefore(token, { includeComments: true }),
|
57
|
+
hasSpace = sourceCode.isSpaceBetween(prevToken, token);
|
58
|
+
|
59
|
+
if (!astUtils.isTokenOnSameLine(prevToken, token)) {
|
60
|
+
return;
|
61
|
+
}
|
61
62
|
|
62
|
-
if (
|
63
|
-
CLOSE_PAREN.test(token.value) &&
|
64
|
-
astUtils.isTokenOnSameLine(prevToken, token) &&
|
65
|
-
sourceCode.isSpaceBetweenTokens(prevToken, token) !== always
|
66
|
-
) {
|
63
|
+
if (always && !hasSpace) {
|
67
64
|
context.report({
|
68
|
-
loc:
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
65
|
+
loc: {
|
66
|
+
start: token.loc.start,
|
67
|
+
end: {
|
68
|
+
line: token.loc.start.line,
|
69
|
+
column: token.loc.start.column + 1
|
73
70
|
}
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
71
|
+
},
|
72
|
+
messageId: "expectedBefore",
|
73
|
+
fix: fixer => fixer.insertTextBefore(token, " ")
|
74
|
+
});
|
75
|
+
}
|
76
|
+
|
77
|
+
if (!always && hasSpace) {
|
78
|
+
context.report({
|
79
|
+
loc: {
|
80
|
+
start: prevToken.loc.end,
|
81
|
+
end: token.loc.start
|
82
|
+
},
|
83
|
+
messageId: "unexpectedBefore",
|
84
|
+
fix: fixer => fixer.removeRange([prevToken.range[1], token.range[0]])
|
79
85
|
});
|
80
86
|
}
|
81
87
|
}
|
@@ -86,28 +92,39 @@ module.exports = {
|
|
86
92
|
* @returns {void}
|
87
93
|
*/
|
88
94
|
function checkSpacingAfter(token) {
|
89
|
-
|
95
|
+
if (!token.value.endsWith("${")) {
|
96
|
+
return; // ends with a backtick, this is the last template element in the template literal
|
97
|
+
}
|
98
|
+
|
99
|
+
const nextToken = sourceCode.getTokenAfter(token, { includeComments: true }),
|
100
|
+
hasSpace = sourceCode.isSpaceBetween(token, nextToken);
|
90
101
|
|
91
|
-
if (nextToken
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
) {
|
102
|
+
if (!astUtils.isTokenOnSameLine(token, nextToken)) {
|
103
|
+
return;
|
104
|
+
}
|
105
|
+
|
106
|
+
if (always && !hasSpace) {
|
96
107
|
context.report({
|
97
108
|
loc: {
|
98
|
-
|
99
|
-
|
109
|
+
start: {
|
110
|
+
line: token.loc.end.line,
|
111
|
+
column: token.loc.end.column - 2
|
112
|
+
},
|
113
|
+
end: token.loc.end
|
100
114
|
},
|
101
|
-
messageId:
|
102
|
-
fix(
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
109
|
-
|
110
|
-
|
115
|
+
messageId: "expectedAfter",
|
116
|
+
fix: fixer => fixer.insertTextAfter(token, " ")
|
117
|
+
});
|
118
|
+
}
|
119
|
+
|
120
|
+
if (!always && hasSpace) {
|
121
|
+
context.report({
|
122
|
+
loc: {
|
123
|
+
start: token.loc.end,
|
124
|
+
end: nextToken.loc.start
|
125
|
+
},
|
126
|
+
messageId: "unexpectedAfter",
|
127
|
+
fix: fixer => fixer.removeRange([token.range[1], nextToken.range[0]])
|
111
128
|
});
|
112
129
|
}
|
113
130
|
}
|
@@ -1357,17 +1357,65 @@ module.exports = {
|
|
1357
1357
|
* next to each other, behavior is undefined (although it should return `true` in most cases).
|
1358
1358
|
*/
|
1359
1359
|
canTokensBeAdjacent(leftValue, rightValue) {
|
1360
|
+
const espreeOptions = {
|
1361
|
+
ecmaVersion: espree.latestEcmaVersion,
|
1362
|
+
comment: true,
|
1363
|
+
range: true
|
1364
|
+
};
|
1365
|
+
|
1360
1366
|
let leftToken;
|
1361
1367
|
|
1362
1368
|
if (typeof leftValue === "string") {
|
1363
|
-
|
1369
|
+
let tokens;
|
1370
|
+
|
1371
|
+
try {
|
1372
|
+
tokens = espree.tokenize(leftValue, espreeOptions);
|
1373
|
+
} catch (e) {
|
1374
|
+
return false;
|
1375
|
+
}
|
1376
|
+
|
1377
|
+
const comments = tokens.comments;
|
1364
1378
|
|
1365
|
-
leftToken =
|
1379
|
+
leftToken = tokens[tokens.length - 1];
|
1380
|
+
if (comments.length) {
|
1381
|
+
const lastComment = comments[comments.length - 1];
|
1382
|
+
|
1383
|
+
if (lastComment.range[0] > leftToken.range[0]) {
|
1384
|
+
leftToken = lastComment;
|
1385
|
+
}
|
1386
|
+
}
|
1366
1387
|
} else {
|
1367
1388
|
leftToken = leftValue;
|
1368
1389
|
}
|
1369
1390
|
|
1370
|
-
|
1391
|
+
if (leftToken.type === "Shebang") {
|
1392
|
+
return false;
|
1393
|
+
}
|
1394
|
+
|
1395
|
+
let rightToken;
|
1396
|
+
|
1397
|
+
if (typeof rightValue === "string") {
|
1398
|
+
let tokens;
|
1399
|
+
|
1400
|
+
try {
|
1401
|
+
tokens = espree.tokenize(rightValue, espreeOptions);
|
1402
|
+
} catch (e) {
|
1403
|
+
return false;
|
1404
|
+
}
|
1405
|
+
|
1406
|
+
const comments = tokens.comments;
|
1407
|
+
|
1408
|
+
rightToken = tokens[0];
|
1409
|
+
if (comments.length) {
|
1410
|
+
const firstComment = comments[0];
|
1411
|
+
|
1412
|
+
if (firstComment.range[0] < rightToken.range[0]) {
|
1413
|
+
rightToken = firstComment;
|
1414
|
+
}
|
1415
|
+
}
|
1416
|
+
} else {
|
1417
|
+
rightToken = rightValue;
|
1418
|
+
}
|
1371
1419
|
|
1372
1420
|
if (leftToken.type === "Punctuator" || rightToken.type === "Punctuator") {
|
1373
1421
|
if (leftToken.type === "Punctuator" && rightToken.type === "Punctuator") {
|
@@ -1379,6 +1427,9 @@ module.exports = {
|
|
1379
1427
|
MINUS_TOKENS.has(leftToken.value) && MINUS_TOKENS.has(rightToken.value)
|
1380
1428
|
);
|
1381
1429
|
}
|
1430
|
+
if (leftToken.type === "Punctuator" && leftToken.value === "/") {
|
1431
|
+
return !["Block", "Line", "RegularExpression"].includes(rightToken.type);
|
1432
|
+
}
|
1382
1433
|
return true;
|
1383
1434
|
}
|
1384
1435
|
|
@@ -1393,6 +1444,10 @@ module.exports = {
|
|
1393
1444
|
return true;
|
1394
1445
|
}
|
1395
1446
|
|
1447
|
+
if (leftToken.type === "Block" || rightToken.type === "Block" || rightToken.type === "Line") {
|
1448
|
+
return true;
|
1449
|
+
}
|
1450
|
+
|
1396
1451
|
return false;
|
1397
1452
|
},
|
1398
1453
|
|
@@ -1413,11 +1468,17 @@ module.exports = {
|
|
1413
1468
|
const match = namePattern.exec(comment.value);
|
1414
1469
|
|
1415
1470
|
// Convert the index to loc.
|
1416
|
-
|
1471
|
+
const start = sourceCode.getLocFromIndex(
|
1417
1472
|
comment.range[0] +
|
1418
1473
|
"/*".length +
|
1419
1474
|
(match ? match.index + 1 : 0)
|
1420
1475
|
);
|
1476
|
+
const end = {
|
1477
|
+
line: start.line,
|
1478
|
+
column: start.column + (match ? name.length : 1)
|
1479
|
+
};
|
1480
|
+
|
1481
|
+
return { start, end };
|
1421
1482
|
},
|
1422
1483
|
|
1423
1484
|
/**
|