eslint 6.5.1 → 6.7.2

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 (197) hide show
  1. package/CHANGELOG.md +118 -0
  2. package/README.md +10 -9
  3. package/conf/config-schema.js +1 -0
  4. package/conf/default-cli-options.js +1 -1
  5. package/lib/cli-engine/cascading-config-array-factory.js +40 -14
  6. package/lib/cli-engine/cli-engine.js +49 -21
  7. package/lib/cli-engine/config-array/config-array.js +13 -4
  8. package/lib/cli-engine/config-array/config-dependency.js +2 -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/override-tester.js +2 -0
  13. package/lib/cli-engine/config-array-factory.js +120 -2
  14. package/lib/cli-engine/file-enumerator.js +65 -34
  15. package/lib/cli-engine/formatters/html.js +1 -0
  16. package/lib/init/autoconfig.js +1 -11
  17. package/lib/init/config-file.js +0 -1
  18. package/lib/init/config-initializer.js +4 -4
  19. package/lib/init/config-rule.js +1 -5
  20. package/lib/init/npm-utils.js +0 -5
  21. package/lib/linter/code-path-analysis/code-path-analyzer.js +24 -38
  22. package/lib/linter/code-path-analysis/code-path-segment.js +17 -25
  23. package/lib/linter/code-path-analysis/code-path-state.js +40 -81
  24. package/lib/linter/code-path-analysis/code-path.js +10 -11
  25. package/lib/linter/code-path-analysis/debug-helpers.js +8 -12
  26. package/lib/linter/code-path-analysis/fork-context.js +23 -34
  27. package/lib/linter/code-path-analysis/id-generator.js +2 -2
  28. package/lib/linter/linter.js +121 -95
  29. package/lib/linter/node-event-generator.js +3 -2
  30. package/lib/linter/report-translator.js +73 -7
  31. package/lib/rule-tester/rule-tester.js +46 -14
  32. package/lib/rules/accessor-pairs.js +8 -8
  33. package/lib/rules/array-bracket-newline.js +12 -15
  34. package/lib/rules/array-bracket-spacing.js +12 -12
  35. package/lib/rules/array-callback-return.js +6 -11
  36. package/lib/rules/array-element-newline.js +5 -8
  37. package/lib/rules/arrow-parens.js +0 -1
  38. package/lib/rules/block-scoped-var.js +3 -3
  39. package/lib/rules/block-spacing.js +4 -4
  40. package/lib/rules/camelcase.js +19 -6
  41. package/lib/rules/capitalized-comments.js +0 -7
  42. package/lib/rules/class-methods-use-this.js +3 -3
  43. package/lib/rules/comma-dangle.js +20 -25
  44. package/lib/rules/comma-spacing.js +1 -1
  45. package/lib/rules/computed-property-spacing.js +14 -14
  46. package/lib/rules/consistent-return.js +4 -5
  47. package/lib/rules/consistent-this.js +5 -5
  48. package/lib/rules/constructor-super.js +14 -16
  49. package/lib/rules/curly.js +12 -9
  50. package/lib/rules/default-param-last.js +1 -0
  51. package/lib/rules/dot-location.js +11 -12
  52. package/lib/rules/func-names.js +6 -6
  53. package/lib/rules/function-call-argument-newline.js +8 -6
  54. package/lib/rules/generator-star-spacing.js +4 -9
  55. package/lib/rules/getter-return.js +4 -7
  56. package/lib/rules/grouped-accessor-pairs.js +224 -0
  57. package/lib/rules/indent.js +13 -2
  58. package/lib/rules/index.js +5 -0
  59. package/lib/rules/init-declarations.js +2 -2
  60. package/lib/rules/jsx-quotes.js +1 -1
  61. package/lib/rules/keyword-spacing.js +32 -56
  62. package/lib/rules/lines-around-directive.js +1 -1
  63. package/lib/rules/max-len.js +0 -5
  64. package/lib/rules/max-statements-per-line.js +3 -7
  65. package/lib/rules/multiline-comment-style.js +237 -106
  66. package/lib/rules/multiline-ternary.js +3 -3
  67. package/lib/rules/newline-after-var.js +6 -7
  68. package/lib/rules/newline-before-return.js +8 -9
  69. package/lib/rules/newline-per-chained-call.js +2 -4
  70. package/lib/rules/no-class-assign.js +2 -2
  71. package/lib/rules/no-compare-neg-zero.js +1 -2
  72. package/lib/rules/no-cond-assign.js +14 -4
  73. package/lib/rules/no-confusing-arrow.js +2 -2
  74. package/lib/rules/no-console.js +4 -8
  75. package/lib/rules/no-const-assign.js +1 -1
  76. package/lib/rules/no-constructor-return.js +62 -0
  77. package/lib/rules/no-dupe-args.js +1 -1
  78. package/lib/rules/no-dupe-class-members.js +3 -4
  79. package/lib/rules/no-dupe-else-if.js +122 -0
  80. package/lib/rules/no-dupe-keys.js +6 -5
  81. package/lib/rules/no-duplicate-imports.js +14 -18
  82. package/lib/rules/no-else-return.js +0 -8
  83. package/lib/rules/no-empty-function.js +2 -4
  84. package/lib/rules/no-eval.js +10 -18
  85. package/lib/rules/no-ex-assign.js +1 -1
  86. package/lib/rules/no-extra-bind.js +5 -12
  87. package/lib/rules/no-extra-boolean-cast.js +0 -2
  88. package/lib/rules/no-extra-label.js +4 -9
  89. package/lib/rules/no-extra-parens.js +17 -15
  90. package/lib/rules/no-extra-semi.js +5 -6
  91. package/lib/rules/no-fallthrough.js +6 -6
  92. package/lib/rules/no-func-assign.js +3 -3
  93. package/lib/rules/no-global-assign.js +4 -4
  94. package/lib/rules/no-implicit-coercion.js +10 -10
  95. package/lib/rules/no-implicit-globals.js +90 -8
  96. package/lib/rules/no-implied-eval.js +0 -1
  97. package/lib/rules/no-inline-comments.js +25 -11
  98. package/lib/rules/no-invalid-this.js +17 -5
  99. package/lib/rules/no-labels.js +3 -6
  100. package/lib/rules/no-lone-blocks.js +1 -1
  101. package/lib/rules/no-loop-func.js +6 -11
  102. package/lib/rules/no-magic-numbers.js +6 -6
  103. package/lib/rules/no-misleading-character-class.js +14 -7
  104. package/lib/rules/no-mixed-operators.js +13 -22
  105. package/lib/rules/no-mixed-requires.js +0 -1
  106. package/lib/rules/no-multi-spaces.js +1 -1
  107. package/lib/rules/no-native-reassign.js +4 -4
  108. package/lib/rules/no-octal-escape.js +1 -1
  109. package/lib/rules/no-param-reassign.js +28 -7
  110. package/lib/rules/no-redeclare.js +1 -1
  111. package/lib/rules/no-regex-spaces.js +0 -1
  112. package/lib/rules/no-restricted-imports.js +11 -11
  113. package/lib/rules/no-self-assign.js +12 -13
  114. package/lib/rules/no-sequences.js +3 -3
  115. package/lib/rules/no-setter-return.js +227 -0
  116. package/lib/rules/no-shadow.js +1 -4
  117. package/lib/rules/no-tabs.js +8 -2
  118. package/lib/rules/no-this-before-super.js +12 -13
  119. package/lib/rules/no-trailing-spaces.js +19 -7
  120. package/lib/rules/no-underscore-dangle.js +23 -4
  121. package/lib/rules/no-unexpected-multiline.js +8 -0
  122. package/lib/rules/no-unmodified-loop-condition.js +16 -29
  123. package/lib/rules/no-unneeded-ternary.js +3 -3
  124. package/lib/rules/no-unreachable.js +7 -7
  125. package/lib/rules/no-unsafe-finally.js +4 -7
  126. package/lib/rules/no-unsafe-negation.js +32 -9
  127. package/lib/rules/no-unused-expressions.js +11 -7
  128. package/lib/rules/no-unused-labels.js +3 -6
  129. package/lib/rules/no-unused-vars.js +22 -29
  130. package/lib/rules/no-use-before-define.js +10 -15
  131. package/lib/rules/no-useless-call.js +4 -4
  132. package/lib/rules/no-useless-computed-key.js +60 -33
  133. package/lib/rules/no-useless-concat.js +4 -4
  134. package/lib/rules/no-useless-constructor.js +14 -22
  135. package/lib/rules/no-useless-escape.js +29 -8
  136. package/lib/rules/no-useless-rename.js +7 -7
  137. package/lib/rules/no-useless-return.js +8 -15
  138. package/lib/rules/no-var.js +12 -25
  139. package/lib/rules/no-warning-comments.js +0 -1
  140. package/lib/rules/no-whitespace-before-property.js +3 -3
  141. package/lib/rules/object-curly-newline.js +7 -10
  142. package/lib/rules/object-curly-spacing.js +21 -22
  143. package/lib/rules/object-shorthand.js +1 -1
  144. package/lib/rules/one-var-declaration-per-line.js +2 -2
  145. package/lib/rules/operator-assignment.js +33 -3
  146. package/lib/rules/padded-blocks.js +1 -1
  147. package/lib/rules/padding-line-between-statements.js +0 -16
  148. package/lib/rules/prefer-arrow-callback.js +6 -6
  149. package/lib/rules/prefer-const.js +27 -28
  150. package/lib/rules/prefer-destructuring.js +1 -7
  151. package/lib/rules/prefer-exponentiation-operator.js +189 -0
  152. package/lib/rules/prefer-named-capture-group.js +0 -1
  153. package/lib/rules/prefer-numeric-literals.js +32 -4
  154. package/lib/rules/prefer-object-spread.js +7 -7
  155. package/lib/rules/prefer-rest-params.js +3 -6
  156. package/lib/rules/prefer-spread.js +4 -4
  157. package/lib/rules/prefer-template.js +5 -6
  158. package/lib/rules/quote-props.js +1 -1
  159. package/lib/rules/quotes.js +5 -6
  160. package/lib/rules/radix.js +5 -10
  161. package/lib/rules/require-await.js +10 -5
  162. package/lib/rules/require-yield.js +2 -2
  163. package/lib/rules/rest-spread-spacing.js +1 -1
  164. package/lib/rules/semi.js +6 -3
  165. package/lib/rules/sort-imports.js +3 -4
  166. package/lib/rules/sort-keys.js +1 -3
  167. package/lib/rules/space-before-blocks.js +1 -2
  168. package/lib/rules/space-in-parens.js +4 -4
  169. package/lib/rules/space-infix-ops.js +6 -6
  170. package/lib/rules/spaced-comment.js +20 -22
  171. package/lib/rules/strict.js +2 -4
  172. package/lib/rules/symbol-description.js +1 -2
  173. package/lib/rules/template-curly-spacing.js +2 -2
  174. package/lib/rules/use-isnan.js +40 -3
  175. package/lib/rules/utils/ast-utils.js +84 -85
  176. package/lib/rules/utils/fix-tracker.js +0 -6
  177. package/lib/rules/utils/lazy-loading-rule-map.js +0 -1
  178. package/lib/rules/vars-on-top.js +11 -11
  179. package/lib/shared/config-ops.js +2 -2
  180. package/lib/shared/runtime-info.js +8 -8
  181. package/lib/shared/traverser.js +2 -0
  182. package/lib/shared/types.js +9 -0
  183. package/lib/source-code/source-code.js +94 -17
  184. package/lib/source-code/token-store/backward-token-comment-cursor.js +5 -5
  185. package/lib/source-code/token-store/backward-token-cursor.js +5 -5
  186. package/lib/source-code/token-store/cursors.js +17 -19
  187. package/lib/source-code/token-store/decorative-cursor.js +1 -1
  188. package/lib/source-code/token-store/filter-cursor.js +2 -2
  189. package/lib/source-code/token-store/forward-token-comment-cursor.js +5 -5
  190. package/lib/source-code/token-store/forward-token-cursor.js +5 -5
  191. package/lib/source-code/token-store/index.js +86 -92
  192. package/lib/source-code/token-store/limit-cursor.js +2 -2
  193. package/lib/source-code/token-store/padded-token-cursor.js +7 -7
  194. package/lib/source-code/token-store/skip-cursor.js +2 -2
  195. package/lib/source-code/token-store/utils.js +9 -13
  196. package/package.json +9 -7
  197. package/lib/cli-engine/ignored-paths.js +0 -362
@@ -31,6 +31,7 @@
31
31
  //------------------------------------------------------------------------------
32
32
 
33
33
  const { ExtractedConfig } = require("./extracted-config");
34
+ const { IgnorePattern } = require("./ignore-pattern");
34
35
 
35
36
  //------------------------------------------------------------------------------
36
37
  // Helpers
@@ -54,6 +55,7 @@ const { ExtractedConfig } = require("./extracted-config");
54
55
  * @property {InstanceType<OverrideTester>|null} criteria The tester for the `files` and `excludedFiles` of this config element.
55
56
  * @property {Record<string, boolean>|undefined} env The environment settings.
56
57
  * @property {Record<string, GlobalConf>|undefined} globals The global variable settings.
58
+ * @property {IgnorePattern|undefined} ignorePattern The ignore patterns.
57
59
  * @property {boolean|undefined} noInlineConfig The flag that disables directive comments.
58
60
  * @property {DependentParser|undefined} parser The parser loader.
59
61
  * @property {Object|undefined} parserOptions The parser options.
@@ -126,7 +128,6 @@ function isNonNullObject(x) {
126
128
  *
127
129
  * Assign every property values of `y` to `x` if `x` doesn't have the property.
128
130
  * If `x`'s property value is an object, it does recursive.
129
- *
130
131
  * @param {Object} target The destination to merge
131
132
  * @param {Object|undefined} source The source to merge.
132
133
  * @returns {void}
@@ -157,7 +158,6 @@ function mergeWithoutOverwrite(target, source) {
157
158
  /**
158
159
  * Merge plugins.
159
160
  * `target`'s definition is prior to `source`'s.
160
- *
161
161
  * @param {Record<string, DependentPlugin>} target The destination to merge
162
162
  * @param {Record<string, DependentPlugin>|undefined} source The source to merge.
163
163
  * @returns {void}
@@ -187,7 +187,6 @@ function mergePlugins(target, source) {
187
187
  /**
188
188
  * Merge rule configs.
189
189
  * `target`'s definition is prior to `source`'s.
190
- *
191
190
  * @param {Record<string, Array>} target The destination to merge
192
191
  * @param {Record<string, RuleConf>|undefined} source The source to merge.
193
192
  * @returns {void}
@@ -234,6 +233,7 @@ function mergeRuleConfigs(target, source) {
234
233
  */
235
234
  function createConfig(instance, indices) {
236
235
  const config = new ExtractedConfig();
236
+ const ignorePatterns = [];
237
237
 
238
238
  // Merge elements.
239
239
  for (const index of indices) {
@@ -263,6 +263,11 @@ function createConfig(instance, indices) {
263
263
  config.reportUnusedDisableDirectives = element.reportUnusedDisableDirectives;
264
264
  }
265
265
 
266
+ // Collect ignorePatterns
267
+ if (element.ignorePattern) {
268
+ ignorePatterns.push(element.ignorePattern);
269
+ }
270
+
266
271
  // Merge others.
267
272
  mergeWithoutOverwrite(config.env, element.env);
268
273
  mergeWithoutOverwrite(config.globals, element.globals);
@@ -272,6 +277,11 @@ function createConfig(instance, indices) {
272
277
  mergeRuleConfigs(config.rules, element.rules);
273
278
  }
274
279
 
280
+ // Create the predicate function for ignore patterns.
281
+ if (ignorePatterns.length > 0) {
282
+ config.ignores = IgnorePattern.createIgnore(ignorePatterns.reverse());
283
+ }
284
+
275
285
  return config;
276
286
  }
277
287
 
@@ -382,7 +392,6 @@ function ensurePluginMemberMaps(instance) {
382
392
  * You need to call `ConfigArray#extractConfig(filePath)` method in order to
383
393
  * extract, merge and get only the config data which is related to an arbitrary
384
394
  * file.
385
- *
386
395
  * @extends {Array<ConfigArrayElement>}
387
396
  */
388
397
  class ConfigArray extends Array {
@@ -81,6 +81,7 @@ class ConfigDependency {
81
81
  this.importerPath = importerPath;
82
82
  }
83
83
 
84
+ // eslint-disable-next-line jsdoc/require-description
84
85
  /**
85
86
  * @returns {Object} a JSON compatible object.
86
87
  */
@@ -95,6 +96,7 @@ class ConfigDependency {
95
96
  return obj;
96
97
  }
97
98
 
99
+ // eslint-disable-next-line jsdoc/require-description
98
100
  /**
99
101
  * @returns {Object} an object to display by `console.log()`.
100
102
  */
@@ -16,6 +16,8 @@
16
16
  */
17
17
  "use strict";
18
18
 
19
+ const { IgnorePattern } = require("./ignore-pattern");
20
+
19
21
  // For VSCode intellisense
20
22
  /** @typedef {import("../../shared/types").ConfigData} ConfigData */
21
23
  /** @typedef {import("../../shared/types").GlobalConf} GlobalConf */
@@ -23,6 +25,17 @@
23
25
  /** @typedef {import("./config-dependency").DependentParser} DependentParser */
24
26
  /** @typedef {import("./config-dependency").DependentPlugin} DependentPlugin */
25
27
 
28
+ /**
29
+ * Check if `xs` starts with `ys`.
30
+ * @template T
31
+ * @param {T[]} xs The array to check.
32
+ * @param {T[]} ys The array that may be the first part of `xs`.
33
+ * @returns {boolean} `true` if `xs` starts with `ys`.
34
+ */
35
+ function startsWith(xs, ys) {
36
+ return xs.length >= ys.length && ys.every((y, i) => y === xs[i]);
37
+ }
38
+
26
39
  /**
27
40
  * The class for extracted config data.
28
41
  */
@@ -47,6 +60,12 @@ class ExtractedConfig {
47
60
  */
48
61
  this.globals = {};
49
62
 
63
+ /**
64
+ * The glob patterns that ignore to lint.
65
+ * @type {(((filePath:string, dot?:boolean) => boolean) & { basePath:string; patterns:string[] }) | undefined}
66
+ */
67
+ this.ignores = void 0;
68
+
50
69
  /**
51
70
  * The flag that disables directive comments.
52
71
  * @type {boolean|undefined}
@@ -106,11 +125,19 @@ class ExtractedConfig {
106
125
  configNameOfNoInlineConfig: _ignore1,
107
126
  processor: _ignore2,
108
127
  /* eslint-enable no-unused-vars */
128
+ ignores,
109
129
  ...config
110
130
  } = this;
111
131
 
112
132
  config.parser = config.parser && config.parser.filePath;
113
133
  config.plugins = Object.keys(config.plugins).filter(Boolean).reverse();
134
+ config.ignorePatterns = ignores ? ignores.patterns : [];
135
+
136
+ // Strip the default patterns from `ignorePatterns`.
137
+ if (startsWith(config.ignorePatterns, IgnorePattern.DefaultPatterns)) {
138
+ config.ignorePatterns =
139
+ config.ignorePatterns.slice(IgnorePattern.DefaultPatterns.length);
140
+ }
114
141
 
115
142
  return config;
116
143
  }
@@ -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
  };
@@ -166,6 +166,7 @@ class OverrideTester {
166
166
  ));
167
167
  }
168
168
 
169
+ // eslint-disable-next-line jsdoc/require-description
169
170
  /**
170
171
  * @returns {Object} a JSON compatible object.
171
172
  */
@@ -182,6 +183,7 @@ class OverrideTester {
182
183
  };
183
184
  }
184
185
 
186
+ // eslint-disable-next-line jsdoc/require-description
185
187
  /**
186
188
  * @returns {Object} an object to display by `console.log()`.
187
189
  */
@@ -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
  //------------------------------------------------------------------------------
@@ -221,6 +232,26 @@ function loadPackageJSONConfigFile(filePath) {
221
232
  }
222
233
  }
223
234
 
235
+ /**
236
+ * Loads a `.eslintignore` from a file.
237
+ * @param {string} filePath The filename to load.
238
+ * @returns {string[]} The ignore patterns from the file.
239
+ * @private
240
+ */
241
+ function loadESLintIgnoreFile(filePath) {
242
+ debug(`Loading .eslintignore file: ${filePath}`);
243
+
244
+ try {
245
+ return readFile(filePath)
246
+ .split(/\r?\n/gu)
247
+ .filter(line => line.trim() !== "" && !line.startsWith("#"));
248
+ } catch (e) {
249
+ debug(`Error reading .eslintignore file: ${filePath}`);
250
+ e.message = `Cannot read .eslintignore file: ${filePath}\nError: ${e.message}`;
251
+ throw e;
252
+ }
253
+ }
254
+
224
255
  /**
225
256
  * Creates an error to notify about a missing config to extend from.
226
257
  * @param {string} configName The name of the missing config.
@@ -403,6 +434,54 @@ class ConfigArrayFactory {
403
434
  );
404
435
  }
405
436
 
437
+ /**
438
+ * Load `.eslintignore` file.
439
+ * @param {string} filePath The path to a `.eslintignore` file to load.
440
+ * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
441
+ */
442
+ loadESLintIgnore(filePath) {
443
+ const { cwd } = internalSlotsMap.get(this);
444
+ const absolutePath = path.resolve(cwd, filePath);
445
+ const name = path.relative(cwd, absolutePath);
446
+ const ignorePatterns = loadESLintIgnoreFile(absolutePath);
447
+
448
+ return createConfigArray(
449
+ this._normalizeESLintIgnoreData(ignorePatterns, absolutePath, name)
450
+ );
451
+ }
452
+
453
+ /**
454
+ * Load `.eslintignore` file in the current working directory.
455
+ * @returns {ConfigArray} Loaded config. An empty `ConfigArray` if any config doesn't exist.
456
+ */
457
+ loadDefaultESLintIgnore() {
458
+ const { cwd } = internalSlotsMap.get(this);
459
+ const eslintIgnorePath = path.resolve(cwd, ".eslintignore");
460
+ const packageJsonPath = path.resolve(cwd, "package.json");
461
+
462
+ if (fs.existsSync(eslintIgnorePath)) {
463
+ return this.loadESLintIgnore(eslintIgnorePath);
464
+ }
465
+ if (fs.existsSync(packageJsonPath)) {
466
+ const data = loadJSONConfigFile(packageJsonPath);
467
+
468
+ if (Object.hasOwnProperty.call(data, "eslintIgnore")) {
469
+ if (!Array.isArray(data.eslintIgnore)) {
470
+ throw new Error("Package.json eslintIgnore property requires an array of paths");
471
+ }
472
+ return createConfigArray(
473
+ this._normalizeESLintIgnoreData(
474
+ data.eslintIgnore,
475
+ packageJsonPath,
476
+ "eslintIgnore in package.json"
477
+ )
478
+ );
479
+ }
480
+ }
481
+
482
+ return new ConfigArray();
483
+ }
484
+
406
485
  /**
407
486
  * Load a given config file.
408
487
  * @param {string} filePath The path to a config file.
@@ -451,6 +530,30 @@ class ConfigArrayFactory {
451
530
  return null;
452
531
  }
453
532
 
533
+ /**
534
+ * Normalize a given `.eslintignore` data to config array elements.
535
+ * @param {string[]} ignorePatterns The patterns to ignore files.
536
+ * @param {string|undefined} filePath The file path of this config.
537
+ * @param {string|undefined} name The name of this config.
538
+ * @returns {IterableIterator<ConfigArrayElement>} The normalized config.
539
+ * @private
540
+ */
541
+ *_normalizeESLintIgnoreData(ignorePatterns, filePath, name) {
542
+ const elements = this._normalizeObjectConfigData(
543
+ { ignorePatterns },
544
+ filePath,
545
+ name
546
+ );
547
+
548
+ // Set `ignorePattern.loose` flag for backward compatibility.
549
+ for (const element of elements) {
550
+ if (element.ignorePattern) {
551
+ element.ignorePattern.loose = true;
552
+ }
553
+ yield element;
554
+ }
555
+ }
556
+
454
557
  /**
455
558
  * Normalize a given config to an array.
456
559
  * @param {ConfigData} configData The config data to normalize.
@@ -494,6 +597,9 @@ class ConfigArrayFactory {
494
597
  if (element.criteria) {
495
598
  element.criteria.basePath = basePath;
496
599
  }
600
+ if (element.ignorePattern) {
601
+ element.ignorePattern.basePath = basePath;
602
+ }
497
603
 
498
604
  /*
499
605
  * Merge the criteria; this is for only file extension processors in
@@ -526,6 +632,7 @@ class ConfigArrayFactory {
526
632
  env,
527
633
  extends: extend,
528
634
  globals,
635
+ ignorePatterns,
529
636
  noInlineConfig,
530
637
  parser: parserName,
531
638
  parserOptions,
@@ -541,6 +648,10 @@ class ConfigArrayFactory {
541
648
  name
542
649
  ) {
543
650
  const extendList = Array.isArray(extend) ? extend : [extend];
651
+ const ignorePattern = ignorePatterns && new IgnorePattern(
652
+ Array.isArray(ignorePatterns) ? ignorePatterns : [ignorePatterns],
653
+ filePath ? path.dirname(filePath) : internalSlotsMap.get(this).cwd
654
+ );
544
655
 
545
656
  // Flatten `extends`.
546
657
  for (const extendName of extendList.filter(Boolean)) {
@@ -569,6 +680,7 @@ class ConfigArrayFactory {
569
680
  criteria: null,
570
681
  env,
571
682
  globals,
683
+ ignorePattern,
572
684
  noInlineConfig,
573
685
  parser,
574
686
  parserOptions,
@@ -859,8 +971,14 @@ class ConfigArrayFactory {
859
971
  if (filePath) {
860
972
  try {
861
973
  writeDebugLogForLoading(request, relativeTo, filePath);
974
+
975
+ const startTime = Date.now();
976
+ const pluginDefinition = require(filePath);
977
+
978
+ debug(`Plugin ${filePath} loaded in: ${Date.now() - startTime}ms`);
979
+
862
980
  return new ConfigDependency({
863
- definition: normalizePlugin(require(filePath)),
981
+ definition: normalizePlugin(pluginDefinition),
864
982
  filePath,
865
983
  id,
866
984
  importerName,