1 | /**
|
---|
2 | * @fileoverview `CascadingConfigArrayFactory` class.
|
---|
3 | *
|
---|
4 | * `CascadingConfigArrayFactory` class has a responsibility:
|
---|
5 | *
|
---|
6 | * 1. Handles cascading of config files.
|
---|
7 | *
|
---|
8 | * It provides two methods:
|
---|
9 | *
|
---|
10 | * - `getConfigArrayForFile(filePath)`
|
---|
11 | * Get the corresponded configuration of a given file. This method doesn't
|
---|
12 | * throw even if the given file didn't exist.
|
---|
13 | * - `clearCache()`
|
---|
14 | * Clear the internal cache. You have to call this method when
|
---|
15 | * `additionalPluginPool` was updated if `baseConfig` or `cliConfig` depends
|
---|
16 | * on the additional plugins. (`CLIEngine#addPlugin()` method calls this.)
|
---|
17 | *
|
---|
18 | * @author Toru Nagashima <https://github.com/mysticatea>
|
---|
19 | */
|
---|
20 |
|
---|
21 | //------------------------------------------------------------------------------
|
---|
22 | // Requirements
|
---|
23 | //------------------------------------------------------------------------------
|
---|
24 |
|
---|
25 | import debugOrig from "debug";
|
---|
26 | import os from "os";
|
---|
27 | import path from "path";
|
---|
28 |
|
---|
29 | import { ConfigArrayFactory } from "./config-array-factory.js";
|
---|
30 | import {
|
---|
31 | ConfigArray,
|
---|
32 | ConfigDependency,
|
---|
33 | IgnorePattern
|
---|
34 | } from "./config-array/index.js";
|
---|
35 | import ConfigValidator from "./shared/config-validator.js";
|
---|
36 | import { emitDeprecationWarning } from "./shared/deprecation-warnings.js";
|
---|
37 |
|
---|
38 | const debug = debugOrig("eslintrc:cascading-config-array-factory");
|
---|
39 |
|
---|
40 | //------------------------------------------------------------------------------
|
---|
41 | // Helpers
|
---|
42 | //------------------------------------------------------------------------------
|
---|
43 |
|
---|
44 | // Define types for VSCode IntelliSense.
|
---|
45 | /** @typedef {import("./shared/types").ConfigData} ConfigData */
|
---|
46 | /** @typedef {import("./shared/types").Parser} Parser */
|
---|
47 | /** @typedef {import("./shared/types").Plugin} Plugin */
|
---|
48 | /** @typedef {import("./shared/types").Rule} Rule */
|
---|
49 | /** @typedef {ReturnType<ConfigArrayFactory["create"]>} ConfigArray */
|
---|
50 |
|
---|
51 | /**
|
---|
52 | * @typedef {Object} CascadingConfigArrayFactoryOptions
|
---|
53 | * @property {Map<string,Plugin>} [additionalPluginPool] The map for additional plugins.
|
---|
54 | * @property {ConfigData} [baseConfig] The config by `baseConfig` option.
|
---|
55 | * @property {ConfigData} [cliConfig] The config by CLI options (`--env`, `--global`, `--ignore-pattern`, `--parser`, `--parser-options`, `--plugin`, and `--rule`). CLI options overwrite the setting in config files.
|
---|
56 | * @property {string} [cwd] The base directory to start lookup.
|
---|
57 | * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
|
---|
58 | * @property {string[]} [rulePaths] The value of `--rulesdir` option.
|
---|
59 | * @property {string} [specificConfigPath] The value of `--config` option.
|
---|
60 | * @property {boolean} [useEslintrc] if `false` then it doesn't load config files.
|
---|
61 | * @property {Function} loadRules The function to use to load rules.
|
---|
62 | * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
|
---|
63 | * @property {Object} [resolver=ModuleResolver] The module resolver object.
|
---|
64 | * @property {string} eslintAllPath The path to the definitions for eslint:all.
|
---|
65 | * @property {Function} getEslintAllConfig Returns the config data for eslint:all.
|
---|
66 | * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
|
---|
67 | * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.
|
---|
68 | */
|
---|
69 |
|
---|
70 | /**
|
---|
71 | * @typedef {Object} CascadingConfigArrayFactoryInternalSlots
|
---|
72 | * @property {ConfigArray} baseConfigArray The config array of `baseConfig` option.
|
---|
73 | * @property {ConfigData} baseConfigData The config data of `baseConfig` option. This is used to reset `baseConfigArray`.
|
---|
74 | * @property {ConfigArray} cliConfigArray The config array of CLI options.
|
---|
75 | * @property {ConfigData} cliConfigData The config data of CLI options. This is used to reset `cliConfigArray`.
|
---|
76 | * @property {ConfigArrayFactory} configArrayFactory The factory for config arrays.
|
---|
77 | * @property {Map<string, ConfigArray>} configCache The cache from directory paths to config arrays.
|
---|
78 | * @property {string} cwd The base directory to start lookup.
|
---|
79 | * @property {WeakMap<ConfigArray, ConfigArray>} finalizeCache The cache from config arrays to finalized config arrays.
|
---|
80 | * @property {string} [ignorePath] The path to the alternative file of `.eslintignore`.
|
---|
81 | * @property {string[]|null} rulePaths The value of `--rulesdir` option. This is used to reset `baseConfigArray`.
|
---|
82 | * @property {string|null} specificConfigPath The value of `--config` option. This is used to reset `cliConfigArray`.
|
---|
83 | * @property {boolean} useEslintrc if `false` then it doesn't load config files.
|
---|
84 | * @property {Function} loadRules The function to use to load rules.
|
---|
85 | * @property {Map<string,Rule>} builtInRules The rules that are built in to ESLint.
|
---|
86 | * @property {Object} [resolver=ModuleResolver] The module resolver object.
|
---|
87 | * @property {string} eslintAllPath The path to the definitions for eslint:all.
|
---|
88 | * @property {Function} getEslintAllConfig Returns the config data for eslint:all.
|
---|
89 | * @property {string} eslintRecommendedPath The path to the definitions for eslint:recommended.
|
---|
90 | * @property {Function} getEslintRecommendedConfig Returns the config data for eslint:recommended.
|
---|
91 | */
|
---|
92 |
|
---|
93 | /** @type {WeakMap<CascadingConfigArrayFactory, CascadingConfigArrayFactoryInternalSlots>} */
|
---|
94 | const internalSlotsMap = new WeakMap();
|
---|
95 |
|
---|
96 | /**
|
---|
97 | * Create the config array from `baseConfig` and `rulePaths`.
|
---|
98 | * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
|
---|
99 | * @returns {ConfigArray} The config array of the base configs.
|
---|
100 | */
|
---|
101 | function createBaseConfigArray({
|
---|
102 | configArrayFactory,
|
---|
103 | baseConfigData,
|
---|
104 | rulePaths,
|
---|
105 | cwd,
|
---|
106 | loadRules
|
---|
107 | }) {
|
---|
108 | const baseConfigArray = configArrayFactory.create(
|
---|
109 | baseConfigData,
|
---|
110 | { name: "BaseConfig" }
|
---|
111 | );
|
---|
112 |
|
---|
113 | /*
|
---|
114 | * Create the config array element for the default ignore patterns.
|
---|
115 | * This element has `ignorePattern` property that ignores the default
|
---|
116 | * patterns in the current working directory.
|
---|
117 | */
|
---|
118 | baseConfigArray.unshift(configArrayFactory.create(
|
---|
119 | { ignorePatterns: IgnorePattern.DefaultPatterns },
|
---|
120 | { name: "DefaultIgnorePattern" }
|
---|
121 | )[0]);
|
---|
122 |
|
---|
123 | /*
|
---|
124 | * Load rules `--rulesdir` option as a pseudo plugin.
|
---|
125 | * Use a pseudo plugin to define rules of `--rulesdir`, so we can validate
|
---|
126 | * the rule's options with only information in the config array.
|
---|
127 | */
|
---|
128 | if (rulePaths && rulePaths.length > 0) {
|
---|
129 | baseConfigArray.push({
|
---|
130 | type: "config",
|
---|
131 | name: "--rulesdir",
|
---|
132 | filePath: "",
|
---|
133 | plugins: {
|
---|
134 | "": new ConfigDependency({
|
---|
135 | definition: {
|
---|
136 | rules: rulePaths.reduce(
|
---|
137 | (map, rulesPath) => Object.assign(
|
---|
138 | map,
|
---|
139 | loadRules(rulesPath, cwd)
|
---|
140 | ),
|
---|
141 | {}
|
---|
142 | )
|
---|
143 | },
|
---|
144 | filePath: "",
|
---|
145 | id: "",
|
---|
146 | importerName: "--rulesdir",
|
---|
147 | importerPath: ""
|
---|
148 | })
|
---|
149 | }
|
---|
150 | });
|
---|
151 | }
|
---|
152 |
|
---|
153 | return baseConfigArray;
|
---|
154 | }
|
---|
155 |
|
---|
156 | /**
|
---|
157 | * Create the config array from CLI options.
|
---|
158 | * @param {CascadingConfigArrayFactoryInternalSlots} slots The slots.
|
---|
159 | * @returns {ConfigArray} The config array of the base configs.
|
---|
160 | */
|
---|
161 | function createCLIConfigArray({
|
---|
162 | cliConfigData,
|
---|
163 | configArrayFactory,
|
---|
164 | cwd,
|
---|
165 | ignorePath,
|
---|
166 | specificConfigPath
|
---|
167 | }) {
|
---|
168 | const cliConfigArray = configArrayFactory.create(
|
---|
169 | cliConfigData,
|
---|
170 | { name: "CLIOptions" }
|
---|
171 | );
|
---|
172 |
|
---|
173 | cliConfigArray.unshift(
|
---|
174 | ...(ignorePath
|
---|
175 | ? configArrayFactory.loadESLintIgnore(ignorePath)
|
---|
176 | : configArrayFactory.loadDefaultESLintIgnore())
|
---|
177 | );
|
---|
178 |
|
---|
179 | if (specificConfigPath) {
|
---|
180 | cliConfigArray.unshift(
|
---|
181 | ...configArrayFactory.loadFile(
|
---|
182 | specificConfigPath,
|
---|
183 | { name: "--config", basePath: cwd }
|
---|
184 | )
|
---|
185 | );
|
---|
186 | }
|
---|
187 |
|
---|
188 | return cliConfigArray;
|
---|
189 | }
|
---|
190 |
|
---|
191 | /**
|
---|
192 | * The error type when there are files matched by a glob, but all of them have been ignored.
|
---|
193 | */
|
---|
194 | class ConfigurationNotFoundError extends Error {
|
---|
195 |
|
---|
196 | // eslint-disable-next-line jsdoc/require-description
|
---|
197 | /**
|
---|
198 | * @param {string} directoryPath The directory path.
|
---|
199 | */
|
---|
200 | constructor(directoryPath) {
|
---|
201 | super(`No ESLint configuration found in ${directoryPath}.`);
|
---|
202 | this.messageTemplate = "no-config-found";
|
---|
203 | this.messageData = { directoryPath };
|
---|
204 | }
|
---|
205 | }
|
---|
206 |
|
---|
207 | /**
|
---|
208 | * This class provides the functionality that enumerates every file which is
|
---|
209 | * matched by given glob patterns and that configuration.
|
---|
210 | */
|
---|
211 | class CascadingConfigArrayFactory {
|
---|
212 |
|
---|
213 | /**
|
---|
214 | * Initialize this enumerator.
|
---|
215 | * @param {CascadingConfigArrayFactoryOptions} options The options.
|
---|
216 | */
|
---|
217 | constructor({
|
---|
218 | additionalPluginPool = new Map(),
|
---|
219 | baseConfig: baseConfigData = null,
|
---|
220 | cliConfig: cliConfigData = null,
|
---|
221 | cwd = process.cwd(),
|
---|
222 | ignorePath,
|
---|
223 | resolvePluginsRelativeTo,
|
---|
224 | rulePaths = [],
|
---|
225 | specificConfigPath = null,
|
---|
226 | useEslintrc = true,
|
---|
227 | builtInRules = new Map(),
|
---|
228 | loadRules,
|
---|
229 | resolver,
|
---|
230 | eslintRecommendedPath,
|
---|
231 | getEslintRecommendedConfig,
|
---|
232 | eslintAllPath,
|
---|
233 | getEslintAllConfig
|
---|
234 | } = {}) {
|
---|
235 | const configArrayFactory = new ConfigArrayFactory({
|
---|
236 | additionalPluginPool,
|
---|
237 | cwd,
|
---|
238 | resolvePluginsRelativeTo,
|
---|
239 | builtInRules,
|
---|
240 | resolver,
|
---|
241 | eslintRecommendedPath,
|
---|
242 | getEslintRecommendedConfig,
|
---|
243 | eslintAllPath,
|
---|
244 | getEslintAllConfig
|
---|
245 | });
|
---|
246 |
|
---|
247 | internalSlotsMap.set(this, {
|
---|
248 | baseConfigArray: createBaseConfigArray({
|
---|
249 | baseConfigData,
|
---|
250 | configArrayFactory,
|
---|
251 | cwd,
|
---|
252 | rulePaths,
|
---|
253 | loadRules
|
---|
254 | }),
|
---|
255 | baseConfigData,
|
---|
256 | cliConfigArray: createCLIConfigArray({
|
---|
257 | cliConfigData,
|
---|
258 | configArrayFactory,
|
---|
259 | cwd,
|
---|
260 | ignorePath,
|
---|
261 | specificConfigPath
|
---|
262 | }),
|
---|
263 | cliConfigData,
|
---|
264 | configArrayFactory,
|
---|
265 | configCache: new Map(),
|
---|
266 | cwd,
|
---|
267 | finalizeCache: new WeakMap(),
|
---|
268 | ignorePath,
|
---|
269 | rulePaths,
|
---|
270 | specificConfigPath,
|
---|
271 | useEslintrc,
|
---|
272 | builtInRules,
|
---|
273 | loadRules
|
---|
274 | });
|
---|
275 | }
|
---|
276 |
|
---|
277 | /**
|
---|
278 | * The path to the current working directory.
|
---|
279 | * This is used by tests.
|
---|
280 | * @type {string}
|
---|
281 | */
|
---|
282 | get cwd() {
|
---|
283 | const { cwd } = internalSlotsMap.get(this);
|
---|
284 |
|
---|
285 | return cwd;
|
---|
286 | }
|
---|
287 |
|
---|
288 | /**
|
---|
289 | * Get the config array of a given file.
|
---|
290 | * If `filePath` was not given, it returns the config which contains only
|
---|
291 | * `baseConfigData` and `cliConfigData`.
|
---|
292 | * @param {string} [filePath] The file path to a file.
|
---|
293 | * @param {Object} [options] The options.
|
---|
294 | * @param {boolean} [options.ignoreNotFoundError] If `true` then it doesn't throw `ConfigurationNotFoundError`.
|
---|
295 | * @returns {ConfigArray} The config array of the file.
|
---|
296 | */
|
---|
297 | getConfigArrayForFile(filePath, { ignoreNotFoundError = false } = {}) {
|
---|
298 | const {
|
---|
299 | baseConfigArray,
|
---|
300 | cliConfigArray,
|
---|
301 | cwd
|
---|
302 | } = internalSlotsMap.get(this);
|
---|
303 |
|
---|
304 | if (!filePath) {
|
---|
305 | return new ConfigArray(...baseConfigArray, ...cliConfigArray);
|
---|
306 | }
|
---|
307 |
|
---|
308 | const directoryPath = path.dirname(path.resolve(cwd, filePath));
|
---|
309 |
|
---|
310 | debug(`Load config files for ${directoryPath}.`);
|
---|
311 |
|
---|
312 | return this._finalizeConfigArray(
|
---|
313 | this._loadConfigInAncestors(directoryPath),
|
---|
314 | directoryPath,
|
---|
315 | ignoreNotFoundError
|
---|
316 | );
|
---|
317 | }
|
---|
318 |
|
---|
319 | /**
|
---|
320 | * Set the config data to override all configs.
|
---|
321 | * Require to call `clearCache()` method after this method is called.
|
---|
322 | * @param {ConfigData} configData The config data to override all configs.
|
---|
323 | * @returns {void}
|
---|
324 | */
|
---|
325 | setOverrideConfig(configData) {
|
---|
326 | const slots = internalSlotsMap.get(this);
|
---|
327 |
|
---|
328 | slots.cliConfigData = configData;
|
---|
329 | }
|
---|
330 |
|
---|
331 | /**
|
---|
332 | * Clear config cache.
|
---|
333 | * @returns {void}
|
---|
334 | */
|
---|
335 | clearCache() {
|
---|
336 | const slots = internalSlotsMap.get(this);
|
---|
337 |
|
---|
338 | slots.baseConfigArray = createBaseConfigArray(slots);
|
---|
339 | slots.cliConfigArray = createCLIConfigArray(slots);
|
---|
340 | slots.configCache.clear();
|
---|
341 | }
|
---|
342 |
|
---|
343 | /**
|
---|
344 | * Load and normalize config files from the ancestor directories.
|
---|
345 | * @param {string} directoryPath The path to a leaf directory.
|
---|
346 | * @param {boolean} configsExistInSubdirs `true` if configurations exist in subdirectories.
|
---|
347 | * @returns {ConfigArray} The loaded config.
|
---|
348 | * @private
|
---|
349 | */
|
---|
350 | _loadConfigInAncestors(directoryPath, configsExistInSubdirs = false) {
|
---|
351 | const {
|
---|
352 | baseConfigArray,
|
---|
353 | configArrayFactory,
|
---|
354 | configCache,
|
---|
355 | cwd,
|
---|
356 | useEslintrc
|
---|
357 | } = internalSlotsMap.get(this);
|
---|
358 |
|
---|
359 | if (!useEslintrc) {
|
---|
360 | return baseConfigArray;
|
---|
361 | }
|
---|
362 |
|
---|
363 | let configArray = configCache.get(directoryPath);
|
---|
364 |
|
---|
365 | // Hit cache.
|
---|
366 | if (configArray) {
|
---|
367 | debug(`Cache hit: ${directoryPath}.`);
|
---|
368 | return configArray;
|
---|
369 | }
|
---|
370 | debug(`No cache found: ${directoryPath}.`);
|
---|
371 |
|
---|
372 | const homePath = os.homedir();
|
---|
373 |
|
---|
374 | // Consider this is root.
|
---|
375 | if (directoryPath === homePath && cwd !== homePath) {
|
---|
376 | debug("Stop traversing because of considered root.");
|
---|
377 | if (configsExistInSubdirs) {
|
---|
378 | const filePath = ConfigArrayFactory.getPathToConfigFileInDirectory(directoryPath);
|
---|
379 |
|
---|
380 | if (filePath) {
|
---|
381 | emitDeprecationWarning(
|
---|
382 | filePath,
|
---|
383 | "ESLINT_PERSONAL_CONFIG_SUPPRESS"
|
---|
384 | );
|
---|
385 | }
|
---|
386 | }
|
---|
387 | return this._cacheConfig(directoryPath, baseConfigArray);
|
---|
388 | }
|
---|
389 |
|
---|
390 | // Load the config on this directory.
|
---|
391 | try {
|
---|
392 | configArray = configArrayFactory.loadInDirectory(directoryPath);
|
---|
393 | } catch (error) {
|
---|
394 | /* istanbul ignore next */
|
---|
395 | if (error.code === "EACCES") {
|
---|
396 | debug("Stop traversing because of 'EACCES' error.");
|
---|
397 | return this._cacheConfig(directoryPath, baseConfigArray);
|
---|
398 | }
|
---|
399 | throw error;
|
---|
400 | }
|
---|
401 |
|
---|
402 | if (configArray.length > 0 && configArray.isRoot()) {
|
---|
403 | debug("Stop traversing because of 'root:true'.");
|
---|
404 | configArray.unshift(...baseConfigArray);
|
---|
405 | return this._cacheConfig(directoryPath, configArray);
|
---|
406 | }
|
---|
407 |
|
---|
408 | // Load from the ancestors and merge it.
|
---|
409 | const parentPath = path.dirname(directoryPath);
|
---|
410 | const parentConfigArray = parentPath && parentPath !== directoryPath
|
---|
411 | ? this._loadConfigInAncestors(
|
---|
412 | parentPath,
|
---|
413 | configsExistInSubdirs || configArray.length > 0
|
---|
414 | )
|
---|
415 | : baseConfigArray;
|
---|
416 |
|
---|
417 | if (configArray.length > 0) {
|
---|
418 | configArray.unshift(...parentConfigArray);
|
---|
419 | } else {
|
---|
420 | configArray = parentConfigArray;
|
---|
421 | }
|
---|
422 |
|
---|
423 | // Cache and return.
|
---|
424 | return this._cacheConfig(directoryPath, configArray);
|
---|
425 | }
|
---|
426 |
|
---|
427 | /**
|
---|
428 | * Freeze and cache a given config.
|
---|
429 | * @param {string} directoryPath The path to a directory as a cache key.
|
---|
430 | * @param {ConfigArray} configArray The config array as a cache value.
|
---|
431 | * @returns {ConfigArray} The `configArray` (frozen).
|
---|
432 | */
|
---|
433 | _cacheConfig(directoryPath, configArray) {
|
---|
434 | const { configCache } = internalSlotsMap.get(this);
|
---|
435 |
|
---|
436 | Object.freeze(configArray);
|
---|
437 | configCache.set(directoryPath, configArray);
|
---|
438 |
|
---|
439 | return configArray;
|
---|
440 | }
|
---|
441 |
|
---|
442 | /**
|
---|
443 | * Finalize a given config array.
|
---|
444 | * Concatenate `--config` and other CLI options.
|
---|
445 | * @param {ConfigArray} configArray The parent config array.
|
---|
446 | * @param {string} directoryPath The path to the leaf directory to find config files.
|
---|
447 | * @param {boolean} ignoreNotFoundError If `true` then it doesn't throw `ConfigurationNotFoundError`.
|
---|
448 | * @returns {ConfigArray} The loaded config.
|
---|
449 | * @private
|
---|
450 | */
|
---|
451 | _finalizeConfigArray(configArray, directoryPath, ignoreNotFoundError) {
|
---|
452 | const {
|
---|
453 | cliConfigArray,
|
---|
454 | configArrayFactory,
|
---|
455 | finalizeCache,
|
---|
456 | useEslintrc,
|
---|
457 | builtInRules
|
---|
458 | } = internalSlotsMap.get(this);
|
---|
459 |
|
---|
460 | let finalConfigArray = finalizeCache.get(configArray);
|
---|
461 |
|
---|
462 | if (!finalConfigArray) {
|
---|
463 | finalConfigArray = configArray;
|
---|
464 |
|
---|
465 | // Load the personal config if there are no regular config files.
|
---|
466 | if (
|
---|
467 | useEslintrc &&
|
---|
468 | configArray.every(c => !c.filePath) &&
|
---|
469 | cliConfigArray.every(c => !c.filePath) // `--config` option can be a file.
|
---|
470 | ) {
|
---|
471 | const homePath = os.homedir();
|
---|
472 |
|
---|
473 | debug("Loading the config file of the home directory:", homePath);
|
---|
474 |
|
---|
475 | const personalConfigArray = configArrayFactory.loadInDirectory(
|
---|
476 | homePath,
|
---|
477 | { name: "PersonalConfig" }
|
---|
478 | );
|
---|
479 |
|
---|
480 | if (
|
---|
481 | personalConfigArray.length > 0 &&
|
---|
482 | !directoryPath.startsWith(homePath)
|
---|
483 | ) {
|
---|
484 | const lastElement =
|
---|
485 | personalConfigArray[personalConfigArray.length - 1];
|
---|
486 |
|
---|
487 | emitDeprecationWarning(
|
---|
488 | lastElement.filePath,
|
---|
489 | "ESLINT_PERSONAL_CONFIG_LOAD"
|
---|
490 | );
|
---|
491 | }
|
---|
492 |
|
---|
493 | finalConfigArray = finalConfigArray.concat(personalConfigArray);
|
---|
494 | }
|
---|
495 |
|
---|
496 | // Apply CLI options.
|
---|
497 | if (cliConfigArray.length > 0) {
|
---|
498 | finalConfigArray = finalConfigArray.concat(cliConfigArray);
|
---|
499 | }
|
---|
500 |
|
---|
501 | // Validate rule settings and environments.
|
---|
502 | const validator = new ConfigValidator({
|
---|
503 | builtInRules
|
---|
504 | });
|
---|
505 |
|
---|
506 | validator.validateConfigArray(finalConfigArray);
|
---|
507 |
|
---|
508 | // Cache it.
|
---|
509 | Object.freeze(finalConfigArray);
|
---|
510 | finalizeCache.set(configArray, finalConfigArray);
|
---|
511 |
|
---|
512 | debug(
|
---|
513 | "Configuration was determined: %o on %s",
|
---|
514 | finalConfigArray,
|
---|
515 | directoryPath
|
---|
516 | );
|
---|
517 | }
|
---|
518 |
|
---|
519 | // At least one element (the default ignore patterns) exists.
|
---|
520 | if (!ignoreNotFoundError && useEslintrc && finalConfigArray.length <= 1) {
|
---|
521 | throw new ConfigurationNotFoundError(directoryPath);
|
---|
522 | }
|
---|
523 |
|
---|
524 | return finalConfigArray;
|
---|
525 | }
|
---|
526 | }
|
---|
527 |
|
---|
528 | //------------------------------------------------------------------------------
|
---|
529 | // Public Interface
|
---|
530 | //------------------------------------------------------------------------------
|
---|
531 |
|
---|
532 | export { CascadingConfigArrayFactory };
|
---|