eslint 6.6.0 → 6.8.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.
Files changed (62) hide show
  1. package/CHANGELOG.md +94 -0
  2. package/README.md +7 -8
  3. package/conf/config-schema.js +2 -0
  4. package/conf/default-cli-options.js +1 -1
  5. package/conf/eslint-recommended.js +0 -1
  6. package/lib/cli-engine/cascading-config-array-factory.js +38 -13
  7. package/lib/cli-engine/cli-engine.js +41 -14
  8. package/lib/cli-engine/config-array/config-array.js +13 -0
  9. package/lib/cli-engine/config-array/extracted-config.js +27 -0
  10. package/lib/cli-engine/config-array/ignore-pattern.js +231 -0
  11. package/lib/cli-engine/config-array/index.js +2 -0
  12. package/lib/cli-engine/config-array-factory.js +115 -1
  13. package/lib/cli-engine/file-enumerator.js +73 -40
  14. package/lib/cli-engine/lint-result-cache.js +2 -1
  15. package/lib/cli.js +2 -1
  16. package/lib/init/config-initializer.js +4 -3
  17. package/lib/linter/config-comment-parser.js +1 -1
  18. package/lib/linter/report-translator.js +73 -7
  19. package/lib/options.js +6 -0
  20. package/lib/rule-tester/rule-tester.js +42 -6
  21. package/lib/rules/array-bracket-spacing.js +8 -8
  22. package/lib/rules/camelcase.js +19 -6
  23. package/lib/rules/comma-dangle.js +5 -2
  24. package/lib/rules/computed-property-spacing.js +4 -4
  25. package/lib/rules/curly.js +9 -4
  26. package/lib/rules/function-call-argument-newline.js +3 -1
  27. package/lib/rules/grouped-accessor-pairs.js +224 -0
  28. package/lib/rules/indent.js +11 -0
  29. package/lib/rules/index.js +5 -0
  30. package/lib/rules/key-spacing.js +34 -15
  31. package/lib/rules/lines-between-class-members.js +42 -53
  32. package/lib/rules/multiline-comment-style.js +237 -106
  33. package/lib/rules/no-cond-assign.js +14 -4
  34. package/lib/rules/no-constructor-return.js +62 -0
  35. package/lib/rules/no-dupe-else-if.js +122 -0
  36. package/lib/rules/no-implicit-globals.js +90 -8
  37. package/lib/rules/no-inline-comments.js +25 -11
  38. package/lib/rules/no-invalid-this.js +16 -2
  39. package/lib/rules/no-multiple-empty-lines.js +1 -1
  40. package/lib/rules/no-octal-escape.js +1 -1
  41. package/lib/rules/no-restricted-imports.js +2 -2
  42. package/lib/rules/no-setter-return.js +227 -0
  43. package/lib/rules/no-underscore-dangle.js +23 -4
  44. package/lib/rules/no-unexpected-multiline.js +8 -0
  45. package/lib/rules/no-unsafe-negation.js +30 -5
  46. package/lib/rules/no-useless-computed-key.js +60 -33
  47. package/lib/rules/no-useless-escape.js +26 -3
  48. package/lib/rules/object-curly-spacing.js +8 -8
  49. package/lib/rules/operator-assignment.js +11 -2
  50. package/lib/rules/prefer-const.js +14 -7
  51. package/lib/rules/prefer-exponentiation-operator.js +189 -0
  52. package/lib/rules/prefer-numeric-literals.js +29 -28
  53. package/lib/rules/require-atomic-updates.js +1 -1
  54. package/lib/rules/require-await.js +8 -0
  55. package/lib/rules/semi.js +6 -3
  56. package/lib/rules/space-infix-ops.js +1 -1
  57. package/lib/rules/spaced-comment.js +5 -4
  58. package/lib/rules/utils/ast-utils.js +31 -4
  59. package/lib/shared/types.js +9 -0
  60. package/lib/source-code/source-code.js +87 -10
  61. package/package.json +4 -3
  62. package/lib/cli-engine/ignored-paths.js +0 -363
@@ -0,0 +1,231 @@
1
+ /**
2
+ * @fileoverview `IgnorePattern` class.
3
+ *
4
+ * `IgnorePattern` class has the set of glob patterns and the base path.
5
+ *
6
+ * It provides two static methods.
7
+ *
8
+ * - `IgnorePattern.createDefaultIgnore(cwd)`
9
+ * Create the default predicate function.
10
+ * - `IgnorePattern.createIgnore(ignorePatterns)`
11
+ * Create the predicate function from multiple `IgnorePattern` objects.
12
+ *
13
+ * It provides two properties and a method.
14
+ *
15
+ * - `patterns`
16
+ * The glob patterns that ignore to lint.
17
+ * - `basePath`
18
+ * The base path of the glob patterns. If absolute paths existed in the
19
+ * glob patterns, those are handled as relative paths to the base path.
20
+ * - `getPatternsRelativeTo(basePath)`
21
+ * Get `patterns` as modified for a given base path. It modifies the
22
+ * absolute paths in the patterns as prepending the difference of two base
23
+ * paths.
24
+ *
25
+ * `ConfigArrayFactory` creates `IgnorePattern` objects when it processes
26
+ * `ignorePatterns` properties.
27
+ *
28
+ * @author Toru Nagashima <https://github.com/mysticatea>
29
+ */
30
+ "use strict";
31
+
32
+ //------------------------------------------------------------------------------
33
+ // Requirements
34
+ //------------------------------------------------------------------------------
35
+
36
+ const assert = require("assert");
37
+ const path = require("path");
38
+ const ignore = require("ignore");
39
+ const debug = require("debug")("eslint:ignore-pattern");
40
+
41
+ /** @typedef {ReturnType<import("ignore").default>} Ignore */
42
+
43
+ //------------------------------------------------------------------------------
44
+ // Helpers
45
+ //------------------------------------------------------------------------------
46
+
47
+ /**
48
+ * Get the path to the common ancestor directory of given paths.
49
+ * @param {string[]} sourcePaths The paths to calculate the common ancestor.
50
+ * @returns {string} The path to the common ancestor directory.
51
+ */
52
+ function getCommonAncestorPath(sourcePaths) {
53
+ let result = sourcePaths[0];
54
+
55
+ for (let i = 1; i < sourcePaths.length; ++i) {
56
+ const a = result;
57
+ const b = sourcePaths[i];
58
+
59
+ // Set the shorter one (it's the common ancestor if one includes the other).
60
+ result = a.length < b.length ? a : b;
61
+
62
+ // Set the common ancestor.
63
+ for (let j = 0, lastSepPos = 0; j < a.length && j < b.length; ++j) {
64
+ if (a[j] !== b[j]) {
65
+ result = a.slice(0, lastSepPos);
66
+ break;
67
+ }
68
+ if (a[j] === path.sep) {
69
+ lastSepPos = j;
70
+ }
71
+ }
72
+ }
73
+
74
+ return result || path.sep;
75
+ }
76
+
77
+ /**
78
+ * Make relative path.
79
+ * @param {string} from The source path to get relative path.
80
+ * @param {string} to The destination path to get relative path.
81
+ * @returns {string} The relative path.
82
+ */
83
+ function relative(from, to) {
84
+ const relPath = path.relative(from, to);
85
+
86
+ if (path.sep === "/") {
87
+ return relPath;
88
+ }
89
+ return relPath.split(path.sep).join("/");
90
+ }
91
+
92
+ /**
93
+ * Get the trailing slash if existed.
94
+ * @param {string} filePath The path to check.
95
+ * @returns {string} The trailing slash if existed.
96
+ */
97
+ function dirSuffix(filePath) {
98
+ const isDir = (
99
+ filePath.endsWith(path.sep) ||
100
+ (process.platform === "win32" && filePath.endsWith("/"))
101
+ );
102
+
103
+ return isDir ? "/" : "";
104
+ }
105
+
106
+ const DefaultPatterns = Object.freeze(["/node_modules/*", "/bower_components/*"]);
107
+ const DotPatterns = Object.freeze([".*", "!../"]);
108
+
109
+ //------------------------------------------------------------------------------
110
+ // Public
111
+ //------------------------------------------------------------------------------
112
+
113
+ class IgnorePattern {
114
+
115
+ /**
116
+ * The default patterns.
117
+ * @type {string[]}
118
+ */
119
+ static get DefaultPatterns() {
120
+ return DefaultPatterns;
121
+ }
122
+
123
+ /**
124
+ * Create the default predicate function.
125
+ * @param {string} cwd The current working directory.
126
+ * @returns {((filePath:string, dot:boolean) => boolean) & {basePath:string; patterns:string[]}}
127
+ * The preficate function.
128
+ * The first argument is an absolute path that is checked.
129
+ * The second argument is the flag to not ignore dotfiles.
130
+ * If the predicate function returned `true`, it means the path should be ignored.
131
+ */
132
+ static createDefaultIgnore(cwd) {
133
+ return this.createIgnore([new IgnorePattern(DefaultPatterns, cwd)]);
134
+ }
135
+
136
+ /**
137
+ * Create the predicate function from multiple `IgnorePattern` objects.
138
+ * @param {IgnorePattern[]} ignorePatterns The list of ignore patterns.
139
+ * @returns {((filePath:string, dot?:boolean) => boolean) & {basePath:string; patterns:string[]}}
140
+ * The preficate function.
141
+ * The first argument is an absolute path that is checked.
142
+ * The second argument is the flag to not ignore dotfiles.
143
+ * If the predicate function returned `true`, it means the path should be ignored.
144
+ */
145
+ static createIgnore(ignorePatterns) {
146
+ debug("Create with: %o", ignorePatterns);
147
+
148
+ const basePath = getCommonAncestorPath(ignorePatterns.map(p => p.basePath));
149
+ const patterns = [].concat(
150
+ ...ignorePatterns.map(p => p.getPatternsRelativeTo(basePath))
151
+ );
152
+ const ig = ignore().add([...DotPatterns, ...patterns]);
153
+ const dotIg = ignore().add(patterns);
154
+
155
+ debug(" processed: %o", { basePath, patterns });
156
+
157
+ return Object.assign(
158
+ (filePath, dot = false) => {
159
+ assert(path.isAbsolute(filePath), "'filePath' should be an absolute path.");
160
+ const relPathRaw = relative(basePath, filePath);
161
+ const relPath = relPathRaw && (relPathRaw + dirSuffix(filePath));
162
+ const adoptedIg = dot ? dotIg : ig;
163
+ const result = relPath !== "" && adoptedIg.ignores(relPath);
164
+
165
+ debug("Check", { filePath, dot, relativePath: relPath, result });
166
+ return result;
167
+ },
168
+ { basePath, patterns }
169
+ );
170
+ }
171
+
172
+ /**
173
+ * Initialize a new `IgnorePattern` instance.
174
+ * @param {string[]} patterns The glob patterns that ignore to lint.
175
+ * @param {string} basePath The base path of `patterns`.
176
+ */
177
+ constructor(patterns, basePath) {
178
+ assert(path.isAbsolute(basePath), "'basePath' should be an absolute path.");
179
+
180
+ /**
181
+ * The glob patterns that ignore to lint.
182
+ * @type {string[]}
183
+ */
184
+ this.patterns = patterns;
185
+
186
+ /**
187
+ * The base path of `patterns`.
188
+ * @type {string}
189
+ */
190
+ this.basePath = basePath;
191
+
192
+ /**
193
+ * If `true` then patterns which don't start with `/` will match the paths to the outside of `basePath`. Defaults to `false`.
194
+ *
195
+ * It's set `true` for `.eslintignore`, `package.json`, and `--ignore-path` for backward compatibility.
196
+ * It's `false` as-is for `ignorePatterns` property in config files.
197
+ * @type {boolean}
198
+ */
199
+ this.loose = false;
200
+ }
201
+
202
+ /**
203
+ * Get `patterns` as modified for a given base path. It modifies the
204
+ * absolute paths in the patterns as prepending the difference of two base
205
+ * paths.
206
+ * @param {string} newBasePath The base path.
207
+ * @returns {string[]} Modifired patterns.
208
+ */
209
+ getPatternsRelativeTo(newBasePath) {
210
+ assert(path.isAbsolute(newBasePath), "'newBasePath' should be an absolute path.");
211
+ const { basePath, loose, patterns } = this;
212
+
213
+ if (newBasePath === basePath) {
214
+ return patterns;
215
+ }
216
+ const prefix = `/${relative(newBasePath, basePath)}`;
217
+
218
+ return patterns.map(pattern => {
219
+ const negative = pattern.startsWith("!");
220
+ const head = negative ? "!" : "";
221
+ const body = negative ? pattern.slice(1) : pattern;
222
+
223
+ if (body.startsWith("/") || body.startsWith("../")) {
224
+ return `${head}${prefix}${body}`;
225
+ }
226
+ return loose ? pattern : `${head}${prefix}/**/${body}`;
227
+ });
228
+ }
229
+ }
230
+
231
+ module.exports = { IgnorePattern };
@@ -7,12 +7,14 @@
7
7
  const { ConfigArray, getUsedExtractedConfigs } = require("./config-array");
8
8
  const { ConfigDependency } = require("./config-dependency");
9
9
  const { ExtractedConfig } = require("./extracted-config");
10
+ const { IgnorePattern } = require("./ignore-pattern");
10
11
  const { OverrideTester } = require("./override-tester");
11
12
 
12
13
  module.exports = {
13
14
  ConfigArray,
14
15
  ConfigDependency,
15
16
  ExtractedConfig,
17
+ IgnorePattern,
16
18
  OverrideTester,
17
19
  getUsedExtractedConfigs
18
20
  };
@@ -17,6 +17,12 @@
17
17
  * Create a `ConfigArray` instance from a config file which is on a given
18
18
  * directory. This tries to load `.eslintrc.*` or `package.json`. If not
19
19
  * found, returns an empty `ConfigArray`.
20
+ * - `loadESLintIgnore(filePath)`
21
+ * Create a `ConfigArray` instance from a config file that is `.eslintignore`
22
+ * format. This is to handle `--ignore-path` option.
23
+ * - `loadDefaultESLintIgnore()`
24
+ * Create a `ConfigArray` instance from `.eslintignore` or `package.json` in
25
+ * the current working directory.
20
26
  *
21
27
  * `ConfigArrayFactory` class has the responsibility that loads configuration
22
28
  * files, including loading `extends`, `parser`, and `plugins`. The created
@@ -40,7 +46,12 @@ const stripComments = require("strip-json-comments");
40
46
  const { validateConfigSchema } = require("../shared/config-validator");
41
47
  const naming = require("../shared/naming");
42
48
  const ModuleResolver = require("../shared/relative-module-resolver");
43
- const { ConfigArray, ConfigDependency, OverrideTester } = require("./config-array");
49
+ const {
50
+ ConfigArray,
51
+ ConfigDependency,
52
+ IgnorePattern,
53
+ OverrideTester
54
+ } = require("./config-array");
44
55
  const debug = require("debug")("eslint:config-array-factory");
45
56
 
46
57
  //------------------------------------------------------------------------------
@@ -51,6 +62,7 @@ const eslintRecommendedPath = path.resolve(__dirname, "../../conf/eslint-recomme
51
62
  const eslintAllPath = path.resolve(__dirname, "../../conf/eslint-all.js");
52
63
  const configFilenames = [
53
64
  ".eslintrc.js",
65
+ ".eslintrc.cjs",
54
66
  ".eslintrc.yaml",
55
67
  ".eslintrc.yml",
56
68
  ".eslintrc.json",
@@ -221,6 +233,26 @@ function loadPackageJSONConfigFile(filePath) {
221
233
  }
222
234
  }
223
235
 
236
+ /**
237
+ * Loads a `.eslintignore` from a file.
238
+ * @param {string} filePath The filename to load.
239
+ * @returns {string[]} The ignore patterns from the file.
240
+ * @private
241
+ */
242
+ function loadESLintIgnoreFile(filePath) {
243
+ debug(`Loading .eslintignore file: ${filePath}`);
244
+
245
+ try {
246
+ return readFile(filePath)
247
+ .split(/\r?\n/gu)
248
+ .filter(line => line.trim() !== "" && !line.startsWith("#"));
249
+ } catch (e) {
250
+ debug(`Error reading .eslintignore file: ${filePath}`);
251
+ e.message = `Cannot read .eslintignore file: ${filePath}\nError: ${e.message}`;
252
+ throw e;
253
+ }
254
+ }
255
+
224
256
  /**
225
257
  * Creates an error to notify about a missing config to extend from.
226
258
  * @param {string} configName The name of the missing config.
@@ -248,6 +280,7 @@ function configMissingError(configName, importerName) {
248
280
  function loadConfigFile(filePath) {
249
281
  switch (path.extname(filePath)) {
250
282
  case ".js":
283
+ case ".cjs":
251
284
  return loadJSConfigFile(filePath);
252
285
 
253
286
  case ".json":
@@ -403,6 +436,54 @@ class ConfigArrayFactory {
403
436
  );
404
437
  }
405
438
 
439
+ /**
440
+ * Load `.eslintignore` file.
441
+ * @param {string} filePath The path to a `.eslintignore` file to load.
442
+ * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
443
+ */
444
+ loadESLintIgnore(filePath) {
445
+ const { cwd } = internalSlotsMap.get(this);
446
+ const absolutePath = path.resolve(cwd, filePath);
447
+ const name = path.relative(cwd, absolutePath);
448
+ const ignorePatterns = loadESLintIgnoreFile(absolutePath);
449
+
450
+ return createConfigArray(
451
+ this._normalizeESLintIgnoreData(ignorePatterns, absolutePath, name)
452
+ );
453
+ }
454
+
455
+ /**
456
+ * Load `.eslintignore` file in the current working directory.
457
+ * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
458
+ */
459
+ loadDefaultESLintIgnore() {
460
+ const { cwd } = internalSlotsMap.get(this);
461
+ const eslintIgnorePath = path.resolve(cwd, ".eslintignore");
462
+ const packageJsonPath = path.resolve(cwd, "package.json");
463
+
464
+ if (fs.existsSync(eslintIgnorePath)) {
465
+ return this.loadESLintIgnore(eslintIgnorePath);
466
+ }
467
+ if (fs.existsSync(packageJsonPath)) {
468
+ const data = loadJSONConfigFile(packageJsonPath);
469
+
470
+ if (Object.hasOwnProperty.call(data, "eslintIgnore")) {
471
+ if (!Array.isArray(data.eslintIgnore)) {
472
+ throw new Error("Package.json eslintIgnore property requires an array of paths");
473
+ }
474
+ return createConfigArray(
475
+ this._normalizeESLintIgnoreData(
476
+ data.eslintIgnore,
477
+ packageJsonPath,
478
+ "eslintIgnore in package.json"
479
+ )
480
+ );
481
+ }
482
+ }
483
+
484
+ return new ConfigArray();
485
+ }
486
+
406
487
  /**
407
488
  * Load a given config file.
408
489
  * @param {string} filePath The path to a config file.
@@ -451,6 +532,30 @@ class ConfigArrayFactory {
451
532
  return null;
452
533
  }
453
534
 
535
+ /**
536
+ * Normalize a given `.eslintignore` data to config array elements.
537
+ * @param {string[]} ignorePatterns The patterns to ignore files.
538
+ * @param {string|undefined} filePath The file path of this config.
539
+ * @param {string|undefined} name The name of this config.
540
+ * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
541
+ * @private
542
+ */
543
+ *_normalizeESLintIgnoreData(ignorePatterns, filePath, name) {
544
+ const elements = this._normalizeObjectConfigData(
545
+ { ignorePatterns },
546
+ filePath,
547
+ name
548
+ );
549
+
550
+ // Set `ignorePattern.loose` flag for backward compatibility.
551
+ for (const element of elements) {
552
+ if (element.ignorePattern) {
553
+ element.ignorePattern.loose = true;
554
+ }
555
+ yield element;
556
+ }
557
+ }
558
+
454
559
  /**
455
560
  * Normalize a given config to an array.
456
561
  * @param {ConfigData} configData The config data to normalize.
@@ -494,6 +599,9 @@ class ConfigArrayFactory {
494
599
  if (element.criteria) {
495
600
  element.criteria.basePath = basePath;
496
601
  }
602
+ if (element.ignorePattern) {
603
+ element.ignorePattern.basePath = basePath;
604
+ }
497
605
 
498
606
  /*
499
607
  * Merge the criteria; this is for only file extension processors in
@@ -526,6 +634,7 @@ class ConfigArrayFactory {
526
634
  env,
527
635
  extends: extend,
528
636
  globals,
637
+ ignorePatterns,
529
638
  noInlineConfig,
530
639
  parser: parserName,
531
640
  parserOptions,
@@ -541,6 +650,10 @@ class ConfigArrayFactory {
541
650
  name
542
651
  ) {
543
652
  const extendList = Array.isArray(extend) ? extend : [extend];
653
+ const ignorePattern = ignorePatterns && new IgnorePattern(
654
+ Array.isArray(ignorePatterns) ? ignorePatterns : [ignorePatterns],
655
+ filePath ? path.dirname(filePath) : internalSlotsMap.get(this).cwd
656
+ );
544
657
 
545
658
  // Flatten `extends`.
546
659
  for (const extendName of extendList.filter(Boolean)) {
@@ -569,6 +682,7 @@ class ConfigArrayFactory {
569
682
  criteria: null,
570
683
  env,
571
684
  globals,
685
+ ignorePattern,
572
686
  noInlineConfig,
573
687
  parser,
574
688
  parserOptions,
@@ -40,8 +40,8 @@ const getGlobParent = require("glob-parent");
40
40
  const isGlob = require("is-glob");
41
41
  const { escapeRegExp } = require("lodash");
42
42
  const { Minimatch } = require("minimatch");
43
+ const { IgnorePattern } = require("./config-array");
43
44
  const { CascadingConfigArrayFactory } = require("./cascading-config-array-factory");
44
- const { IgnoredPaths } = require("./ignored-paths");
45
45
  const debug = require("debug")("eslint:file-enumerator");
46
46
 
47
47
  //------------------------------------------------------------------------------
@@ -64,7 +64,6 @@ const IGNORED = 2;
64
64
  * @property {string[]} [extensions] The extensions to match files for directory patterns.
65
65
  * @property {boolean} [globInputPaths] Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
66
66
  * @property {boolean} [ignore] The flag to check ignored files.
67
- * @property {IgnoredPaths} [ignoredPaths] The ignored paths.
68
67
  * @property {string[]} [rulePaths] The value of `--rulesdir` option.
69
68
  */
70
69
 
@@ -92,8 +91,7 @@ const IGNORED = 2;
92
91
  * @property {RegExp} extensionRegExp The RegExp to test if a string ends with specific file extensions.
93
92
  * @property {boolean} globInputPaths Set to false to skip glob resolution of input file paths to lint (default: true). If false, each input file paths is assumed to be a non-glob path to an existing file.
94
93
  * @property {boolean} ignoreFlag The flag to check ignored files.
95
- * @property {IgnoredPaths} ignoredPathsWithDotfiles The ignored paths but don't include dot files.
96
- * @property {IgnoredPaths} ignoredPaths The ignored paths.
94
+ * @property {(filePath:string, dot:boolean) => boolean} defaultIgnores The default predicate function to ignore files.
97
95
  */
98
96
 
99
97
  /** @type {WeakMap<FileEnumerator, FileEnumeratorInternalSlots>} */
@@ -192,12 +190,13 @@ class FileEnumerator {
192
190
  configArrayFactory = new CascadingConfigArrayFactory({ cwd }),
193
191
  extensions = [".js"],
194
192
  globInputPaths = true,
195
- ignore = true,
196
- ignoredPaths = new IgnoredPaths({ cwd, ignore })
193
+ errorOnUnmatchedPattern = true,
194
+ ignore = true
197
195
  } = {}) {
198
196
  internalSlotsMap.set(this, {
199
197
  configArrayFactory,
200
198
  cwd,
199
+ defaultIgnores: IgnorePattern.createDefaultIgnore(cwd),
201
200
  extensionRegExp: new RegExp(
202
201
  `.\\.(?:${extensions
203
202
  .map(ext => escapeRegExp(
@@ -210,12 +209,8 @@ class FileEnumerator {
210
209
  "u"
211
210
  ),
212
211
  globInputPaths,
213
- ignoreFlag: ignore,
214
- ignoredPaths,
215
- ignoredPathsWithDotfiles: new IgnoredPaths({
216
- ...ignoredPaths.options,
217
- dotfiles: true
218
- })
212
+ errorOnUnmatchedPattern,
213
+ ignoreFlag: ignore
219
214
  });
220
215
  }
221
216
 
@@ -233,7 +228,7 @@ class FileEnumerator {
233
228
  * @returns {IterableIterator<FileAndConfig>} The found files.
234
229
  */
235
230
  *iterateFiles(patternOrPatterns) {
236
- const { globInputPaths } = internalSlotsMap.get(this);
231
+ const { globInputPaths, errorOnUnmatchedPattern } = internalSlotsMap.get(this);
237
232
  const patterns = Array.isArray(patternOrPatterns)
238
233
  ? patternOrPatterns
239
234
  : [patternOrPatterns];
@@ -272,14 +267,16 @@ class FileEnumerator {
272
267
  }
273
268
 
274
269
  // Raise an error if any files were not found.
275
- if (!foundRegardlessOfIgnored) {
276
- throw new NoFilesFoundError(
277
- pattern,
278
- !globInputPaths && isGlob(pattern)
279
- );
280
- }
281
- if (!found) {
282
- throw new AllFilesIgnoredError(pattern);
270
+ if (errorOnUnmatchedPattern) {
271
+ if (!foundRegardlessOfIgnored) {
272
+ throw new NoFilesFoundError(
273
+ pattern,
274
+ !globInputPaths && isGlob(pattern)
275
+ );
276
+ }
277
+ if (!found) {
278
+ throw new AllFilesIgnoredError(pattern);
279
+ }
283
280
  }
284
281
  }
285
282
 
@@ -321,7 +318,7 @@ class FileEnumerator {
321
318
 
322
319
  const { configArrayFactory } = internalSlotsMap.get(this);
323
320
  const config = configArrayFactory.getConfigArrayForFile(filePath);
324
- const ignored = this._isIgnoredFile(filePath, { direct: true });
321
+ const ignored = this._isIgnoredFile(filePath, { config, direct: true });
325
322
  const flag = ignored ? IGNORED : NONE;
326
323
 
327
324
  return [{ config, filePath, flag }];
@@ -353,7 +350,7 @@ class FileEnumerator {
353
350
  _iterateFilesWithGlob(pattern, dotfiles) {
354
351
  debug(`Glob: ${pattern}`);
355
352
 
356
- const directoryPath = getGlobParent(pattern);
353
+ const directoryPath = path.resolve(getGlobParent(pattern));
357
354
  const globPart = pattern.slice(directoryPath.length + 1);
358
355
 
359
356
  /*
@@ -382,9 +379,6 @@ class FileEnumerator {
382
379
  * @private
383
380
  */
384
381
  *_iterateFilesRecursive(directoryPath, options) {
385
- if (this._isIgnoredFile(directoryPath + path.sep, options)) {
386
- return;
387
- }
388
382
  debug(`Enter the directory: ${directoryPath}`);
389
383
  const { configArrayFactory, extensionRegExp } = internalSlotsMap.get(this);
390
384
 
@@ -399,9 +393,18 @@ class FileEnumerator {
399
393
  // Check if the file is matched.
400
394
  if (stat && stat.isFile()) {
401
395
  if (!config) {
402
- config = configArrayFactory.getConfigArrayForFile(filePath);
396
+ config = configArrayFactory.getConfigArrayForFile(
397
+ filePath,
398
+
399
+ /*
400
+ * We must ignore `ConfigurationNotFoundError` at this
401
+ * point because we don't know if target files exist in
402
+ * this directory.
403
+ */
404
+ { ignoreNotFoundError: true }
405
+ );
403
406
  }
404
- const ignored = this._isIgnoredFile(filePath, options);
407
+ const ignored = this._isIgnoredFile(filePath, { ...options, config });
405
408
  const flag = ignored ? IGNORED_SILENTLY : NONE;
406
409
  const matched = options.selector
407
410
 
@@ -413,14 +416,31 @@ class FileEnumerator {
413
416
 
414
417
  if (matched) {
415
418
  debug(`Yield: ${filename}${ignored ? " but ignored" : ""}`);
416
- yield { config, filePath, flag };
419
+ yield {
420
+ config: configArrayFactory.getConfigArrayForFile(filePath),
421
+ filePath,
422
+ flag
423
+ };
417
424
  } else {
418
425
  debug(`Didn't match: ${filename}`);
419
426
  }
420
427
 
421
428
  // Dive into the sub directory.
422
429
  } else if (options.recursive && stat && stat.isDirectory()) {
423
- yield* this._iterateFilesRecursive(filePath, options);
430
+ if (!config) {
431
+ config = configArrayFactory.getConfigArrayForFile(
432
+ filePath,
433
+ { ignoreNotFoundError: true }
434
+ );
435
+ }
436
+ const ignored = this._isIgnoredFile(
437
+ filePath + path.sep,
438
+ { ...options, config }
439
+ );
440
+
441
+ if (!ignored) {
442
+ yield* this._iterateFilesRecursive(filePath, options);
443
+ }
424
444
  }
425
445
  }
426
446
 
@@ -431,24 +451,37 @@ class FileEnumerator {
431
451
  * Check if a given file should be ignored.
432
452
  * @param {string} filePath The path to a file to check.
433
453
  * @param {Object} options Options
454
+ * @param {ConfigArray} [options.config] The config for this file.
434
455
  * @param {boolean} [options.dotfiles] If `true` then this is not ignore dot files by default.
435
456
  * @param {boolean} [options.direct] If `true` then this is a direct specified file.
436
457
  * @returns {boolean} `true` if the file should be ignored.
437
458
  * @private
438
459
  */
439
- _isIgnoredFile(filePath, { dotfiles = false, direct = false }) {
460
+ _isIgnoredFile(filePath, {
461
+ config: providedConfig,
462
+ dotfiles = false,
463
+ direct = false
464
+ }) {
440
465
  const {
441
- ignoreFlag,
442
- ignoredPaths,
443
- ignoredPathsWithDotfiles
466
+ configArrayFactory,
467
+ defaultIgnores,
468
+ ignoreFlag
444
469
  } = internalSlotsMap.get(this);
445
- const adoptedIgnoredPaths = dotfiles
446
- ? ignoredPathsWithDotfiles
447
- : ignoredPaths;
448
470
 
449
- return ignoreFlag
450
- ? adoptedIgnoredPaths.contains(filePath)
451
- : (!direct && adoptedIgnoredPaths.contains(filePath, "default"));
471
+ if (ignoreFlag) {
472
+ const config =
473
+ providedConfig ||
474
+ configArrayFactory.getConfigArrayForFile(
475
+ filePath,
476
+ { ignoreNotFoundError: true }
477
+ );
478
+ const ignores =
479
+ config.extractConfig(filePath).ignores || defaultIgnores;
480
+
481
+ return ignores(filePath, dotfiles);
482
+ }
483
+
484
+ return !direct && defaultIgnores(filePath, dotfiles);
452
485
  }
453
486
  }
454
487
 
@@ -20,6 +20,7 @@ const hash = require("./hash");
20
20
  //-----------------------------------------------------------------------------
21
21
 
22
22
  const configHashCache = new WeakMap();
23
+ const nodeVersion = process && process.version;
23
24
 
24
25
  /**
25
26
  * Calculates the hash of the config
@@ -28,7 +29,7 @@ const configHashCache = new WeakMap();
28
29
  */
29
30
  function hashOfConfigFor(config) {
30
31
  if (!configHashCache.has(config)) {
31
- configHashCache.set(config, hash(`${pkg.version}_${stringify(config)}`));
32
+ configHashCache.set(config, hash(`${pkg.version}_${nodeVersion}_${stringify(config)}`));
32
33
  }
33
34
 
34
35
  return configHashCache.get(config);
package/lib/cli.js CHANGED
@@ -68,7 +68,8 @@ function translateOptions(cliOptions) {
68
68
  fixTypes: cliOptions.fixType,
69
69
  allowInlineConfig: cliOptions.inlineConfig,
70
70
  reportUnusedDisableDirectives: cliOptions.reportUnusedDisableDirectives,
71
- resolvePluginsRelativeTo: cliOptions.resolvePluginsRelativeTo
71
+ resolvePluginsRelativeTo: cliOptions.resolvePluginsRelativeTo,
72
+ errorOnUnmatchedPattern: cliOptions.errorOnUnmatchedPattern
72
73
  };
73
74
  }
74
75