eslint 3.16.1 → 3.19.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 +103 -0
- package/README.md +1 -0
- package/conf/eslint-recommended.js +2 -0
- package/lib/ast-utils.js +3 -67
- package/lib/code-path-analysis/code-path-analyzer.js +2 -7
- package/lib/code-path-analysis/debug-helpers.js +17 -16
- package/lib/config/config-file.js +68 -38
- package/lib/config/config-rule.js +14 -10
- package/lib/config/plugins.js +19 -8
- package/lib/eslint.js +11 -10
- package/lib/formatters/codeframe.js +4 -9
- package/lib/formatters/stylish.js +5 -4
- package/lib/ignored-paths.js +6 -0
- package/lib/internal-rules/internal-no-invalid-meta.js +2 -40
- package/lib/rules/array-callback-return.js +15 -5
- package/lib/rules/arrow-body-style.js +2 -2
- package/lib/rules/arrow-parens.js +9 -3
- package/lib/rules/capitalized-comments.js +2 -1
- package/lib/rules/comma-dangle.js +3 -2
- package/lib/rules/comma-spacing.js +4 -14
- package/lib/rules/comma-style.js +8 -14
- package/lib/rules/complexity.js +14 -8
- package/lib/rules/consistent-return.js +17 -10
- package/lib/rules/curly.js +2 -2
- package/lib/rules/dot-notation.js +12 -6
- package/lib/rules/func-name-matching.js +18 -7
- package/lib/rules/func-names.js +20 -5
- package/lib/rules/keyword-spacing.js +19 -4
- package/lib/rules/line-comment-position.js +15 -5
- package/lib/rules/lines-around-comment.js +19 -0
- package/lib/rules/lines-around-directive.js +1 -1
- package/lib/rules/max-params.js +17 -4
- package/lib/rules/max-statements.js +11 -10
- package/lib/rules/new-parens.js +7 -21
- package/lib/rules/no-compare-neg-zero.js +53 -0
- package/lib/rules/no-cond-assign.js +4 -17
- package/lib/rules/no-else-return.js +19 -4
- package/lib/rules/no-empty-function.js +9 -16
- package/lib/rules/no-extra-parens.js +110 -121
- package/lib/rules/no-extra-semi.js +16 -3
- package/lib/rules/no-global-assign.js +1 -1
- package/lib/rules/no-implicit-coercion.js +21 -8
- package/lib/rules/no-invalid-regexp.js +2 -1
- package/lib/rules/no-multiple-empty-lines.js +2 -4
- package/lib/rules/no-native-reassign.js +1 -1
- package/lib/rules/no-negated-in-lhs.js +1 -1
- package/lib/rules/no-new-func.js +6 -8
- package/lib/rules/no-new.js +2 -6
- package/lib/rules/no-param-reassign.js +37 -7
- package/lib/rules/no-process-exit.js +2 -10
- package/lib/rules/no-restricted-properties.js +2 -0
- package/lib/rules/no-restricted-syntax.js +32 -21
- package/lib/rules/no-return-await.js +1 -1
- package/lib/rules/no-sequences.js +2 -2
- package/lib/rules/no-sync.js +8 -13
- package/lib/rules/no-unsafe-negation.js +1 -1
- package/lib/rules/no-unused-expressions.js +10 -1
- package/lib/rules/no-unused-vars.js +12 -12
- package/lib/rules/no-use-before-define.js +1 -1
- package/lib/rules/no-useless-computed-key.js +12 -1
- package/lib/rules/no-useless-escape.js +8 -2
- package/lib/rules/no-useless-return.js +13 -2
- package/lib/rules/nonblock-statement-body-position.js +114 -0
- package/lib/rules/object-curly-spacing.js +2 -2
- package/lib/rules/object-shorthand.js +10 -3
- package/lib/rules/operator-assignment.js +20 -3
- package/lib/rules/padded-blocks.js +37 -31
- package/lib/rules/prefer-const.js +1 -1
- package/lib/rules/prefer-destructuring.js +1 -1
- package/lib/rules/quotes.js +1 -0
- package/lib/rules/semi-spacing.js +2 -15
- package/lib/rules/semi.js +17 -13
- package/lib/rules/sort-vars.js +3 -5
- package/lib/rules/space-before-function-paren.js +53 -77
- package/lib/rules/space-in-parens.js +4 -8
- package/lib/rules/space-unary-ops.js +19 -1
- package/lib/rules/strict.js +8 -2
- package/lib/rules/yoda.js +2 -2
- package/lib/testers/rule-tester.js +44 -13
- package/lib/util/fix-tracker.js +121 -0
- package/lib/util/glob-util.js +1 -1
- package/lib/util/node-event-generator.js +274 -4
- package/lib/util/source-code-fixer.js +3 -9
- package/lib/util/source-code.js +99 -2
- package/lib/util/traverser.js +16 -25
- package/package.json +34 -34
@@ -90,23 +90,32 @@ module.exports = {
|
|
90
90
|
return node.type === "Line" || node.type === "Block";
|
91
91
|
}
|
92
92
|
|
93
|
+
/**
|
94
|
+
* Checks if there is padding between two tokens
|
95
|
+
* @param {Token} first The first token
|
96
|
+
* @param {Token} second The second token
|
97
|
+
* @returns {boolean} True if there is at least a line between the tokens
|
98
|
+
*/
|
99
|
+
function isPaddingBetweenTokens(first, second) {
|
100
|
+
return second.loc.start.line - first.loc.end.line >= 2;
|
101
|
+
}
|
102
|
+
|
103
|
+
|
93
104
|
/**
|
94
105
|
* Checks if the given token has a blank line after it.
|
95
106
|
* @param {Token} token The token to check.
|
96
107
|
* @returns {boolean} Whether or not the token is followed by a blank line.
|
97
108
|
*/
|
98
|
-
function
|
99
|
-
|
100
|
-
|
101
|
-
let first = token;
|
109
|
+
function getFirstBlockToken(token) {
|
110
|
+
let prev = token,
|
111
|
+
first = token;
|
102
112
|
|
103
113
|
do {
|
114
|
+
prev = first;
|
104
115
|
first = sourceCode.getTokenAfter(first, { includeComments: true });
|
105
|
-
} while (isComment(first) && first.loc.start.line ===
|
106
|
-
|
107
|
-
const firstLine = first.loc.start.line;
|
116
|
+
} while (isComment(first) && first.loc.start.line === prev.loc.end.line);
|
108
117
|
|
109
|
-
return
|
118
|
+
return first;
|
110
119
|
}
|
111
120
|
|
112
121
|
/**
|
@@ -114,18 +123,16 @@ module.exports = {
|
|
114
123
|
* @param {Token} token The token to check
|
115
124
|
* @returns {boolean} Whether or not the token is preceeded by a blank line
|
116
125
|
*/
|
117
|
-
function
|
118
|
-
|
119
|
-
|
120
|
-
let last = token;
|
126
|
+
function getLastBlockToken(token) {
|
127
|
+
let last = token,
|
128
|
+
next = token;
|
121
129
|
|
122
130
|
do {
|
131
|
+
next = last;
|
123
132
|
last = sourceCode.getTokenBefore(last, { includeComments: true });
|
124
|
-
} while (isComment(last) && last.loc.end.line ===
|
133
|
+
} while (isComment(last) && last.loc.end.line === next.loc.start.line);
|
125
134
|
|
126
|
-
|
127
|
-
|
128
|
-
return lastLine <= expectedLastLine;
|
135
|
+
return last;
|
129
136
|
}
|
130
137
|
|
131
138
|
/**
|
@@ -155,17 +162,21 @@ module.exports = {
|
|
155
162
|
*/
|
156
163
|
function checkPadding(node) {
|
157
164
|
const openBrace = getOpenBrace(node),
|
165
|
+
firstBlockToken = getFirstBlockToken(openBrace),
|
166
|
+
tokenBeforeFirst = sourceCode.getTokenBefore(firstBlockToken, { includeComments: true }),
|
158
167
|
closeBrace = sourceCode.getLastToken(node),
|
159
|
-
|
160
|
-
|
168
|
+
lastBlockToken = getLastBlockToken(closeBrace),
|
169
|
+
tokenAfterLast = sourceCode.getTokenAfter(lastBlockToken, { includeComments: true }),
|
170
|
+
blockHasTopPadding = isPaddingBetweenTokens(tokenBeforeFirst, firstBlockToken),
|
171
|
+
blockHasBottomPadding = isPaddingBetweenTokens(lastBlockToken, tokenAfterLast);
|
161
172
|
|
162
173
|
if (requirePaddingFor(node)) {
|
163
174
|
if (!blockHasTopPadding) {
|
164
175
|
context.report({
|
165
176
|
node,
|
166
|
-
loc: { line:
|
177
|
+
loc: { line: tokenBeforeFirst.loc.start.line, column: tokenBeforeFirst.loc.start.column },
|
167
178
|
fix(fixer) {
|
168
|
-
return fixer.insertTextAfter(
|
179
|
+
return fixer.insertTextAfter(tokenBeforeFirst, "\n");
|
169
180
|
},
|
170
181
|
message: ALWAYS_MESSAGE
|
171
182
|
});
|
@@ -173,39 +184,34 @@ module.exports = {
|
|
173
184
|
if (!blockHasBottomPadding) {
|
174
185
|
context.report({
|
175
186
|
node,
|
176
|
-
loc: { line:
|
187
|
+
loc: { line: tokenAfterLast.loc.end.line, column: tokenAfterLast.loc.end.column - 1 },
|
177
188
|
fix(fixer) {
|
178
|
-
return fixer.insertTextBefore(
|
189
|
+
return fixer.insertTextBefore(tokenAfterLast, "\n");
|
179
190
|
},
|
180
191
|
message: ALWAYS_MESSAGE
|
181
192
|
});
|
182
193
|
}
|
183
194
|
} else {
|
184
195
|
if (blockHasTopPadding) {
|
185
|
-
const nextToken = sourceCode.getTokenAfter(openBrace, { includeComments: true });
|
186
196
|
|
187
197
|
context.report({
|
188
198
|
node,
|
189
|
-
loc: { line:
|
199
|
+
loc: { line: tokenBeforeFirst.loc.start.line, column: tokenBeforeFirst.loc.start.column },
|
190
200
|
fix(fixer) {
|
191
|
-
|
192
|
-
// FIXME: The start of this range is sometimes larger than the end.
|
193
|
-
// https://github.com/eslint/eslint/issues/8116
|
194
|
-
return fixer.replaceTextRange([openBrace.end, nextToken.start - nextToken.loc.start.column], "\n");
|
201
|
+
return fixer.replaceTextRange([tokenBeforeFirst.end, firstBlockToken.start - firstBlockToken.loc.start.column], "\n");
|
195
202
|
},
|
196
203
|
message: NEVER_MESSAGE
|
197
204
|
});
|
198
205
|
}
|
199
206
|
|
200
207
|
if (blockHasBottomPadding) {
|
201
|
-
const previousToken = sourceCode.getTokenBefore(closeBrace, { includeComments: true });
|
202
208
|
|
203
209
|
context.report({
|
204
210
|
node,
|
205
|
-
loc: { line:
|
211
|
+
loc: { line: tokenAfterLast.loc.end.line, column: tokenAfterLast.loc.end.column - 1 },
|
206
212
|
message: NEVER_MESSAGE,
|
207
213
|
fix(fixer) {
|
208
|
-
return fixer.replaceTextRange([
|
214
|
+
return fixer.replaceTextRange([lastBlockToken.end, tokenAfterLast.start - tokenAfterLast.loc.start.column], "\n");
|
209
215
|
}
|
210
216
|
});
|
211
217
|
}
|
@@ -9,7 +9,7 @@
|
|
9
9
|
// Helpers
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
-
const PATTERN_TYPE = /^(?:.+?Pattern|RestElement|Property)$/;
|
12
|
+
const PATTERN_TYPE = /^(?:.+?Pattern|RestElement|SpreadProperty|ExperimentalRestProperty|Property)$/;
|
13
13
|
const DECLARATION_HOST_TYPE = /^(?:Program|BlockStatement|SwitchCase)$/;
|
14
14
|
const DESTRUCTURING_HOST_TYPE = /^(?:VariableDeclarator|AssignmentExpression)$/;
|
15
15
|
|
@@ -89,7 +89,7 @@ module.exports = {
|
|
89
89
|
* @returns {void}
|
90
90
|
*/
|
91
91
|
function report(reportNode, type) {
|
92
|
-
context.report({ node: reportNode, message:
|
92
|
+
context.report({ node: reportNode, message: "Use {{type}} destructuring.", data: { type } });
|
93
93
|
}
|
94
94
|
|
95
95
|
/**
|
package/lib/rules/quotes.js
CHANGED
@@ -105,20 +105,7 @@ module.exports = {
|
|
105
105
|
function isBeforeClosingParen(token) {
|
106
106
|
const nextToken = sourceCode.getTokenAfter(token);
|
107
107
|
|
108
|
-
return (
|
109
|
-
nextToken &&
|
110
|
-
nextToken.type === "Punctuator" &&
|
111
|
-
(nextToken.value === "}" || nextToken.value === ")")
|
112
|
-
);
|
113
|
-
}
|
114
|
-
|
115
|
-
/**
|
116
|
-
* Checks if the given token is a semicolon.
|
117
|
-
* @param {Token} token The token to check.
|
118
|
-
* @returns {boolean} Whether or not the given token is a semicolon.
|
119
|
-
*/
|
120
|
-
function isSemicolon(token) {
|
121
|
-
return token.type === "Punctuator" && token.value === ";";
|
108
|
+
return (nextToken && astUtils.isClosingBraceToken(nextToken) || astUtils.isClosingParenToken(nextToken));
|
122
109
|
}
|
123
110
|
|
124
111
|
/**
|
@@ -128,7 +115,7 @@ module.exports = {
|
|
128
115
|
* @returns {void}
|
129
116
|
*/
|
130
117
|
function checkSemicolonSpacing(token, node) {
|
131
|
-
if (
|
118
|
+
if (astUtils.isSemicolonToken(token)) {
|
132
119
|
const location = token.loc.start;
|
133
120
|
|
134
121
|
if (hasLeadingSpace(token)) {
|
package/lib/rules/semi.js
CHANGED
@@ -4,6 +4,13 @@
|
|
4
4
|
*/
|
5
5
|
"use strict";
|
6
6
|
|
7
|
+
//------------------------------------------------------------------------------
|
8
|
+
// Requirements
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
|
11
|
+
const FixTracker = require("../util/fix-tracker");
|
12
|
+
const astUtils = require("../ast-utils");
|
13
|
+
|
7
14
|
//------------------------------------------------------------------------------
|
8
15
|
// Rule Definition
|
9
16
|
//------------------------------------------------------------------------------
|
@@ -85,7 +92,13 @@ module.exports = {
|
|
85
92
|
message = "Extra semicolon.";
|
86
93
|
loc = loc.start;
|
87
94
|
fix = function(fixer) {
|
88
|
-
|
95
|
+
|
96
|
+
// Expand the replacement range to include the surrounding
|
97
|
+
// tokens to avoid conflicting with no-extra-semi.
|
98
|
+
// https://github.com/eslint/eslint/issues/7928
|
99
|
+
return new FixTracker(fixer, sourceCode)
|
100
|
+
.retainSurroundingTokens(lastToken)
|
101
|
+
.remove(lastToken);
|
89
102
|
};
|
90
103
|
}
|
91
104
|
|
@@ -98,15 +111,6 @@ module.exports = {
|
|
98
111
|
|
99
112
|
}
|
100
113
|
|
101
|
-
/**
|
102
|
-
* Checks whether a token is a semicolon punctuator.
|
103
|
-
* @param {Token} token The token.
|
104
|
-
* @returns {boolean} True if token is a semicolon punctuator.
|
105
|
-
*/
|
106
|
-
function isSemicolon(token) {
|
107
|
-
return (token.type === "Punctuator" && token.value === ";");
|
108
|
-
}
|
109
|
-
|
110
114
|
/**
|
111
115
|
* Check if a semicolon is unnecessary, only true if:
|
112
116
|
* - next token is on a new line and is not one of the opt-out tokens
|
@@ -115,7 +119,7 @@ module.exports = {
|
|
115
119
|
* @returns {boolean} whether the semicolon is unnecessary.
|
116
120
|
*/
|
117
121
|
function isUnnecessarySemicolon(lastToken) {
|
118
|
-
if (!
|
122
|
+
if (!astUtils.isSemicolonToken(lastToken)) {
|
119
123
|
return false;
|
120
124
|
}
|
121
125
|
|
@@ -128,7 +132,7 @@ module.exports = {
|
|
128
132
|
const lastTokenLine = lastToken.loc.end.line;
|
129
133
|
const nextTokenLine = nextToken.loc.start.line;
|
130
134
|
const isOptOutToken = OPT_OUT_PATTERN.test(nextToken.value) && nextToken.value !== "++" && nextToken.value !== "--";
|
131
|
-
const isDivider = (nextToken
|
135
|
+
const isDivider = (astUtils.isClosingBraceToken(nextToken) || astUtils.isSemicolonToken(nextToken));
|
132
136
|
|
133
137
|
return (lastTokenLine !== nextTokenLine && !isOptOutToken) || isDivider;
|
134
138
|
}
|
@@ -164,7 +168,7 @@ module.exports = {
|
|
164
168
|
report(node, true);
|
165
169
|
}
|
166
170
|
} else {
|
167
|
-
if (!
|
171
|
+
if (!astUtils.isSemicolonToken(lastToken)) {
|
168
172
|
if (!exceptOneLine || !isOneLinerBlock(node)) {
|
169
173
|
report(node);
|
170
174
|
}
|
package/lib/rules/sort-vars.js
CHANGED
@@ -37,11 +37,9 @@ module.exports = {
|
|
37
37
|
|
38
38
|
return {
|
39
39
|
VariableDeclaration(node) {
|
40
|
-
node.declarations.
|
41
|
-
if (decl.id.type === "ObjectPattern" || decl.id.type === "ArrayPattern") {
|
42
|
-
return memo;
|
43
|
-
}
|
40
|
+
const idDeclarations = node.declarations.filter(decl => decl.id.type === "Identifier");
|
44
41
|
|
42
|
+
idDeclarations.slice(1).reduce((memo, decl) => {
|
45
43
|
let lastVariableName = memo.id.name,
|
46
44
|
currenVariableName = decl.id.name;
|
47
45
|
|
@@ -56,7 +54,7 @@ module.exports = {
|
|
56
54
|
}
|
57
55
|
return decl;
|
58
56
|
|
59
|
-
},
|
57
|
+
}, idDeclarations[0]);
|
60
58
|
}
|
61
59
|
};
|
62
60
|
}
|
@@ -51,31 +51,9 @@ module.exports = {
|
|
51
51
|
},
|
52
52
|
|
53
53
|
create(context) {
|
54
|
-
|
55
|
-
const
|
56
|
-
|
57
|
-
let requireAnonymousFunctionSpacing = true,
|
58
|
-
forbidAnonymousFunctionSpacing = false,
|
59
|
-
requireNamedFunctionSpacing = true,
|
60
|
-
forbidNamedFunctionSpacing = false,
|
61
|
-
requireArrowFunctionSpacing = false,
|
62
|
-
forbidArrowFunctionSpacing = false;
|
63
|
-
|
64
|
-
if (typeof configuration === "object") {
|
65
|
-
requireAnonymousFunctionSpacing = (
|
66
|
-
!configuration.anonymous || configuration.anonymous === "always");
|
67
|
-
forbidAnonymousFunctionSpacing = configuration.anonymous === "never";
|
68
|
-
requireNamedFunctionSpacing = (
|
69
|
-
!configuration.named || configuration.named === "always");
|
70
|
-
forbidNamedFunctionSpacing = configuration.named === "never";
|
71
|
-
requireArrowFunctionSpacing = configuration.asyncArrow === "always";
|
72
|
-
forbidArrowFunctionSpacing = configuration.asyncArrow === "never";
|
73
|
-
} else if (configuration === "never") {
|
74
|
-
requireAnonymousFunctionSpacing = false;
|
75
|
-
forbidAnonymousFunctionSpacing = true;
|
76
|
-
requireNamedFunctionSpacing = false;
|
77
|
-
forbidNamedFunctionSpacing = true;
|
78
|
-
}
|
54
|
+
const sourceCode = context.getSourceCode();
|
55
|
+
const baseConfig = typeof context.options[0] === "string" ? context.options[0] : "always";
|
56
|
+
const overrideConfig = typeof context.options[0] === "object" ? context.options[0] : {};
|
79
57
|
|
80
58
|
/**
|
81
59
|
* Determines whether a function has a name.
|
@@ -100,69 +78,67 @@ module.exports = {
|
|
100
78
|
}
|
101
79
|
|
102
80
|
/**
|
103
|
-
*
|
104
|
-
* @param {ASTNode} node The node
|
105
|
-
* @returns {
|
81
|
+
* Gets the config for a given function
|
82
|
+
* @param {ASTNode} node The function node
|
83
|
+
* @returns {string} "always", "never", or "ignore"
|
106
84
|
*/
|
107
|
-
function
|
108
|
-
|
109
|
-
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
|
117
|
-
|
118
|
-
|
119
|
-
|
85
|
+
function getConfigForFunction(node) {
|
86
|
+
if (node.type === "ArrowFunctionExpression") {
|
87
|
+
|
88
|
+
// Always ignore non-async functions and arrow functions without parens, e.g. async foo => bar
|
89
|
+
if (node.async && astUtils.isOpeningParenToken(sourceCode.getFirstToken(node, { skip: 1 }))) {
|
90
|
+
|
91
|
+
// For backwards compatibility, the base config does not apply to async arrow functions.
|
92
|
+
return overrideConfig.asyncArrow || "ignore";
|
93
|
+
}
|
94
|
+
} else if (isNamedFunction(node)) {
|
95
|
+
return overrideConfig.named || baseConfig;
|
96
|
+
|
97
|
+
// `generator-star-spacing` should warn anonymous generators. E.g. `function* () {}`
|
98
|
+
} else if (!node.generator) {
|
99
|
+
return overrideConfig.anonymous || baseConfig;
|
120
100
|
}
|
121
101
|
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
127
|
-
|
128
|
-
|
129
|
-
|
130
|
-
|
102
|
+
return "ignore";
|
103
|
+
}
|
104
|
+
|
105
|
+
/**
|
106
|
+
* Checks the parens of a function node
|
107
|
+
* @param {ASTNode} node A function node
|
108
|
+
* @returns {void}
|
109
|
+
*/
|
110
|
+
function checkFunction(node) {
|
111
|
+
const functionConfig = getConfigForFunction(node);
|
112
|
+
|
113
|
+
if (functionConfig === "ignore") {
|
114
|
+
return;
|
131
115
|
}
|
132
116
|
|
133
117
|
const rightToken = sourceCode.getFirstToken(node, astUtils.isOpeningParenToken);
|
134
118
|
const leftToken = sourceCode.getTokenBefore(rightToken);
|
135
|
-
const
|
136
|
-
|
137
|
-
if (
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
node,
|
152
|
-
loc: location,
|
153
|
-
message: "Missing space before function parentheses.",
|
154
|
-
fix(fixer) {
|
155
|
-
return fixer.insertTextAfter(leftToken, " ");
|
156
|
-
}
|
157
|
-
});
|
158
|
-
}
|
119
|
+
const hasSpacing = sourceCode.isSpaceBetweenTokens(leftToken, rightToken);
|
120
|
+
|
121
|
+
if (hasSpacing && functionConfig === "never") {
|
122
|
+
context.report({
|
123
|
+
node,
|
124
|
+
loc: leftToken.loc.end,
|
125
|
+
message: "Unexpected space before function parentheses.",
|
126
|
+
fix: fixer => fixer.removeRange([leftToken.range[1], rightToken.range[0]])
|
127
|
+
});
|
128
|
+
} else if (!hasSpacing && functionConfig === "always") {
|
129
|
+
context.report({
|
130
|
+
node,
|
131
|
+
loc: leftToken.loc.end,
|
132
|
+
message: "Missing space before function parentheses.",
|
133
|
+
fix: fixer => fixer.insertTextAfter(leftToken, " ")
|
134
|
+
});
|
159
135
|
}
|
160
136
|
}
|
161
137
|
|
162
138
|
return {
|
163
|
-
|
164
|
-
|
165
|
-
|
139
|
+
ArrowFunctionExpression: checkFunction,
|
140
|
+
FunctionDeclaration: checkFunction,
|
141
|
+
FunctionExpression: checkFunction
|
166
142
|
};
|
167
143
|
}
|
168
144
|
};
|
@@ -128,7 +128,7 @@ module.exports = {
|
|
128
128
|
}
|
129
129
|
|
130
130
|
if (ALWAYS) {
|
131
|
-
if (
|
131
|
+
if (astUtils.isClosingParenToken(right)) {
|
132
132
|
return false;
|
133
133
|
}
|
134
134
|
return !isOpenerException(right);
|
@@ -144,7 +144,7 @@ module.exports = {
|
|
144
144
|
* @returns {boolean} True if the paren should have a space
|
145
145
|
*/
|
146
146
|
function shouldCloserHaveSpace(left, right) {
|
147
|
-
if (
|
147
|
+
if (astUtils.isOpeningParenToken(left)) {
|
148
148
|
return false;
|
149
149
|
}
|
150
150
|
|
@@ -192,7 +192,7 @@ module.exports = {
|
|
192
192
|
* @returns {boolean} True if the paren should reject the space
|
193
193
|
*/
|
194
194
|
function shouldCloserRejectSpace(left, right) {
|
195
|
-
if (
|
195
|
+
if (astUtils.isOpeningParenToken(left)) {
|
196
196
|
return false;
|
197
197
|
}
|
198
198
|
|
@@ -224,11 +224,7 @@ module.exports = {
|
|
224
224
|
const prevToken = tokens[i - 1];
|
225
225
|
const nextToken = tokens[i + 1];
|
226
226
|
|
227
|
-
if (token
|
228
|
-
return;
|
229
|
-
}
|
230
|
-
|
231
|
-
if (token.value !== "(" && token.value !== ")") {
|
227
|
+
if (!astUtils.isOpeningParenToken(token) && !astUtils.isClosingParenToken(token)) {
|
232
228
|
return;
|
233
229
|
}
|
234
230
|
|
@@ -68,6 +68,21 @@ module.exports = {
|
|
68
68
|
return node.argument && node.argument.type && node.argument.type === "ObjectExpression";
|
69
69
|
}
|
70
70
|
|
71
|
+
/**
|
72
|
+
* Check if it is safe to remove the spaces between the two tokens in
|
73
|
+
* the context of a non-word prefix unary operator. For example, `+ +1`
|
74
|
+
* cannot safely be changed to `++1`.
|
75
|
+
* @param {Token} firstToken The operator for a non-word prefix unary operator
|
76
|
+
* @param {Token} secondToken The first token of its operand
|
77
|
+
* @returns {boolean} Whether or not the spacing between the tokens can be removed
|
78
|
+
*/
|
79
|
+
function canRemoveSpacesBetween(firstToken, secondToken) {
|
80
|
+
return !(
|
81
|
+
(firstToken.value === "+" && secondToken.value[0] === "+") ||
|
82
|
+
(firstToken.value === "-" && secondToken.value[0] === "-")
|
83
|
+
);
|
84
|
+
}
|
85
|
+
|
71
86
|
/**
|
72
87
|
* Checks if an override exists for a given operator.
|
73
88
|
* @param {ASTnode} node AST node
|
@@ -244,7 +259,10 @@ module.exports = {
|
|
244
259
|
operator: firstToken.value
|
245
260
|
},
|
246
261
|
fix(fixer) {
|
247
|
-
|
262
|
+
if (canRemoveSpacesBetween(firstToken, secondToken)) {
|
263
|
+
return fixer.removeRange([firstToken.range[1], secondToken.range[0]]);
|
264
|
+
}
|
265
|
+
return null;
|
248
266
|
}
|
249
267
|
});
|
250
268
|
}
|
package/lib/rules/strict.js
CHANGED
@@ -9,6 +9,8 @@
|
|
9
9
|
// Requirements
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
|
+
const astUtils = require("../ast-utils");
|
13
|
+
|
12
14
|
//------------------------------------------------------------------------------
|
13
15
|
// Helpers
|
14
16
|
//------------------------------------------------------------------------------
|
@@ -23,7 +25,7 @@ const messages = {
|
|
23
25
|
implied: "'use strict' is unnecessary when implied strict mode is enabled.",
|
24
26
|
unnecessaryInClasses: "'use strict' is unnecessary inside of classes.",
|
25
27
|
nonSimpleParameterList: "'use strict' directive inside a function with non-simple parameter list throws a syntax error since ES2016.",
|
26
|
-
wrap: "Wrap
|
28
|
+
wrap: "Wrap {{name}} in a function with 'use strict' directive."
|
27
29
|
};
|
28
30
|
|
29
31
|
/**
|
@@ -188,7 +190,11 @@ module.exports = {
|
|
188
190
|
if (isSimpleParameterList(node.params)) {
|
189
191
|
context.report({ node, message: messages.function });
|
190
192
|
} else {
|
191
|
-
context.report({
|
193
|
+
context.report({
|
194
|
+
node,
|
195
|
+
message: messages.wrap,
|
196
|
+
data: { name: astUtils.getFunctionNameWithKind(node) }
|
197
|
+
});
|
192
198
|
}
|
193
199
|
}
|
194
200
|
|
package/lib/rules/yoda.js
CHANGED
@@ -267,8 +267,8 @@ module.exports = {
|
|
267
267
|
const operatorToken = sourceCode.getFirstTokenBetween(node.left, node.right, token => token.value === node.operator);
|
268
268
|
const textBeforeOperator = sourceCode.getText().slice(sourceCode.getTokenBefore(operatorToken).range[1], operatorToken.range[0]);
|
269
269
|
const textAfterOperator = sourceCode.getText().slice(operatorToken.range[1], sourceCode.getTokenAfter(operatorToken).range[0]);
|
270
|
-
const leftText = sourceCode.getText().slice(
|
271
|
-
const rightText = sourceCode.getText().slice(sourceCode.getTokenAfter(operatorToken).range[0],
|
270
|
+
const leftText = sourceCode.getText().slice(node.range[0], sourceCode.getTokenBefore(operatorToken).range[1]);
|
271
|
+
const rightText = sourceCode.getText().slice(sourceCode.getTokenAfter(operatorToken).range[0], node.range[1]);
|
272
272
|
|
273
273
|
return rightText + textBeforeOperator + OPERATOR_FLIP_MAP[operatorToken.value] + textAfterOperator + leftText;
|
274
274
|
}
|