eslint 7.0.0-alpha.1 → 7.0.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 (84) hide show
  1. package/CHANGELOG.md +329 -0
  2. package/README.md +7 -7
  3. package/bin/eslint.js +115 -77
  4. package/conf/category-list.json +2 -3
  5. package/conf/environments.js +2 -1
  6. package/conf/eslint-recommended.js +3 -0
  7. package/lib/api.js +2 -0
  8. package/lib/cli-engine/cascading-config-array-factory.js +16 -2
  9. package/lib/cli-engine/cli-engine.js +53 -47
  10. package/lib/cli-engine/config-array/config-array.js +30 -1
  11. package/lib/cli-engine/config-array/ignore-pattern.js +7 -1
  12. package/lib/cli-engine/config-array-factory.js +244 -235
  13. package/lib/cli.js +181 -95
  14. package/lib/eslint/eslint.js +656 -0
  15. package/lib/eslint/index.js +7 -0
  16. package/lib/init/autoconfig.js +4 -4
  17. package/lib/init/config-file.js +2 -2
  18. package/lib/init/config-initializer.js +2 -4
  19. package/lib/init/source-code-utils.js +2 -2
  20. package/lib/linter/node-event-generator.js +2 -2
  21. package/lib/options.js +0 -1
  22. package/lib/rule-tester/rule-tester.js +178 -23
  23. package/lib/rules/accessor-pairs.js +2 -2
  24. package/lib/rules/array-callback-return.js +3 -18
  25. package/lib/rules/arrow-body-style.js +26 -15
  26. package/lib/rules/callback-return.js +4 -0
  27. package/lib/rules/camelcase.js +38 -1
  28. package/lib/rules/comma-style.js +3 -8
  29. package/lib/rules/computed-property-spacing.js +2 -2
  30. package/lib/rules/curly.js +124 -40
  31. package/lib/rules/func-call-spacing.js +4 -3
  32. package/lib/rules/func-names.js +31 -24
  33. package/lib/rules/getter-return.js +2 -12
  34. package/lib/rules/global-require.js +4 -0
  35. package/lib/rules/handle-callback-err.js +4 -0
  36. package/lib/rules/id-blacklist.js +140 -64
  37. package/lib/rules/id-length.js +14 -4
  38. package/lib/rules/indent-legacy.js +0 -16
  39. package/lib/rules/key-spacing.js +1 -1
  40. package/lib/rules/new-cap.js +1 -1
  41. package/lib/rules/newline-per-chained-call.js +6 -3
  42. package/lib/rules/no-alert.js +5 -3
  43. package/lib/rules/no-buffer-constructor.js +4 -0
  44. package/lib/rules/no-dupe-else-if.js +1 -1
  45. package/lib/rules/no-empty-function.js +4 -2
  46. package/lib/rules/no-eval.js +3 -2
  47. package/lib/rules/no-extra-bind.js +1 -1
  48. package/lib/rules/no-extra-boolean-cast.js +168 -38
  49. package/lib/rules/no-extra-parens.js +9 -5
  50. package/lib/rules/no-implied-eval.js +83 -101
  51. package/lib/rules/no-import-assign.js +1 -1
  52. package/lib/rules/no-inner-declarations.js +31 -39
  53. package/lib/rules/no-lone-blocks.js +1 -1
  54. package/lib/rules/no-magic-numbers.js +72 -37
  55. package/lib/rules/no-mixed-requires.js +4 -0
  56. package/lib/rules/no-new-object.js +15 -3
  57. package/lib/rules/no-new-require.js +4 -0
  58. package/lib/rules/no-new-wrappers.js +1 -1
  59. package/lib/rules/no-obj-calls.js +24 -5
  60. package/lib/rules/no-path-concat.js +4 -0
  61. package/lib/rules/no-plusplus.js +39 -3
  62. package/lib/rules/no-process-env.js +4 -0
  63. package/lib/rules/no-process-exit.js +4 -0
  64. package/lib/rules/no-prototype-builtins.js +1 -1
  65. package/lib/rules/no-restricted-modules.js +52 -18
  66. package/lib/rules/no-setter-return.js +1 -1
  67. package/lib/rules/no-sync.js +4 -0
  68. package/lib/rules/no-underscore-dangle.js +1 -1
  69. package/lib/rules/no-unexpected-multiline.js +22 -12
  70. package/lib/rules/no-useless-concat.js +1 -1
  71. package/lib/rules/operator-assignment.js +3 -3
  72. package/lib/rules/operator-linebreak.js +4 -16
  73. package/lib/rules/prefer-numeric-literals.js +3 -3
  74. package/lib/rules/prefer-object-spread.js +2 -2
  75. package/lib/rules/require-await.js +1 -1
  76. package/lib/rules/space-before-function-paren.js +5 -2
  77. package/lib/rules/template-curly-spacing.js +59 -42
  78. package/lib/rules/utils/ast-utils.js +65 -4
  79. package/lib/rules/wrap-iife.js +54 -17
  80. package/lib/rules/yoda.js +101 -51
  81. package/lib/shared/relative-module-resolver.js +1 -0
  82. package/lib/shared/types.js +9 -2
  83. package/messages/plugin-conflict.txt +7 -0
  84. package/package.json +27 -26
package/bin/eslint.js CHANGED
@@ -12,97 +12,135 @@
12
12
  // to use V8's code cache to speed up instantiation time
13
13
  require("v8-compile-cache");
14
14
 
15
- //------------------------------------------------------------------------------
16
- // Helpers
17
- //------------------------------------------------------------------------------
18
-
19
- const useStdIn = process.argv.includes("--stdin"),
20
- init = process.argv.includes("--init"),
21
- debug = process.argv.includes("--debug");
22
-
23
15
  // must do this initialization *before* other requires in order to work
24
- if (debug) {
16
+ if (process.argv.includes("--debug")) {
25
17
  require("debug").enable("eslint:*,-eslint:code-path");
26
18
  }
27
19
 
28
20
  //------------------------------------------------------------------------------
29
- // Requirements
21
+ // Helpers
30
22
  //------------------------------------------------------------------------------
31
23
 
32
- // now we can safely include the other modules that use debug
33
- const path = require("path"),
34
- fs = require("fs"),
35
- cli = require("../lib/cli");
36
-
37
- //------------------------------------------------------------------------------
38
- // Execution
39
- //------------------------------------------------------------------------------
24
+ /**
25
+ * Read data from stdin til the end.
26
+ *
27
+ * Note: See
28
+ * - https://github.com/nodejs/node/blob/master/doc/api/process.md#processstdin
29
+ * - https://github.com/nodejs/node/blob/master/doc/api/process.md#a-note-on-process-io
30
+ * - https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-01/msg00419.html
31
+ * - https://github.com/nodejs/node/issues/7439 (historical)
32
+ *
33
+ * On Windows using `fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8")` seems
34
+ * to read 4096 bytes before blocking and never drains to read further data.
35
+ *
36
+ * The investigation on the Emacs thread indicates:
37
+ *
38
+ * > Emacs on MS-Windows uses pipes to communicate with subprocesses; a
39
+ * > pipe on Windows has a 4K buffer. So as soon as Emacs writes more than
40
+ * > 4096 bytes to the pipe, the pipe becomes full, and Emacs then waits for
41
+ * > the subprocess to read its end of the pipe, at which time Emacs will
42
+ * > write the rest of the stuff.
43
+ * @returns {Promise<string>} The read text.
44
+ */
45
+ function readStdin() {
46
+ return new Promise((resolve, reject) => {
47
+ let content = "";
48
+ let chunk = "";
49
+
50
+ process.stdin
51
+ .setEncoding("utf8")
52
+ .on("readable", () => {
53
+ while ((chunk = process.stdin.read()) !== null) {
54
+ content += chunk;
55
+ }
56
+ })
57
+ .on("end", () => resolve(content))
58
+ .on("error", reject);
59
+ });
60
+ }
40
61
 
41
- process.once("uncaughtException", err => {
62
+ /**
63
+ * Get the error message of a given value.
64
+ * @param {any} error The value to get.
65
+ * @returns {string} The error message.
66
+ */
67
+ function getErrorMessage(error) {
42
68
 
43
- // lazy load
69
+ // Lazy loading because those are used only if error happened.
70
+ const fs = require("fs");
71
+ const path = require("path");
72
+ const util = require("util");
44
73
  const lodash = require("lodash");
45
74
 
46
- if (typeof err.messageTemplate === "string" && err.messageTemplate.length > 0) {
47
- const template = lodash.template(fs.readFileSync(path.resolve(__dirname, `../messages/${err.messageTemplate}.txt`), "utf-8"));
48
- const pkg = require("../package.json");
75
+ // Foolproof -- thirdparty module might throw non-object.
76
+ if (typeof error !== "object" || error === null) {
77
+ return String(error);
78
+ }
79
+
80
+ // Use templates if `error.messageTemplate` is present.
81
+ if (typeof error.messageTemplate === "string") {
82
+ try {
83
+ const templateFilePath = path.resolve(
84
+ __dirname,
85
+ `../messages/${error.messageTemplate}.txt`
86
+ );
87
+
88
+ // Use sync API because Node.js should exit at this tick.
89
+ const templateText = fs.readFileSync(templateFilePath, "utf-8");
90
+ const template = lodash.template(templateText);
91
+
92
+ return template(error.messageData || {});
93
+ } catch {
94
+
95
+ // Ignore template error then fallback to use `error.stack`.
96
+ }
97
+ }
49
98
 
50
- console.error("\nOops! Something went wrong! :(");
51
- console.error(`\nESLint: ${pkg.version}.\n\n${template(err.messageData || {})}`);
52
- } else {
53
- console.error(err.stack);
99
+ // Use the stacktrace if it's an error object.
100
+ if (typeof error.stack === "string") {
101
+ return error.stack;
54
102
  }
55
103
 
104
+ // Otherwise, dump the object.
105
+ return util.format("%o", error);
106
+ }
107
+
108
+ /**
109
+ * Catch and report unexpected error.
110
+ * @param {any} error The thrown error object.
111
+ * @returns {void}
112
+ */
113
+ function onFatalError(error) {
56
114
  process.exitCode = 2;
57
- });
58
-
59
- if (useStdIn) {
60
-
61
- /*
62
- * Note: See
63
- * - https://github.com/nodejs/node/blob/master/doc/api/process.md#processstdin
64
- * - https://github.com/nodejs/node/blob/master/doc/api/process.md#a-note-on-process-io
65
- * - https://lists.gnu.org/archive/html/bug-gnu-emacs/2016-01/msg00419.html
66
- * - https://github.com/nodejs/node/issues/7439 (historical)
67
- *
68
- * On Windows using `fs.readFileSync(STDIN_FILE_DESCRIPTOR, "utf8")` seems
69
- * to read 4096 bytes before blocking and never drains to read further data.
70
- *
71
- * The investigation on the Emacs thread indicates:
72
- *
73
- * > Emacs on MS-Windows uses pipes to communicate with subprocesses; a
74
- * > pipe on Windows has a 4K buffer. So as soon as Emacs writes more than
75
- * > 4096 bytes to the pipe, the pipe becomes full, and Emacs then waits for
76
- * > the subprocess to read its end of the pipe, at which time Emacs will
77
- * > write the rest of the stuff.
78
- *
79
- * Using the nodejs code example for reading from stdin.
80
- */
81
- let contents = "",
82
- chunk = "";
83
-
84
- process.stdin.setEncoding("utf8");
85
- process.stdin.on("readable", () => {
86
-
87
- // Use a loop to make sure we read all available data.
88
- while ((chunk = process.stdin.read()) !== null) {
89
- contents += chunk;
90
- }
91
- });
92
115
 
93
- process.stdin.on("end", () => {
94
- process.exitCode = cli.execute(process.argv, contents, "utf8");
95
- });
96
- } else if (init) {
97
- const configInit = require("../lib/init/config-initializer");
98
-
99
- configInit.initializeConfig().then(() => {
100
- process.exitCode = 0;
101
- }).catch(err => {
102
- process.exitCode = 1;
103
- console.error(err.message);
104
- console.error(err.stack);
105
- });
106
- } else {
107
- process.exitCode = cli.execute(process.argv);
116
+ const { version } = require("../package.json");
117
+ const message = getErrorMessage(error);
118
+
119
+ console.error(`
120
+ Oops! Something went wrong! :(
121
+
122
+ ESLint: ${version}
123
+
124
+ ${message}`);
108
125
  }
126
+
127
+ //------------------------------------------------------------------------------
128
+ // Execution
129
+ //------------------------------------------------------------------------------
130
+
131
+ (async function main() {
132
+ process.on("uncaughtException", onFatalError);
133
+ process.on("unhandledRejection", onFatalError);
134
+
135
+ // Call the config initializer if `--init` is present.
136
+ if (process.argv.includes("--init")) {
137
+ await require("../lib/init/config-initializer").initializeConfig();
138
+ return;
139
+ }
140
+
141
+ // Otherwise, call the CLI.
142
+ process.exitCode = await require("../lib/cli").execute(
143
+ process.argv,
144
+ process.argv.includes("--stdin") ? await readStdin() : null
145
+ );
146
+ }()).catch(onFatalError);
@@ -4,18 +4,17 @@
4
4
  { "name": "Best Practices", "description": "These rules relate to better ways of doing things to help you avoid problems:" },
5
5
  { "name": "Strict Mode", "description": "These rules relate to strict mode directives:" },
6
6
  { "name": "Variables", "description": "These rules relate to variable declarations:" },
7
- { "name": "Node.js and CommonJS", "description": "These rules relate to code running in Node.js, or in browsers with CommonJS:" },
8
7
  { "name": "Stylistic Issues", "description": "These rules relate to style guidelines, and are therefore quite subjective:" },
9
8
  { "name": "ECMAScript 6", "description": "These rules relate to ES6, also known as ES2015:" }
10
9
  ],
11
10
  "deprecated": {
12
11
  "name": "Deprecated",
13
- "description": "These rules have been deprecated in accordance with the [deprecation policy](/docs/user-guide/rule-deprecation), and replaced by newer rules:",
12
+ "description": "These rules have been deprecated in accordance with the <a href=\"/docs/user-guide/rule-deprecation\">deprecation policy</a>, and replaced by newer rules:",
14
13
  "rules": []
15
14
  },
16
15
  "removed": {
17
16
  "name": "Removed",
18
- "description": "These rules from older versions of ESLint (before the [deprecation policy](/docs/user-guide/rule-deprecation) existed) have been replaced by newer rules:",
17
+ "description": "These rules from older versions of ESLint (before the <a href=\"/docs/user-guide/rule-deprecation\">deprecation policy</a> existed) have been replaced by newer rules:",
19
18
  "rules": [
20
19
  { "removed": "generator-star", "replacedBy": ["generator-star-spacing"] },
21
20
  { "removed": "global-strict", "replacedBy": ["strict"] },
@@ -40,7 +40,8 @@ const newGlobals2017 = {
40
40
  const newGlobals2020 = {
41
41
  BigInt: false,
42
42
  BigInt64Array: false,
43
- BigUint64Array: false
43
+ BigUint64Array: false,
44
+ globalThis: false
44
45
  };
45
46
 
46
47
  //------------------------------------------------------------------------------
@@ -26,6 +26,7 @@ module.exports = {
26
26
  "no-delete-var": "error",
27
27
  "no-dupe-args": "error",
28
28
  "no-dupe-class-members": "error",
29
+ "no-dupe-else-if": "error",
29
30
  "no-dupe-keys": "error",
30
31
  "no-duplicate-case": "error",
31
32
  "no-empty": "error",
@@ -37,6 +38,7 @@ module.exports = {
37
38
  "no-fallthrough": "error",
38
39
  "no-func-assign": "error",
39
40
  "no-global-assign": "error",
41
+ "no-import-assign": "error",
40
42
  "no-inner-declarations": "error",
41
43
  "no-invalid-regexp": "error",
42
44
  "no-irregular-whitespace": "error",
@@ -49,6 +51,7 @@ module.exports = {
49
51
  "no-redeclare": "error",
50
52
  "no-regex-spaces": "error",
51
53
  "no-self-assign": "error",
54
+ "no-setter-return": "error",
52
55
  "no-shadow-restricted-names": "error",
53
56
  "no-sparse-arrays": "error",
54
57
  "no-this-before-super": "error",
package/lib/api.js CHANGED
@@ -6,6 +6,7 @@
6
6
  "use strict";
7
7
 
8
8
  const { CLIEngine } = require("./cli-engine");
9
+ const { ESLint } = require("./eslint");
9
10
  const { Linter } = require("./linter");
10
11
  const { RuleTester } = require("./rule-tester");
11
12
  const { SourceCode } = require("./source-code");
@@ -13,6 +14,7 @@ const { SourceCode } = require("./source-code");
13
14
  module.exports = {
14
15
  Linter,
15
16
  CLIEngine,
17
+ ESLint,
16
18
  RuleTester,
17
19
  SourceCode
18
20
  };
@@ -140,6 +140,7 @@ function createBaseConfigArray({
140
140
  function createCLIConfigArray({
141
141
  cliConfigData,
142
142
  configArrayFactory,
143
+ cwd,
143
144
  ignorePath,
144
145
  specificConfigPath
145
146
  }) {
@@ -158,7 +159,7 @@ function createCLIConfigArray({
158
159
  cliConfigArray.unshift(
159
160
  ...configArrayFactory.loadFile(
160
161
  specificConfigPath,
161
- { name: "--config" }
162
+ { name: "--config", basePath: cwd }
162
163
  )
163
164
  );
164
165
  }
@@ -198,7 +199,7 @@ class CascadingConfigArrayFactory {
198
199
  cliConfig: cliConfigData = null,
199
200
  cwd = process.cwd(),
200
201
  ignorePath,
201
- resolvePluginsRelativeTo = cwd,
202
+ resolvePluginsRelativeTo,
202
203
  rulePaths = [],
203
204
  specificConfigPath = null,
204
205
  useEslintrc = true
@@ -220,6 +221,7 @@ class CascadingConfigArrayFactory {
220
221
  cliConfigArray: createCLIConfigArray({
221
222
  cliConfigData,
222
223
  configArrayFactory,
224
+ cwd,
223
225
  ignorePath,
224
226
  specificConfigPath
225
227
  }),
@@ -277,6 +279,18 @@ class CascadingConfigArrayFactory {
277
279
  );
278
280
  }
279
281
 
282
+ /**
283
+ * Set the config data to override all configs.
284
+ * Require to call `clearCache()` method after this method is called.
285
+ * @param {ConfigData} configData The config data to override all configs.
286
+ * @returns {void}
287
+ */
288
+ setOverrideConfig(configData) {
289
+ const slots = internalSlotsMap.get(this);
290
+
291
+ slots.cliConfigData = configData;
292
+ }
293
+
280
294
  /**
281
295
  * Clear config cache.
282
296
  * @returns {void}
@@ -39,6 +39,7 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]);
39
39
 
40
40
  // For VSCode IntelliSense
41
41
  /** @typedef {import("../shared/types").ConfigData} ConfigData */
42
+ /** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */
42
43
  /** @typedef {import("../shared/types").LintMessage} LintMessage */
43
44
  /** @typedef {import("../shared/types").ParserOptions} ParserOptions */
44
45
  /** @typedef {import("../shared/types").Plugin} Plugin */
@@ -50,29 +51,29 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]);
50
51
  /**
51
52
  * The options to configure a CLI engine with.
52
53
  * @typedef {Object} CLIEngineOptions
53
- * @property {boolean} allowInlineConfig Enable or disable inline configuration comments.
54
- * @property {ConfigData} baseConfig Base config object, extended by all configs used with this CLIEngine instance
55
- * @property {boolean} cache Enable result caching.
56
- * @property {string} cacheLocation The cache file to use instead of .eslintcache.
57
- * @property {string} configFile The configuration file to use.
58
- * @property {string} cwd The value to use for the current working directory.
59
- * @property {string[]} envs An array of environments to load.
60
- * @property {string[]|null} extensions An array of file extensions to check.
61
- * @property {boolean|Function} fix Execute in autofix mode. If a function, should return a boolean.
62
- * @property {string[]} fixTypes Array of rule types to apply fixes for.
63
- * @property {string[]} globals An array of global variables to declare.
64
- * @property {boolean} ignore False disables use of .eslintignore.
65
- * @property {string} ignorePath The ignore file to use instead of .eslintignore.
66
- * @property {string|string[]} ignorePattern One or more glob patterns to ignore.
67
- * @property {boolean} useEslintrc False disables looking for .eslintrc
68
- * @property {string} parser The name of the parser to use.
69
- * @property {ParserOptions} parserOptions An object of parserOption settings to use.
70
- * @property {string[]} plugins An array of plugins to load.
71
- * @property {Record<string,RuleConf>} rules An object of rules to use.
72
- * @property {string[]} rulePaths An array of directories to load custom rules from.
73
- * @property {boolean} reportUnusedDisableDirectives `true` adds reports for unused eslint-disable directives
74
- * @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.
75
- * @property {string} resolvePluginsRelativeTo The folder where plugins should be resolved from, defaulting to the CWD
54
+ * @property {boolean} [allowInlineConfig] Enable or disable inline configuration comments.
55
+ * @property {ConfigData} [baseConfig] Base config object, extended by all configs used with this CLIEngine instance
56
+ * @property {boolean} [cache] Enable result caching.
57
+ * @property {string} [cacheLocation] The cache file to use instead of .eslintcache.
58
+ * @property {string} [configFile] The configuration file to use.
59
+ * @property {string} [cwd] The value to use for the current working directory.
60
+ * @property {string[]} [envs] An array of environments to load.
61
+ * @property {string[]|null} [extensions] An array of file extensions to check.
62
+ * @property {boolean|Function} [fix] Execute in autofix mode. If a function, should return a boolean.
63
+ * @property {string[]} [fixTypes] Array of rule types to apply fixes for.
64
+ * @property {string[]} [globals] An array of global variables to declare.
65
+ * @property {boolean} [ignore] False disables use of .eslintignore.
66
+ * @property {string} [ignorePath] The ignore file to use instead of .eslintignore.
67
+ * @property {string|string[]} [ignorePattern] One or more glob patterns to ignore.
68
+ * @property {boolean} [useEslintrc] False disables looking for .eslintrc
69
+ * @property {string} [parser] The name of the parser to use.
70
+ * @property {ParserOptions} [parserOptions] An object of parserOption settings to use.
71
+ * @property {string[]} [plugins] An array of plugins to load.
72
+ * @property {Record<string,RuleConf>} [rules] An object of rules to use.
73
+ * @property {string[]} [rulePaths] An array of directories to load custom rules from.
74
+ * @property {boolean} [reportUnusedDisableDirectives] `true` adds reports for unused eslint-disable directives
75
+ * @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.
76
+ * @property {string} [resolvePluginsRelativeTo] The folder where plugins should be resolved from, defaulting to the CWD
76
77
  */
77
78
 
78
79
  /**
@@ -88,13 +89,6 @@ const validFixTypes = new Set(["problem", "suggestion", "layout"]);
88
89
  * @property {string} [output] The source code of the file that was linted, with as many fixes applied as possible.
89
90
  */
90
91
 
91
- /**
92
- * Information of deprecated rules.
93
- * @typedef {Object} DeprecatedRuleInfo
94
- * @property {string} ruleId The rule ID.
95
- * @property {string[]} replacedBy The rule IDs that replace this deprecated rule.
96
- */
97
-
98
92
  /**
99
93
  * Linting results.
100
94
  * @typedef {Object} LintReport
@@ -276,7 +270,8 @@ function verifyText({
276
270
  */
277
271
  function createIgnoreResult(filePath, baseDir) {
278
272
  let message;
279
- const isHidden = /^\./u.test(path.basename(filePath));
273
+ const isHidden = filePath.split(path.sep)
274
+ .find(segment => /^\./u.test(segment));
280
275
  const isInNodeModules = baseDir && path.relative(baseDir, filePath).startsWith("node_modules");
281
276
 
282
277
  if (isHidden) {
@@ -820,16 +815,22 @@ class CLIEngine {
820
815
  lintResultCache.reconcile();
821
816
  }
822
817
 
823
- // Collect used deprecated rules.
824
- const usedDeprecatedRules = Array.from(
825
- iterateRuleDeprecationWarnings(lastConfigArrays)
826
- );
827
-
828
818
  debug(`Linting complete in: ${Date.now() - startTime}ms`);
819
+ let usedDeprecatedRules;
820
+
829
821
  return {
830
822
  results,
831
823
  ...calculateStatsPerRun(results),
832
- usedDeprecatedRules
824
+
825
+ // Initialize it lazily because CLI and `ESLint` API don't use it.
826
+ get usedDeprecatedRules() {
827
+ if (!usedDeprecatedRules) {
828
+ usedDeprecatedRules = Array.from(
829
+ iterateRuleDeprecationWarnings(lastConfigArrays)
830
+ );
831
+ }
832
+ return usedDeprecatedRules;
833
+ }
833
834
  };
834
835
  }
835
836
 
@@ -857,9 +858,9 @@ class CLIEngine {
857
858
  const startTime = Date.now();
858
859
  const resolvedFilename = filename && path.resolve(cwd, filename);
859
860
 
861
+
860
862
  // Clear the last used config arrays.
861
863
  lastConfigArrays.length = 0;
862
-
863
864
  if (resolvedFilename && this.isPathIgnored(resolvedFilename)) {
864
865
  if (warnIgnored) {
865
866
  results.push(createIgnoreResult(resolvedFilename, cwd));
@@ -891,16 +892,22 @@ class CLIEngine {
891
892
  }));
892
893
  }
893
894
 
894
- // Collect used deprecated rules.
895
- const usedDeprecatedRules = Array.from(
896
- iterateRuleDeprecationWarnings(lastConfigArrays)
897
- );
898
-
899
895
  debug(`Linting complete in: ${Date.now() - startTime}ms`);
896
+ let usedDeprecatedRules;
897
+
900
898
  return {
901
899
  results,
902
900
  ...calculateStatsPerRun(results),
903
- usedDeprecatedRules
901
+
902
+ // Initialize it lazily because CLI and `ESLint` API don't use it.
903
+ get usedDeprecatedRules() {
904
+ if (!usedDeprecatedRules) {
905
+ usedDeprecatedRules = Array.from(
906
+ iterateRuleDeprecationWarnings(lastConfigArrays)
907
+ );
908
+ }
909
+ return usedDeprecatedRules;
910
+ }
904
911
  };
905
912
  }
906
913
 
@@ -954,11 +961,10 @@ class CLIEngine {
954
961
  }
955
962
 
956
963
  /**
957
- * Returns the formatter representing the given format or null if no formatter
958
- * with the given name can be found.
964
+ * Returns the formatter representing the given format or null if the `format` is not a string.
959
965
  * @param {string} [format] The name of the format to load or the path to a
960
966
  * custom formatter.
961
- * @returns {Function} The formatter function or null if not found.
967
+ * @returns {(Function|null)} The formatter function or null if the `format` is not a string.
962
968
  */
963
969
  getFormatter(format) {
964
970
 
@@ -65,6 +65,7 @@ const { IgnorePattern } = require("./ignore-pattern");
65
65
  * @property {boolean|undefined} root The flag to express root.
66
66
  * @property {Record<string, RuleConf>|undefined} rules The rule settings
67
67
  * @property {Object|undefined} settings The shared settings.
68
+ * @property {"config" | "ignore" | "implicit-processor"} type The element type.
68
69
  */
69
70
 
70
71
  /**
@@ -106,7 +107,7 @@ function getMatchedIndices(elements, filePath) {
106
107
  for (let i = elements.length - 1; i >= 0; --i) {
107
108
  const element = elements[i];
108
109
 
109
- if (!element.criteria || element.criteria.test(filePath)) {
110
+ if (!element.criteria || (filePath && element.criteria.test(filePath))) {
110
111
  indices.push(i);
111
112
  }
112
113
  }
@@ -155,6 +156,23 @@ function mergeWithoutOverwrite(target, source) {
155
156
  }
156
157
  }
157
158
 
159
+ /**
160
+ * The error for plugin conflicts.
161
+ */
162
+ class PluginConflictError extends Error {
163
+
164
+ /**
165
+ * Initialize this error object.
166
+ * @param {string} pluginId The plugin ID.
167
+ * @param {{filePath:string, importerName:string}[]} plugins The resolved plugins.
168
+ */
169
+ constructor(pluginId, plugins) {
170
+ super(`Plugin "${pluginId}" was conflicted between ${plugins.map(p => `"${p.importerName}"`).join(" and ")}.`);
171
+ this.messageTemplate = "plugin-conflict";
172
+ this.messageData = { pluginId, plugins };
173
+ }
174
+ }
175
+
158
176
  /**
159
177
  * Merge plugins.
160
178
  * `target`'s definition is prior to `source`'s.
@@ -180,6 +198,17 @@ function mergePlugins(target, source) {
180
198
  throw sourceValue.error;
181
199
  }
182
200
  target[key] = sourceValue;
201
+ } else if (sourceValue.filePath !== targetValue.filePath) {
202
+ throw new PluginConflictError(key, [
203
+ {
204
+ filePath: targetValue.filePath,
205
+ importerName: targetValue.importerName
206
+ },
207
+ {
208
+ filePath: sourceValue.filePath,
209
+ importerName: sourceValue.importerName
210
+ }
211
+ ]);
183
212
  }
184
213
  }
185
214
  }
@@ -71,7 +71,13 @@ function getCommonAncestorPath(sourcePaths) {
71
71
  }
72
72
  }
73
73
 
74
- return result || path.sep;
74
+ let resolvedResult = result || path.sep;
75
+
76
+ // if Windows common ancestor is root of drive must have trailing slash to be absolute.
77
+ if (resolvedResult && resolvedResult.endsWith(":") && process.platform === "win32") {
78
+ resolvedResult += path.sep;
79
+ }
80
+ return resolvedResult;
75
81
  }
76
82
 
77
83
  /**