massive update, probably broken
[dotfiles/.git] / .config / coc / extensions / node_modules / coc-prettier / node_modules / eslint / lib / eslint / eslint.js
1 /**
2  * @fileoverview Main API Class
3  * @author Kai Cataldo
4  * @author Toru Nagashima
5  */
6
7 "use strict";
8
9 //------------------------------------------------------------------------------
10 // Requirements
11 //------------------------------------------------------------------------------
12
13 const path = require("path");
14 const fs = require("fs");
15 const { promisify } = require("util");
16 const { CLIEngine, getCLIEngineInternalSlots } = require("../cli-engine/cli-engine");
17 const BuiltinRules = require("../rules");
18 const {
19     Legacy: {
20         ConfigOps: {
21             getRuleSeverity
22         }
23     }
24 } = require("@eslint/eslintrc");
25 const { version } = require("../../package.json");
26
27 //------------------------------------------------------------------------------
28 // Typedefs
29 //------------------------------------------------------------------------------
30
31 /** @typedef {import("../cli-engine/cli-engine").LintReport} CLIEngineLintReport */
32 /** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */
33 /** @typedef {import("../shared/types").ConfigData} ConfigData */
34 /** @typedef {import("../shared/types").LintMessage} LintMessage */
35 /** @typedef {import("../shared/types").Plugin} Plugin */
36 /** @typedef {import("../shared/types").Rule} Rule */
37 /** @typedef {import("./load-formatter").Formatter} Formatter */
38
39 /**
40  * The options with which to configure the ESLint instance.
41  * @typedef {Object} ESLintOptions
42  * @property {boolean} [allowInlineConfig] Enable or disable inline configuration comments.
43  * @property {ConfigData} [baseConfig] Base config object, extended by all configs used with this instance
44  * @property {boolean} [cache] Enable result caching.
45  * @property {string} [cacheLocation] The cache file to use instead of .eslintcache.
46  * @property {"metadata" | "content"} [cacheStrategy] The strategy used to detect changed files.
47  * @property {string} [cwd] The value to use for the current working directory.
48  * @property {boolean} [errorOnUnmatchedPattern] If `false` then `ESLint#lintFiles()` doesn't throw even if no target files found. Defaults to `true`.
49  * @property {string[]} [extensions] An array of file extensions to check.
50  * @property {boolean|Function} [fix] Execute in autofix mode. If a function, should return a boolean.
51  * @property {string[]} [fixTypes] Array of rule types to apply fixes for.
52  * @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.
53  * @property {boolean} [ignore] False disables use of .eslintignore.
54  * @property {string} [ignorePath] The ignore file to use instead of .eslintignore.
55  * @property {ConfigData} [overrideConfig] Override config object, overrides all configs used with this instance
56  * @property {string} [overrideConfigFile] The configuration file to use.
57  * @property {Record<string,Plugin>} [plugins] An array of plugin implementations.
58  * @property {"error" | "warn" | "off"} [reportUnusedDisableDirectives] the severity to report unused eslint-disable directives.
59  * @property {string} [resolvePluginsRelativeTo] The folder where plugins should be resolved from, defaulting to the CWD.
60  * @property {string[]} [rulePaths] An array of directories to load custom rules from.
61  * @property {boolean} [useEslintrc] False disables looking for .eslintrc.* files.
62  */
63
64 /**
65  * A rules metadata object.
66  * @typedef {Object} RulesMeta
67  * @property {string} id The plugin ID.
68  * @property {Object} definition The plugin definition.
69  */
70
71 /**
72  * A linting result.
73  * @typedef {Object} LintResult
74  * @property {string} filePath The path to the file that was linted.
75  * @property {LintMessage[]} messages All of the messages for the result.
76  * @property {number} errorCount Number of errors for the result.
77  * @property {number} warningCount Number of warnings for the result.
78  * @property {number} fixableErrorCount Number of fixable errors for the result.
79  * @property {number} fixableWarningCount Number of fixable warnings for the result.
80  * @property {string} [source] The source code of the file that was linted.
81  * @property {string} [output] The source code of the file that was linted, with as many fixes applied as possible.
82  * @property {DeprecatedRuleInfo[]} usedDeprecatedRules The list of used deprecated rules.
83  */
84
85 /**
86  * Private members for the `ESLint` instance.
87  * @typedef {Object} ESLintPrivateMembers
88  * @property {CLIEngine} cliEngine The wrapped CLIEngine instance.
89  * @property {ESLintOptions} options The options used to instantiate the ESLint instance.
90  */
91
92 //------------------------------------------------------------------------------
93 // Helpers
94 //------------------------------------------------------------------------------
95
96 const writeFile = promisify(fs.writeFile);
97
98 /**
99  * The map with which to store private class members.
100  * @type {WeakMap<ESLint, ESLintPrivateMembers>}
101  */
102 const privateMembersMap = new WeakMap();
103
104 /**
105  * Check if a given value is a non-empty string or not.
106  * @param {any} x The value to check.
107  * @returns {boolean} `true` if `x` is a non-empty string.
108  */
109 function isNonEmptyString(x) {
110     return typeof x === "string" && x.trim() !== "";
111 }
112
113 /**
114  * Check if a given value is an array of non-empty stringss or not.
115  * @param {any} x The value to check.
116  * @returns {boolean} `true` if `x` is an array of non-empty stringss.
117  */
118 function isArrayOfNonEmptyString(x) {
119     return Array.isArray(x) && x.every(isNonEmptyString);
120 }
121
122 /**
123  * Check if a given value is a valid fix type or not.
124  * @param {any} x The value to check.
125  * @returns {boolean} `true` if `x` is valid fix type.
126  */
127 function isFixType(x) {
128     return x === "problem" || x === "suggestion" || x === "layout";
129 }
130
131 /**
132  * Check if a given value is an array of fix types or not.
133  * @param {any} x The value to check.
134  * @returns {boolean} `true` if `x` is an array of fix types.
135  */
136 function isFixTypeArray(x) {
137     return Array.isArray(x) && x.every(isFixType);
138 }
139
140 /**
141  * The error for invalid options.
142  */
143 class ESLintInvalidOptionsError extends Error {
144     constructor(messages) {
145         super(`Invalid Options:\n- ${messages.join("\n- ")}`);
146         this.code = "ESLINT_INVALID_OPTIONS";
147         Error.captureStackTrace(this, ESLintInvalidOptionsError);
148     }
149 }
150
151 /**
152  * Validates and normalizes options for the wrapped CLIEngine instance.
153  * @param {ESLintOptions} options The options to process.
154  * @returns {ESLintOptions} The normalized options.
155  */
156 function processOptions({
157     allowInlineConfig = true, // ← we cannot use `overrideConfig.noInlineConfig` instead because `allowInlineConfig` has side-effect that suppress warnings that show inline configs are ignored.
158     baseConfig = null,
159     cache = false,
160     cacheLocation = ".eslintcache",
161     cacheStrategy = "metadata",
162     cwd = process.cwd(),
163     errorOnUnmatchedPattern = true,
164     extensions = null, // ← should be null by default because if it's an array then it suppresses RFC20 feature.
165     fix = false,
166     fixTypes = null, // ← should be null by default because if it's an array then it suppresses rules that don't have the `meta.type` property.
167     globInputPaths = true,
168     ignore = true,
169     ignorePath = null, // ← should be null by default because if it's a string then it may throw ENOENT.
170     overrideConfig = null,
171     overrideConfigFile = null,
172     plugins = {},
173     reportUnusedDisableDirectives = null, // ← should be null by default because if it's a string then it overrides the 'reportUnusedDisableDirectives' setting in config files. And we cannot use `overrideConfig.reportUnusedDisableDirectives` instead because we cannot configure the `error` severity with that.
174     resolvePluginsRelativeTo = null, // ← should be null by default because if it's a string then it suppresses RFC47 feature.
175     rulePaths = [],
176     useEslintrc = true,
177     ...unknownOptions
178 }) {
179     const errors = [];
180     const unknownOptionKeys = Object.keys(unknownOptions);
181
182     if (unknownOptionKeys.length >= 1) {
183         errors.push(`Unknown options: ${unknownOptionKeys.join(", ")}`);
184         if (unknownOptionKeys.includes("cacheFile")) {
185             errors.push("'cacheFile' has been removed. Please use the 'cacheLocation' option instead.");
186         }
187         if (unknownOptionKeys.includes("configFile")) {
188             errors.push("'configFile' has been removed. Please use the 'overrideConfigFile' option instead.");
189         }
190         if (unknownOptionKeys.includes("envs")) {
191             errors.push("'envs' has been removed. Please use the 'overrideConfig.env' option instead.");
192         }
193         if (unknownOptionKeys.includes("globals")) {
194             errors.push("'globals' has been removed. Please use the 'overrideConfig.globals' option instead.");
195         }
196         if (unknownOptionKeys.includes("ignorePattern")) {
197             errors.push("'ignorePattern' has been removed. Please use the 'overrideConfig.ignorePatterns' option instead.");
198         }
199         if (unknownOptionKeys.includes("parser")) {
200             errors.push("'parser' has been removed. Please use the 'overrideConfig.parser' option instead.");
201         }
202         if (unknownOptionKeys.includes("parserOptions")) {
203             errors.push("'parserOptions' has been removed. Please use the 'overrideConfig.parserOptions' option instead.");
204         }
205         if (unknownOptionKeys.includes("rules")) {
206             errors.push("'rules' has been removed. Please use the 'overrideConfig.rules' option instead.");
207         }
208     }
209     if (typeof allowInlineConfig !== "boolean") {
210         errors.push("'allowInlineConfig' must be a boolean.");
211     }
212     if (typeof baseConfig !== "object") {
213         errors.push("'baseConfig' must be an object or null.");
214     }
215     if (typeof cache !== "boolean") {
216         errors.push("'cache' must be a boolean.");
217     }
218     if (!isNonEmptyString(cacheLocation)) {
219         errors.push("'cacheLocation' must be a non-empty string.");
220     }
221     if (
222         cacheStrategy !== "metadata" &&
223         cacheStrategy !== "content"
224     ) {
225         errors.push("'cacheStrategy' must be any of \"metadata\", \"content\".");
226     }
227     if (!isNonEmptyString(cwd) || !path.isAbsolute(cwd)) {
228         errors.push("'cwd' must be an absolute path.");
229     }
230     if (typeof errorOnUnmatchedPattern !== "boolean") {
231         errors.push("'errorOnUnmatchedPattern' must be a boolean.");
232     }
233     if (!isArrayOfNonEmptyString(extensions) && extensions !== null) {
234         errors.push("'extensions' must be an array of non-empty strings or null.");
235     }
236     if (typeof fix !== "boolean" && typeof fix !== "function") {
237         errors.push("'fix' must be a boolean or a function.");
238     }
239     if (fixTypes !== null && !isFixTypeArray(fixTypes)) {
240         errors.push("'fixTypes' must be an array of any of \"problem\", \"suggestion\", and \"layout\".");
241     }
242     if (typeof globInputPaths !== "boolean") {
243         errors.push("'globInputPaths' must be a boolean.");
244     }
245     if (typeof ignore !== "boolean") {
246         errors.push("'ignore' must be a boolean.");
247     }
248     if (!isNonEmptyString(ignorePath) && ignorePath !== null) {
249         errors.push("'ignorePath' must be a non-empty string or null.");
250     }
251     if (typeof overrideConfig !== "object") {
252         errors.push("'overrideConfig' must be an object or null.");
253     }
254     if (!isNonEmptyString(overrideConfigFile) && overrideConfigFile !== null) {
255         errors.push("'overrideConfigFile' must be a non-empty string or null.");
256     }
257     if (typeof plugins !== "object") {
258         errors.push("'plugins' must be an object or null.");
259     } else if (plugins !== null && Object.keys(plugins).includes("")) {
260         errors.push("'plugins' must not include an empty string.");
261     }
262     if (Array.isArray(plugins)) {
263         errors.push("'plugins' doesn't add plugins to configuration to load. Please use the 'overrideConfig.plugins' option instead.");
264     }
265     if (
266         reportUnusedDisableDirectives !== "error" &&
267         reportUnusedDisableDirectives !== "warn" &&
268         reportUnusedDisableDirectives !== "off" &&
269         reportUnusedDisableDirectives !== null
270     ) {
271         errors.push("'reportUnusedDisableDirectives' must be any of \"error\", \"warn\", \"off\", and null.");
272     }
273     if (
274         !isNonEmptyString(resolvePluginsRelativeTo) &&
275         resolvePluginsRelativeTo !== null
276     ) {
277         errors.push("'resolvePluginsRelativeTo' must be a non-empty string or null.");
278     }
279     if (!isArrayOfNonEmptyString(rulePaths)) {
280         errors.push("'rulePaths' must be an array of non-empty strings.");
281     }
282     if (typeof useEslintrc !== "boolean") {
283         errors.push("'useEslintrc' must be a boolean.");
284     }
285
286     if (errors.length > 0) {
287         throw new ESLintInvalidOptionsError(errors);
288     }
289
290     return {
291         allowInlineConfig,
292         baseConfig,
293         cache,
294         cacheLocation,
295         cacheStrategy,
296         configFile: overrideConfigFile,
297         cwd,
298         errorOnUnmatchedPattern,
299         extensions,
300         fix,
301         fixTypes,
302         globInputPaths,
303         ignore,
304         ignorePath,
305         reportUnusedDisableDirectives,
306         resolvePluginsRelativeTo,
307         rulePaths,
308         useEslintrc
309     };
310 }
311
312 /**
313  * Check if a value has one or more properties and that value is not undefined.
314  * @param {any} obj The value to check.
315  * @returns {boolean} `true` if `obj` has one or more properties that that value is not undefined.
316  */
317 function hasDefinedProperty(obj) {
318     if (typeof obj === "object" && obj !== null) {
319         for (const key in obj) {
320             if (typeof obj[key] !== "undefined") {
321                 return true;
322             }
323         }
324     }
325     return false;
326 }
327
328 /**
329  * Create rulesMeta object.
330  * @param {Map<string,Rule>} rules a map of rules from which to generate the object.
331  * @returns {Object} metadata for all enabled rules.
332  */
333 function createRulesMeta(rules) {
334     return Array.from(rules).reduce((retVal, [id, rule]) => {
335         retVal[id] = rule.meta;
336         return retVal;
337     }, {});
338 }
339
340 /** @type {WeakMap<ExtractedConfig, DeprecatedRuleInfo[]>} */
341 const usedDeprecatedRulesCache = new WeakMap();
342
343 /**
344  * Create used deprecated rule list.
345  * @param {CLIEngine} cliEngine The CLIEngine instance.
346  * @param {string} maybeFilePath The absolute path to a lint target file or `"<text>"`.
347  * @returns {DeprecatedRuleInfo[]} The used deprecated rule list.
348  */
349 function getOrFindUsedDeprecatedRules(cliEngine, maybeFilePath) {
350     const {
351         configArrayFactory,
352         options: { cwd }
353     } = getCLIEngineInternalSlots(cliEngine);
354     const filePath = path.isAbsolute(maybeFilePath)
355         ? maybeFilePath
356         : path.join(cwd, "__placeholder__.js");
357     const configArray = configArrayFactory.getConfigArrayForFile(filePath);
358     const config = configArray.extractConfig(filePath);
359
360     // Most files use the same config, so cache it.
361     if (!usedDeprecatedRulesCache.has(config)) {
362         const pluginRules = configArray.pluginRules;
363         const retv = [];
364
365         for (const [ruleId, ruleConf] of Object.entries(config.rules)) {
366             if (getRuleSeverity(ruleConf) === 0) {
367                 continue;
368             }
369             const rule = pluginRules.get(ruleId) || BuiltinRules.get(ruleId);
370             const meta = rule && rule.meta;
371
372             if (meta && meta.deprecated) {
373                 retv.push({ ruleId, replacedBy: meta.replacedBy || [] });
374             }
375         }
376
377         usedDeprecatedRulesCache.set(config, Object.freeze(retv));
378     }
379
380     return usedDeprecatedRulesCache.get(config);
381 }
382
383 /**
384  * Processes the linting results generated by a CLIEngine linting report to
385  * match the ESLint class's API.
386  * @param {CLIEngine} cliEngine The CLIEngine instance.
387  * @param {CLIEngineLintReport} report The CLIEngine linting report to process.
388  * @returns {LintResult[]} The processed linting results.
389  */
390 function processCLIEngineLintReport(cliEngine, { results }) {
391     const descriptor = {
392         configurable: true,
393         enumerable: true,
394         get() {
395             return getOrFindUsedDeprecatedRules(cliEngine, this.filePath);
396         }
397     };
398
399     for (const result of results) {
400         Object.defineProperty(result, "usedDeprecatedRules", descriptor);
401     }
402
403     return results;
404 }
405
406 /**
407  * An Array.prototype.sort() compatible compare function to order results by their file path.
408  * @param {LintResult} a The first lint result.
409  * @param {LintResult} b The second lint result.
410  * @returns {number} An integer representing the order in which the two results should occur.
411  */
412 function compareResultsByFilePath(a, b) {
413     if (a.filePath < b.filePath) {
414         return -1;
415     }
416
417     if (a.filePath > b.filePath) {
418         return 1;
419     }
420
421     return 0;
422 }
423
424 class ESLint {
425
426     /**
427      * Creates a new instance of the main ESLint API.
428      * @param {ESLintOptions} options The options for this instance.
429      */
430     constructor(options = {}) {
431         const processedOptions = processOptions(options);
432         const cliEngine = new CLIEngine(processedOptions);
433         const {
434             additionalPluginPool,
435             configArrayFactory,
436             lastConfigArrays
437         } = getCLIEngineInternalSlots(cliEngine);
438         let updated = false;
439
440         /*
441          * Address `plugins` to add plugin implementations.
442          * Operate the `additionalPluginPool` internal slot directly to avoid
443          * using `addPlugin(id, plugin)` method that resets cache everytime.
444          */
445         if (options.plugins) {
446             for (const [id, plugin] of Object.entries(options.plugins)) {
447                 additionalPluginPool.set(id, plugin);
448                 updated = true;
449             }
450         }
451
452         /*
453          * Address `overrideConfig` to set override config.
454          * Operate the `configArrayFactory` internal slot directly because this
455          * functionality doesn't exist as the public API of CLIEngine.
456          */
457         if (hasDefinedProperty(options.overrideConfig)) {
458             configArrayFactory.setOverrideConfig(options.overrideConfig);
459             updated = true;
460         }
461
462         // Update caches.
463         if (updated) {
464             configArrayFactory.clearCache();
465             lastConfigArrays[0] = configArrayFactory.getConfigArrayForFile();
466         }
467
468         // Initialize private properties.
469         privateMembersMap.set(this, {
470             cliEngine,
471             options: processedOptions
472         });
473     }
474
475     /**
476      * The version text.
477      * @type {string}
478      */
479     static get version() {
480         return version;
481     }
482
483     /**
484      * Outputs fixes from the given results to files.
485      * @param {LintResult[]} results The lint results.
486      * @returns {Promise<void>} Returns a promise that is used to track side effects.
487      */
488     static async outputFixes(results) {
489         if (!Array.isArray(results)) {
490             throw new Error("'results' must be an array");
491         }
492
493         await Promise.all(
494             results
495                 .filter(result => {
496                     if (typeof result !== "object" || result === null) {
497                         throw new Error("'results' must include only objects");
498                     }
499                     return (
500                         typeof result.output === "string" &&
501                         path.isAbsolute(result.filePath)
502                     );
503                 })
504                 .map(r => writeFile(r.filePath, r.output))
505         );
506     }
507
508     /**
509      * Returns results that only contains errors.
510      * @param {LintResult[]} results The results to filter.
511      * @returns {LintResult[]} The filtered results.
512      */
513     static getErrorResults(results) {
514         return CLIEngine.getErrorResults(results);
515     }
516
517     /**
518      * Returns meta objects for each rule represented in the lint results.
519      * @param {LintResult[]} results The results to fetch rules meta for.
520      * @returns {Object} A mapping of ruleIds to rule meta objects.
521      */
522     getRulesMetaForResults(results) {
523
524         const resultRuleIds = new Set();
525
526         // first gather all ruleIds from all results
527
528         for (const result of results) {
529             for (const { ruleId } of result.messages) {
530                 resultRuleIds.add(ruleId);
531             }
532         }
533
534         // create a map of all rules in the results
535
536         const { cliEngine } = privateMembersMap.get(this);
537         const rules = cliEngine.getRules();
538         const resultRules = new Map();
539
540         for (const [ruleId, rule] of rules) {
541             if (resultRuleIds.has(ruleId)) {
542                 resultRules.set(ruleId, rule);
543             }
544         }
545
546         return createRulesMeta(resultRules);
547
548     }
549
550     /**
551      * Executes the current configuration on an array of file and directory names.
552      * @param {string[]} patterns An array of file and directory names.
553      * @returns {Promise<LintResult[]>} The results of linting the file patterns given.
554      */
555     async lintFiles(patterns) {
556         if (!isNonEmptyString(patterns) && !isArrayOfNonEmptyString(patterns)) {
557             throw new Error("'patterns' must be a non-empty string or an array of non-empty strings");
558         }
559         const { cliEngine } = privateMembersMap.get(this);
560
561         return processCLIEngineLintReport(
562             cliEngine,
563             cliEngine.executeOnFiles(patterns)
564         );
565     }
566
567     /**
568      * Executes the current configuration on text.
569      * @param {string} code A string of JavaScript code to lint.
570      * @param {Object} [options] The options.
571      * @param {string} [options.filePath] The path to the file of the source code.
572      * @param {boolean} [options.warnIgnored] When set to true, warn if given filePath is an ignored path.
573      * @returns {Promise<LintResult[]>} The results of linting the string of code given.
574      */
575     async lintText(code, options = {}) {
576         if (typeof code !== "string") {
577             throw new Error("'code' must be a string");
578         }
579         if (typeof options !== "object") {
580             throw new Error("'options' must be an object, null, or undefined");
581         }
582         const {
583             filePath,
584             warnIgnored = false,
585             ...unknownOptions
586         } = options || {};
587
588         const unknownOptionKeys = Object.keys(unknownOptions);
589
590         if (unknownOptionKeys.length > 0) {
591             throw new Error(`'options' must not include the unknown option(s): ${unknownOptionKeys.join(", ")}`);
592         }
593
594         if (filePath !== void 0 && !isNonEmptyString(filePath)) {
595             throw new Error("'options.filePath' must be a non-empty string or undefined");
596         }
597         if (typeof warnIgnored !== "boolean") {
598             throw new Error("'options.warnIgnored' must be a boolean or undefined");
599         }
600
601         const { cliEngine } = privateMembersMap.get(this);
602
603         return processCLIEngineLintReport(
604             cliEngine,
605             cliEngine.executeOnText(code, filePath, warnIgnored)
606         );
607     }
608
609     /**
610      * Returns the formatter representing the given formatter name.
611      * @param {string} [name] The name of the formatter to load.
612      * The following values are allowed:
613      * - `undefined` ... Load `stylish` builtin formatter.
614      * - A builtin formatter name ... Load the builtin formatter.
615      * - A thirdparty formatter name:
616      *   - `foo` → `eslint-formatter-foo`
617      *   - `@foo` → `@foo/eslint-formatter`
618      *   - `@foo/bar` → `@foo/eslint-formatter-bar`
619      * - A file path ... Load the file.
620      * @returns {Promise<Formatter>} A promise resolving to the formatter object.
621      * This promise will be rejected if the given formatter was not found or not
622      * a function.
623      */
624     async loadFormatter(name = "stylish") {
625         if (typeof name !== "string") {
626             throw new Error("'name' must be a string");
627         }
628
629         const { cliEngine } = privateMembersMap.get(this);
630         const formatter = cliEngine.getFormatter(name);
631
632         if (typeof formatter !== "function") {
633             throw new Error(`Formatter must be a function, but got a ${typeof formatter}.`);
634         }
635
636         return {
637
638             /**
639              * The main formatter method.
640              * @param {LintResults[]} results The lint results to format.
641              * @returns {string} The formatted lint results.
642              */
643             format(results) {
644                 let rulesMeta = null;
645
646                 results.sort(compareResultsByFilePath);
647
648                 return formatter(results, {
649                     get rulesMeta() {
650                         if (!rulesMeta) {
651                             rulesMeta = createRulesMeta(cliEngine.getRules());
652                         }
653
654                         return rulesMeta;
655                     }
656                 });
657             }
658         };
659     }
660
661     /**
662      * Returns a configuration object for the given file based on the CLI options.
663      * This is the same logic used by the ESLint CLI executable to determine
664      * configuration for each file it processes.
665      * @param {string} filePath The path of the file to retrieve a config object for.
666      * @returns {Promise<ConfigData>} A configuration object for the file.
667      */
668     async calculateConfigForFile(filePath) {
669         if (!isNonEmptyString(filePath)) {
670             throw new Error("'filePath' must be a non-empty string");
671         }
672         const { cliEngine } = privateMembersMap.get(this);
673
674         return cliEngine.getConfigForFile(filePath);
675     }
676
677     /**
678      * Checks if a given path is ignored by ESLint.
679      * @param {string} filePath The path of the file to check.
680      * @returns {Promise<boolean>} Whether or not the given path is ignored.
681      */
682     async isPathIgnored(filePath) {
683         if (!isNonEmptyString(filePath)) {
684             throw new Error("'filePath' must be a non-empty string");
685         }
686         const { cliEngine } = privateMembersMap.get(this);
687
688         return cliEngine.isPathIgnored(filePath);
689     }
690 }
691
692 //------------------------------------------------------------------------------
693 // Public Interface
694 //------------------------------------------------------------------------------
695
696 module.exports = {
697     ESLint,
698
699     /**
700      * Get the private class members of a given ESLint instance for tests.
701      * @param {ESLint} instance The ESLint instance to get.
702      * @returns {ESLintPrivateMembers} The instance's private class members.
703      */
704     getESLintPrivateMembers(instance) {
705         return privateMembersMap.get(instance);
706     }
707 };