eslint 4.7.2 → 4.11.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/CHANGELOG.md +123 -0
- package/README.md +34 -19
- package/conf/default-cli-options.js +7 -4
- package/conf/eslint-recommended.js +2 -0
- package/lib/ast-utils.js +83 -42
- package/lib/cli-engine.js +53 -17
- package/lib/cli.js +17 -9
- package/lib/code-path-analysis/code-path-analyzer.js +8 -4
- package/lib/code-path-analysis/code-path-segment.js +43 -41
- package/lib/code-path-analysis/code-path-state.js +7 -2
- package/lib/config/autoconfig.js +14 -12
- package/lib/config/config-file.js +8 -51
- package/lib/config/config-initializer.js +10 -6
- package/lib/config/config-ops.js +21 -21
- package/lib/config/config-rule.js +24 -24
- package/lib/config/config-validator.js +38 -36
- package/lib/config/plugins.js +8 -35
- package/lib/config.js +12 -8
- package/lib/formatters/html-template-message.html +1 -1
- package/lib/formatters/html-template-page.html +3 -1
- package/lib/formatters/html.js +2 -1
- package/lib/formatters/junit.js +21 -15
- package/lib/formatters/tap.js +5 -3
- package/lib/ignored-paths.js +5 -3
- package/lib/linter.js +42 -42
- package/lib/logging.js +2 -2
- package/lib/options.js +12 -0
- package/lib/rules/.eslintrc.yml +2 -2
- package/lib/rules/array-bracket-newline.js +39 -25
- package/lib/rules/array-bracket-spacing.js +28 -28
- package/lib/rules/array-callback-return.js +13 -9
- package/lib/rules/array-element-newline.js +8 -8
- package/lib/rules/arrow-body-style.js +12 -6
- package/lib/rules/arrow-parens.js +4 -2
- package/lib/rules/block-spacing.js +1 -1
- package/lib/rules/brace-style.js +14 -14
- package/lib/rules/callback-return.js +2 -1
- package/lib/rules/capitalized-comments.js +2 -1
- package/lib/rules/comma-style.js +3 -1
- package/lib/rules/computed-property-spacing.js +22 -22
- package/lib/rules/consistent-return.js +4 -4
- package/lib/rules/consistent-this.js +4 -2
- package/lib/rules/curly.js +13 -9
- package/lib/rules/dot-notation.js +56 -35
- package/lib/rules/func-call-spacing.js +4 -2
- package/lib/rules/generator-star-spacing.js +3 -3
- package/lib/rules/getter-return.js +2 -1
- package/lib/rules/indent-legacy.js +25 -14
- package/lib/rules/indent.js +101 -91
- package/lib/rules/key-spacing.js +5 -3
- package/lib/rules/lines-around-comment.js +33 -4
- package/lib/rules/lines-around-directive.js +16 -12
- package/lib/rules/lines-between-class-members.js +91 -0
- package/lib/rules/max-len.js +2 -3
- package/lib/rules/max-statements-per-line.js +5 -3
- package/lib/rules/multiline-comment-style.js +294 -0
- package/lib/rules/new-cap.js +2 -1
- package/lib/rules/newline-after-var.js +8 -6
- package/lib/rules/newline-before-return.js +13 -9
- package/lib/rules/no-alert.js +7 -15
- package/lib/rules/no-await-in-loop.js +17 -9
- package/lib/rules/no-bitwise.js +5 -3
- package/lib/rules/no-catch-shadow.js +4 -2
- package/lib/rules/no-console.js +2 -1
- package/lib/rules/no-constant-condition.js +2 -2
- package/lib/rules/no-control-regex.js +2 -1
- package/lib/rules/no-else-return.js +60 -19
- package/lib/rules/no-empty-character-class.js +11 -11
- package/lib/rules/no-extra-parens.js +22 -11
- package/lib/rules/no-extra-semi.js +5 -3
- package/lib/rules/no-global-assign.js +4 -2
- package/lib/rules/no-implicit-coercion.js +6 -6
- package/lib/rules/no-implied-eval.js +2 -1
- package/lib/rules/no-label-var.js +4 -2
- package/lib/rules/no-lone-blocks.js +3 -3
- package/lib/rules/no-lonely-if.js +2 -1
- package/lib/rules/no-loop-func.js +10 -7
- package/lib/rules/no-mixed-requires.js +8 -4
- package/lib/rules/no-native-reassign.js +4 -2
- package/lib/rules/no-param-reassign.js +4 -2
- package/lib/rules/no-regex-spaces.js +1 -1
- package/lib/rules/no-restricted-imports.js +86 -17
- package/lib/rules/no-restricted-modules.js +84 -15
- package/lib/rules/no-restricted-properties.js +10 -10
- package/lib/rules/no-return-await.js +6 -6
- package/lib/rules/no-self-assign.js +4 -2
- package/lib/rules/no-sequences.js +6 -4
- package/lib/rules/no-trailing-spaces.js +14 -8
- package/lib/rules/no-unneeded-ternary.js +3 -1
- package/lib/rules/no-unreachable.js +4 -2
- package/lib/rules/no-unused-labels.js +2 -1
- package/lib/rules/no-use-before-define.js +13 -11
- package/lib/rules/no-useless-call.js +1 -25
- package/lib/rules/no-useless-computed-key.js +2 -1
- package/lib/rules/no-useless-escape.js +31 -23
- package/lib/rules/no-useless-return.js +14 -8
- package/lib/rules/no-var.js +11 -0
- package/lib/rules/no-whitespace-before-property.js +4 -2
- package/lib/rules/object-curly-newline.js +9 -2
- package/lib/rules/object-curly-spacing.js +20 -20
- package/lib/rules/object-shorthand.js +47 -35
- package/lib/rules/operator-assignment.js +9 -9
- package/lib/rules/operator-linebreak.js +15 -11
- package/lib/rules/padding-line-between-statements.js +6 -4
- package/lib/rules/prefer-arrow-callback.js +12 -10
- package/lib/rules/prefer-const.js +18 -10
- package/lib/rules/prefer-destructuring.js +4 -2
- package/lib/rules/prefer-numeric-literals.js +4 -2
- package/lib/rules/prefer-promise-reject-errors.js +16 -16
- package/lib/rules/prefer-rest-params.js +4 -2
- package/lib/rules/prefer-spread.js +1 -25
- package/lib/rules/prefer-template.js +33 -29
- package/lib/rules/quote-props.js +8 -8
- package/lib/rules/require-jsdoc.js +11 -18
- package/lib/rules/semi-style.js +44 -19
- package/lib/rules/semi.js +5 -3
- package/lib/rules/sort-imports.js +11 -6
- package/lib/rules/space-unary-ops.js +67 -69
- package/lib/rules/strict.js +8 -8
- package/lib/rules/valid-jsdoc.js +39 -33
- package/lib/rules/valid-typeof.js +4 -4
- package/lib/rules/wrap-iife.js +4 -4
- package/lib/rules/yoda.js +9 -7
- package/lib/testers/rule-tester.js +63 -40
- package/lib/token-store/backward-token-cursor.js +5 -3
- package/lib/token-store/forward-token-cursor.js +5 -3
- package/lib/token-store/utils.js +8 -4
- package/lib/util/apply-disable-directives.js +56 -27
- package/lib/util/glob.js +1 -1
- package/lib/util/naming.js +112 -0
- package/lib/util/node-event-generator.js +13 -27
- package/lib/util/safe-emitter.js +54 -0
- package/lib/util/source-code-fixer.js +4 -2
- package/lib/util/source-code.js +70 -65
- package/messages/no-config-found.txt +1 -1
- package/package.json +8 -8
- package/lib/internal-rules/.eslintrc.yml +0 -3
- package/lib/internal-rules/internal-consistent-docs-description.js +0 -130
- package/lib/internal-rules/internal-no-invalid-meta.js +0 -188
@@ -127,8 +127,10 @@ module.exports = {
|
|
127
127
|
if (identifier &&
|
128
128
|
!reference.init &&
|
129
129
|
|
130
|
-
|
131
|
-
|
130
|
+
/*
|
131
|
+
* Destructuring assignments can have multiple default value,
|
132
|
+
* so possibly there are multiple writeable references for the same identifier.
|
133
|
+
*/
|
132
134
|
(index === 0 || references[index - 1].identifier !== identifier)
|
133
135
|
) {
|
134
136
|
if (reference.isWrite()) {
|
@@ -32,7 +32,7 @@ module.exports = {
|
|
32
32
|
* @param {ASTNode} node node to validate
|
33
33
|
* @param {string} value regular expression to validate
|
34
34
|
* @param {number} valueStart The start location of the regex/string literal. It will always be the case that
|
35
|
-
`sourceCode.getText().slice(valueStart, valueStart + value.length) === value`
|
35
|
+
* `sourceCode.getText().slice(valueStart, valueStart + value.length) === value`
|
36
36
|
* @returns {void}
|
37
37
|
* @private
|
38
38
|
*/
|
@@ -4,6 +4,13 @@
|
|
4
4
|
*/
|
5
5
|
"use strict";
|
6
6
|
|
7
|
+
//------------------------------------------------------------------------------
|
8
|
+
// Helpers
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
|
11
|
+
const DEFAULT_MESSAGE_TEMPLATE = "'{{importName}}' import is restricted from being used.";
|
12
|
+
const CUSTOM_MESSAGE_TEMPLATE = "'{{importName}}' import is restricted from being used. {{customMessage}}";
|
13
|
+
|
7
14
|
//------------------------------------------------------------------------------
|
8
15
|
// Rule Definition
|
9
16
|
//------------------------------------------------------------------------------
|
@@ -11,9 +18,29 @@
|
|
11
18
|
const ignore = require("ignore");
|
12
19
|
|
13
20
|
const arrayOfStrings = {
|
21
|
+
type: "array",
|
22
|
+
items: { type: "string" },
|
23
|
+
uniqueItems: true
|
24
|
+
};
|
25
|
+
|
26
|
+
const arrayOfStringsOrObjects = {
|
14
27
|
type: "array",
|
15
28
|
items: {
|
16
|
-
|
29
|
+
anyOf: [
|
30
|
+
{ type: "string" },
|
31
|
+
{
|
32
|
+
type: "object",
|
33
|
+
properties: {
|
34
|
+
name: { type: "string" },
|
35
|
+
message: {
|
36
|
+
type: "string",
|
37
|
+
minLength: 1
|
38
|
+
}
|
39
|
+
},
|
40
|
+
additionalProperties: false,
|
41
|
+
required: ["name"]
|
42
|
+
}
|
43
|
+
]
|
17
44
|
},
|
18
45
|
uniqueItems: true
|
19
46
|
};
|
@@ -28,17 +55,17 @@ module.exports = {
|
|
28
55
|
|
29
56
|
schema: {
|
30
57
|
anyOf: [
|
31
|
-
|
58
|
+
arrayOfStringsOrObjects,
|
32
59
|
{
|
33
60
|
type: "array",
|
34
|
-
items:
|
61
|
+
items: {
|
35
62
|
type: "object",
|
36
63
|
properties: {
|
37
|
-
paths:
|
64
|
+
paths: arrayOfStringsOrObjects,
|
38
65
|
patterns: arrayOfStrings
|
39
66
|
},
|
40
67
|
additionalProperties: false
|
41
|
-
}
|
68
|
+
},
|
42
69
|
additionalItems: false
|
43
70
|
}
|
44
71
|
]
|
@@ -47,35 +74,77 @@ module.exports = {
|
|
47
74
|
|
48
75
|
create(context) {
|
49
76
|
const options = Array.isArray(context.options) ? context.options : [];
|
50
|
-
const
|
51
|
-
|
52
|
-
|
77
|
+
const isPathAndPatternsObject =
|
78
|
+
typeof options[0] === "object" &&
|
79
|
+
(options[0].hasOwnProperty("paths") || options[0].hasOwnProperty("patterns"));
|
80
|
+
|
81
|
+
const restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || [];
|
82
|
+
const restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
|
83
|
+
|
84
|
+
const restrictedPathMessages = restrictedPaths.reduce((memo, importName) => {
|
85
|
+
if (typeof importName === "string") {
|
86
|
+
memo[importName] = null;
|
87
|
+
} else {
|
88
|
+
memo[importName.name] = importName.message;
|
89
|
+
}
|
90
|
+
return memo;
|
91
|
+
}, {});
|
53
92
|
|
54
93
|
// if no imports are restricted we don"t need to check
|
55
|
-
if (restrictedPaths.
|
94
|
+
if (Object.keys(restrictedPaths).length === 0 && restrictedPatterns.length === 0) {
|
56
95
|
return {};
|
57
96
|
}
|
58
97
|
|
59
98
|
const ig = ignore().add(restrictedPatterns);
|
60
99
|
|
100
|
+
/**
|
101
|
+
* Report a restricted path.
|
102
|
+
* @param {node} node representing the restricted path reference
|
103
|
+
* @returns {void}
|
104
|
+
* @private
|
105
|
+
*/
|
106
|
+
function reportPath(node) {
|
107
|
+
const importName = node.source.value.trim();
|
108
|
+
const customMessage = restrictedPathMessages[importName];
|
109
|
+
const message = customMessage
|
110
|
+
? CUSTOM_MESSAGE_TEMPLATE
|
111
|
+
: DEFAULT_MESSAGE_TEMPLATE;
|
112
|
+
|
113
|
+
context.report({
|
114
|
+
node,
|
115
|
+
message,
|
116
|
+
data: {
|
117
|
+
importName,
|
118
|
+
customMessage
|
119
|
+
}
|
120
|
+
});
|
121
|
+
}
|
122
|
+
|
123
|
+
/**
|
124
|
+
* Check if the given name is a restricted path name.
|
125
|
+
* @param {string} name name of a variable
|
126
|
+
* @returns {boolean} whether the variable is a restricted path or not
|
127
|
+
* @private
|
128
|
+
*/
|
129
|
+
function isRestrictedPath(name) {
|
130
|
+
return Object.prototype.hasOwnProperty.call(restrictedPathMessages, name);
|
131
|
+
}
|
132
|
+
|
61
133
|
return {
|
62
134
|
ImportDeclaration(node) {
|
63
135
|
if (node && node.source && node.source.value) {
|
64
|
-
|
65
136
|
const importName = node.source.value.trim();
|
66
137
|
|
67
|
-
if (
|
68
|
-
|
69
|
-
node,
|
70
|
-
message: "'{{importName}}' import is restricted from being used.",
|
71
|
-
data: { importName }
|
72
|
-
});
|
138
|
+
if (isRestrictedPath(importName)) {
|
139
|
+
reportPath(node);
|
73
140
|
}
|
74
141
|
if (restrictedPatterns.length > 0 && ig.ignores(importName)) {
|
75
142
|
context.report({
|
76
143
|
node,
|
77
144
|
message: "'{{importName}}' import is restricted from being used by a pattern.",
|
78
|
-
data: {
|
145
|
+
data: {
|
146
|
+
importName
|
147
|
+
}
|
79
148
|
});
|
80
149
|
}
|
81
150
|
}
|
@@ -4,6 +4,13 @@
|
|
4
4
|
*/
|
5
5
|
"use strict";
|
6
6
|
|
7
|
+
//------------------------------------------------------------------------------
|
8
|
+
// Helpers
|
9
|
+
//------------------------------------------------------------------------------
|
10
|
+
|
11
|
+
const DEFAULT_MESSAGE_TEMPLATE = "'{{moduleName}}' module is restricted from being used.";
|
12
|
+
const CUSTOM_MESSAGE_TEMPLATE = "'{{moduleName}}' module is restricted from being used. {{customMessage}}";
|
13
|
+
|
7
14
|
//------------------------------------------------------------------------------
|
8
15
|
// Rule Definition
|
9
16
|
//------------------------------------------------------------------------------
|
@@ -11,9 +18,29 @@
|
|
11
18
|
const ignore = require("ignore");
|
12
19
|
|
13
20
|
const arrayOfStrings = {
|
21
|
+
type: "array",
|
22
|
+
items: { type: "string" },
|
23
|
+
uniqueItems: true
|
24
|
+
};
|
25
|
+
|
26
|
+
const arrayOfStringsOrObjects = {
|
14
27
|
type: "array",
|
15
28
|
items: {
|
16
|
-
|
29
|
+
anyOf: [
|
30
|
+
{ type: "string" },
|
31
|
+
{
|
32
|
+
type: "object",
|
33
|
+
properties: {
|
34
|
+
name: { type: "string" },
|
35
|
+
message: {
|
36
|
+
type: "string",
|
37
|
+
minLength: 1
|
38
|
+
}
|
39
|
+
},
|
40
|
+
additionalProperties: false,
|
41
|
+
required: ["name"]
|
42
|
+
}
|
43
|
+
]
|
17
44
|
},
|
18
45
|
uniqueItems: true
|
19
46
|
};
|
@@ -28,17 +55,17 @@ module.exports = {
|
|
28
55
|
|
29
56
|
schema: {
|
30
57
|
anyOf: [
|
31
|
-
|
58
|
+
arrayOfStringsOrObjects,
|
32
59
|
{
|
33
60
|
type: "array",
|
34
|
-
items:
|
61
|
+
items: {
|
35
62
|
type: "object",
|
36
63
|
properties: {
|
37
|
-
paths:
|
64
|
+
paths: arrayOfStringsOrObjects,
|
38
65
|
patterns: arrayOfStrings
|
39
66
|
},
|
40
67
|
additionalProperties: false
|
41
|
-
}
|
68
|
+
},
|
42
69
|
additionalItems: false
|
43
70
|
}
|
44
71
|
]
|
@@ -47,17 +74,30 @@ module.exports = {
|
|
47
74
|
|
48
75
|
create(context) {
|
49
76
|
const options = Array.isArray(context.options) ? context.options : [];
|
50
|
-
const
|
51
|
-
|
52
|
-
|
77
|
+
const isPathAndPatternsObject =
|
78
|
+
typeof options[0] === "object" &&
|
79
|
+
(options[0].hasOwnProperty("paths") || options[0].hasOwnProperty("patterns"));
|
80
|
+
|
81
|
+
const restrictedPaths = (isPathAndPatternsObject ? options[0].paths : context.options) || [];
|
82
|
+
const restrictedPatterns = (isPathAndPatternsObject ? options[0].patterns : []) || [];
|
83
|
+
|
84
|
+
const restrictedPathMessages = restrictedPaths.reduce((memo, importName) => {
|
85
|
+
if (typeof importName === "string") {
|
86
|
+
memo[importName] = null;
|
87
|
+
} else {
|
88
|
+
memo[importName.name] = importName.message;
|
89
|
+
}
|
90
|
+
return memo;
|
91
|
+
}, {});
|
53
92
|
|
54
93
|
// if no imports are restricted we don"t need to check
|
55
|
-
if (restrictedPaths.
|
94
|
+
if (Object.keys(restrictedPaths).length === 0 && restrictedPatterns.length === 0) {
|
56
95
|
return {};
|
57
96
|
}
|
58
97
|
|
59
98
|
const ig = ignore().add(restrictedPatterns);
|
60
99
|
|
100
|
+
|
61
101
|
/**
|
62
102
|
* Function to check if a node is a string literal.
|
63
103
|
* @param {ASTNode} node The node to check.
|
@@ -76,6 +116,39 @@ module.exports = {
|
|
76
116
|
return node.callee.type === "Identifier" && node.callee.name === "require";
|
77
117
|
}
|
78
118
|
|
119
|
+
/**
|
120
|
+
* Report a restricted path.
|
121
|
+
* @param {node} node representing the restricted path reference
|
122
|
+
* @returns {void}
|
123
|
+
* @private
|
124
|
+
*/
|
125
|
+
function reportPath(node) {
|
126
|
+
const moduleName = node.arguments[0].value.trim();
|
127
|
+
const customMessage = restrictedPathMessages[moduleName];
|
128
|
+
const message = customMessage
|
129
|
+
? CUSTOM_MESSAGE_TEMPLATE
|
130
|
+
: DEFAULT_MESSAGE_TEMPLATE;
|
131
|
+
|
132
|
+
context.report({
|
133
|
+
node,
|
134
|
+
message,
|
135
|
+
data: {
|
136
|
+
moduleName,
|
137
|
+
customMessage
|
138
|
+
}
|
139
|
+
});
|
140
|
+
}
|
141
|
+
|
142
|
+
/**
|
143
|
+
* Check if the given name is a restricted path name
|
144
|
+
* @param {string} name name of a variable
|
145
|
+
* @returns {boolean} whether the variable is a restricted path or not
|
146
|
+
* @private
|
147
|
+
*/
|
148
|
+
function isRestrictedPath(name) {
|
149
|
+
return Object.prototype.hasOwnProperty.call(restrictedPathMessages, name);
|
150
|
+
}
|
151
|
+
|
79
152
|
return {
|
80
153
|
CallExpression(node) {
|
81
154
|
if (isRequireCall(node)) {
|
@@ -85,12 +158,8 @@ module.exports = {
|
|
85
158
|
const moduleName = node.arguments[0].value.trim();
|
86
159
|
|
87
160
|
// check if argument value is in restricted modules array
|
88
|
-
if (
|
89
|
-
|
90
|
-
node,
|
91
|
-
message: "'{{moduleName}}' module is restricted from being used.",
|
92
|
-
data: { moduleName }
|
93
|
-
});
|
161
|
+
if (isRestrictedPath(moduleName)) {
|
162
|
+
reportPath(node);
|
94
163
|
}
|
95
164
|
|
96
165
|
if (restrictedPatterns.length > 0 && ig.ignores(moduleName)) {
|
@@ -92,12 +92,12 @@ module.exports = {
|
|
92
92
|
});
|
93
93
|
|
94
94
|
/**
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
95
|
+
* Checks to see whether a property access is restricted, and reports it if so.
|
96
|
+
* @param {ASTNode} node The node to report
|
97
|
+
* @param {string} objectName The name of the object
|
98
|
+
* @param {string} propertyName The name of the property
|
99
|
+
* @returns {undefined}
|
100
|
+
*/
|
101
101
|
function checkPropertyAccess(node, objectName, propertyName) {
|
102
102
|
if (propertyName === null) {
|
103
103
|
return;
|
@@ -135,10 +135,10 @@ module.exports = {
|
|
135
135
|
}
|
136
136
|
|
137
137
|
/**
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
138
|
+
* Checks property accesses in a destructuring assignment expression, e.g. `var foo; ({foo} = bar);`
|
139
|
+
* @param {ASTNode} node An AssignmentExpression or AssignmentPattern node
|
140
|
+
* @returns {undefined}
|
141
|
+
*/
|
142
142
|
function checkDestructuringAssignment(node) {
|
143
143
|
if (node.right.type === "Identifier") {
|
144
144
|
const objectName = node.right.name;
|
@@ -40,12 +40,12 @@ module.exports = {
|
|
40
40
|
}
|
41
41
|
|
42
42
|
/**
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
43
|
+
* Determines whether a thrown error from this node will be caught/handled within this function rather than immediately halting
|
44
|
+
* this function. For example, a statement in a `try` block will always have an error handler. A statement in
|
45
|
+
* a `catch` block will only have an error handler if there is also a `finally` block.
|
46
|
+
* @param {ASTNode} node A node representing a location where an could be thrown
|
47
|
+
* @returns {boolean} `true` if a thrown error will be caught/handled in this function
|
48
|
+
*/
|
49
49
|
function hasErrorHandler(node) {
|
50
50
|
let ancestor = node;
|
51
51
|
|
@@ -114,8 +114,10 @@ function eachSelfAssignment(left, right, props, report) {
|
|
114
114
|
right.properties.length >= 1
|
115
115
|
) {
|
116
116
|
|
117
|
-
|
118
|
-
|
117
|
+
/*
|
118
|
+
* Gets the index of the last spread property.
|
119
|
+
* It's possible to overwrite properties followed by it.
|
120
|
+
*/
|
119
121
|
let startJ = 0;
|
120
122
|
|
121
123
|
for (let i = right.properties.length - 1; i >= 0; --i) {
|
@@ -40,10 +40,12 @@ module.exports = {
|
|
40
40
|
WithStatement: "object",
|
41
41
|
ArrowFunctionExpression: "body"
|
42
42
|
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
43
|
+
/*
|
44
|
+
* Omitting CallExpression - commas are parsed as argument separators
|
45
|
+
* Omitting NewExpression - commas are parsed as argument separators
|
46
|
+
* Omitting ForInStatement - parts aren't individually parenthesised
|
47
|
+
* Omitting ForStatement - parts aren't individually parenthesised
|
48
|
+
*/
|
47
49
|
};
|
48
50
|
|
49
51
|
/**
|
@@ -49,7 +49,7 @@ module.exports = {
|
|
49
49
|
|
50
50
|
const options = context.options[0] || {},
|
51
51
|
skipBlankLines = options.skipBlankLines || false,
|
52
|
-
ignoreComments = typeof options.ignoreComments === "
|
52
|
+
ignoreComments = typeof options.ignoreComments === "boolean" && options.ignoreComments;
|
53
53
|
|
54
54
|
/**
|
55
55
|
* Report the error message
|
@@ -101,8 +101,10 @@ module.exports = {
|
|
101
101
|
|
102
102
|
Program: function checkTrailingSpaces(node) {
|
103
103
|
|
104
|
-
|
105
|
-
|
104
|
+
/*
|
105
|
+
* Let's hack. Since Espree does not return whitespace nodes,
|
106
|
+
* fetch the source code and do matching via regexps.
|
107
|
+
*/
|
106
108
|
|
107
109
|
const re = new RegExp(NONBLANK),
|
108
110
|
skipMatch = new RegExp(SKIP_BLANK),
|
@@ -117,9 +119,11 @@ module.exports = {
|
|
117
119
|
for (let i = 0, ii = lines.length; i < ii; i++) {
|
118
120
|
const matches = re.exec(lines[i]);
|
119
121
|
|
120
|
-
|
121
|
-
|
122
|
-
|
122
|
+
/*
|
123
|
+
* Always add linebreak length to line length to accommodate for line break (\n or \r\n)
|
124
|
+
* Because during the fix time they also reserve one spot in the array.
|
125
|
+
* Usually linebreak length is 2 for \r\n (CRLF) and 1 for \n (LF)
|
126
|
+
*/
|
123
127
|
const linebreakLength = linebreaks && linebreaks[i] ? linebreaks[i].length : 1;
|
124
128
|
const lineLength = lines[i].length + linebreakLength;
|
125
129
|
|
@@ -140,8 +144,10 @@ module.exports = {
|
|
140
144
|
continue;
|
141
145
|
}
|
142
146
|
|
143
|
-
|
144
|
-
|
147
|
+
/*
|
148
|
+
* If the line has only whitespace, and skipBlankLines
|
149
|
+
* is true, don't report it
|
150
|
+
*/
|
145
151
|
if (skipBlankLines && skipMatch.test(lines[i])) {
|
146
152
|
totalLength += lineLength;
|
147
153
|
continue;
|
@@ -72,8 +72,10 @@ module.exports = {
|
|
72
72
|
node.right,
|
73
73
|
token => token.value === node.operator
|
74
74
|
);
|
75
|
+
const text = sourceCode.getText();
|
75
76
|
|
76
|
-
return
|
77
|
+
return text.slice(node.range[0],
|
78
|
+
operatorToken.range[0]) + OPERATOR_INVERSES[node.operator] + text.slice(operatorToken.range[1], node.range[1]);
|
77
79
|
}
|
78
80
|
|
79
81
|
if (astUtils.getPrecedence(node) < astUtils.getPrecedence({ type: "UnaryExpression" })) {
|
@@ -145,8 +145,10 @@ module.exports = {
|
|
145
145
|
nextNode = node;
|
146
146
|
}
|
147
147
|
|
148
|
-
|
149
|
-
|
148
|
+
/*
|
149
|
+
* Report the current range since this statement is reachable or is
|
150
|
+
* not consecutive to the current range.
|
151
|
+
*/
|
150
152
|
if (!range.isEmpty) {
|
151
153
|
context.report({
|
152
154
|
message: "Unreachable code.",
|
@@ -59,7 +59,8 @@ module.exports = {
|
|
59
59
|
* Only perform a fix if there are no comments between the label and the body. This will be the case
|
60
60
|
* when there is exactly one token/comment (the ":") between the label and the body.
|
61
61
|
*/
|
62
|
-
if (sourceCode.getTokenAfter(node.label, { includeComments: true }) ===
|
62
|
+
if (sourceCode.getTokenAfter(node.label, { includeComments: true }) ===
|
63
|
+
sourceCode.getTokenBefore(node.body, { includeComments: true })) {
|
63
64
|
return fixer.removeRange([node.range[0], node.body.range[0]]);
|
64
65
|
}
|
65
66
|
|
@@ -59,11 +59,11 @@ function isOuterClass(variable, reference) {
|
|
59
59
|
}
|
60
60
|
|
61
61
|
/**
|
62
|
-
* Checks whether or not a given variable is a variable declaration in an upper function scope.
|
63
|
-
* @param {eslint-scope.Variable} variable - A variable to check.
|
64
|
-
* @param {eslint-scope.Reference} reference - A reference to check.
|
65
|
-
* @returns {boolean} `true` if the variable is a variable declaration.
|
66
|
-
*/
|
62
|
+
* Checks whether or not a given variable is a variable declaration in an upper function scope.
|
63
|
+
* @param {eslint-scope.Variable} variable - A variable to check.
|
64
|
+
* @param {eslint-scope.Reference} reference - A reference to check.
|
65
|
+
* @returns {boolean} `true` if the variable is a variable declaration.
|
66
|
+
*/
|
67
67
|
function isOuterVariable(variable, reference) {
|
68
68
|
return (
|
69
69
|
variable.defs[0].type === "Variable" &&
|
@@ -194,12 +194,14 @@ module.exports = {
|
|
194
194
|
scope.references.forEach(reference => {
|
195
195
|
const variable = reference.resolved;
|
196
196
|
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
197
|
+
/*
|
198
|
+
* Skips when the reference is:
|
199
|
+
* - initialization's.
|
200
|
+
* - referring to an undefined variable.
|
201
|
+
* - referring to a global environment variable (there're no identifiers).
|
202
|
+
* - located preceded by the variable (except in initializers).
|
203
|
+
* - allowed by options.
|
204
|
+
*/
|
203
205
|
if (reference.init ||
|
204
206
|
!variable ||
|
205
207
|
variable.identifiers.length === 0 ||
|
@@ -28,30 +28,6 @@ function isCallOrNonVariadicApply(node) {
|
|
28
28
|
);
|
29
29
|
}
|
30
30
|
|
31
|
-
/**
|
32
|
-
* Checks whether or not the tokens of two given nodes are same.
|
33
|
-
* @param {ASTNode} left - A node 1 to compare.
|
34
|
-
* @param {ASTNode} right - A node 2 to compare.
|
35
|
-
* @param {SourceCode} sourceCode - The ESLint source code object.
|
36
|
-
* @returns {boolean} the source code for the given node.
|
37
|
-
*/
|
38
|
-
function equalTokens(left, right, sourceCode) {
|
39
|
-
const tokensL = sourceCode.getTokens(left);
|
40
|
-
const tokensR = sourceCode.getTokens(right);
|
41
|
-
|
42
|
-
if (tokensL.length !== tokensR.length) {
|
43
|
-
return false;
|
44
|
-
}
|
45
|
-
for (let i = 0; i < tokensL.length; ++i) {
|
46
|
-
if (tokensL[i].type !== tokensR[i].type ||
|
47
|
-
tokensL[i].value !== tokensR[i].value
|
48
|
-
) {
|
49
|
-
return false;
|
50
|
-
}
|
51
|
-
}
|
52
|
-
|
53
|
-
return true;
|
54
|
-
}
|
55
31
|
|
56
32
|
/**
|
57
33
|
* Checks whether or not `thisArg` is not changed by `.call()`/`.apply()`.
|
@@ -64,7 +40,7 @@ function isValidThisArg(expectedThis, thisArg, sourceCode) {
|
|
64
40
|
if (!expectedThis) {
|
65
41
|
return astUtils.isNullOrUndefined(thisArg);
|
66
42
|
}
|
67
|
-
return equalTokens(expectedThis, thisArg, sourceCode);
|
43
|
+
return astUtils.equalTokens(expectedThis, thisArg, sourceCode);
|
68
44
|
}
|
69
45
|
|
70
46
|
//------------------------------------------------------------------------------
|
@@ -50,7 +50,8 @@ module.exports = {
|
|
50
50
|
const rightSquareBracket = sourceCode.getFirstTokenBetween(node.key, node.value, astUtils.isClosingBracketToken);
|
51
51
|
const tokensBetween = sourceCode.getTokensBetween(leftSquareBracket, rightSquareBracket, 1);
|
52
52
|
|
53
|
-
if (tokensBetween.slice(0, -1).some((token, index) =>
|
53
|
+
if (tokensBetween.slice(0, -1).some((token, index) =>
|
54
|
+
sourceCode.getText().slice(token.range[1], tokensBetween[index + 1].range[0]).trim())) {
|
54
55
|
|
55
56
|
// If there are comments between the brackets and the property name, don't do a fix.
|
56
57
|
return null;
|