eslint 4.2.0 → 4.5.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 +80 -0
- package/bin/eslint.js +5 -4
- package/conf/category-list.json +2 -2
- package/conf/config-schema.js +3 -1
- package/conf/eslint-recommended.js +11 -14
- package/lib/config/config-file.js +5 -5
- package/lib/config/config-initializer.js +123 -14
- package/lib/config/config-validator.js +25 -1
- package/lib/config/plugins.js +13 -1
- package/lib/formatters/junit.js +2 -8
- package/lib/formatters/stylish.js +2 -1
- package/lib/linter.js +21 -13
- package/lib/rule-context.js +53 -41
- package/lib/rules/arrow-parens.js +1 -1
- package/lib/rules/curly.js +1 -1
- package/lib/rules/getter-return.js +34 -9
- package/lib/rules/id-blacklist.js +7 -3
- package/lib/rules/id-match.js +8 -4
- package/lib/rules/indent-legacy.js +2 -2
- package/lib/rules/indent.js +451 -380
- package/lib/rules/key-spacing.js +2 -2
- package/lib/rules/no-cond-assign.js +7 -3
- package/lib/rules/no-constant-condition.js +62 -6
- package/lib/rules/no-else-return.js +1 -1
- package/lib/rules/no-extra-parens.js +3 -1
- package/lib/rules/no-inner-declarations.js +8 -4
- package/lib/rules/no-multi-spaces.js +53 -115
- package/lib/rules/no-regex-spaces.js +2 -2
- package/lib/rules/no-restricted-globals.js +50 -9
- package/lib/rules/no-restricted-properties.js +19 -11
- package/lib/rules/no-tabs.js +8 -4
- package/lib/rules/no-underscore-dangle.js +28 -1
- package/lib/rules/object-curly-newline.js +18 -0
- package/lib/rules/object-curly-spacing.js +1 -1
- package/lib/rules/padded-blocks.js +2 -2
- package/lib/rules/padding-line-between-statements.js +1 -1
- package/lib/rules/prefer-destructuring.js +70 -32
- package/lib/rules/prefer-numeric-literals.js +36 -7
- package/lib/rules/prefer-reflect.js +8 -4
- package/lib/rules/prefer-template.js +2 -2
- package/lib/rules/space-infix-ops.js +1 -1
- package/lib/rules/spaced-comment.js +2 -2
- package/lib/rules/valid-jsdoc.js +15 -7
- package/lib/testers/rule-tester.js +13 -21
- package/lib/testers/test-parser.js +48 -0
- package/lib/util/npm-util.js +9 -8
- package/package.json +11 -6
package/lib/rules/key-spacing.js
CHANGED
@@ -433,9 +433,9 @@ module.exports = {
|
|
433
433
|
|
434
434
|
// Remove whitespace
|
435
435
|
if (isKeySide) {
|
436
|
-
range = [tokenBeforeColon.
|
436
|
+
range = [tokenBeforeColon.range[1], tokenBeforeColon.range[1] + diffAbs];
|
437
437
|
} else {
|
438
|
-
range = [tokenAfterColon.
|
438
|
+
range = [tokenAfterColon.range[0] - diffAbs, tokenAfterColon.range[0]];
|
439
439
|
}
|
440
440
|
fix = function(fixer) {
|
441
441
|
return fixer.removeRange(range);
|
@@ -112,9 +112,13 @@ module.exports = {
|
|
112
112
|
const ancestor = findConditionalAncestor(node);
|
113
113
|
|
114
114
|
if (ancestor) {
|
115
|
-
context.report({
|
116
|
-
|
117
|
-
|
115
|
+
context.report({
|
116
|
+
node: ancestor,
|
117
|
+
message: "Unexpected assignment within {{type}}.",
|
118
|
+
data: {
|
119
|
+
type: NODE_DESCRIPTIONS[ancestor.type] || ancestor.type
|
120
|
+
}
|
121
|
+
});
|
118
122
|
}
|
119
123
|
}
|
120
124
|
|
@@ -33,7 +33,10 @@ module.exports = {
|
|
33
33
|
|
34
34
|
create(context) {
|
35
35
|
const options = context.options[0] || {},
|
36
|
-
checkLoops = options.checkLoops !== false
|
36
|
+
checkLoops = options.checkLoops !== false,
|
37
|
+
loopSetStack = [];
|
38
|
+
|
39
|
+
let loopsInCurrentScope = new Set();
|
37
40
|
|
38
41
|
//--------------------------------------------------------------------------
|
39
42
|
// Helpers
|
@@ -114,18 +117,64 @@ module.exports = {
|
|
114
117
|
return false;
|
115
118
|
}
|
116
119
|
|
120
|
+
/**
|
121
|
+
* Tracks when the given node contains a constant condition.
|
122
|
+
* @param {ASTNode} node The AST node to check.
|
123
|
+
* @returns {void}
|
124
|
+
* @private
|
125
|
+
*/
|
126
|
+
function trackConstantConditionLoop(node) {
|
127
|
+
if (node.test && isConstant(node.test, true)) {
|
128
|
+
loopsInCurrentScope.add(node);
|
129
|
+
}
|
130
|
+
}
|
131
|
+
|
132
|
+
/**
|
133
|
+
* Reports when the set contains the given constant condition node
|
134
|
+
* @param {ASTNode} node The AST node to check.
|
135
|
+
* @returns {void}
|
136
|
+
* @private
|
137
|
+
*/
|
138
|
+
function checkConstantConditionLoopInSet(node) {
|
139
|
+
if (loopsInCurrentScope.has(node)) {
|
140
|
+
loopsInCurrentScope.delete(node);
|
141
|
+
context.report({ node, message: "Unexpected constant condition." });
|
142
|
+
}
|
143
|
+
}
|
144
|
+
|
117
145
|
/**
|
118
146
|
* Reports when the given node contains a constant condition.
|
119
147
|
* @param {ASTNode} node The AST node to check.
|
120
148
|
* @returns {void}
|
121
149
|
* @private
|
122
150
|
*/
|
123
|
-
function
|
151
|
+
function reportIfConstant(node) {
|
124
152
|
if (node.test && isConstant(node.test, true)) {
|
125
153
|
context.report({ node, message: "Unexpected constant condition." });
|
126
154
|
}
|
127
155
|
}
|
128
156
|
|
157
|
+
/**
|
158
|
+
* Stores current set of constant loops in loopSetStack temporarily
|
159
|
+
* and uses a new set to track constant loops
|
160
|
+
* @returns {void}
|
161
|
+
* @private
|
162
|
+
*/
|
163
|
+
function enterFunction() {
|
164
|
+
loopSetStack.push(loopsInCurrentScope);
|
165
|
+
loopsInCurrentScope = new Set();
|
166
|
+
}
|
167
|
+
|
168
|
+
/**
|
169
|
+
* Reports when the set still contains stored constant conditions
|
170
|
+
* @param {ASTNode} node The AST node to check.
|
171
|
+
* @returns {void}
|
172
|
+
* @private
|
173
|
+
*/
|
174
|
+
function exitFunction() {
|
175
|
+
loopsInCurrentScope = loopSetStack.pop();
|
176
|
+
}
|
177
|
+
|
129
178
|
/**
|
130
179
|
* Checks node when checkLoops option is enabled
|
131
180
|
* @param {ASTNode} node The AST node to check.
|
@@ -134,7 +183,7 @@ module.exports = {
|
|
134
183
|
*/
|
135
184
|
function checkLoop(node) {
|
136
185
|
if (checkLoops) {
|
137
|
-
|
186
|
+
trackConstantConditionLoop(node);
|
138
187
|
}
|
139
188
|
}
|
140
189
|
|
@@ -143,11 +192,18 @@ module.exports = {
|
|
143
192
|
//--------------------------------------------------------------------------
|
144
193
|
|
145
194
|
return {
|
146
|
-
ConditionalExpression:
|
147
|
-
IfStatement:
|
195
|
+
ConditionalExpression: reportIfConstant,
|
196
|
+
IfStatement: reportIfConstant,
|
148
197
|
WhileStatement: checkLoop,
|
198
|
+
"WhileStatement:exit": checkConstantConditionLoopInSet,
|
149
199
|
DoWhileStatement: checkLoop,
|
150
|
-
|
200
|
+
"DoWhileStatement:exit": checkConstantConditionLoopInSet,
|
201
|
+
ForStatement: checkLoop,
|
202
|
+
"ForStatement > .test": node => checkLoop(node.parent),
|
203
|
+
"ForStatement:exit": checkConstantConditionLoopInSet,
|
204
|
+
FunctionDeclaration: enterFunction,
|
205
|
+
"FunctionDeclaration:exit": exitFunction,
|
206
|
+
YieldExpression: () => loopsInCurrentScope.clear()
|
151
207
|
};
|
152
208
|
|
153
209
|
}
|
@@ -99,7 +99,7 @@ module.exports = {
|
|
99
99
|
// https://github.com/eslint/eslint/issues/8026
|
100
100
|
return new FixTracker(fixer, sourceCode)
|
101
101
|
.retainEnclosingFunction(node)
|
102
|
-
.replaceTextRange([elseToken.
|
102
|
+
.replaceTextRange([elseToken.range[0], node.range[1]], fixedSource);
|
103
103
|
}
|
104
104
|
});
|
105
105
|
}
|
@@ -418,6 +418,7 @@ module.exports = {
|
|
418
418
|
function checkExpressionOrExportStatement(node) {
|
419
419
|
const firstToken = isParenthesised(node) ? sourceCode.getTokenBefore(node) : sourceCode.getFirstToken(node);
|
420
420
|
const secondToken = sourceCode.getTokenAfter(firstToken, astUtils.isNotOpeningParenToken);
|
421
|
+
const thirdToken = secondToken ? sourceCode.getTokenAfter(secondToken) : null;
|
421
422
|
|
422
423
|
if (
|
423
424
|
astUtils.isOpeningParenToken(firstToken) &&
|
@@ -427,7 +428,8 @@ module.exports = {
|
|
427
428
|
secondToken.value === "function" ||
|
428
429
|
secondToken.value === "class" ||
|
429
430
|
secondToken.value === "let" && astUtils.isOpeningBracketToken(sourceCode.getTokenAfter(secondToken, astUtils.isNotClosingParenToken))
|
430
|
-
)
|
431
|
+
) ||
|
432
|
+
secondToken && secondToken.type === "Identifier" && secondToken.value === "async" && thirdToken && thirdToken.type === "Keyword" && thirdToken.value === "function"
|
431
433
|
)
|
432
434
|
) {
|
433
435
|
tokensToIgnore.add(secondToken);
|
@@ -63,10 +63,14 @@ module.exports = {
|
|
63
63
|
body.distance === 2);
|
64
64
|
|
65
65
|
if (!valid) {
|
66
|
-
context.report({
|
67
|
-
|
68
|
-
|
69
|
-
|
66
|
+
context.report({
|
67
|
+
node,
|
68
|
+
message: "Move {{type}} declaration to {{body}} root.",
|
69
|
+
data: {
|
70
|
+
type: (node.type === "FunctionDeclaration" ? "function" : "variable"),
|
71
|
+
body: (body.type === "Program" ? "program" : "function body")
|
72
|
+
}
|
73
|
+
});
|
70
74
|
}
|
71
75
|
}
|
72
76
|
|
@@ -44,68 +44,11 @@ module.exports = {
|
|
44
44
|
},
|
45
45
|
|
46
46
|
create(context) {
|
47
|
-
|
48
|
-
|
49
|
-
const
|
50
|
-
|
51
|
-
|
52
|
-
ignoreEOLComments = options.ignoreEOLComments;
|
53
|
-
let hasExceptions = true,
|
54
|
-
lastCommentIndex = 0;
|
55
|
-
|
56
|
-
if (options && options.exceptions) {
|
57
|
-
Object.keys(options.exceptions).forEach(key => {
|
58
|
-
if (options.exceptions[key]) {
|
59
|
-
exceptions[key] = true;
|
60
|
-
} else {
|
61
|
-
delete exceptions[key];
|
62
|
-
}
|
63
|
-
});
|
64
|
-
hasExceptions = Object.keys(exceptions).length > 0;
|
65
|
-
}
|
66
|
-
|
67
|
-
/**
|
68
|
-
* Checks if a given token is the last token of the line or not.
|
69
|
-
* @param {Token} token The token to check.
|
70
|
-
* @returns {boolean} Whether or not a token is at the end of the line it occurs in.
|
71
|
-
* @private
|
72
|
-
*/
|
73
|
-
function isLastTokenOfLine(token) {
|
74
|
-
const nextToken = sourceCode.getTokenAfter(token, { includeComments: true });
|
75
|
-
|
76
|
-
// nextToken is null if the comment is the last token in the program.
|
77
|
-
if (!nextToken) {
|
78
|
-
return true;
|
79
|
-
}
|
80
|
-
|
81
|
-
return !astUtils.isTokenOnSameLine(token, nextToken);
|
82
|
-
}
|
83
|
-
|
84
|
-
/**
|
85
|
-
* Determines if a given source index is in a comment or not by checking
|
86
|
-
* the index against the comment range. Since the check goes straight
|
87
|
-
* through the file, once an index is passed a certain comment, we can
|
88
|
-
* go to the next comment to check that.
|
89
|
-
* @param {int} index The source index to check.
|
90
|
-
* @param {ASTNode[]} comments An array of comment nodes.
|
91
|
-
* @returns {boolean} True if the index is within a comment, false if not.
|
92
|
-
* @private
|
93
|
-
*/
|
94
|
-
function isIndexInComment(index, comments) {
|
95
|
-
while (lastCommentIndex < comments.length) {
|
96
|
-
const comment = comments[lastCommentIndex];
|
97
|
-
|
98
|
-
if (comment.range[0] < index && index < comment.range[1]) {
|
99
|
-
return true;
|
100
|
-
} else if (index > comment.range[1]) {
|
101
|
-
lastCommentIndex++;
|
102
|
-
} else {
|
103
|
-
break;
|
104
|
-
}
|
105
|
-
}
|
106
|
-
|
107
|
-
return false;
|
108
|
-
}
|
47
|
+
const sourceCode = context.getSourceCode();
|
48
|
+
const options = context.options[0] || {};
|
49
|
+
const ignoreEOLComments = options.ignoreEOLComments;
|
50
|
+
const exceptions = Object.assign({ Property: true }, options.exceptions);
|
51
|
+
const hasExceptions = Object.keys(exceptions).filter(key => exceptions[key]).length > 0;
|
109
52
|
|
110
53
|
/**
|
111
54
|
* Formats value of given comment token for error message by truncating its length.
|
@@ -116,75 +59,70 @@ module.exports = {
|
|
116
59
|
function formatReportedCommentValue(token) {
|
117
60
|
const valueLines = token.value.split("\n");
|
118
61
|
const value = valueLines[0];
|
119
|
-
const formattedValue = `${value.
|
62
|
+
const formattedValue = `${value.slice(0, 12)}...`;
|
120
63
|
|
121
64
|
return valueLines.length === 1 && value.length <= 12 ? value : formattedValue;
|
122
65
|
}
|
123
66
|
|
124
|
-
/**
|
125
|
-
* Creates a fix function that removes the multiple spaces between the two tokens
|
126
|
-
* @param {Token} leftToken left token
|
127
|
-
* @param {Token} rightToken right token
|
128
|
-
* @returns {Function} fix function
|
129
|
-
* @private
|
130
|
-
*/
|
131
|
-
function createFix(leftToken, rightToken) {
|
132
|
-
return function(fixer) {
|
133
|
-
return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ");
|
134
|
-
};
|
135
|
-
}
|
136
|
-
|
137
67
|
//--------------------------------------------------------------------------
|
138
68
|
// Public
|
139
69
|
//--------------------------------------------------------------------------
|
140
70
|
|
141
71
|
return {
|
142
72
|
Program() {
|
73
|
+
sourceCode.tokensAndComments.forEach((leftToken, leftIndex, tokensAndComments) => {
|
74
|
+
if (leftIndex === tokensAndComments.length - 1) {
|
75
|
+
return;
|
76
|
+
}
|
77
|
+
const rightToken = tokensAndComments[leftIndex + 1];
|
78
|
+
|
79
|
+
// Ignore tokens that don't have 2 spaces between them or are on different lines
|
80
|
+
if (
|
81
|
+
!sourceCode.text.slice(leftToken.range[1], rightToken.range[0]).includes(" ") ||
|
82
|
+
leftToken.loc.end.line < rightToken.loc.start.line
|
83
|
+
) {
|
84
|
+
return;
|
85
|
+
}
|
143
86
|
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
149
|
-
|
150
|
-
|
151
|
-
|
152
|
-
|
153
|
-
|
154
|
-
|
155
|
-
|
156
|
-
if (token) {
|
157
|
-
if (ignoreEOLComments && astUtils.isCommentToken(token) && isLastTokenOfLine(token)) {
|
158
|
-
return;
|
159
|
-
}
|
160
|
-
|
161
|
-
const previousToken = sourceCode.getTokenBefore(token, { includeComments: true });
|
87
|
+
// Ignore comments that are the last token on their line if `ignoreEOLComments` is active.
|
88
|
+
if (
|
89
|
+
ignoreEOLComments &&
|
90
|
+
astUtils.isCommentToken(rightToken) &&
|
91
|
+
(
|
92
|
+
leftIndex === tokensAndComments.length - 2 ||
|
93
|
+
rightToken.loc.end.line < tokensAndComments[leftIndex + 2].loc.start.line
|
94
|
+
)
|
95
|
+
) {
|
96
|
+
return;
|
97
|
+
}
|
162
98
|
|
163
|
-
|
164
|
-
|
165
|
-
|
99
|
+
// Ignore tokens that are in a node in the "exceptions" object
|
100
|
+
if (hasExceptions) {
|
101
|
+
const parentNode = sourceCode.getNodeByRangeIndex(rightToken.range[0] - 1);
|
166
102
|
|
167
|
-
|
168
|
-
|
169
|
-
|
170
|
-
if (token.type === "Block") {
|
171
|
-
value = `/*${formatReportedCommentValue(token)}*/`;
|
172
|
-
} else if (token.type === "Line") {
|
173
|
-
value = `//${formatReportedCommentValue(token)}`;
|
174
|
-
}
|
175
|
-
|
176
|
-
context.report({
|
177
|
-
node: token,
|
178
|
-
loc: token.loc.start,
|
179
|
-
message: "Multiple spaces found before '{{value}}'.",
|
180
|
-
data: { value },
|
181
|
-
fix: createFix(previousToken, token)
|
182
|
-
});
|
183
|
-
}
|
103
|
+
if (parentNode && exceptions[parentNode.type]) {
|
104
|
+
return;
|
184
105
|
}
|
106
|
+
}
|
185
107
|
|
108
|
+
let displayValue;
|
109
|
+
|
110
|
+
if (rightToken.type === "Block") {
|
111
|
+
displayValue = `/*${formatReportedCommentValue(rightToken)}*/`;
|
112
|
+
} else if (rightToken.type === "Line") {
|
113
|
+
displayValue = `//${formatReportedCommentValue(rightToken)}`;
|
114
|
+
} else {
|
115
|
+
displayValue = rightToken.value;
|
186
116
|
}
|
187
|
-
|
117
|
+
|
118
|
+
context.report({
|
119
|
+
node: rightToken,
|
120
|
+
loc: rightToken.loc.start,
|
121
|
+
message: "Multiple spaces found before '{{displayValue}}'.",
|
122
|
+
data: { displayValue },
|
123
|
+
fix: fixer => fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], " ")
|
124
|
+
});
|
125
|
+
});
|
188
126
|
}
|
189
127
|
};
|
190
128
|
|
@@ -74,7 +74,7 @@ module.exports = {
|
|
74
74
|
nodeValue = token.value;
|
75
75
|
|
76
76
|
if (nodeType === "RegularExpression") {
|
77
|
-
checkRegex(node, nodeValue, token.
|
77
|
+
checkRegex(node, nodeValue, token.range[0]);
|
78
78
|
}
|
79
79
|
}
|
80
80
|
|
@@ -100,7 +100,7 @@ module.exports = {
|
|
100
100
|
const shadowed = regExpVar && regExpVar.defs.length > 0;
|
101
101
|
|
102
102
|
if (node.callee.type === "Identifier" && node.callee.name === "RegExp" && isString(node.arguments[0]) && !shadowed) {
|
103
|
-
checkRegex(node, node.arguments[0].value, node.arguments[0].
|
103
|
+
checkRegex(node, node.arguments[0].value, node.arguments[0].range[0] + 1);
|
104
104
|
}
|
105
105
|
}
|
106
106
|
|
@@ -4,6 +4,13 @@
|
|
4
4
|
*/
|
5
5
|
"use strict";
|
6
6
|
|
7
|
+
//------------------------------------------------------------------------------
|
8
|
+
// Helpers
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
|
11
|
+
const DEFAULT_MESSAGE_TEMPLATE = "Unexpected use of '{{name}}'.",
|
12
|
+
CUSTOM_MESSAGE_TEMPLATE = "Unexpected use of '{{name}}'. {{customMessage}}";
|
13
|
+
|
7
14
|
//------------------------------------------------------------------------------
|
8
15
|
// Rule Definition
|
9
16
|
//------------------------------------------------------------------------------
|
@@ -19,20 +26,43 @@ module.exports = {
|
|
19
26
|
schema: {
|
20
27
|
type: "array",
|
21
28
|
items: {
|
22
|
-
|
29
|
+
oneOf: [
|
30
|
+
{
|
31
|
+
type: "string"
|
32
|
+
},
|
33
|
+
{
|
34
|
+
type: "object",
|
35
|
+
properties: {
|
36
|
+
name: { type: "string" },
|
37
|
+
message: { type: "string" }
|
38
|
+
},
|
39
|
+
required: ["name"],
|
40
|
+
additionalProperties: false
|
41
|
+
}
|
42
|
+
]
|
23
43
|
},
|
24
|
-
uniqueItems: true
|
44
|
+
uniqueItems: true,
|
45
|
+
minItems: 0
|
25
46
|
}
|
26
47
|
},
|
27
48
|
|
28
49
|
create(context) {
|
29
|
-
const restrictedGlobals = context.options;
|
30
50
|
|
31
|
-
//
|
32
|
-
if (
|
51
|
+
// If no globals are restricted, we don't need to do anything
|
52
|
+
if (context.options.length === 0) {
|
33
53
|
return {};
|
34
54
|
}
|
35
55
|
|
56
|
+
const restrictedGlobalMessages = context.options.reduce((memo, option) => {
|
57
|
+
if (typeof option === "string") {
|
58
|
+
memo[option] = null;
|
59
|
+
} else {
|
60
|
+
memo[option.name] = option.message;
|
61
|
+
}
|
62
|
+
|
63
|
+
return memo;
|
64
|
+
}, {});
|
65
|
+
|
36
66
|
/**
|
37
67
|
* Report a variable to be used as a restricted global.
|
38
68
|
* @param {Reference} reference the variable reference
|
@@ -40,9 +70,20 @@ module.exports = {
|
|
40
70
|
* @private
|
41
71
|
*/
|
42
72
|
function reportReference(reference) {
|
43
|
-
|
44
|
-
|
45
|
-
|
73
|
+
const name = reference.identifier.name,
|
74
|
+
customMessage = restrictedGlobalMessages[name],
|
75
|
+
message = customMessage
|
76
|
+
? CUSTOM_MESSAGE_TEMPLATE
|
77
|
+
: DEFAULT_MESSAGE_TEMPLATE;
|
78
|
+
|
79
|
+
context.report({
|
80
|
+
node: reference.identifier,
|
81
|
+
message,
|
82
|
+
data: {
|
83
|
+
name,
|
84
|
+
customMessage
|
85
|
+
}
|
86
|
+
});
|
46
87
|
}
|
47
88
|
|
48
89
|
/**
|
@@ -52,7 +93,7 @@ module.exports = {
|
|
52
93
|
* @private
|
53
94
|
*/
|
54
95
|
function isRestricted(name) {
|
55
|
-
return
|
96
|
+
return restrictedGlobalMessages.hasOwnProperty(name);
|
56
97
|
}
|
57
98
|
|
58
99
|
return {
|
@@ -109,20 +109,28 @@ module.exports = {
|
|
109
109
|
if (matchedObjectProperty) {
|
110
110
|
const message = matchedObjectProperty.message ? ` ${matchedObjectProperty.message}` : "";
|
111
111
|
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
propertyName,
|
116
|
-
|
117
|
-
|
112
|
+
context.report({
|
113
|
+
node,
|
114
|
+
// eslint-disable-next-line eslint-plugin/report-message-format
|
115
|
+
message: "'{{objectName}}.{{propertyName}}' is restricted from being used.{{message}}",
|
116
|
+
data: {
|
117
|
+
objectName,
|
118
|
+
propertyName,
|
119
|
+
message
|
120
|
+
}
|
121
|
+
});
|
118
122
|
} else if (globalMatchedProperty) {
|
119
123
|
const message = globalMatchedProperty.message ? ` ${globalMatchedProperty.message}` : "";
|
120
124
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
message
|
125
|
-
|
125
|
+
context.report({
|
126
|
+
node,
|
127
|
+
// eslint-disable-next-line eslint-plugin/report-message-format
|
128
|
+
message: "'{{propertyName}}' is restricted from being used.{{message}}",
|
129
|
+
data: {
|
130
|
+
propertyName,
|
131
|
+
message
|
132
|
+
}
|
133
|
+
});
|
126
134
|
}
|
127
135
|
}
|
128
136
|
|
package/lib/rules/no-tabs.js
CHANGED
@@ -31,10 +31,14 @@ module.exports = {
|
|
31
31
|
const match = regex.exec(line);
|
32
32
|
|
33
33
|
if (match) {
|
34
|
-
context.report({
|
35
|
-
|
36
|
-
|
37
|
-
|
34
|
+
context.report({
|
35
|
+
node,
|
36
|
+
loc: {
|
37
|
+
line: index + 1,
|
38
|
+
column: match.index + 1
|
39
|
+
},
|
40
|
+
message: "Unexpected tab character."
|
41
|
+
});
|
38
42
|
}
|
39
43
|
});
|
40
44
|
}
|
@@ -32,6 +32,9 @@ module.exports = {
|
|
32
32
|
},
|
33
33
|
allowAfterSuper: {
|
34
34
|
type: "boolean"
|
35
|
+
},
|
36
|
+
enforceInMethodNames: {
|
37
|
+
type: "boolean"
|
35
38
|
}
|
36
39
|
},
|
37
40
|
additionalProperties: false
|
@@ -45,6 +48,7 @@ module.exports = {
|
|
45
48
|
const ALLOWED_VARIABLES = options.allow ? options.allow : [];
|
46
49
|
const allowAfterThis = typeof options.allowAfterThis !== "undefined" ? options.allowAfterThis : false;
|
47
50
|
const allowAfterSuper = typeof options.allowAfterSuper !== "undefined" ? options.allowAfterSuper : false;
|
51
|
+
const enforceInMethodNames = typeof options.enforceInMethodNames !== "undefined" ? options.enforceInMethodNames : false;
|
48
52
|
|
49
53
|
//-------------------------------------------------------------------------
|
50
54
|
// Helpers
|
@@ -162,6 +166,27 @@ module.exports = {
|
|
162
166
|
}
|
163
167
|
}
|
164
168
|
|
169
|
+
/**
|
170
|
+
* Check if method declaration or method property has a underscore at the end
|
171
|
+
* @param {ASTNode} node node to evaluate
|
172
|
+
* @returns {void}
|
173
|
+
* @private
|
174
|
+
*/
|
175
|
+
function checkForTrailingUnderscoreInMethod(node) {
|
176
|
+
const identifier = node.key.name;
|
177
|
+
const isMethod = node.type === "MethodDefinition" || node.type === "Property" && node.method;
|
178
|
+
|
179
|
+
if (typeof identifier !== "undefined" && enforceInMethodNames && isMethod && hasTrailingUnderscore(identifier)) {
|
180
|
+
context.report({
|
181
|
+
node,
|
182
|
+
message: "Unexpected dangling '_' in '{{identifier}}'.",
|
183
|
+
data: {
|
184
|
+
identifier
|
185
|
+
}
|
186
|
+
});
|
187
|
+
}
|
188
|
+
}
|
189
|
+
|
165
190
|
//--------------------------------------------------------------------------
|
166
191
|
// Public API
|
167
192
|
//--------------------------------------------------------------------------
|
@@ -169,7 +194,9 @@ module.exports = {
|
|
169
194
|
return {
|
170
195
|
FunctionDeclaration: checkForTrailingUnderscoreInFunctionDeclaration,
|
171
196
|
VariableDeclarator: checkForTrailingUnderscoreInVariableExpression,
|
172
|
-
MemberExpression: checkForTrailingUnderscoreInMemberExpression
|
197
|
+
MemberExpression: checkForTrailingUnderscoreInMemberExpression,
|
198
|
+
MethodDefinition: checkForTrailingUnderscoreInMethod,
|
199
|
+
Property: checkForTrailingUnderscoreInMethod
|
173
200
|
};
|
174
201
|
|
175
202
|
}
|
@@ -143,6 +143,8 @@ module.exports = {
|
|
143
143
|
first.loc.start.line !== last.loc.end.line
|
144
144
|
)
|
145
145
|
);
|
146
|
+
const hasCommentsFirstToken = astUtils.isCommentToken(first);
|
147
|
+
const hasCommentsLastToken = astUtils.isCommentToken(last);
|
146
148
|
|
147
149
|
/*
|
148
150
|
* Use tokens or comments to check multiline or not.
|
@@ -162,6 +164,10 @@ module.exports = {
|
|
162
164
|
node,
|
163
165
|
loc: openBrace.loc.start,
|
164
166
|
fix(fixer) {
|
167
|
+
if (hasCommentsFirstToken) {
|
168
|
+
return null;
|
169
|
+
}
|
170
|
+
|
165
171
|
return fixer.insertTextAfter(openBrace, "\n");
|
166
172
|
}
|
167
173
|
});
|
@@ -172,6 +178,10 @@ module.exports = {
|
|
172
178
|
node,
|
173
179
|
loc: closeBrace.loc.start,
|
174
180
|
fix(fixer) {
|
181
|
+
if (hasCommentsLastToken) {
|
182
|
+
return null;
|
183
|
+
}
|
184
|
+
|
175
185
|
return fixer.insertTextBefore(closeBrace, "\n");
|
176
186
|
}
|
177
187
|
});
|
@@ -190,6 +200,10 @@ module.exports = {
|
|
190
200
|
node,
|
191
201
|
loc: openBrace.loc.start,
|
192
202
|
fix(fixer) {
|
203
|
+
if (hasCommentsFirstToken) {
|
204
|
+
return null;
|
205
|
+
}
|
206
|
+
|
193
207
|
return fixer.removeRange([
|
194
208
|
openBrace.range[1],
|
195
209
|
first.range[0]
|
@@ -206,6 +220,10 @@ module.exports = {
|
|
206
220
|
node,
|
207
221
|
loc: closeBrace.loc.start,
|
208
222
|
fix(fixer) {
|
223
|
+
if (hasCommentsLastToken) {
|
224
|
+
return null;
|
225
|
+
}
|
226
|
+
|
209
227
|
return fixer.removeRange([
|
210
228
|
last.range[1],
|
211
229
|
closeBrace.range[0]
|