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
@@ -174,7 +174,7 @@ module.exports = {
|
|
174
174
|
options.arraysInObjectsException && astUtils.isClosingBracketToken(penultimate) ||
|
175
175
|
options.objectsInObjectsException && astUtils.isClosingBraceToken(penultimate)
|
176
176
|
);
|
177
|
-
const penultimateType = shouldCheckPenultimate && sourceCode.getNodeByRangeIndex(penultimate.
|
177
|
+
const penultimateType = shouldCheckPenultimate && sourceCode.getNodeByRangeIndex(penultimate.range[0]).type;
|
178
178
|
|
179
179
|
const closingCurlyBraceMustBeSpaced = (
|
180
180
|
options.arraysInObjectsException && penultimateType === "ArrayExpression" ||
|
@@ -202,7 +202,7 @@ module.exports = {
|
|
202
202
|
node,
|
203
203
|
loc: { line: tokenBeforeFirst.loc.start.line, column: tokenBeforeFirst.loc.start.column },
|
204
204
|
fix(fixer) {
|
205
|
-
return fixer.replaceTextRange([tokenBeforeFirst.
|
205
|
+
return fixer.replaceTextRange([tokenBeforeFirst.range[1], firstBlockToken.range[0] - firstBlockToken.loc.start.column], "\n");
|
206
206
|
},
|
207
207
|
message: NEVER_MESSAGE
|
208
208
|
});
|
@@ -215,7 +215,7 @@ module.exports = {
|
|
215
215
|
loc: { line: tokenAfterLast.loc.end.line, column: tokenAfterLast.loc.end.column - 1 },
|
216
216
|
message: NEVER_MESSAGE,
|
217
217
|
fix(fixer) {
|
218
|
-
return fixer.replaceTextRange([lastBlockToken.
|
218
|
+
return fixer.replaceTextRange([lastBlockToken.range[1], tokenAfterLast.range[0] - tokenAfterLast.loc.start.column], "\n");
|
219
219
|
}
|
220
220
|
});
|
221
221
|
}
|
@@ -93,7 +93,7 @@ function isBlockLikeStatement(sourceCode, node) {
|
|
93
93
|
|
94
94
|
// Checks the last token is a closing brace of blocks.
|
95
95
|
const lastToken = sourceCode.getLastToken(node, astUtils.isNotSemicolonToken);
|
96
|
-
const belongingNode = astUtils.isClosingBraceToken(lastToken)
|
96
|
+
const belongingNode = lastToken && astUtils.isClosingBraceToken(lastToken)
|
97
97
|
? sourceCode.getNodeByRangeIndex(lastToken.range[0])
|
98
98
|
: null;
|
99
99
|
|
@@ -15,19 +15,55 @@ module.exports = {
|
|
15
15
|
category: "ECMAScript 6",
|
16
16
|
recommended: false
|
17
17
|
},
|
18
|
-
|
19
18
|
schema: [
|
20
19
|
{
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
20
|
+
|
21
|
+
// old support {array: Boolean, object: Boolean}
|
22
|
+
// new support {VariableDeclarator: {}, AssignmentExpression: {}}
|
23
|
+
oneOf: [
|
24
|
+
{
|
25
|
+
type: "object",
|
26
|
+
properties: {
|
27
|
+
VariableDeclarator: {
|
28
|
+
type: "object",
|
29
|
+
properties: {
|
30
|
+
array: {
|
31
|
+
type: "boolean"
|
32
|
+
},
|
33
|
+
object: {
|
34
|
+
type: "boolean"
|
35
|
+
}
|
36
|
+
},
|
37
|
+
additionalProperties: false
|
38
|
+
},
|
39
|
+
AssignmentExpression: {
|
40
|
+
type: "object",
|
41
|
+
properties: {
|
42
|
+
array: {
|
43
|
+
type: "boolean"
|
44
|
+
},
|
45
|
+
object: {
|
46
|
+
type: "boolean"
|
47
|
+
}
|
48
|
+
},
|
49
|
+
additionalProperties: false
|
50
|
+
}
|
51
|
+
},
|
52
|
+
additionalProperties: false
|
25
53
|
},
|
26
|
-
|
27
|
-
type: "
|
54
|
+
{
|
55
|
+
type: "object",
|
56
|
+
properties: {
|
57
|
+
array: {
|
58
|
+
type: "boolean"
|
59
|
+
},
|
60
|
+
object: {
|
61
|
+
type: "boolean"
|
62
|
+
}
|
63
|
+
},
|
64
|
+
additionalProperties: false
|
28
65
|
}
|
29
|
-
|
30
|
-
additionalProperties: false
|
66
|
+
]
|
31
67
|
},
|
32
68
|
{
|
33
69
|
type: "object",
|
@@ -42,26 +78,17 @@ module.exports = {
|
|
42
78
|
},
|
43
79
|
create(context) {
|
44
80
|
|
45
|
-
let checkArrays = true;
|
46
|
-
let checkObjects = true;
|
47
|
-
let enforceForRenamedProperties = false;
|
48
81
|
const enabledTypes = context.options[0];
|
49
|
-
const
|
82
|
+
const enforceForRenamedProperties = context.options[1] && context.options[1].enforceForRenamedProperties;
|
83
|
+
let normalizedOptions = {
|
84
|
+
VariableDeclarator: { array: true, object: true },
|
85
|
+
AssignmentExpression: { array: true, object: true }
|
86
|
+
};
|
50
87
|
|
51
88
|
if (enabledTypes) {
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
if (typeof enabledTypes.object !== "undefined") {
|
57
|
-
checkObjects = enabledTypes.object;
|
58
|
-
}
|
59
|
-
}
|
60
|
-
|
61
|
-
if (additionalOptions) {
|
62
|
-
if (typeof additionalOptions.enforceForRenamedProperties !== "undefined") {
|
63
|
-
enforceForRenamedProperties = additionalOptions.enforceForRenamedProperties;
|
64
|
-
}
|
89
|
+
normalizedOptions = typeof enabledTypes.array !== "undefined" || typeof enabledTypes.object !== "undefined"
|
90
|
+
? { VariableDeclarator: enabledTypes, AssignmentExpression: enabledTypes }
|
91
|
+
: enabledTypes;
|
65
92
|
}
|
66
93
|
|
67
94
|
//--------------------------------------------------------------------------
|
@@ -69,7 +96,18 @@ module.exports = {
|
|
69
96
|
//--------------------------------------------------------------------------
|
70
97
|
|
71
98
|
/**
|
72
|
-
*
|
99
|
+
* @param {string} nodeType "AssignmentExpression" or "VariableDeclarator"
|
100
|
+
* @param {string} destructuringType "array" or "object"
|
101
|
+
* @returns {boolean} `true` if the destructuring type should be checked for the given node
|
102
|
+
*/
|
103
|
+
function shouldCheck(nodeType, destructuringType) {
|
104
|
+
return normalizedOptions &&
|
105
|
+
normalizedOptions[nodeType] &&
|
106
|
+
normalizedOptions[nodeType][destructuringType];
|
107
|
+
}
|
108
|
+
|
109
|
+
/**
|
110
|
+
* Determines if the given node is accessing an array index
|
73
111
|
*
|
74
112
|
* This is used to differentiate array index access from object property
|
75
113
|
* access.
|
@@ -110,22 +148,22 @@ module.exports = {
|
|
110
148
|
}
|
111
149
|
|
112
150
|
if (isArrayIndexAccess(rightNode)) {
|
113
|
-
if (
|
151
|
+
if (shouldCheck(reportNode.type, "array")) {
|
114
152
|
report(reportNode, "array");
|
115
153
|
}
|
116
154
|
return;
|
117
155
|
}
|
118
156
|
|
119
|
-
if (
|
157
|
+
if (shouldCheck(reportNode.type, "object") && enforceForRenamedProperties) {
|
120
158
|
report(reportNode, "object");
|
121
159
|
return;
|
122
160
|
}
|
123
161
|
|
124
|
-
if (
|
162
|
+
if (shouldCheck(reportNode.type, "object")) {
|
125
163
|
const property = rightNode.property;
|
126
164
|
|
127
|
-
if ((property.type === "Literal" && leftNode.name === property.value) ||
|
128
|
-
|
165
|
+
if ((property.type === "Literal" && leftNode.name === property.value) || (property.type === "Identifier" &&
|
166
|
+
leftNode.name === property.name)) {
|
129
167
|
report(reportNode, "object");
|
130
168
|
}
|
131
169
|
}
|
@@ -5,6 +5,33 @@
|
|
5
5
|
|
6
6
|
"use strict";
|
7
7
|
|
8
|
+
//------------------------------------------------------------------------------
|
9
|
+
// Helpers
|
10
|
+
//------------------------------------------------------------------------------
|
11
|
+
|
12
|
+
/**
|
13
|
+
* Checks to see if a CallExpression's callee node is `parseInt` or
|
14
|
+
* `Number.parseInt`.
|
15
|
+
* @param {ASTNode} calleeNode The callee node to evaluate.
|
16
|
+
* @returns {boolean} True if the callee is `parseInt` or `Number.parseInt`,
|
17
|
+
* false otherwise.
|
18
|
+
*/
|
19
|
+
function isParseInt(calleeNode) {
|
20
|
+
switch (calleeNode.type) {
|
21
|
+
case "Identifier":
|
22
|
+
return calleeNode.name === "parseInt";
|
23
|
+
case "MemberExpression":
|
24
|
+
return calleeNode.object.type === "Identifier" &&
|
25
|
+
calleeNode.object.name === "Number" &&
|
26
|
+
calleeNode.property.type === "Identifier" &&
|
27
|
+
calleeNode.property.name === "parseInt";
|
28
|
+
|
29
|
+
// no default
|
30
|
+
}
|
31
|
+
|
32
|
+
return false;
|
33
|
+
}
|
34
|
+
|
8
35
|
//------------------------------------------------------------------------------
|
9
36
|
// Rule Definition
|
10
37
|
//------------------------------------------------------------------------------
|
@@ -12,7 +39,7 @@
|
|
12
39
|
module.exports = {
|
13
40
|
meta: {
|
14
41
|
docs: {
|
15
|
-
description: "disallow `parseInt()` in favor of binary, octal, and hexadecimal literals",
|
42
|
+
description: "disallow `parseInt()` and `Number.parseInt()` in favor of binary, octal, and hexadecimal literals",
|
16
43
|
category: "ECMAScript 6",
|
17
44
|
recommended: false
|
18
45
|
},
|
@@ -23,6 +50,8 @@ module.exports = {
|
|
23
50
|
},
|
24
51
|
|
25
52
|
create(context) {
|
53
|
+
const sourceCode = context.getSourceCode();
|
54
|
+
|
26
55
|
const radixMap = {
|
27
56
|
2: "binary",
|
28
57
|
8: "octal",
|
@@ -35,9 +64,9 @@ module.exports = {
|
|
35
64
|
16: "0x"
|
36
65
|
};
|
37
66
|
|
38
|
-
|
67
|
+
//----------------------------------------------------------------------
|
39
68
|
// Public
|
40
|
-
|
69
|
+
//----------------------------------------------------------------------
|
41
70
|
|
42
71
|
return {
|
43
72
|
|
@@ -51,16 +80,16 @@ module.exports = {
|
|
51
80
|
// only error if the radix is 2, 8, or 16
|
52
81
|
const radixName = radixMap[node.arguments[1].value];
|
53
82
|
|
54
|
-
if (node.callee
|
55
|
-
node.callee.name === "parseInt" &&
|
83
|
+
if (isParseInt(node.callee) &&
|
56
84
|
radixName &&
|
57
85
|
node.arguments[0].type === "Literal"
|
58
86
|
) {
|
59
87
|
context.report({
|
60
88
|
node,
|
61
|
-
message: "Use {{radixName}} literals instead of
|
89
|
+
message: "Use {{radixName}} literals instead of {{functionName}}().",
|
62
90
|
data: {
|
63
|
-
radixName
|
91
|
+
radixName,
|
92
|
+
functionName: sourceCode.getText(node.callee)
|
64
93
|
},
|
65
94
|
fix(fixer) {
|
66
95
|
const newPrefix = prefixMap[node.arguments[1].value];
|
@@ -83,10 +83,14 @@ module.exports = {
|
|
83
83
|
* @returns {void}
|
84
84
|
*/
|
85
85
|
function report(node, existing, substitute) {
|
86
|
-
context.report({
|
87
|
-
|
88
|
-
substitute
|
89
|
-
|
86
|
+
context.report({
|
87
|
+
node,
|
88
|
+
message: "Avoid using {{existing}}, instead use {{substitute}}.",
|
89
|
+
data: {
|
90
|
+
existing,
|
91
|
+
substitute
|
92
|
+
}
|
93
|
+
});
|
90
94
|
}
|
91
95
|
|
92
96
|
return {
|
@@ -74,7 +74,7 @@ function startsWithTemplateCurly(node) {
|
|
74
74
|
return startsWithTemplateCurly(node.left);
|
75
75
|
}
|
76
76
|
if (node.type === "TemplateLiteral") {
|
77
|
-
return node.expressions.length && node.quasis.length && node.quasis[0].
|
77
|
+
return node.expressions.length && node.quasis.length && node.quasis[0].range[0] === node.quasis[0].range[1];
|
78
78
|
}
|
79
79
|
return node.type !== "Literal" || typeof node.value !== "string";
|
80
80
|
}
|
@@ -89,7 +89,7 @@ function endsWithTemplateCurly(node) {
|
|
89
89
|
return startsWithTemplateCurly(node.right);
|
90
90
|
}
|
91
91
|
if (node.type === "TemplateLiteral") {
|
92
|
-
return node.expressions.length && node.quasis.length && node.quasis[node.quasis.length - 1].
|
92
|
+
return node.expressions.length && node.quasis.length && node.quasis[node.quasis.length - 1].range[0] === node.quasis[node.quasis.length - 1].range[1];
|
93
93
|
}
|
94
94
|
return node.type !== "Literal" || typeof node.value !== "string";
|
95
95
|
}
|
@@ -112,7 +112,7 @@ module.exports = {
|
|
112
112
|
const nonSpacedNode = getFirstNonSpacedToken(leftNode, rightNode);
|
113
113
|
|
114
114
|
if (nonSpacedNode) {
|
115
|
-
if (!(int32Hint && sourceCode.getText(node).
|
115
|
+
if (!(int32Hint && sourceCode.getText(node).endsWith("|0"))) {
|
116
116
|
report(node, nonSpacedNode);
|
117
117
|
}
|
118
118
|
}
|
@@ -303,9 +303,9 @@ module.exports = {
|
|
303
303
|
node,
|
304
304
|
fix(fixer) {
|
305
305
|
if (requireSpace) {
|
306
|
-
return fixer.insertTextAfterRange([node.
|
306
|
+
return fixer.insertTextAfterRange([node.range[0], node.range[1] - 2], " ");
|
307
307
|
}
|
308
|
-
const end = node.
|
308
|
+
const end = node.range[1] - 2,
|
309
309
|
start = end - match[0].length;
|
310
310
|
|
311
311
|
return fixer.replaceTextRange([start, end], "");
|
package/lib/rules/valid-jsdoc.js
CHANGED
@@ -362,14 +362,22 @@ module.exports = {
|
|
362
362
|
// TODO(nzakas): Figure out logical things to do with destructured, default, rest params
|
363
363
|
if (param.type === "Identifier") {
|
364
364
|
if (jsdocParams[i] && (name !== jsdocParams[i])) {
|
365
|
-
context.report({
|
366
|
-
|
367
|
-
|
368
|
-
|
365
|
+
context.report({
|
366
|
+
node: jsdocNode,
|
367
|
+
message: "Expected JSDoc for '{{name}}' but found '{{jsdocName}}'.",
|
368
|
+
data: {
|
369
|
+
name,
|
370
|
+
jsdocName: jsdocParams[i]
|
371
|
+
}
|
372
|
+
});
|
369
373
|
} else if (!params[name] && !isOverride) {
|
370
|
-
context.report({
|
371
|
-
|
372
|
-
|
374
|
+
context.report({
|
375
|
+
node: jsdocNode,
|
376
|
+
message: "Missing JSDoc for parameter '{{name}}'.",
|
377
|
+
data: {
|
378
|
+
name
|
379
|
+
}
|
380
|
+
});
|
373
381
|
}
|
374
382
|
}
|
375
383
|
});
|
@@ -9,7 +9,7 @@
|
|
9
9
|
/*
|
10
10
|
* This is a wrapper around mocha to allow for DRY unittests for eslint
|
11
11
|
* Format:
|
12
|
-
* RuleTester.
|
12
|
+
* RuleTester.run("{ruleName}", {
|
13
13
|
* valid: [
|
14
14
|
* "{code}",
|
15
15
|
* { code: "{code}", options: {options}, globals: {globals}, parser: "{parser}", settings: {settings} }
|
@@ -250,7 +250,6 @@ class RuleTester {
|
|
250
250
|
const testerConfig = this.testerConfig,
|
251
251
|
requiredScenarios = ["valid", "invalid"],
|
252
252
|
scenarioErrors = [],
|
253
|
-
result = {},
|
254
253
|
linter = this.linter;
|
255
254
|
|
256
255
|
if (lodash.isNil(test) || typeof test !== "object") {
|
@@ -269,16 +268,13 @@ class RuleTester {
|
|
269
268
|
].concat(scenarioErrors).join("\n"));
|
270
269
|
}
|
271
270
|
|
272
|
-
/* eslint-disable no-shadow */
|
273
|
-
|
274
271
|
/**
|
275
272
|
* Run the rule for the given item
|
276
|
-
* @param {string} ruleName name of the rule
|
277
273
|
* @param {string|Object} item Item to run the rule against
|
278
274
|
* @returns {Object} Eslint run result
|
279
275
|
* @private
|
280
276
|
*/
|
281
|
-
function runRuleForItem(
|
277
|
+
function runRuleForItem(item) {
|
282
278
|
let config = lodash.cloneDeep(testerConfig),
|
283
279
|
code, filename, beforeAST, afterAST;
|
284
280
|
|
@@ -350,27 +346,27 @@ class RuleTester {
|
|
350
346
|
|
351
347
|
try {
|
352
348
|
linter.rules.get = function(ruleId) {
|
353
|
-
const
|
349
|
+
const originalRule = originalGet.call(linter.rules, ruleId);
|
354
350
|
|
355
|
-
if (typeof
|
351
|
+
if (typeof originalRule === "function") {
|
356
352
|
return function(context) {
|
357
353
|
Object.freeze(context);
|
358
354
|
freezeDeeply(context.options);
|
359
355
|
freezeDeeply(context.settings);
|
360
356
|
freezeDeeply(context.parserOptions);
|
361
357
|
|
362
|
-
return
|
358
|
+
return originalRule(context);
|
363
359
|
};
|
364
360
|
}
|
365
361
|
return {
|
366
|
-
meta:
|
362
|
+
meta: originalRule.meta,
|
367
363
|
create(context) {
|
368
364
|
Object.freeze(context);
|
369
365
|
freezeDeeply(context.options);
|
370
366
|
freezeDeeply(context.settings);
|
371
367
|
freezeDeeply(context.parserOptions);
|
372
368
|
|
373
|
-
return
|
369
|
+
return originalRule.create(context);
|
374
370
|
}
|
375
371
|
};
|
376
372
|
|
@@ -404,13 +400,12 @@ class RuleTester {
|
|
404
400
|
/**
|
405
401
|
* Check if the template is valid or not
|
406
402
|
* all valid cases go through this
|
407
|
-
* @param {string} ruleName name of the rule
|
408
403
|
* @param {string|Object} item Item to run the rule against
|
409
404
|
* @returns {void}
|
410
405
|
* @private
|
411
406
|
*/
|
412
|
-
function testValidTemplate(
|
413
|
-
const result = runRuleForItem(
|
407
|
+
function testValidTemplate(item) {
|
408
|
+
const result = runRuleForItem(item);
|
414
409
|
const messages = result.messages;
|
415
410
|
|
416
411
|
assert.equal(messages.length, 0, util.format("Should have no errors but had %d: %s",
|
@@ -444,16 +439,15 @@ class RuleTester {
|
|
444
439
|
/**
|
445
440
|
* Check if the template is invalid or not
|
446
441
|
* all invalid cases go through this.
|
447
|
-
* @param {string} ruleName name of the rule
|
448
442
|
* @param {string|Object} item Item to run the rule against
|
449
443
|
* @returns {void}
|
450
444
|
* @private
|
451
445
|
*/
|
452
|
-
function testInvalidTemplate(
|
446
|
+
function testInvalidTemplate(item) {
|
453
447
|
assert.ok(item.errors || item.errors === 0,
|
454
448
|
`Did not specify errors for an invalid test of ${ruleName}`);
|
455
449
|
|
456
|
-
const result = runRuleForItem(
|
450
|
+
const result = runRuleForItem(item);
|
457
451
|
const messages = result.messages;
|
458
452
|
|
459
453
|
|
@@ -543,7 +537,7 @@ class RuleTester {
|
|
543
537
|
test.valid.forEach(valid => {
|
544
538
|
RuleTester.it(typeof valid === "object" ? valid.code : valid, () => {
|
545
539
|
linter.defineRules(this.rules);
|
546
|
-
testValidTemplate(
|
540
|
+
testValidTemplate(valid);
|
547
541
|
});
|
548
542
|
});
|
549
543
|
});
|
@@ -552,13 +546,11 @@ class RuleTester {
|
|
552
546
|
test.invalid.forEach(invalid => {
|
553
547
|
RuleTester.it(invalid.code, () => {
|
554
548
|
linter.defineRules(this.rules);
|
555
|
-
testInvalidTemplate(
|
549
|
+
testInvalidTemplate(invalid);
|
556
550
|
});
|
557
551
|
});
|
558
552
|
});
|
559
553
|
});
|
560
|
-
|
561
|
-
return result.suite;
|
562
554
|
}
|
563
555
|
}
|
564
556
|
|
@@ -0,0 +1,48 @@
|
|
1
|
+
/**
|
2
|
+
* @author Toru Nagashima <https://github.com/mysticatea>
|
3
|
+
*/
|
4
|
+
"use strict";
|
5
|
+
|
6
|
+
const espree = require("espree");
|
7
|
+
const Traverser = require("../util/traverser");
|
8
|
+
|
9
|
+
/**
|
10
|
+
* Define `start`/`end` properties as throwing error.
|
11
|
+
* @param {ASTNode} node The node to define.
|
12
|
+
* @returns {void}
|
13
|
+
*/
|
14
|
+
function defineStartEndAsError(node) {
|
15
|
+
Object.defineProperty(node, "start", {
|
16
|
+
get() {
|
17
|
+
throw new Error("Use node.range[0] instead of node.start");
|
18
|
+
},
|
19
|
+
configurable: true,
|
20
|
+
enumerable: false
|
21
|
+
});
|
22
|
+
Object.defineProperty(node, "end", {
|
23
|
+
get() {
|
24
|
+
throw new Error("Use node.range[1] instead of node.end");
|
25
|
+
},
|
26
|
+
configurable: true,
|
27
|
+
enumerable: false
|
28
|
+
});
|
29
|
+
}
|
30
|
+
|
31
|
+
/**
|
32
|
+
* Define `start`/`end` properties of all nodes of the given AST as throwing error.
|
33
|
+
* @param {ASTNode} ast The root node to errorize `start`/`end` properties.
|
34
|
+
* @returns {void}
|
35
|
+
*/
|
36
|
+
function defineStartEndAsErrorInTree(ast) {
|
37
|
+
new Traverser().traverse(ast, { enter: defineStartEndAsError });
|
38
|
+
ast.tokens.forEach(defineStartEndAsError);
|
39
|
+
ast.comments.forEach(defineStartEndAsError);
|
40
|
+
}
|
41
|
+
|
42
|
+
module.exports.parse = (code, options) => {
|
43
|
+
const ret = espree.parse(code, options);
|
44
|
+
|
45
|
+
defineStartEndAsErrorInTree(ret.ast || ret);
|
46
|
+
|
47
|
+
return ret;
|
48
|
+
};
|
package/lib/util/npm-util.js
CHANGED
@@ -10,7 +10,7 @@
|
|
10
10
|
//------------------------------------------------------------------------------
|
11
11
|
|
12
12
|
const fs = require("fs"),
|
13
|
-
|
13
|
+
spawn = require("cross-spawn"),
|
14
14
|
path = require("path"),
|
15
15
|
log = require("../logging");
|
16
16
|
|
@@ -50,22 +50,23 @@ function findPackageJson(startDir) {
|
|
50
50
|
* @returns {void}
|
51
51
|
*/
|
52
52
|
function installSyncSaveDev(packages) {
|
53
|
-
if (Array.isArray(packages)) {
|
54
|
-
packages = packages
|
53
|
+
if (!Array.isArray(packages)) {
|
54
|
+
packages = [packages];
|
55
55
|
}
|
56
|
-
|
56
|
+
spawn.sync("npm", ["i", "--save-dev"].concat(packages), { stdio: "inherit" });
|
57
57
|
}
|
58
58
|
|
59
59
|
/**
|
60
60
|
* Fetch `peerDependencies` of the given package by `npm show` command.
|
61
61
|
* @param {string} packageName The package name to fetch peerDependencies.
|
62
|
-
* @returns {
|
62
|
+
* @returns {Object} Gotten peerDependencies.
|
63
63
|
*/
|
64
64
|
function fetchPeerDependencies(packageName) {
|
65
|
-
const fetchedText =
|
66
|
-
|
65
|
+
const fetchedText = spawn.sync(
|
66
|
+
"npm",
|
67
|
+
["show", "--json", packageName, "peerDependencies"],
|
67
68
|
{ encoding: "utf8" }
|
68
|
-
).trim();
|
69
|
+
).stdout.trim();
|
69
70
|
|
70
71
|
return JSON.parse(fetchedText || "{}");
|
71
72
|
}
|
package/package.json
CHANGED
@@ -1,6 +1,6 @@
|
|
1
1
|
{
|
2
2
|
"name": "eslint",
|
3
|
-
"version": "4.
|
3
|
+
"version": "4.5.0",
|
4
4
|
"author": "Nicholas C. Zakas <nicholas+npm@nczconsulting.com>",
|
5
5
|
"description": "An AST-based pattern checker for JavaScript.",
|
6
6
|
"bin": {
|
@@ -10,6 +10,7 @@
|
|
10
10
|
"scripts": {
|
11
11
|
"test": "node Makefile.js test",
|
12
12
|
"lint": "node Makefile.js lint",
|
13
|
+
"fuzz": "node Makefile.js fuzz",
|
13
14
|
"release": "node Makefile.js release",
|
14
15
|
"ci-release": "node Makefile.js ciRelease",
|
15
16
|
"alpharelease": "node Makefile.js prerelease -- alpha",
|
@@ -36,23 +37,25 @@
|
|
36
37
|
"dependencies": {
|
37
38
|
"ajv": "^5.2.0",
|
38
39
|
"babel-code-frame": "^6.22.0",
|
39
|
-
"chalk": "^
|
40
|
+
"chalk": "^2.1.0",
|
40
41
|
"concat-stream": "^1.6.0",
|
42
|
+
"cross-spawn": "^5.1.0",
|
41
43
|
"debug": "^2.6.8",
|
42
44
|
"doctrine": "^2.0.0",
|
43
45
|
"eslint-scope": "^3.7.1",
|
44
|
-
"espree": "^3.
|
46
|
+
"espree": "^3.5.0",
|
45
47
|
"esquery": "^1.0.0",
|
46
48
|
"estraverse": "^4.2.0",
|
47
49
|
"esutils": "^2.0.2",
|
48
50
|
"file-entry-cache": "^2.0.0",
|
51
|
+
"functional-red-black-tree": "^1.0.1",
|
49
52
|
"glob": "^7.1.2",
|
50
53
|
"globals": "^9.17.0",
|
51
54
|
"ignore": "^3.3.3",
|
52
55
|
"imurmurhash": "^0.1.4",
|
53
56
|
"inquirer": "^3.0.6",
|
54
57
|
"is-resolvable": "^1.0.0",
|
55
|
-
"js-yaml": "^3.
|
58
|
+
"js-yaml": "^3.9.1",
|
56
59
|
"json-stable-stringify": "^1.0.1",
|
57
60
|
"levn": "^0.3.0",
|
58
61
|
"lodash": "^4.17.4",
|
@@ -64,6 +67,8 @@
|
|
64
67
|
"pluralize": "^4.0.0",
|
65
68
|
"progress": "^2.0.0",
|
66
69
|
"require-uncached": "^1.0.3",
|
70
|
+
"semver": "^5.3.0",
|
71
|
+
"strip-ansi": "^4.0.0",
|
67
72
|
"strip-json-comments": "~2.0.1",
|
68
73
|
"table": "^4.0.1",
|
69
74
|
"text-table": "~0.2.0"
|
@@ -80,9 +85,10 @@
|
|
80
85
|
"coveralls": "^2.13.1",
|
81
86
|
"dateformat": "^2.0.0",
|
82
87
|
"ejs": "^2.5.6",
|
83
|
-
"eslint-plugin-eslint-plugin": "^0.
|
88
|
+
"eslint-plugin-eslint-plugin": "^0.8.0",
|
84
89
|
"eslint-plugin-node": "^5.1.0",
|
85
90
|
"eslint-release": "^0.10.1",
|
91
|
+
"eslump": "1.6.0",
|
86
92
|
"esprima": "^3.1.3",
|
87
93
|
"esprima-fb": "^15001.1001.0-dev-harmony-fb",
|
88
94
|
"istanbul": "^0.4.5",
|
@@ -100,7 +106,6 @@
|
|
100
106
|
"npm-license": "^0.3.3",
|
101
107
|
"phantomjs-prebuilt": "^2.1.14",
|
102
108
|
"proxyquire": "^1.8.0",
|
103
|
-
"semver": "^5.3.0",
|
104
109
|
"shelljs": "^0.7.7",
|
105
110
|
"shelljs-nodecli": "~0.1.1",
|
106
111
|
"sinon": "^2.3.2",
|