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