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
package/lib/cli.js
CHANGED
@@ -63,8 +63,9 @@ function translateOptions(cliOptions) {
|
|
63
63
|
cache: cliOptions.cache,
|
64
64
|
cacheFile: cliOptions.cacheFile,
|
65
65
|
cacheLocation: cliOptions.cacheLocation,
|
66
|
-
fix: cliOptions.fix && (cliOptions.quiet ? quietFixPredicate : true),
|
67
|
-
allowInlineConfig: cliOptions.inlineConfig
|
66
|
+
fix: (cliOptions.fix || cliOptions.fixDryRun) && (cliOptions.quiet ? quietFixPredicate : true),
|
67
|
+
allowInlineConfig: cliOptions.inlineConfig,
|
68
|
+
reportUnusedDisableDirectives: cliOptions.reportUnusedDisableDirectives
|
68
69
|
};
|
69
70
|
}
|
70
71
|
|
@@ -143,6 +144,8 @@ const cli = {
|
|
143
144
|
|
144
145
|
const files = currentOptions._;
|
145
146
|
|
147
|
+
const useStdin = typeof text === "string";
|
148
|
+
|
146
149
|
if (currentOptions.version) { // version from package.json
|
147
150
|
|
148
151
|
log.info(`v${require("../package.json").version}`);
|
@@ -151,7 +154,8 @@ const cli = {
|
|
151
154
|
if (files.length) {
|
152
155
|
log.error("The --print-config option must be used with exactly one file name.");
|
153
156
|
return 1;
|
154
|
-
}
|
157
|
+
}
|
158
|
+
if (useStdin) {
|
155
159
|
log.error("The --print-config option is not available for piped-in code.");
|
156
160
|
return 1;
|
157
161
|
}
|
@@ -162,23 +166,27 @@ const cli = {
|
|
162
166
|
|
163
167
|
log.info(JSON.stringify(fileConfig, null, " "));
|
164
168
|
return 0;
|
165
|
-
} else if (currentOptions.help || (!files.length && !
|
169
|
+
} else if (currentOptions.help || (!files.length && !useStdin)) {
|
166
170
|
|
167
171
|
log.info(options.generateHelp());
|
168
172
|
|
169
173
|
} else {
|
170
174
|
|
171
|
-
debug(`Running on ${
|
175
|
+
debug(`Running on ${useStdin ? "text" : "files"}`);
|
176
|
+
|
177
|
+
if (currentOptions.fix && currentOptions.fixDryRun) {
|
178
|
+
log.error("The --fix option and the --fix-dry-run option cannot be used together.");
|
179
|
+
return 1;
|
180
|
+
}
|
172
181
|
|
173
|
-
|
174
|
-
|
175
|
-
log.error("The --fix option is not available for piped-in code.");
|
182
|
+
if (useStdin && currentOptions.fix) {
|
183
|
+
log.error("The --fix option is not available for piped-in code; use --fix-dry-run instead.");
|
176
184
|
return 1;
|
177
185
|
}
|
178
186
|
|
179
187
|
const engine = new CLIEngine(translateOptions(currentOptions));
|
180
188
|
|
181
|
-
const report =
|
189
|
+
const report = useStdin ? engine.executeOnText(text, currentOptions.stdinFilename, true) : engine.executeOnFiles(files);
|
182
190
|
|
183
191
|
if (currentOptions.fix) {
|
184
192
|
debug("Fix mode enabled - applying fixes");
|
@@ -598,8 +598,10 @@ class CodePathAnalyzer {
|
|
598
598
|
preprocess(this, node);
|
599
599
|
}
|
600
600
|
|
601
|
-
|
602
|
-
|
601
|
+
/*
|
602
|
+
* Updates the code path.
|
603
|
+
* And emits onCodePathStart/onCodePathSegmentStart events.
|
604
|
+
*/
|
603
605
|
processCodePathToEnter(this, node);
|
604
606
|
|
605
607
|
// Emits node events.
|
@@ -618,8 +620,10 @@ class CodePathAnalyzer {
|
|
618
620
|
leaveNode(node) {
|
619
621
|
this.currentNode = node;
|
620
622
|
|
621
|
-
|
622
|
-
|
623
|
+
/*
|
624
|
+
* Updates the code path.
|
625
|
+
* And emits onCodePathStart/onCodePathSegmentStart events.
|
626
|
+
*/
|
623
627
|
processCodePathToExit(this, node);
|
624
628
|
|
625
629
|
// Emits node events.
|
@@ -15,43 +15,6 @@ const debug = require("./debug-helpers");
|
|
15
15
|
// Helpers
|
16
16
|
//------------------------------------------------------------------------------
|
17
17
|
|
18
|
-
/**
|
19
|
-
* Replaces unused segments with the previous segments of each unused segment.
|
20
|
-
*
|
21
|
-
* @param {CodePathSegment[]} segments - An array of segments to replace.
|
22
|
-
* @returns {CodePathSegment[]} The replaced array.
|
23
|
-
*/
|
24
|
-
function flattenUnusedSegments(segments) {
|
25
|
-
const done = Object.create(null);
|
26
|
-
const retv = [];
|
27
|
-
|
28
|
-
for (let i = 0; i < segments.length; ++i) {
|
29
|
-
const segment = segments[i];
|
30
|
-
|
31
|
-
// Ignores duplicated.
|
32
|
-
if (done[segment.id]) {
|
33
|
-
continue;
|
34
|
-
}
|
35
|
-
|
36
|
-
// Use previous segments if unused.
|
37
|
-
if (!segment.internal.used) {
|
38
|
-
for (let j = 0; j < segment.allPrevSegments.length; ++j) {
|
39
|
-
const prevSegment = segment.allPrevSegments[j];
|
40
|
-
|
41
|
-
if (!done[prevSegment.id]) {
|
42
|
-
done[prevSegment.id] = true;
|
43
|
-
retv.push(prevSegment);
|
44
|
-
}
|
45
|
-
}
|
46
|
-
} else {
|
47
|
-
done[segment.id] = true;
|
48
|
-
retv.push(segment);
|
49
|
-
}
|
50
|
-
}
|
51
|
-
|
52
|
-
return retv;
|
53
|
-
}
|
54
|
-
|
55
18
|
/**
|
56
19
|
* Checks whether or not a given segment is reachable.
|
57
20
|
*
|
@@ -163,7 +126,7 @@ class CodePathSegment {
|
|
163
126
|
static newNext(id, allPrevSegments) {
|
164
127
|
return new CodePathSegment(
|
165
128
|
id,
|
166
|
-
flattenUnusedSegments(allPrevSegments),
|
129
|
+
CodePathSegment.flattenUnusedSegments(allPrevSegments),
|
167
130
|
allPrevSegments.some(isReachable)
|
168
131
|
);
|
169
132
|
}
|
@@ -176,10 +139,12 @@ class CodePathSegment {
|
|
176
139
|
* @returns {CodePathSegment} The created segment.
|
177
140
|
*/
|
178
141
|
static newUnreachable(id, allPrevSegments) {
|
179
|
-
const segment = new CodePathSegment(id, flattenUnusedSegments(allPrevSegments), false);
|
142
|
+
const segment = new CodePathSegment(id, CodePathSegment.flattenUnusedSegments(allPrevSegments), false);
|
180
143
|
|
181
|
-
|
182
|
-
|
144
|
+
/*
|
145
|
+
* In `if (a) return a; foo();` case, the unreachable segment preceded by
|
146
|
+
* the return statement is not used but must not be remove.
|
147
|
+
*/
|
183
148
|
CodePathSegment.markUsed(segment);
|
184
149
|
|
185
150
|
return segment;
|
@@ -238,6 +203,43 @@ class CodePathSegment {
|
|
238
203
|
static markPrevSegmentAsLooped(segment, prevSegment) {
|
239
204
|
segment.internal.loopedPrevSegments.push(prevSegment);
|
240
205
|
}
|
206
|
+
|
207
|
+
/**
|
208
|
+
* Replaces unused segments with the previous segments of each unused segment.
|
209
|
+
*
|
210
|
+
* @param {CodePathSegment[]} segments - An array of segments to replace.
|
211
|
+
* @returns {CodePathSegment[]} The replaced array.
|
212
|
+
*/
|
213
|
+
static flattenUnusedSegments(segments) {
|
214
|
+
const done = Object.create(null);
|
215
|
+
const retv = [];
|
216
|
+
|
217
|
+
for (let i = 0; i < segments.length; ++i) {
|
218
|
+
const segment = segments[i];
|
219
|
+
|
220
|
+
// Ignores duplicated.
|
221
|
+
if (done[segment.id]) {
|
222
|
+
continue;
|
223
|
+
}
|
224
|
+
|
225
|
+
// Use previous segments if unused.
|
226
|
+
if (!segment.internal.used) {
|
227
|
+
for (let j = 0; j < segment.allPrevSegments.length; ++j) {
|
228
|
+
const prevSegment = segment.allPrevSegments[j];
|
229
|
+
|
230
|
+
if (!done[prevSegment.id]) {
|
231
|
+
done[prevSegment.id] = true;
|
232
|
+
retv.push(prevSegment);
|
233
|
+
}
|
234
|
+
}
|
235
|
+
} else {
|
236
|
+
done[segment.id] = true;
|
237
|
+
retv.push(segment);
|
238
|
+
}
|
239
|
+
}
|
240
|
+
|
241
|
+
return retv;
|
242
|
+
}
|
241
243
|
}
|
242
244
|
|
243
245
|
module.exports = CodePathSegment;
|
@@ -169,6 +169,9 @@ function removeConnection(prevSegments, nextSegments) {
|
|
169
169
|
* @returns {void}
|
170
170
|
*/
|
171
171
|
function makeLooped(state, fromSegments, toSegments) {
|
172
|
+
fromSegments = CodePathSegment.flattenUnusedSegments(fromSegments);
|
173
|
+
toSegments = CodePathSegment.flattenUnusedSegments(toSegments);
|
174
|
+
|
172
175
|
const end = Math.min(fromSegments.length, toSegments.length);
|
173
176
|
|
174
177
|
for (let i = 0; i < end; ++i) {
|
@@ -771,8 +774,10 @@ class CodePathState {
|
|
771
774
|
// Sets the normal path as the next.
|
772
775
|
this.forkContext.replaceHead(normalSegments);
|
773
776
|
|
774
|
-
|
775
|
-
|
777
|
+
/*
|
778
|
+
* If both paths of the `try` block and the `catch` block are
|
779
|
+
* unreachable, the next path becomes unreachable as well.
|
780
|
+
*/
|
776
781
|
if (!context.lastOfTryIsReachable && !context.lastOfCatchIsReachable) {
|
777
782
|
this.forkContext.makeUnreachable();
|
778
783
|
}
|
package/lib/config/autoconfig.js
CHANGED
@@ -61,13 +61,13 @@ function makeRegistryItems(rulesConfig) {
|
|
61
61
|
}
|
62
62
|
|
63
63
|
/**
|
64
|
-
* Creates an object in which to store rule configs and error counts
|
65
|
-
*
|
66
|
-
* Unless a rulesConfig is provided at construction, the registry will not contain
|
67
|
-
* any rules, only methods. This will be useful for building up registries manually.
|
68
|
-
*
|
69
|
-
* Registry class
|
70
|
-
*/
|
64
|
+
* Creates an object in which to store rule configs and error counts
|
65
|
+
*
|
66
|
+
* Unless a rulesConfig is provided at construction, the registry will not contain
|
67
|
+
* any rules, only methods. This will be useful for building up registries manually.
|
68
|
+
*
|
69
|
+
* Registry class
|
70
|
+
*/
|
71
71
|
class Registry {
|
72
72
|
|
73
73
|
/**
|
@@ -293,11 +293,13 @@ class Registry {
|
|
293
293
|
|
294
294
|
lintResults.forEach(result => {
|
295
295
|
|
296
|
-
|
297
|
-
|
298
|
-
|
299
|
-
|
300
|
-
|
296
|
+
/*
|
297
|
+
* It is possible that the error is from a configuration comment
|
298
|
+
* in a linted file, in which case there may not be a config
|
299
|
+
* set in this ruleSetIdx.
|
300
|
+
* (https://github.com/eslint/eslint/issues/5992)
|
301
|
+
* (https://github.com/eslint/eslint/issues/7860)
|
302
|
+
*/
|
301
303
|
if (
|
302
304
|
lintedRegistry.rules[result.ruleId] &&
|
303
305
|
lintedRegistry.rules[result.ruleId][ruleSetIdx]
|
@@ -13,11 +13,11 @@ const fs = require("fs"),
|
|
13
13
|
path = require("path"),
|
14
14
|
ConfigOps = require("./config-ops"),
|
15
15
|
validator = require("./config-validator"),
|
16
|
-
pathUtil = require("../util/path-util"),
|
17
16
|
ModuleResolver = require("../util/module-resolver"),
|
17
|
+
naming = require("../util/naming"),
|
18
18
|
pathIsInside = require("path-is-inside"),
|
19
19
|
stripComments = require("strip-json-comments"),
|
20
|
-
stringify = require("json-stable-stringify"),
|
20
|
+
stringify = require("json-stable-stringify-without-jsonify"),
|
21
21
|
requireUncached = require("require-uncached");
|
22
22
|
|
23
23
|
const debug = require("debug")("eslint:config-file");
|
@@ -29,7 +29,7 @@ const debug = require("debug")("eslint:config-file");
|
|
29
29
|
/**
|
30
30
|
* Determines sort order for object keys for json-stable-stringify
|
31
31
|
*
|
32
|
-
* see: https://github.com/
|
32
|
+
* see: https://github.com/samn/json-stable-stringify#cmp
|
33
33
|
*
|
34
34
|
* @param {Object} a The first comparison object ({key: akey, value: avalue})
|
35
35
|
* @param {Object} b The second comparison object ({key: bkey, value: bvalue})
|
@@ -436,50 +436,6 @@ function applyExtends(config, configContext, filePath, relativeTo) {
|
|
436
436
|
return config;
|
437
437
|
}
|
438
438
|
|
439
|
-
/**
|
440
|
-
* Brings package name to correct format based on prefix
|
441
|
-
* @param {string} name The name of the package.
|
442
|
-
* @param {string} prefix Can be either "eslint-plugin" or "eslint-config
|
443
|
-
* @returns {string} Normalized name of the package
|
444
|
-
* @private
|
445
|
-
*/
|
446
|
-
function normalizePackageName(name, prefix) {
|
447
|
-
|
448
|
-
/*
|
449
|
-
* On Windows, name can come in with Windows slashes instead of Unix slashes.
|
450
|
-
* Normalize to Unix first to avoid errors later on.
|
451
|
-
* https://github.com/eslint/eslint/issues/5644
|
452
|
-
*/
|
453
|
-
if (name.indexOf("\\") > -1) {
|
454
|
-
name = pathUtil.convertPathToPosix(name);
|
455
|
-
}
|
456
|
-
|
457
|
-
if (name.charAt(0) === "@") {
|
458
|
-
|
459
|
-
/*
|
460
|
-
* it's a scoped package
|
461
|
-
* package name is "eslint-config", or just a username
|
462
|
-
*/
|
463
|
-
const scopedPackageShortcutRegex = new RegExp(`^(@[^/]+)(?:/(?:${prefix})?)?$`),
|
464
|
-
scopedPackageNameRegex = new RegExp(`^${prefix}(-|$)`);
|
465
|
-
|
466
|
-
if (scopedPackageShortcutRegex.test(name)) {
|
467
|
-
name = name.replace(scopedPackageShortcutRegex, `$1/${prefix}`);
|
468
|
-
} else if (!scopedPackageNameRegex.test(name.split("/")[1])) {
|
469
|
-
|
470
|
-
/*
|
471
|
-
* for scoped packages, insert the eslint-config after the first / unless
|
472
|
-
* the path is already @scope/eslint or @scope/eslint-config-xxx
|
473
|
-
*/
|
474
|
-
name = name.replace(/^@([^/]+)\/(.*)$/, `@$1/${prefix}-$2`);
|
475
|
-
}
|
476
|
-
} else if (name.indexOf(`${prefix}-`) !== 0) {
|
477
|
-
name = `${prefix}-${name}`;
|
478
|
-
}
|
479
|
-
|
480
|
-
return name;
|
481
|
-
}
|
482
|
-
|
483
439
|
/**
|
484
440
|
* Resolves a configuration file path into the fully-formed path, whether filename
|
485
441
|
* or package name.
|
@@ -505,12 +461,12 @@ function resolve(filePath, relativeTo) {
|
|
505
461
|
const pluginName = filePath.slice(7, filePath.lastIndexOf("/"));
|
506
462
|
const configName = filePath.slice(filePath.lastIndexOf("/") + 1);
|
507
463
|
|
508
|
-
normalizedPackageName = normalizePackageName(pluginName, "eslint-plugin");
|
464
|
+
normalizedPackageName = naming.normalizePackageName(pluginName, "eslint-plugin");
|
509
465
|
debug(`Attempting to resolve ${normalizedPackageName}`);
|
510
466
|
filePath = resolver.resolve(normalizedPackageName, getLookupPath(relativeTo));
|
511
467
|
return { filePath, configName, configFullName };
|
512
468
|
}
|
513
|
-
normalizedPackageName = normalizePackageName(filePath, "eslint-config");
|
469
|
+
normalizedPackageName = naming.normalizePackageName(filePath, "eslint-config");
|
514
470
|
debug(`Attempting to resolve ${normalizedPackageName}`);
|
515
471
|
filePath = resolver.resolve(normalizedPackageName, getLookupPath(relativeTo));
|
516
472
|
return { filePath, configFullName: filePath };
|
@@ -545,8 +501,10 @@ function loadFromDisk(resolvedPath, configContext) {
|
|
545
501
|
}
|
546
502
|
}
|
547
503
|
|
504
|
+
const ruleMap = configContext.linterContext.getRules();
|
505
|
+
|
548
506
|
// validate the configuration before continuing
|
549
|
-
validator.validate(config, resolvedPath.configFullName,
|
507
|
+
validator.validate(config, resolvedPath.configFullName, ruleMap.get.bind(ruleMap), configContext.linterContext.environments);
|
550
508
|
|
551
509
|
/*
|
552
510
|
* If an `extends` property is defined, it represents a configuration file to use as
|
@@ -614,7 +572,6 @@ module.exports = {
|
|
614
572
|
resolve,
|
615
573
|
write,
|
616
574
|
applyExtends,
|
617
|
-
normalizePackageName,
|
618
575
|
CONFIG_FILES,
|
619
576
|
|
620
577
|
/**
|
@@ -201,14 +201,18 @@ function configureRules(answers, config) {
|
|
201
201
|
// Now that we know which rules to disable, strip out configs with errors
|
202
202
|
registry = registry.stripFailingConfigs();
|
203
203
|
|
204
|
-
|
205
|
-
|
204
|
+
/*
|
205
|
+
* If there is only one config that results in no errors for a rule, we should use it.
|
206
|
+
* createConfig will only add rules that have one configuration in the registry.
|
207
|
+
*/
|
206
208
|
const singleConfigs = registry.createConfig().rules;
|
207
209
|
|
208
|
-
|
209
|
-
|
210
|
-
|
211
|
-
|
210
|
+
/*
|
211
|
+
* The "sweet spot" for number of options in a config seems to be two (severity plus one option).
|
212
|
+
* Very often, a third option (usually an object) is available to address
|
213
|
+
* edge cases, exceptions, or unique situations. We will prefer to use a config with
|
214
|
+
* specificity of two.
|
215
|
+
*/
|
212
216
|
const specTwoConfigs = registry.filterBySpecificity(2).createConfig().rules;
|
213
217
|
|
214
218
|
// Maybe a specific combination using all three options works
|
package/lib/config/config-ops.js
CHANGED
@@ -105,27 +105,27 @@ module.exports = {
|
|
105
105
|
merge: function deepmerge(target, src, combine, isRule) {
|
106
106
|
|
107
107
|
/*
|
108
|
-
The MIT License (MIT)
|
109
|
-
|
110
|
-
Copyright (c) 2012 Nicholas Fisher
|
111
|
-
|
112
|
-
Permission is hereby granted, free of charge, to any person obtaining a copy
|
113
|
-
of this software and associated documentation files (the "Software"), to deal
|
114
|
-
in the Software without restriction, including without limitation the rights
|
115
|
-
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
116
|
-
copies of the Software, and to permit persons to whom the Software is
|
117
|
-
furnished to do so, subject to the following conditions:
|
118
|
-
|
119
|
-
The above copyright notice and this permission notice shall be included in
|
120
|
-
all copies or substantial portions of the Software.
|
121
|
-
|
122
|
-
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
123
|
-
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
124
|
-
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
125
|
-
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
126
|
-
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
127
|
-
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
128
|
-
THE SOFTWARE.
|
108
|
+
* The MIT License (MIT)
|
109
|
+
*
|
110
|
+
* Copyright (c) 2012 Nicholas Fisher
|
111
|
+
*
|
112
|
+
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
113
|
+
* of this software and associated documentation files (the "Software"), to deal
|
114
|
+
* in the Software without restriction, including without limitation the rights
|
115
|
+
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
116
|
+
* copies of the Software, and to permit persons to whom the Software is
|
117
|
+
* furnished to do so, subject to the following conditions:
|
118
|
+
*
|
119
|
+
* The above copyright notice and this permission notice shall be included in
|
120
|
+
* all copies or substantial portions of the Software.
|
121
|
+
*
|
122
|
+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
123
|
+
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
124
|
+
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
125
|
+
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
126
|
+
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
127
|
+
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
128
|
+
* THE SOFTWARE.
|
129
129
|
*/
|
130
130
|
|
131
131
|
/*
|
@@ -187,19 +187,19 @@ class RuleConfigSet {
|
|
187
187
|
constructor(configs) {
|
188
188
|
|
189
189
|
/**
|
190
|
-
|
191
|
-
|
192
|
-
|
190
|
+
* Stored valid rule configurations for this instance
|
191
|
+
* @type {array}
|
192
|
+
*/
|
193
193
|
this.ruleConfigs = configs || [];
|
194
194
|
}
|
195
195
|
|
196
196
|
/**
|
197
|
-
|
198
|
-
|
199
|
-
|
200
|
-
|
201
|
-
|
202
|
-
|
197
|
+
* Add a severity level to the front of all configs in the instance.
|
198
|
+
* This should only be called after all configs have been added to the instance.
|
199
|
+
*
|
200
|
+
* @param {number} [severity=2] The level of severity for the rule (0, 1, 2)
|
201
|
+
* @returns {void}
|
202
|
+
*/
|
203
203
|
addErrorSeverity(severity) {
|
204
204
|
severity = severity || 2;
|
205
205
|
|
@@ -213,19 +213,19 @@ class RuleConfigSet {
|
|
213
213
|
}
|
214
214
|
|
215
215
|
/**
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
216
|
+
* Add rule configs from an array of strings (schema enums)
|
217
|
+
* @param {string[]} enums Array of valid rule options (e.g. ["always", "never"])
|
218
|
+
* @returns {void}
|
219
|
+
*/
|
220
220
|
addEnums(enums) {
|
221
221
|
this.ruleConfigs = this.ruleConfigs.concat(combineArrays(this.ruleConfigs, enums));
|
222
222
|
}
|
223
223
|
|
224
224
|
/**
|
225
|
-
|
226
|
-
|
227
|
-
|
228
|
-
|
225
|
+
* Add rule configurations from a schema object
|
226
|
+
* @param {Object} obj Schema item with type === "object"
|
227
|
+
* @returns {boolean} true if at least one schema for the object could be generated, false otherwise
|
228
|
+
*/
|
229
229
|
addObject(obj) {
|
230
230
|
const objectConfigSet = {
|
231
231
|
objectConfigs: [],
|
@@ -267,10 +267,10 @@ class RuleConfigSet {
|
|
267
267
|
}
|
268
268
|
|
269
269
|
/**
|
270
|
-
* Generate valid rule configurations based on a schema object
|
271
|
-
* @param {Object} schema A rule's schema object
|
272
|
-
* @returns {array[]} Valid rule configurations
|
273
|
-
*/
|
270
|
+
* Generate valid rule configurations based on a schema object
|
271
|
+
* @param {Object} schema A rule's schema object
|
272
|
+
* @returns {array[]} Valid rule configurations
|
273
|
+
*/
|
274
274
|
function generateConfigsFromSchema(schema) {
|
275
275
|
const configSet = new RuleConfigSet();
|
276
276
|
|
@@ -296,9 +296,9 @@ function generateConfigsFromSchema(schema) {
|
|
296
296
|
}
|
297
297
|
|
298
298
|
/**
|
299
|
-
* Generate possible rule configurations for all of the core rules
|
300
|
-
* @returns {rulesConfig} Hash of rule names and arrays of possible configurations
|
301
|
-
*/
|
299
|
+
* Generate possible rule configurations for all of the core rules
|
300
|
+
* @returns {rulesConfig} Hash of rule names and arrays of possible configurations
|
301
|
+
*/
|
302
302
|
function createCoreRuleConfigs() {
|
303
303
|
const ruleList = loadRules();
|
304
304
|
|