update socials section
This commit is contained in:
		
							
								
								
									
										54
									
								
								node_modules/eslint/lib/api.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										54
									
								
								node_modules/eslint/lib/api.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,54 @@ | ||||
| /** | ||||
|  * @fileoverview Expose out ESLint and CLI to require. | ||||
|  * @author Ian Christian Myers | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Requirements | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| const { ESLint, FlatESLint } = require("./eslint"); | ||||
| const { shouldUseFlatConfig } = require("./eslint/flat-eslint"); | ||||
| const { Linter } = require("./linter"); | ||||
| const { RuleTester } = require("./rule-tester"); | ||||
| const { SourceCode } = require("./source-code"); | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Functions | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Loads the correct ESLint constructor given the options. | ||||
|  * @param {Object} [options] The options object | ||||
|  * @param {boolean} [options.useFlatConfig] Whether or not to use a flat config | ||||
|  * @param {string} [options.cwd] The current working directory | ||||
|  * @returns {Promise<ESLint|LegacyESLint>} The ESLint constructor | ||||
|  */ | ||||
| async function loadESLint({ useFlatConfig, cwd = process.cwd() } = {}) { | ||||
|  | ||||
|     /* | ||||
|      * Note: The v9.x version of this function doesn't have a cwd option | ||||
|      * because it's not used. It's only used in the v8.x version of this | ||||
|      * function. | ||||
|      */ | ||||
|  | ||||
|     const shouldESLintUseFlatConfig = typeof useFlatConfig === "boolean" | ||||
|         ? useFlatConfig | ||||
|         : await shouldUseFlatConfig({ cwd }); | ||||
|  | ||||
|     return shouldESLintUseFlatConfig ? FlatESLint : ESLint; | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Exports | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| module.exports = { | ||||
|     Linter, | ||||
|     loadESLint, | ||||
|     ESLint, | ||||
|     RuleTester, | ||||
|     SourceCode | ||||
| }; | ||||
							
								
								
									
										1078
									
								
								node_modules/eslint/lib/cli-engine/cli-engine.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1078
									
								
								node_modules/eslint/lib/cli-engine/cli-engine.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										547
									
								
								node_modules/eslint/lib/cli-engine/file-enumerator.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										547
									
								
								node_modules/eslint/lib/cli-engine/file-enumerator.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,547 @@ | ||||
| /** | ||||
|  * @fileoverview `FileEnumerator` class. | ||||
|  * | ||||
|  * `FileEnumerator` class has two responsibilities: | ||||
|  * | ||||
|  * 1. Find target files by processing glob patterns. | ||||
|  * 2. Tie each target file and appropriate configuration. | ||||
|  * | ||||
|  * It provides a method: | ||||
|  * | ||||
|  * - `iterateFiles(patterns)` | ||||
|  *     Iterate files which are matched by given patterns together with the | ||||
|  *     corresponded configuration. This is for `CLIEngine#executeOnFiles()`. | ||||
|  *     While iterating files, it loads the configuration file of each directory | ||||
|  *     before iterate files on the directory, so we can use the configuration | ||||
|  *     files to determine target files. | ||||
|  * | ||||
|  * @example | ||||
|  * const enumerator = new FileEnumerator(); | ||||
|  * const linter = new Linter(); | ||||
|  * | ||||
|  * for (const { config, filePath } of enumerator.iterateFiles(["*.js"])) { | ||||
|  *     const code = fs.readFileSync(filePath, "utf8"); | ||||
|  *     const messages = linter.verify(code, config, filePath); | ||||
|  * | ||||
|  *     console.log(messages); | ||||
|  * } | ||||
|  * | ||||
|  * @author Toru Nagashima <https://github.com/mysticatea> | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const fs = require("fs"); | ||||
| const path = require("path"); | ||||
| const getGlobParent = require("glob-parent"); | ||||
| const isGlob = require("is-glob"); | ||||
| const escapeRegExp = require("escape-string-regexp"); | ||||
| const { Minimatch } = require("minimatch"); | ||||
|  | ||||
| const { | ||||
|     Legacy: { | ||||
|         IgnorePattern, | ||||
|         CascadingConfigArrayFactory | ||||
|     } | ||||
| } = require("@eslint/eslintrc"); | ||||
| const debug = require("debug")("eslint:file-enumerator"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const minimatchOpts = { dot: true, matchBase: true }; | ||||
| const dotfilesPattern = /(?:(?:^\.)|(?:[/\\]\.))[^/\\.].*/u; | ||||
| const NONE = 0; | ||||
| const IGNORED_SILENTLY = 1; | ||||
| const IGNORED = 2; | ||||
|  | ||||
| // For VSCode intellisense | ||||
| /** @typedef {ReturnType<CascadingConfigArrayFactory.getConfigArrayForFile>} ConfigArray */ | ||||
|  | ||||
| /** | ||||
|  * @typedef {Object} FileEnumeratorOptions | ||||
|  * @property {CascadingConfigArrayFactory} [configArrayFactory] The factory for config arrays. | ||||
|  * @property {string} [cwd] The base directory to start lookup. | ||||
|  * @property {string[]} [extensions] The extensions to match files for directory patterns. | ||||
|  * @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. | ||||
|  * @property {boolean} [ignore] The flag to check ignored files. | ||||
|  * @property {string[]} [rulePaths] The value of `--rulesdir` option. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * @typedef {Object} FileAndConfig | ||||
|  * @property {string} filePath The path to a target file. | ||||
|  * @property {ConfigArray} config The config entries of that file. | ||||
|  * @property {boolean} ignored If `true` then this file should be ignored and warned because it was directly specified. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * @typedef {Object} FileEntry | ||||
|  * @property {string} filePath The path to a target file. | ||||
|  * @property {ConfigArray} config The config entries of that file. | ||||
|  * @property {NONE|IGNORED_SILENTLY|IGNORED} flag The flag. | ||||
|  * - `NONE` means the file is a target file. | ||||
|  * - `IGNORED_SILENTLY` means the file should be ignored silently. | ||||
|  * - `IGNORED` means the file should be ignored and warned because it was directly specified. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * @typedef {Object} FileEnumeratorInternalSlots | ||||
|  * @property {CascadingConfigArrayFactory} configArrayFactory The factory for config arrays. | ||||
|  * @property {string} cwd The base directory to start lookup. | ||||
|  * @property {RegExp|null} extensionRegExp The RegExp to test if a string ends with specific file extensions. | ||||
|  * @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. | ||||
|  * @property {boolean} ignoreFlag The flag to check ignored files. | ||||
|  * @property {(filePath:string, dot:boolean) => boolean} defaultIgnores The default predicate function to ignore files. | ||||
|  */ | ||||
|  | ||||
| /** @type {WeakMap<FileEnumerator, FileEnumeratorInternalSlots>} */ | ||||
| const internalSlotsMap = new WeakMap(); | ||||
|  | ||||
| /** | ||||
|  * Check if a string is a glob pattern or not. | ||||
|  * @param {string} pattern A glob pattern. | ||||
|  * @returns {boolean} `true` if the string is a glob pattern. | ||||
|  */ | ||||
| function isGlobPattern(pattern) { | ||||
|     return isGlob(path.sep === "\\" ? pattern.replace(/\\/gu, "/") : pattern); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Get stats of a given path. | ||||
|  * @param {string} filePath The path to target file. | ||||
|  * @throws {Error} As may be thrown by `fs.statSync`. | ||||
|  * @returns {fs.Stats|null} The stats. | ||||
|  * @private | ||||
|  */ | ||||
| function statSafeSync(filePath) { | ||||
|     try { | ||||
|         return fs.statSync(filePath); | ||||
|     } catch (error) { | ||||
|  | ||||
|         /* c8 ignore next */ | ||||
|         if (error.code !== "ENOENT") { | ||||
|             throw error; | ||||
|         } | ||||
|         return null; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Get filenames in a given path to a directory. | ||||
|  * @param {string} directoryPath The path to target directory. | ||||
|  * @throws {Error} As may be thrown by `fs.readdirSync`. | ||||
|  * @returns {import("fs").Dirent[]} The filenames. | ||||
|  * @private | ||||
|  */ | ||||
| function readdirSafeSync(directoryPath) { | ||||
|     try { | ||||
|         return fs.readdirSync(directoryPath, { withFileTypes: true }); | ||||
|     } catch (error) { | ||||
|  | ||||
|         /* c8 ignore next */ | ||||
|         if (error.code !== "ENOENT") { | ||||
|             throw error; | ||||
|         } | ||||
|         return []; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Create a `RegExp` object to detect extensions. | ||||
|  * @param {string[] | null} extensions The extensions to create. | ||||
|  * @returns {RegExp | null} The created `RegExp` object or null. | ||||
|  */ | ||||
| function createExtensionRegExp(extensions) { | ||||
|     if (extensions) { | ||||
|         const normalizedExts = extensions.map(ext => escapeRegExp( | ||||
|             ext.startsWith(".") | ||||
|                 ? ext.slice(1) | ||||
|                 : ext | ||||
|         )); | ||||
|  | ||||
|         return new RegExp( | ||||
|             `.\\.(?:${normalizedExts.join("|")})$`, | ||||
|             "u" | ||||
|         ); | ||||
|     } | ||||
|     return null; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The error type when no files match a glob. | ||||
|  */ | ||||
| class NoFilesFoundError extends Error { | ||||
|  | ||||
|     /** | ||||
|      * @param {string} pattern The glob pattern which was not found. | ||||
|      * @param {boolean} globDisabled If `true` then the pattern was a glob pattern, but glob was disabled. | ||||
|      */ | ||||
|     constructor(pattern, globDisabled) { | ||||
|         super(`No files matching '${pattern}' were found${globDisabled ? " (glob was disabled)" : ""}.`); | ||||
|         this.messageTemplate = "file-not-found"; | ||||
|         this.messageData = { pattern, globDisabled }; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The error type when there are files matched by a glob, but all of them have been ignored. | ||||
|  */ | ||||
| class AllFilesIgnoredError extends Error { | ||||
|  | ||||
|     /** | ||||
|      * @param {string} pattern The glob pattern which was not found. | ||||
|      */ | ||||
|     constructor(pattern) { | ||||
|         super(`All files matched by '${pattern}' are ignored.`); | ||||
|         this.messageTemplate = "all-files-ignored"; | ||||
|         this.messageData = { pattern }; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * This class provides the functionality that enumerates every file which is | ||||
|  * matched by given glob patterns and that configuration. | ||||
|  */ | ||||
| class FileEnumerator { | ||||
|  | ||||
|     /** | ||||
|      * Initialize this enumerator. | ||||
|      * @param {FileEnumeratorOptions} options The options. | ||||
|      */ | ||||
|     constructor({ | ||||
|         cwd = process.cwd(), | ||||
|         configArrayFactory = new CascadingConfigArrayFactory({ | ||||
|             cwd, | ||||
|             getEslintRecommendedConfig: () => require("@eslint/js").configs.recommended, | ||||
|             getEslintAllConfig: () => require("@eslint/js").configs.all | ||||
|         }), | ||||
|         extensions = null, | ||||
|         globInputPaths = true, | ||||
|         errorOnUnmatchedPattern = true, | ||||
|         ignore = true | ||||
|     } = {}) { | ||||
|         internalSlotsMap.set(this, { | ||||
|             configArrayFactory, | ||||
|             cwd, | ||||
|             defaultIgnores: IgnorePattern.createDefaultIgnore(cwd), | ||||
|             extensionRegExp: createExtensionRegExp(extensions), | ||||
|             globInputPaths, | ||||
|             errorOnUnmatchedPattern, | ||||
|             ignoreFlag: ignore | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check if a given file is target or not. | ||||
|      * @param {string} filePath The path to a candidate file. | ||||
|      * @param {ConfigArray} [providedConfig] Optional. The configuration for the file. | ||||
|      * @returns {boolean} `true` if the file is a target. | ||||
|      */ | ||||
|     isTargetPath(filePath, providedConfig) { | ||||
|         const { | ||||
|             configArrayFactory, | ||||
|             extensionRegExp | ||||
|         } = internalSlotsMap.get(this); | ||||
|  | ||||
|         // If `--ext` option is present, use it. | ||||
|         if (extensionRegExp) { | ||||
|             return extensionRegExp.test(filePath); | ||||
|         } | ||||
|  | ||||
|         // `.js` file is target by default. | ||||
|         if (filePath.endsWith(".js")) { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         // use `overrides[].files` to check additional targets. | ||||
|         const config = | ||||
|             providedConfig || | ||||
|             configArrayFactory.getConfigArrayForFile( | ||||
|                 filePath, | ||||
|                 { ignoreNotFoundError: true } | ||||
|             ); | ||||
|  | ||||
|         return config.isAdditionalTargetPath(filePath); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Iterate files which are matched by given glob patterns. | ||||
|      * @param {string|string[]} patternOrPatterns The glob patterns to iterate files. | ||||
|      * @throws {NoFilesFoundError|AllFilesIgnoredError} On an unmatched pattern. | ||||
|      * @returns {IterableIterator<FileAndConfig>} The found files. | ||||
|      */ | ||||
|     *iterateFiles(patternOrPatterns) { | ||||
|         const { globInputPaths, errorOnUnmatchedPattern } = internalSlotsMap.get(this); | ||||
|         const patterns = Array.isArray(patternOrPatterns) | ||||
|             ? patternOrPatterns | ||||
|             : [patternOrPatterns]; | ||||
|  | ||||
|         debug("Start to iterate files: %o", patterns); | ||||
|  | ||||
|         // The set of paths to remove duplicate. | ||||
|         const set = new Set(); | ||||
|  | ||||
|         for (const pattern of patterns) { | ||||
|             let foundRegardlessOfIgnored = false; | ||||
|             let found = false; | ||||
|  | ||||
|             // Skip empty string. | ||||
|             if (!pattern) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // Iterate files of this pattern. | ||||
|             for (const { config, filePath, flag } of this._iterateFiles(pattern)) { | ||||
|                 foundRegardlessOfIgnored = true; | ||||
|                 if (flag === IGNORED_SILENTLY) { | ||||
|                     continue; | ||||
|                 } | ||||
|                 found = true; | ||||
|  | ||||
|                 // Remove duplicate paths while yielding paths. | ||||
|                 if (!set.has(filePath)) { | ||||
|                     set.add(filePath); | ||||
|                     yield { | ||||
|                         config, | ||||
|                         filePath, | ||||
|                         ignored: flag === IGNORED | ||||
|                     }; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Raise an error if any files were not found. | ||||
|             if (errorOnUnmatchedPattern) { | ||||
|                 if (!foundRegardlessOfIgnored) { | ||||
|                     throw new NoFilesFoundError( | ||||
|                         pattern, | ||||
|                         !globInputPaths && isGlob(pattern) | ||||
|                     ); | ||||
|                 } | ||||
|                 if (!found) { | ||||
|                     throw new AllFilesIgnoredError(pattern); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         debug(`Complete iterating files: ${JSON.stringify(patterns)}`); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Iterate files which are matched by a given glob pattern. | ||||
|      * @param {string} pattern The glob pattern to iterate files. | ||||
|      * @returns {IterableIterator<FileEntry>} The found files. | ||||
|      */ | ||||
|     _iterateFiles(pattern) { | ||||
|         const { cwd, globInputPaths } = internalSlotsMap.get(this); | ||||
|         const absolutePath = path.resolve(cwd, pattern); | ||||
|         const isDot = dotfilesPattern.test(pattern); | ||||
|         const stat = statSafeSync(absolutePath); | ||||
|  | ||||
|         if (stat && stat.isDirectory()) { | ||||
|             return this._iterateFilesWithDirectory(absolutePath, isDot); | ||||
|         } | ||||
|         if (stat && stat.isFile()) { | ||||
|             return this._iterateFilesWithFile(absolutePath); | ||||
|         } | ||||
|         if (globInputPaths && isGlobPattern(pattern)) { | ||||
|             return this._iterateFilesWithGlob(pattern, isDot); | ||||
|         } | ||||
|  | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Iterate a file which is matched by a given path. | ||||
|      * @param {string} filePath The path to the target file. | ||||
|      * @returns {IterableIterator<FileEntry>} The found files. | ||||
|      * @private | ||||
|      */ | ||||
|     _iterateFilesWithFile(filePath) { | ||||
|         debug(`File: ${filePath}`); | ||||
|  | ||||
|         const { configArrayFactory } = internalSlotsMap.get(this); | ||||
|         const config = configArrayFactory.getConfigArrayForFile(filePath); | ||||
|         const ignored = this._isIgnoredFile(filePath, { config, direct: true }); | ||||
|         const flag = ignored ? IGNORED : NONE; | ||||
|  | ||||
|         return [{ config, filePath, flag }]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Iterate files in a given path. | ||||
|      * @param {string} directoryPath The path to the target directory. | ||||
|      * @param {boolean} dotfiles If `true` then it doesn't skip dot files by default. | ||||
|      * @returns {IterableIterator<FileEntry>} The found files. | ||||
|      * @private | ||||
|      */ | ||||
|     _iterateFilesWithDirectory(directoryPath, dotfiles) { | ||||
|         debug(`Directory: ${directoryPath}`); | ||||
|  | ||||
|         return this._iterateFilesRecursive( | ||||
|             directoryPath, | ||||
|             { dotfiles, recursive: true, selector: null } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Iterate files which are matched by a given glob pattern. | ||||
|      * @param {string} pattern The glob pattern to iterate files. | ||||
|      * @param {boolean} dotfiles If `true` then it doesn't skip dot files by default. | ||||
|      * @returns {IterableIterator<FileEntry>} The found files. | ||||
|      * @private | ||||
|      */ | ||||
|     _iterateFilesWithGlob(pattern, dotfiles) { | ||||
|         debug(`Glob: ${pattern}`); | ||||
|  | ||||
|         const { cwd } = internalSlotsMap.get(this); | ||||
|         const directoryPath = path.resolve(cwd, getGlobParent(pattern)); | ||||
|         const absolutePath = path.resolve(cwd, pattern); | ||||
|         const globPart = absolutePath.slice(directoryPath.length + 1); | ||||
|  | ||||
|         /* | ||||
|          * recursive if there are `**` or path separators in the glob part. | ||||
|          * Otherwise, patterns such as `src/*.js`, it doesn't need recursive. | ||||
|          */ | ||||
|         const recursive = /\*\*|\/|\\/u.test(globPart); | ||||
|         const selector = new Minimatch(absolutePath, minimatchOpts); | ||||
|  | ||||
|         debug(`recursive? ${recursive}`); | ||||
|  | ||||
|         return this._iterateFilesRecursive( | ||||
|             directoryPath, | ||||
|             { dotfiles, recursive, selector } | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Iterate files in a given path. | ||||
|      * @param {string} directoryPath The path to the target directory. | ||||
|      * @param {Object} options The options to iterate files. | ||||
|      * @param {boolean} [options.dotfiles] If `true` then it doesn't skip dot files by default. | ||||
|      * @param {boolean} [options.recursive] If `true` then it dives into sub directories. | ||||
|      * @param {InstanceType<Minimatch>} [options.selector] The matcher to choose files. | ||||
|      * @returns {IterableIterator<FileEntry>} The found files. | ||||
|      * @private | ||||
|      */ | ||||
|     *_iterateFilesRecursive(directoryPath, options) { | ||||
|         debug(`Enter the directory: ${directoryPath}`); | ||||
|         const { configArrayFactory } = internalSlotsMap.get(this); | ||||
|  | ||||
|         /** @type {ConfigArray|null} */ | ||||
|         let config = null; | ||||
|  | ||||
|         // Enumerate the files of this directory. | ||||
|         for (const entry of readdirSafeSync(directoryPath)) { | ||||
|             const filePath = path.join(directoryPath, entry.name); | ||||
|             const fileInfo = entry.isSymbolicLink() ? statSafeSync(filePath) : entry; | ||||
|  | ||||
|             if (!fileInfo) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // Check if the file is matched. | ||||
|             if (fileInfo.isFile()) { | ||||
|                 if (!config) { | ||||
|                     config = configArrayFactory.getConfigArrayForFile( | ||||
|                         filePath, | ||||
|  | ||||
|                         /* | ||||
|                          * We must ignore `ConfigurationNotFoundError` at this | ||||
|                          * point because we don't know if target files exist in | ||||
|                          * this directory. | ||||
|                          */ | ||||
|                         { ignoreNotFoundError: true } | ||||
|                     ); | ||||
|                 } | ||||
|                 const matched = options.selector | ||||
|  | ||||
|                     // Started with a glob pattern; choose by the pattern. | ||||
|                     ? options.selector.match(filePath) | ||||
|  | ||||
|                     // Started with a directory path; choose by file extensions. | ||||
|                     : this.isTargetPath(filePath, config); | ||||
|  | ||||
|                 if (matched) { | ||||
|                     const ignored = this._isIgnoredFile(filePath, { ...options, config }); | ||||
|                     const flag = ignored ? IGNORED_SILENTLY : NONE; | ||||
|  | ||||
|                     debug(`Yield: ${entry.name}${ignored ? " but ignored" : ""}`); | ||||
|                     yield { | ||||
|                         config: configArrayFactory.getConfigArrayForFile(filePath), | ||||
|                         filePath, | ||||
|                         flag | ||||
|                     }; | ||||
|                 } else { | ||||
|                     debug(`Didn't match: ${entry.name}`); | ||||
|                 } | ||||
|  | ||||
|             // Dive into the sub directory. | ||||
|             } else if (options.recursive && fileInfo.isDirectory()) { | ||||
|                 if (!config) { | ||||
|                     config = configArrayFactory.getConfigArrayForFile( | ||||
|                         filePath, | ||||
|                         { ignoreNotFoundError: true } | ||||
|                     ); | ||||
|                 } | ||||
|                 const ignored = this._isIgnoredFile( | ||||
|                     filePath + path.sep, | ||||
|                     { ...options, config } | ||||
|                 ); | ||||
|  | ||||
|                 if (!ignored) { | ||||
|                     yield* this._iterateFilesRecursive(filePath, options); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         debug(`Leave the directory: ${directoryPath}`); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Check if a given file should be ignored. | ||||
|      * @param {string} filePath The path to a file to check. | ||||
|      * @param {Object} options Options | ||||
|      * @param {ConfigArray} [options.config] The config for this file. | ||||
|      * @param {boolean} [options.dotfiles] If `true` then this is not ignore dot files by default. | ||||
|      * @param {boolean} [options.direct] If `true` then this is a direct specified file. | ||||
|      * @returns {boolean} `true` if the file should be ignored. | ||||
|      * @private | ||||
|      */ | ||||
|     _isIgnoredFile(filePath, { | ||||
|         config: providedConfig, | ||||
|         dotfiles = false, | ||||
|         direct = false | ||||
|     }) { | ||||
|         const { | ||||
|             configArrayFactory, | ||||
|             defaultIgnores, | ||||
|             ignoreFlag | ||||
|         } = internalSlotsMap.get(this); | ||||
|  | ||||
|         if (ignoreFlag) { | ||||
|             const config = | ||||
|                 providedConfig || | ||||
|                 configArrayFactory.getConfigArrayForFile( | ||||
|                     filePath, | ||||
|                     { ignoreNotFoundError: true } | ||||
|                 ); | ||||
|             const ignores = | ||||
|                 config.extractConfig(filePath).ignores || defaultIgnores; | ||||
|  | ||||
|             return ignores(filePath, dotfiles); | ||||
|         } | ||||
|  | ||||
|         return !direct && defaultIgnores(filePath, dotfiles); | ||||
|     } | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = { FileEnumerator }; | ||||
							
								
								
									
										60
									
								
								node_modules/eslint/lib/cli-engine/formatters/checkstyle.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								node_modules/eslint/lib/cli-engine/formatters/checkstyle.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| /** | ||||
|  * @fileoverview CheckStyle XML reporter | ||||
|  * @author Ian Christian Myers | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| const xmlEscape = require("../xml-escape"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helper Functions | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Returns the severity of warning or error | ||||
|  * @param {Object} message message object to examine | ||||
|  * @returns {string} severity level | ||||
|  * @private | ||||
|  */ | ||||
| function getMessageType(message) { | ||||
|     if (message.fatal || message.severity === 2) { | ||||
|         return "error"; | ||||
|     } | ||||
|     return "warning"; | ||||
|  | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = function(results) { | ||||
|  | ||||
|     let output = ""; | ||||
|  | ||||
|     output += "<?xml version=\"1.0\" encoding=\"utf-8\"?>"; | ||||
|     output += "<checkstyle version=\"4.3\">"; | ||||
|  | ||||
|     results.forEach(result => { | ||||
|         const messages = result.messages; | ||||
|  | ||||
|         output += `<file name="${xmlEscape(result.filePath)}">`; | ||||
|  | ||||
|         messages.forEach(message => { | ||||
|             output += [ | ||||
|                 `<error line="${xmlEscape(message.line || 0)}"`, | ||||
|                 `column="${xmlEscape(message.column || 0)}"`, | ||||
|                 `severity="${xmlEscape(getMessageType(message))}"`, | ||||
|                 `message="${xmlEscape(message.message)}${message.ruleId ? ` (${message.ruleId})` : ""}"`, | ||||
|                 `source="${message.ruleId ? xmlEscape(`eslint.rules.${message.ruleId}`) : ""}" />` | ||||
|             ].join(" "); | ||||
|         }); | ||||
|  | ||||
|         output += "</file>"; | ||||
|  | ||||
|     }); | ||||
|  | ||||
|     output += "</checkstyle>"; | ||||
|  | ||||
|     return output; | ||||
| }; | ||||
							
								
								
									
										60
									
								
								node_modules/eslint/lib/cli-engine/formatters/compact.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										60
									
								
								node_modules/eslint/lib/cli-engine/formatters/compact.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,60 @@ | ||||
| /** | ||||
|  * @fileoverview Compact reporter | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helper Functions | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Returns the severity of warning or error | ||||
|  * @param {Object} message message object to examine | ||||
|  * @returns {string} severity level | ||||
|  * @private | ||||
|  */ | ||||
| function getMessageType(message) { | ||||
|     if (message.fatal || message.severity === 2) { | ||||
|         return "Error"; | ||||
|     } | ||||
|     return "Warning"; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = function(results) { | ||||
|  | ||||
|     let output = "", | ||||
|         total = 0; | ||||
|  | ||||
|     results.forEach(result => { | ||||
|  | ||||
|         const messages = result.messages; | ||||
|  | ||||
|         total += messages.length; | ||||
|  | ||||
|         messages.forEach(message => { | ||||
|  | ||||
|             output += `${result.filePath}: `; | ||||
|             output += `line ${message.line || 0}`; | ||||
|             output += `, col ${message.column || 0}`; | ||||
|             output += `, ${getMessageType(message)}`; | ||||
|             output += ` - ${message.message}`; | ||||
|             output += message.ruleId ? ` (${message.ruleId})` : ""; | ||||
|             output += "\n"; | ||||
|  | ||||
|         }); | ||||
|  | ||||
|     }); | ||||
|  | ||||
|     if (total > 0) { | ||||
|         output += `\n${total} problem${total !== 1 ? "s" : ""}`; | ||||
|     } | ||||
|  | ||||
|     return output; | ||||
| }; | ||||
							
								
								
									
										46
									
								
								node_modules/eslint/lib/cli-engine/formatters/formatters-meta.json
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								node_modules/eslint/lib/cli-engine/formatters/formatters-meta.json
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| [ | ||||
|     { | ||||
|         "name": "checkstyle", | ||||
|         "description": "Outputs results to the [Checkstyle](https://checkstyle.sourceforge.io/) format." | ||||
|     }, | ||||
|     { | ||||
|         "name": "compact", | ||||
|         "description": "Human-readable output format. Mimics the default output of JSHint." | ||||
|     }, | ||||
|     { | ||||
|         "name": "html", | ||||
|         "description": "Outputs results to HTML. The `html` formatter is useful for visual presentation in the browser." | ||||
|     }, | ||||
|     { | ||||
|         "name": "jslint-xml", | ||||
|         "description": "Outputs results to format compatible with the [JSLint Jenkins plugin](https://plugins.jenkins.io/jslint/)." | ||||
|     }, | ||||
|     { | ||||
|         "name": "json-with-metadata", | ||||
|         "description": "Outputs JSON-serialized results. The `json-with-metadata` provides the same linting results as the [`json`](#json) formatter with additional metadata about the rules applied. The linting results are included in the `results` property and the rules metadata is included in the `metadata` property.\n\nAlternatively, you can use the [ESLint Node.js API](../../integrate/nodejs-api) to programmatically use ESLint." | ||||
|     }, | ||||
|     { | ||||
|         "name": "json", | ||||
|         "description": "Outputs JSON-serialized results. The `json` formatter is useful when you want to programmatically work with the CLI's linting results.\n\nAlternatively, you can use the [ESLint Node.js API](../../integrate/nodejs-api) to programmatically use ESLint." | ||||
|     }, | ||||
|     { | ||||
|         "name": "junit", | ||||
|         "description": "Outputs results to format compatible with the [JUnit Jenkins plugin](https://plugins.jenkins.io/junit/)." | ||||
|     }, | ||||
|     { | ||||
|         "name": "stylish", | ||||
|         "description": "Human-readable output format. This is the default formatter." | ||||
|     }, | ||||
|     { | ||||
|         "name": "tap", | ||||
|         "description": "Outputs results to the [Test Anything Protocol (TAP)](https://testanything.org/) specification format." | ||||
|     }, | ||||
|     { | ||||
|         "name": "unix", | ||||
|         "description": "Outputs results to a format similar to many commands in UNIX-like systems. Parsable with tools such as [grep](https://www.gnu.org/software/grep/manual/grep.html), [sed](https://www.gnu.org/software/sed/manual/sed.html), and [awk](https://www.gnu.org/software/gawk/manual/gawk.html)." | ||||
|     }, | ||||
|     { | ||||
|         "name": "visualstudio", | ||||
|         "description": "Outputs results to format compatible with the integrated terminal of the [Visual Studio](https://visualstudio.microsoft.com/) IDE. When using Visual Studio, you can click on the linting results in the integrated terminal to go to the issue in the source code." | ||||
|     } | ||||
| ] | ||||
							
								
								
									
										351
									
								
								node_modules/eslint/lib/cli-engine/formatters/html.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										351
									
								
								node_modules/eslint/lib/cli-engine/formatters/html.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,351 @@ | ||||
| /** | ||||
|  * @fileoverview HTML reporter | ||||
|  * @author Julian Laval | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const encodeHTML = (function() { | ||||
|     const encodeHTMLRules = { | ||||
|         "&": "&", | ||||
|         "<": "<", | ||||
|         ">": ">", | ||||
|         '"': """, | ||||
|         "'": "'" | ||||
|     }; | ||||
|     const matchHTML = /[&<>"']/ug; | ||||
|  | ||||
|     return function(code) { | ||||
|         return code | ||||
|             ? code.toString().replace(matchHTML, m => encodeHTMLRules[m] || m) | ||||
|             : ""; | ||||
|     }; | ||||
| }()); | ||||
|  | ||||
| /** | ||||
|  * Get the final HTML document. | ||||
|  * @param {Object} it data for the document. | ||||
|  * @returns {string} HTML document. | ||||
|  */ | ||||
| function pageTemplate(it) { | ||||
|     const { reportColor, reportSummary, date, results } = it; | ||||
|  | ||||
|     return ` | ||||
| <!DOCTYPE html> | ||||
| <html> | ||||
|     <head> | ||||
|         <meta charset="UTF-8"> | ||||
|         <title>ESLint Report</title> | ||||
|         <link rel="icon" type="image/png" sizes="any" href="data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAACAAAAAgCAYAAABzenr0AAAACXBIWXMAAAHaAAAB2gGFomX7AAAAGXRFWHRTb2Z0d2FyZQB3d3cuaW5rc2NhcGUub3Jnm+48GgAABD1JREFUWMPFl11sk2UUx3/nbYtjxS1MF7MLMTECMgSTtSSyrQkLhAj7UBPnDSEGoxegGzMwojhXVpmTAA5iYpSoMQa8GBhFOrMFk03buei6yRAlcmOM0SEmU9d90b19jxcM1o5+sGnsc/e+z/l6ztf/HFFVMnns6QieeOCHBePGsHM+wrOtvLG2C4WRVDSSygNV7sCjlspxwDnPB44aols/DXk+mbMBmx/6OseITF1CuOtfevkPh2Uu+/jbdX8lujSScRlT5r7/QDlAfsRmfzmpnkQ/H3H13gf6bBrBn1uqK8WylgEnU8eZmk1repbfchJG1TyKyIKEwuBHFd3lD3naY3O1siiwXsVoBV2VgM1ht/QQUJk2ByqKghsQziYQ8ifKgexIXmuyzC4r67Y7R+xPAfuB/Nn3Cpva+0s7khpQVtZtd4bt51BWxtBYAiciprG7c7D4SixzU9PYalDL6110Ifb/w8W9eY7JqFeFHbO8fPGyLHwwFHJNJTSgwtVTB9oaw9BlQ+tO93vOxypoaQnfEYlI43SeCHDC4TDq9+51/h5fxr33q0ZfV9g04wat9Q943rjJgCp3952W2i8Bi6eDvdsfKj0cK/DYMRyXL4/sUJUmIHd2zYMezsvLaamp4WpcWN3BXSiHpuMwbGbZlnZ8tXY4rgosy+G7oRwQ0cAsd28YGgqfU5UjCZQDLALxDg+Hv/P5Rqvj4hwrS8izXzWb4spwc1GgENFnkpWRzxeuB+ssUHgLdb9UVdt8vpGdKQpze7n7y1U3DBChNRUuqOo9c+0+qpKKxyZqtAIYla7gY4JszAAQri93BSsMRZoyBcUC+w3Q3AyOA4sNhAOZ0q7Iq0b2vUNvK5zPgP+/H8+Zetdoa6uOikhdGurxebwvJY8Iz3V1rTMNAH+opEuQj5KTT/qA1yC+wyUjBm12OidaUtCcPNNX2h0Hx2JG69VulANZAJZJwfU7rzd/FHixuXniTdM0m4GtSQT7bTartqEh9yfImUEzkwKZmTwmo5a5JwkYBfcDL01/RkR5y8iWhtPBknB8ZxwtU9UjwOrrKCeizzc25nTGg1F/turEHoU9wMLpDvWKf8DTmNCAKnd/tqUTF4ElMXJ+A5rWDJS+41WsGWzALhJ+ErBWrLj9g+pqojHxlXJX8HGUg0BsR/x1yhxf3jm4cSzpQFLp6tmi6PEE7g1ZhtZ91ufpSZUAFa6gC+UoQslNaSmypT1U8mHKiUgEKS8KfgF4EpYunFI16tsHin+OG0LcgQK7yj7g6cSzpva2D3hKVNG0Y3mVO1BkqfSlmJrHBQ4uvM12gJHc6ETW8HZVfMRmXvyxxNC1Z/o839zyXlDuCr4nsC11J+MXueaVJWn6yPv+/pJtc9oLTNN4AeTvNGByd3rlhE2x9s5pLwDoHCy+grDzWmOZ95lUtLYj5Bma126Y8eX0/zj/ADxGyViSg4BXAAAAAElFTkSuQmCC"> | ||||
|         <link rel="icon" type="image/svg+xml" href="data:image/svg+xml;base64,PHN2ZyB2aWV3Qm94PScwIDAgMjk0LjgyNSAyNTguOTgyJyB4bWxucz0naHR0cDovL3d3dy53My5vcmcvMjAwMC9zdmcnPg0KPHBhdGggZmlsbD0nIzgwODBGMicgZD0nTTk3LjAyMSw5OS4wMTZsNDguNDMyLTI3Ljk2MmMxLjIxMi0wLjcsMi43MDYtMC43LDMuOTE4LDBsNDguNDMzLDI3Ljk2MiBjMS4yMTEsMC43LDEuOTU5LDEuOTkzLDEuOTU5LDMuMzkzdjU1LjkyNGMwLDEuMzk5LTAuNzQ4LDIuNjkzLTEuOTU5LDMuMzk0bC00OC40MzMsMjcuOTYyYy0xLjIxMiwwLjctMi43MDYsMC43LTMuOTE4LDAgbC00OC40MzItMjcuOTYyYy0xLjIxMi0wLjctMS45NTktMS45OTQtMS45NTktMy4zOTR2LTU1LjkyNEM5NS4wNjMsMTAxLjAwOSw5NS44MSw5OS43MTYsOTcuMDIxLDk5LjAxNicvPg0KPHBhdGggZmlsbD0nIzRCMzJDMycgZD0nTTI3My4zMzYsMTI0LjQ4OEwyMTUuNDY5LDIzLjgxNmMtMi4xMDItMy42NC01Ljk4NS02LjMyNS0xMC4xODgtNi4zMjVIODkuNTQ1IGMtNC4yMDQsMC04LjA4OCwyLjY4NS0xMC4xOSw2LjMyNWwtNTcuODY3LDEwMC40NWMtMi4xMDIsMy42NDEtMi4xMDIsOC4yMzYsMCwxMS44NzdsNTcuODY3LDk5Ljg0NyBjMi4xMDIsMy42NCw1Ljk4Niw1LjUwMSwxMC4xOSw1LjUwMWgxMTUuNzM1YzQuMjAzLDAsOC4wODctMS44MDUsMTAuMTg4LTUuNDQ2bDU3Ljg2Ny0xMDAuMDEgQzI3NS40MzksMTMyLjM5NiwyNzUuNDM5LDEyOC4xMjgsMjczLjMzNiwxMjQuNDg4IE0yMjUuNDE5LDE3Mi44OThjMCwxLjQ4LTAuODkxLDIuODQ5LTIuMTc0LDMuNTlsLTczLjcxLDQyLjUyNyBjLTEuMjgyLDAuNzQtMi44ODgsMC43NC00LjE3LDBsLTczLjc2Ny00Mi41MjdjLTEuMjgyLTAuNzQxLTIuMTc5LTIuMTA5LTIuMTc5LTMuNTlWODcuODQzYzAtMS40ODEsMC44ODQtMi44NDksMi4xNjctMy41OSBsNzMuNzA3LTQyLjUyN2MxLjI4Mi0wLjc0MSwyLjg4Ni0wLjc0MSw0LjE2OCwwbDczLjc3Miw0Mi41MjdjMS4yODMsMC43NDEsMi4xODYsMi4xMDksMi4xODYsMy41OVYxNzIuODk4eicvPg0KPC9zdmc+"> | ||||
|         <style> | ||||
|             body { | ||||
|                 font-family: Arial, "Helvetica Neue", Helvetica, sans-serif; | ||||
|                 font-size: 16px; | ||||
|                 font-weight: normal; | ||||
|                 margin: 0; | ||||
|                 padding: 0; | ||||
|                 color: #333; | ||||
|             } | ||||
|  | ||||
|             #overview { | ||||
|                 padding: 20px 30px; | ||||
|             } | ||||
|  | ||||
|             td, | ||||
|             th { | ||||
|                 padding: 5px 10px; | ||||
|             } | ||||
|  | ||||
|             h1 { | ||||
|                 margin: 0; | ||||
|             } | ||||
|  | ||||
|             table { | ||||
|                 margin: 30px; | ||||
|                 width: calc(100% - 60px); | ||||
|                 max-width: 1000px; | ||||
|                 border-radius: 5px; | ||||
|                 border: 1px solid #ddd; | ||||
|                 border-spacing: 0; | ||||
|             } | ||||
|  | ||||
|             th { | ||||
|                 font-weight: 400; | ||||
|                 font-size: medium; | ||||
|                 text-align: left; | ||||
|                 cursor: pointer; | ||||
|             } | ||||
|  | ||||
|             td.clr-1, | ||||
|             td.clr-2, | ||||
|             th span { | ||||
|                 font-weight: 700; | ||||
|             } | ||||
|  | ||||
|             th span { | ||||
|                 float: right; | ||||
|                 margin-left: 20px; | ||||
|             } | ||||
|  | ||||
|             th span::after { | ||||
|                 content: ""; | ||||
|                 clear: both; | ||||
|                 display: block; | ||||
|             } | ||||
|  | ||||
|             tr:last-child td { | ||||
|                 border-bottom: none; | ||||
|             } | ||||
|  | ||||
|             tr td:first-child, | ||||
|             tr td:last-child { | ||||
|                 color: #9da0a4; | ||||
|             } | ||||
|  | ||||
|             #overview.bg-0, | ||||
|             tr.bg-0 th { | ||||
|                 color: #468847; | ||||
|                 background: #dff0d8; | ||||
|                 border-bottom: 1px solid #d6e9c6; | ||||
|             } | ||||
|  | ||||
|             #overview.bg-1, | ||||
|             tr.bg-1 th { | ||||
|                 color: #f0ad4e; | ||||
|                 background: #fcf8e3; | ||||
|                 border-bottom: 1px solid #fbeed5; | ||||
|             } | ||||
|  | ||||
|             #overview.bg-2, | ||||
|             tr.bg-2 th { | ||||
|                 color: #b94a48; | ||||
|                 background: #f2dede; | ||||
|                 border-bottom: 1px solid #eed3d7; | ||||
|             } | ||||
|  | ||||
|             td { | ||||
|                 border-bottom: 1px solid #ddd; | ||||
|             } | ||||
|  | ||||
|             td.clr-1 { | ||||
|                 color: #f0ad4e; | ||||
|             } | ||||
|  | ||||
|             td.clr-2 { | ||||
|                 color: #b94a48; | ||||
|             } | ||||
|  | ||||
|             td a { | ||||
|                 color: #3a33d1; | ||||
|                 text-decoration: none; | ||||
|             } | ||||
|  | ||||
|             td a:hover { | ||||
|                 color: #272296; | ||||
|                 text-decoration: underline; | ||||
|             } | ||||
|         </style> | ||||
|     </head> | ||||
|     <body> | ||||
|         <div id="overview" class="bg-${reportColor}"> | ||||
|             <h1>ESLint Report</h1> | ||||
|             <div> | ||||
|                 <span>${reportSummary}</span> - Generated on ${date} | ||||
|             </div> | ||||
|         </div> | ||||
|         <table> | ||||
|             <tbody> | ||||
|                 ${results} | ||||
|             </tbody> | ||||
|         </table> | ||||
|         <script type="text/javascript"> | ||||
|             var groups = document.querySelectorAll("tr[data-group]"); | ||||
|             for (i = 0; i < groups.length; i++) { | ||||
|                 groups[i].addEventListener("click", function() { | ||||
|                     var inGroup = document.getElementsByClassName(this.getAttribute("data-group")); | ||||
|                     this.innerHTML = (this.innerHTML.indexOf("+") > -1) ? this.innerHTML.replace("+", "-") : this.innerHTML.replace("-", "+"); | ||||
|                     for (var j = 0; j < inGroup.length; j++) { | ||||
|                         inGroup[j].style.display = (inGroup[j].style.display !== "none") ? "none" : "table-row"; | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         </script> | ||||
|     </body> | ||||
| </html> | ||||
| `.trimStart(); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Given a word and a count, append an s if count is not one. | ||||
|  * @param {string} word A word in its singular form. | ||||
|  * @param {int} count A number controlling whether word should be pluralized. | ||||
|  * @returns {string} The original word with an s on the end if count is not one. | ||||
|  */ | ||||
| function pluralize(word, count) { | ||||
|     return (count === 1 ? word : `${word}s`); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Renders text along the template of x problems (x errors, x warnings) | ||||
|  * @param {string} totalErrors Total errors | ||||
|  * @param {string} totalWarnings Total warnings | ||||
|  * @returns {string} The formatted string, pluralized where necessary | ||||
|  */ | ||||
| function renderSummary(totalErrors, totalWarnings) { | ||||
|     const totalProblems = totalErrors + totalWarnings; | ||||
|     let renderedText = `${totalProblems} ${pluralize("problem", totalProblems)}`; | ||||
|  | ||||
|     if (totalProblems !== 0) { | ||||
|         renderedText += ` (${totalErrors} ${pluralize("error", totalErrors)}, ${totalWarnings} ${pluralize("warning", totalWarnings)})`; | ||||
|     } | ||||
|     return renderedText; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Get the color based on whether there are errors/warnings... | ||||
|  * @param {string} totalErrors Total errors | ||||
|  * @param {string} totalWarnings Total warnings | ||||
|  * @returns {int} The color code (0 = green, 1 = yellow, 2 = red) | ||||
|  */ | ||||
| function renderColor(totalErrors, totalWarnings) { | ||||
|     if (totalErrors !== 0) { | ||||
|         return 2; | ||||
|     } | ||||
|     if (totalWarnings !== 0) { | ||||
|         return 1; | ||||
|     } | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Get HTML (table row) describing a single message. | ||||
|  * @param {Object} it data for the message. | ||||
|  * @returns {string} HTML (table row) describing the message. | ||||
|  */ | ||||
| function messageTemplate(it) { | ||||
|     const { | ||||
|         parentIndex, | ||||
|         lineNumber, | ||||
|         columnNumber, | ||||
|         severityNumber, | ||||
|         severityName, | ||||
|         message, | ||||
|         ruleUrl, | ||||
|         ruleId | ||||
|     } = it; | ||||
|  | ||||
|     return ` | ||||
| <tr style="display: none;" class="f-${parentIndex}"> | ||||
|     <td>${lineNumber}:${columnNumber}</td> | ||||
|     <td class="clr-${severityNumber}">${severityName}</td> | ||||
|     <td>${encodeHTML(message)}</td> | ||||
|     <td> | ||||
|         <a href="${ruleUrl ? ruleUrl : ""}" target="_blank" rel="noopener noreferrer">${ruleId ? ruleId : ""}</a> | ||||
|     </td> | ||||
| </tr> | ||||
| `.trimStart(); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Get HTML (table rows) describing the messages. | ||||
|  * @param {Array} messages Messages. | ||||
|  * @param {int} parentIndex Index of the parent HTML row. | ||||
|  * @param {Object} rulesMeta Dictionary containing metadata for each rule executed by the analysis. | ||||
|  * @returns {string} HTML (table rows) describing the messages. | ||||
|  */ | ||||
| function renderMessages(messages, parentIndex, rulesMeta) { | ||||
|  | ||||
|     /** | ||||
|      * Get HTML (table row) describing a message. | ||||
|      * @param {Object} message Message. | ||||
|      * @returns {string} HTML (table row) describing a message. | ||||
|      */ | ||||
|     return messages.map(message => { | ||||
|         const lineNumber = message.line || 0; | ||||
|         const columnNumber = message.column || 0; | ||||
|         let ruleUrl; | ||||
|  | ||||
|         if (rulesMeta) { | ||||
|             const meta = rulesMeta[message.ruleId]; | ||||
|  | ||||
|             if (meta && meta.docs && meta.docs.url) { | ||||
|                 ruleUrl = meta.docs.url; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return messageTemplate({ | ||||
|             parentIndex, | ||||
|             lineNumber, | ||||
|             columnNumber, | ||||
|             severityNumber: message.severity, | ||||
|             severityName: message.severity === 1 ? "Warning" : "Error", | ||||
|             message: message.message, | ||||
|             ruleId: message.ruleId, | ||||
|             ruleUrl | ||||
|         }); | ||||
|     }).join("\n"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Get HTML (table row) describing the result for a single file. | ||||
|  * @param {Object} it data for the file. | ||||
|  * @returns {string} HTML (table row) describing the result for the file. | ||||
|  */ | ||||
| function resultTemplate(it) { | ||||
|     const { color, index, filePath, summary } = it; | ||||
|  | ||||
|     return ` | ||||
| <tr class="bg-${color}" data-group="f-${index}"> | ||||
|     <th colspan="4"> | ||||
|         [+] ${encodeHTML(filePath)} | ||||
|         <span>${encodeHTML(summary)}</span> | ||||
|     </th> | ||||
| </tr> | ||||
| `.trimStart(); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Render the results. | ||||
|  * @param {Array} results Test results. | ||||
|  * @param {Object} rulesMeta Dictionary containing metadata for each rule executed by the analysis. | ||||
|  * @returns {string} HTML string describing the results. | ||||
|  */ | ||||
| function renderResults(results, rulesMeta) { | ||||
|     return results.map((result, index) => resultTemplate({ | ||||
|         index, | ||||
|         color: renderColor(result.errorCount, result.warningCount), | ||||
|         filePath: result.filePath, | ||||
|         summary: renderSummary(result.errorCount, result.warningCount) | ||||
|     }) + renderMessages(result.messages, index, rulesMeta)).join("\n"); | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = function(results, data) { | ||||
|     let totalErrors, | ||||
|         totalWarnings; | ||||
|  | ||||
|     const metaData = data ? data.rulesMeta : {}; | ||||
|  | ||||
|     totalErrors = 0; | ||||
|     totalWarnings = 0; | ||||
|  | ||||
|     // Iterate over results to get totals | ||||
|     results.forEach(result => { | ||||
|         totalErrors += result.errorCount; | ||||
|         totalWarnings += result.warningCount; | ||||
|     }); | ||||
|  | ||||
|     return pageTemplate({ | ||||
|         date: new Date(), | ||||
|         reportColor: renderColor(totalErrors, totalWarnings), | ||||
|         reportSummary: renderSummary(totalErrors, totalWarnings), | ||||
|         results: renderResults(results, metaData) | ||||
|     }); | ||||
| }; | ||||
							
								
								
									
										41
									
								
								node_modules/eslint/lib/cli-engine/formatters/jslint-xml.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										41
									
								
								node_modules/eslint/lib/cli-engine/formatters/jslint-xml.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,41 @@ | ||||
| /** | ||||
|  * @fileoverview JSLint XML reporter | ||||
|  * @author Ian Christian Myers | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| const xmlEscape = require("../xml-escape"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = function(results) { | ||||
|  | ||||
|     let output = ""; | ||||
|  | ||||
|     output += "<?xml version=\"1.0\" encoding=\"utf-8\"?>"; | ||||
|     output += "<jslint>"; | ||||
|  | ||||
|     results.forEach(result => { | ||||
|         const messages = result.messages; | ||||
|  | ||||
|         output += `<file name="${result.filePath}">`; | ||||
|  | ||||
|         messages.forEach(message => { | ||||
|             output += [ | ||||
|                 `<issue line="${message.line}"`, | ||||
|                 `char="${message.column}"`, | ||||
|                 `evidence="${xmlEscape(message.source || "")}"`, | ||||
|                 `reason="${xmlEscape(message.message || "")}${message.ruleId ? ` (${message.ruleId})` : ""}" />` | ||||
|             ].join(" "); | ||||
|         }); | ||||
|  | ||||
|         output += "</file>"; | ||||
|  | ||||
|     }); | ||||
|  | ||||
|     output += "</jslint>"; | ||||
|  | ||||
|     return output; | ||||
| }; | ||||
							
								
								
									
										16
									
								
								node_modules/eslint/lib/cli-engine/formatters/json-with-metadata.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										16
									
								
								node_modules/eslint/lib/cli-engine/formatters/json-with-metadata.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,16 @@ | ||||
| /** | ||||
|  * @fileoverview JSON reporter, including rules metadata | ||||
|  * @author Chris Meyer | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = function(results, data) { | ||||
|     return JSON.stringify({ | ||||
|         results, | ||||
|         metadata: data | ||||
|     }); | ||||
| }; | ||||
							
								
								
									
										13
									
								
								node_modules/eslint/lib/cli-engine/formatters/json.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								node_modules/eslint/lib/cli-engine/formatters/json.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| /** | ||||
|  * @fileoverview JSON reporter | ||||
|  * @author Burak Yigit Kaya aka BYK | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = function(results) { | ||||
|     return JSON.stringify(results); | ||||
| }; | ||||
							
								
								
									
										82
									
								
								node_modules/eslint/lib/cli-engine/formatters/junit.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										82
									
								
								node_modules/eslint/lib/cli-engine/formatters/junit.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,82 @@ | ||||
| /** | ||||
|  * @fileoverview jUnit Reporter | ||||
|  * @author Jamund Ferguson | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| const xmlEscape = require("../xml-escape"); | ||||
| const path = require("path"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helper Functions | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Returns the severity of warning or error | ||||
|  * @param {Object} message message object to examine | ||||
|  * @returns {string} severity level | ||||
|  * @private | ||||
|  */ | ||||
| function getMessageType(message) { | ||||
|     if (message.fatal || message.severity === 2) { | ||||
|         return "Error"; | ||||
|     } | ||||
|     return "Warning"; | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Returns a full file path without extension | ||||
|  * @param {string} filePath input file path | ||||
|  * @returns {string} file path without extension | ||||
|  * @private | ||||
|  */ | ||||
| function pathWithoutExt(filePath) { | ||||
|     return path.join(path.dirname(filePath), path.basename(filePath, path.extname(filePath))); | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = function(results) { | ||||
|  | ||||
|     let output = ""; | ||||
|  | ||||
|     output += "<?xml version=\"1.0\" encoding=\"utf-8\"?>\n"; | ||||
|     output += "<testsuites>\n"; | ||||
|  | ||||
|     results.forEach(result => { | ||||
|  | ||||
|         const messages = result.messages; | ||||
|         const classname = pathWithoutExt(result.filePath); | ||||
|  | ||||
|         if (messages.length > 0) { | ||||
|             output += `<testsuite package="org.eslint" time="0" tests="${messages.length}" errors="${messages.length}" name="${result.filePath}">\n`; | ||||
|             messages.forEach(message => { | ||||
|                 const type = message.fatal ? "error" : "failure"; | ||||
|  | ||||
|                 output += `<testcase time="0" name="org.eslint.${message.ruleId || "unknown"}" classname="${classname}">`; | ||||
|                 output += `<${type} message="${xmlEscape(message.message || "")}">`; | ||||
|                 output += "<![CDATA["; | ||||
|                 output += `line ${message.line || 0}, col `; | ||||
|                 output += `${message.column || 0}, ${getMessageType(message)}`; | ||||
|                 output += ` - ${xmlEscape(message.message || "")}`; | ||||
|                 output += (message.ruleId ? ` (${message.ruleId})` : ""); | ||||
|                 output += "]]>"; | ||||
|                 output += `</${type}>`; | ||||
|                 output += "</testcase>\n"; | ||||
|             }); | ||||
|             output += "</testsuite>\n"; | ||||
|         } else { | ||||
|             output += `<testsuite package="org.eslint" time="0" tests="1" errors="0" name="${result.filePath}">\n`; | ||||
|             output += `<testcase time="0" name="${result.filePath}" classname="${classname}" />\n`; | ||||
|             output += "</testsuite>\n"; | ||||
|         } | ||||
|  | ||||
|     }); | ||||
|  | ||||
|     output += "</testsuites>\n"; | ||||
|  | ||||
|     return output; | ||||
| }; | ||||
							
								
								
									
										101
									
								
								node_modules/eslint/lib/cli-engine/formatters/stylish.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								node_modules/eslint/lib/cli-engine/formatters/stylish.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| /** | ||||
|  * @fileoverview Stylish reporter | ||||
|  * @author Sindre Sorhus | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| const chalk = require("chalk"), | ||||
|     stripAnsi = require("strip-ansi"), | ||||
|     table = require("text-table"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Given a word and a count, append an s if count is not one. | ||||
|  * @param {string} word A word in its singular form. | ||||
|  * @param {int} count A number controlling whether word should be pluralized. | ||||
|  * @returns {string} The original word with an s on the end if count is not one. | ||||
|  */ | ||||
| function pluralize(word, count) { | ||||
|     return (count === 1 ? word : `${word}s`); | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = function(results) { | ||||
|  | ||||
|     let output = "\n", | ||||
|         errorCount = 0, | ||||
|         warningCount = 0, | ||||
|         fixableErrorCount = 0, | ||||
|         fixableWarningCount = 0, | ||||
|         summaryColor = "yellow"; | ||||
|  | ||||
|     results.forEach(result => { | ||||
|         const messages = result.messages; | ||||
|  | ||||
|         if (messages.length === 0) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         errorCount += result.errorCount; | ||||
|         warningCount += result.warningCount; | ||||
|         fixableErrorCount += result.fixableErrorCount; | ||||
|         fixableWarningCount += result.fixableWarningCount; | ||||
|  | ||||
|         output += `${chalk.underline(result.filePath)}\n`; | ||||
|  | ||||
|         output += `${table( | ||||
|             messages.map(message => { | ||||
|                 let messageType; | ||||
|  | ||||
|                 if (message.fatal || message.severity === 2) { | ||||
|                     messageType = chalk.red("error"); | ||||
|                     summaryColor = "red"; | ||||
|                 } else { | ||||
|                     messageType = chalk.yellow("warning"); | ||||
|                 } | ||||
|  | ||||
|                 return [ | ||||
|                     "", | ||||
|                     message.line || 0, | ||||
|                     message.column || 0, | ||||
|                     messageType, | ||||
|                     message.message.replace(/([^ ])\.$/u, "$1"), | ||||
|                     chalk.dim(message.ruleId || "") | ||||
|                 ]; | ||||
|             }), | ||||
|             { | ||||
|                 align: ["", "r", "l"], | ||||
|                 stringLength(str) { | ||||
|                     return stripAnsi(str).length; | ||||
|                 } | ||||
|             } | ||||
|         ).split("\n").map(el => el.replace(/(\d+)\s+(\d+)/u, (m, p1, p2) => chalk.dim(`${p1}:${p2}`))).join("\n")}\n\n`; | ||||
|     }); | ||||
|  | ||||
|     const total = errorCount + warningCount; | ||||
|  | ||||
|     if (total > 0) { | ||||
|         output += chalk[summaryColor].bold([ | ||||
|             "\u2716 ", total, pluralize(" problem", total), | ||||
|             " (", errorCount, pluralize(" error", errorCount), ", ", | ||||
|             warningCount, pluralize(" warning", warningCount), ")\n" | ||||
|         ].join("")); | ||||
|  | ||||
|         if (fixableErrorCount > 0 || fixableWarningCount > 0) { | ||||
|             output += chalk[summaryColor].bold([ | ||||
|                 "  ", fixableErrorCount, pluralize(" error", fixableErrorCount), " and ", | ||||
|                 fixableWarningCount, pluralize(" warning", fixableWarningCount), | ||||
|                 " potentially fixable with the `--fix` option.\n" | ||||
|             ].join("")); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Resets output color, for prevent change on top level | ||||
|     return total > 0 ? chalk.reset(output) : ""; | ||||
| }; | ||||
							
								
								
									
										95
									
								
								node_modules/eslint/lib/cli-engine/formatters/tap.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										95
									
								
								node_modules/eslint/lib/cli-engine/formatters/tap.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,95 @@ | ||||
| /** | ||||
|  * @fileoverview TAP reporter | ||||
|  * @author Jonathan Kingston | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| const yaml = require("js-yaml"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helper Functions | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Returns a canonical error level string based upon the error message passed in. | ||||
|  * @param {Object} message Individual error message provided by eslint | ||||
|  * @returns {string} Error level string | ||||
|  */ | ||||
| function getMessageType(message) { | ||||
|     if (message.fatal || message.severity === 2) { | ||||
|         return "error"; | ||||
|     } | ||||
|     return "warning"; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Takes in a JavaScript object and outputs a TAP diagnostics string | ||||
|  * @param {Object} diagnostic JavaScript object to be embedded as YAML into output. | ||||
|  * @returns {string} diagnostics string with YAML embedded - TAP version 13 compliant | ||||
|  */ | ||||
| function outputDiagnostics(diagnostic) { | ||||
|     const prefix = "  "; | ||||
|     let output = `${prefix}---\n`; | ||||
|  | ||||
|     output += prefix + yaml.dump(diagnostic).split("\n").join(`\n${prefix}`); | ||||
|     output += "...\n"; | ||||
|     return output; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = function(results) { | ||||
|     let output = `TAP version 13\n1..${results.length}\n`; | ||||
|  | ||||
|     results.forEach((result, id) => { | ||||
|         const messages = result.messages; | ||||
|         let testResult = "ok"; | ||||
|         let diagnostics = {}; | ||||
|  | ||||
|         if (messages.length > 0) { | ||||
|             messages.forEach(message => { | ||||
|                 const severity = getMessageType(message); | ||||
|                 const diagnostic = { | ||||
|                     message: message.message, | ||||
|                     severity, | ||||
|                     data: { | ||||
|                         line: message.line || 0, | ||||
|                         column: message.column || 0, | ||||
|                         ruleId: message.ruleId || "" | ||||
|                     } | ||||
|                 }; | ||||
|  | ||||
|                 // This ensures a warning message is not flagged as error | ||||
|                 if (severity === "error") { | ||||
|                     testResult = "not ok"; | ||||
|                 } | ||||
|  | ||||
|                 /* | ||||
|                  * If we have multiple messages place them under a messages key | ||||
|                  * The first error will be logged as message key | ||||
|                  * This is to adhere to TAP 13 loosely defined specification of having a message key | ||||
|                  */ | ||||
|                 if ("message" in diagnostics) { | ||||
|                     if (typeof diagnostics.messages === "undefined") { | ||||
|                         diagnostics.messages = []; | ||||
|                     } | ||||
|                     diagnostics.messages.push(diagnostic); | ||||
|                 } else { | ||||
|                     diagnostics = diagnostic; | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         output += `${testResult} ${id + 1} - ${result.filePath}\n`; | ||||
|  | ||||
|         // If we have an error include diagnostics | ||||
|         if (messages.length > 0) { | ||||
|             output += outputDiagnostics(diagnostics); | ||||
|         } | ||||
|  | ||||
|     }); | ||||
|  | ||||
|     return output; | ||||
| }; | ||||
							
								
								
									
										58
									
								
								node_modules/eslint/lib/cli-engine/formatters/unix.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										58
									
								
								node_modules/eslint/lib/cli-engine/formatters/unix.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,58 @@ | ||||
| /** | ||||
|  * @fileoverview unix-style formatter. | ||||
|  * @author oshi-shinobu | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helper Functions | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Returns a canonical error level string based upon the error message passed in. | ||||
|  * @param {Object} message Individual error message provided by eslint | ||||
|  * @returns {string} Error level string | ||||
|  */ | ||||
| function getMessageType(message) { | ||||
|     if (message.fatal || message.severity === 2) { | ||||
|         return "Error"; | ||||
|     } | ||||
|     return "Warning"; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = function(results) { | ||||
|  | ||||
|     let output = "", | ||||
|         total = 0; | ||||
|  | ||||
|     results.forEach(result => { | ||||
|  | ||||
|         const messages = result.messages; | ||||
|  | ||||
|         total += messages.length; | ||||
|  | ||||
|         messages.forEach(message => { | ||||
|  | ||||
|             output += `${result.filePath}:`; | ||||
|             output += `${message.line || 0}:`; | ||||
|             output += `${message.column || 0}:`; | ||||
|             output += ` ${message.message} `; | ||||
|             output += `[${getMessageType(message)}${message.ruleId ? `/${message.ruleId}` : ""}]`; | ||||
|             output += "\n"; | ||||
|  | ||||
|         }); | ||||
|  | ||||
|     }); | ||||
|  | ||||
|     if (total > 0) { | ||||
|         output += `\n${total} problem${total !== 1 ? "s" : ""}`; | ||||
|     } | ||||
|  | ||||
|     return output; | ||||
| }; | ||||
							
								
								
									
										63
									
								
								node_modules/eslint/lib/cli-engine/formatters/visualstudio.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										63
									
								
								node_modules/eslint/lib/cli-engine/formatters/visualstudio.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,63 @@ | ||||
| /** | ||||
|  * @fileoverview Visual Studio compatible formatter | ||||
|  * @author Ronald Pijnacker | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helper Functions | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Returns the severity of warning or error | ||||
|  * @param {Object} message message object to examine | ||||
|  * @returns {string} severity level | ||||
|  * @private | ||||
|  */ | ||||
| function getMessageType(message) { | ||||
|     if (message.fatal || message.severity === 2) { | ||||
|         return "error"; | ||||
|     } | ||||
|     return "warning"; | ||||
|  | ||||
| } | ||||
|  | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = function(results) { | ||||
|  | ||||
|     let output = "", | ||||
|         total = 0; | ||||
|  | ||||
|     results.forEach(result => { | ||||
|  | ||||
|         const messages = result.messages; | ||||
|  | ||||
|         total += messages.length; | ||||
|  | ||||
|         messages.forEach(message => { | ||||
|  | ||||
|             output += result.filePath; | ||||
|             output += `(${message.line || 0}`; | ||||
|             output += message.column ? `,${message.column}` : ""; | ||||
|             output += `): ${getMessageType(message)}`; | ||||
|             output += message.ruleId ? ` ${message.ruleId}` : ""; | ||||
|             output += ` : ${message.message}`; | ||||
|             output += "\n"; | ||||
|  | ||||
|         }); | ||||
|  | ||||
|     }); | ||||
|  | ||||
|     if (total === 0) { | ||||
|         output += "no problems"; | ||||
|     } else { | ||||
|         output += `\n${total} problem${total !== 1 ? "s" : ""}`; | ||||
|     } | ||||
|  | ||||
|     return output; | ||||
| }; | ||||
							
								
								
									
										35
									
								
								node_modules/eslint/lib/cli-engine/hash.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										35
									
								
								node_modules/eslint/lib/cli-engine/hash.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,35 @@ | ||||
| /** | ||||
|  * @fileoverview Defining the hashing function in one place. | ||||
|  * @author Michael Ficarra | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const murmur = require("imurmurhash"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Private | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * hash the given string | ||||
|  * @param {string} str the string to hash | ||||
|  * @returns {string} the hash | ||||
|  */ | ||||
| function hash(str) { | ||||
|     return murmur(str).result().toString(36); | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = hash; | ||||
							
								
								
									
										7
									
								
								node_modules/eslint/lib/cli-engine/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										7
									
								
								node_modules/eslint/lib/cli-engine/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,7 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const { CLIEngine } = require("./cli-engine"); | ||||
|  | ||||
| module.exports = { | ||||
|     CLIEngine | ||||
| }; | ||||
							
								
								
									
										203
									
								
								node_modules/eslint/lib/cli-engine/lint-result-cache.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								node_modules/eslint/lib/cli-engine/lint-result-cache.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | ||||
| /** | ||||
|  * @fileoverview Utility for caching lint results. | ||||
|  * @author Kevin Partington | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Requirements | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| const assert = require("assert"); | ||||
| const fs = require("fs"); | ||||
| const fileEntryCache = require("file-entry-cache"); | ||||
| const stringify = require("json-stable-stringify-without-jsonify"); | ||||
| const pkg = require("../../package.json"); | ||||
| const hash = require("./hash"); | ||||
|  | ||||
| const debug = require("debug")("eslint:lint-result-cache"); | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Helpers | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| const configHashCache = new WeakMap(); | ||||
| const nodeVersion = process && process.version; | ||||
|  | ||||
| const validCacheStrategies = ["metadata", "content"]; | ||||
| const invalidCacheStrategyErrorMessage = `Cache strategy must be one of: ${validCacheStrategies | ||||
|     .map(strategy => `"${strategy}"`) | ||||
|     .join(", ")}`; | ||||
|  | ||||
| /** | ||||
|  * Tests whether a provided cacheStrategy is valid | ||||
|  * @param {string} cacheStrategy The cache strategy to use | ||||
|  * @returns {boolean} true if `cacheStrategy` is one of `validCacheStrategies`; false otherwise | ||||
|  */ | ||||
| function isValidCacheStrategy(cacheStrategy) { | ||||
|     return ( | ||||
|         validCacheStrategies.includes(cacheStrategy) | ||||
|     ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Calculates the hash of the config | ||||
|  * @param {ConfigArray} config The config. | ||||
|  * @returns {string} The hash of the config | ||||
|  */ | ||||
| function hashOfConfigFor(config) { | ||||
|     if (!configHashCache.has(config)) { | ||||
|         configHashCache.set(config, hash(`${pkg.version}_${nodeVersion}_${stringify(config)}`)); | ||||
|     } | ||||
|  | ||||
|     return configHashCache.get(config); | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Public Interface | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Lint result cache. This wraps around the file-entry-cache module, | ||||
|  * transparently removing properties that are difficult or expensive to | ||||
|  * serialize and adding them back in on retrieval. | ||||
|  */ | ||||
| class LintResultCache { | ||||
|  | ||||
|     /** | ||||
|      * Creates a new LintResultCache instance. | ||||
|      * @param {string} cacheFileLocation The cache file location. | ||||
|      * @param {"metadata" | "content"} cacheStrategy The cache strategy to use. | ||||
|      */ | ||||
|     constructor(cacheFileLocation, cacheStrategy) { | ||||
|         assert(cacheFileLocation, "Cache file location is required"); | ||||
|         assert(cacheStrategy, "Cache strategy is required"); | ||||
|         assert( | ||||
|             isValidCacheStrategy(cacheStrategy), | ||||
|             invalidCacheStrategyErrorMessage | ||||
|         ); | ||||
|  | ||||
|         debug(`Caching results to ${cacheFileLocation}`); | ||||
|  | ||||
|         const useChecksum = cacheStrategy === "content"; | ||||
|  | ||||
|         debug( | ||||
|             `Using "${cacheStrategy}" strategy to detect changes` | ||||
|         ); | ||||
|  | ||||
|         this.fileEntryCache = fileEntryCache.create( | ||||
|             cacheFileLocation, | ||||
|             void 0, | ||||
|             useChecksum | ||||
|         ); | ||||
|         this.cacheFileLocation = cacheFileLocation; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Retrieve cached lint results for a given file path, if present in the | ||||
|      * cache. If the file is present and has not been changed, rebuild any | ||||
|      * missing result information. | ||||
|      * @param {string} filePath The file for which to retrieve lint results. | ||||
|      * @param {ConfigArray} config The config of the file. | ||||
|      * @returns {Object|null} The rebuilt lint results, or null if the file is | ||||
|      *   changed or not in the filesystem. | ||||
|      */ | ||||
|     getCachedLintResults(filePath, config) { | ||||
|  | ||||
|         /* | ||||
|          * Cached lint results are valid if and only if: | ||||
|          * 1. The file is present in the filesystem | ||||
|          * 2. The file has not changed since the time it was previously linted | ||||
|          * 3. The ESLint configuration has not changed since the time the file | ||||
|          *    was previously linted | ||||
|          * If any of these are not true, we will not reuse the lint results. | ||||
|          */ | ||||
|         const fileDescriptor = this.fileEntryCache.getFileDescriptor(filePath); | ||||
|         const hashOfConfig = hashOfConfigFor(config); | ||||
|         const changed = | ||||
|             fileDescriptor.changed || | ||||
|             fileDescriptor.meta.hashOfConfig !== hashOfConfig; | ||||
|  | ||||
|         if (fileDescriptor.notFound) { | ||||
|             debug(`File not found on the file system: ${filePath}`); | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         if (changed) { | ||||
|             debug(`Cache entry not found or no longer valid: ${filePath}`); | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         const cachedResults = fileDescriptor.meta.results; | ||||
|  | ||||
|         // Just in case, not sure if this can ever happen. | ||||
|         if (!cachedResults) { | ||||
|             return cachedResults; | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * Shallow clone the object to ensure that any properties added or modified afterwards | ||||
|          * will not be accidentally stored in the cache file when `reconcile()` is called. | ||||
|          * https://github.com/eslint/eslint/issues/13507 | ||||
|          * All intentional changes to the cache file must be done through `setCachedLintResults()`. | ||||
|          */ | ||||
|         const results = { ...cachedResults }; | ||||
|  | ||||
|         // If source is present but null, need to reread the file from the filesystem. | ||||
|         if (results.source === null) { | ||||
|             debug(`Rereading cached result source from filesystem: ${filePath}`); | ||||
|             results.source = fs.readFileSync(filePath, "utf-8"); | ||||
|         } | ||||
|  | ||||
|         return results; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Set the cached lint results for a given file path, after removing any | ||||
|      * information that will be both unnecessary and difficult to serialize. | ||||
|      * Avoids caching results with an "output" property (meaning fixes were | ||||
|      * applied), to prevent potentially incorrect results if fixes are not | ||||
|      * written to disk. | ||||
|      * @param {string} filePath The file for which to set lint results. | ||||
|      * @param {ConfigArray} config The config of the file. | ||||
|      * @param {Object} result The lint result to be set for the file. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     setCachedLintResults(filePath, config, result) { | ||||
|         if (result && Object.prototype.hasOwnProperty.call(result, "output")) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         const fileDescriptor = this.fileEntryCache.getFileDescriptor(filePath); | ||||
|  | ||||
|         if (fileDescriptor && !fileDescriptor.notFound) { | ||||
|             debug(`Updating cached result: ${filePath}`); | ||||
|  | ||||
|             // Serialize the result, except that we want to remove the file source if present. | ||||
|             const resultToSerialize = Object.assign({}, result); | ||||
|  | ||||
|             /* | ||||
|              * Set result.source to null. | ||||
|              * In `getCachedLintResults`, if source is explicitly null, we will | ||||
|              * read the file from the filesystem to set the value again. | ||||
|              */ | ||||
|             if (Object.prototype.hasOwnProperty.call(resultToSerialize, "source")) { | ||||
|                 resultToSerialize.source = null; | ||||
|             } | ||||
|  | ||||
|             fileDescriptor.meta.results = resultToSerialize; | ||||
|             fileDescriptor.meta.hashOfConfig = hashOfConfigFor(config); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Persists the in-memory cache to disk. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     reconcile() { | ||||
|         debug(`Persisting cached results: ${this.cacheFileLocation}`); | ||||
|         this.fileEntryCache.reconcile(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = LintResultCache; | ||||
							
								
								
									
										46
									
								
								node_modules/eslint/lib/cli-engine/load-rules.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								node_modules/eslint/lib/cli-engine/load-rules.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| /** | ||||
|  * @fileoverview Module for loading rules from files and directories. | ||||
|  * @author Michael Ficarra | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const fs = require("fs"), | ||||
|     path = require("path"); | ||||
|  | ||||
| const rulesDirCache = {}; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Load all rule modules from specified directory. | ||||
|  * @param {string} relativeRulesDir Path to rules directory, may be relative. | ||||
|  * @param {string} cwd Current working directory | ||||
|  * @returns {Object} Loaded rule modules. | ||||
|  */ | ||||
| module.exports = function(relativeRulesDir, cwd) { | ||||
|     const rulesDir = path.resolve(cwd, relativeRulesDir); | ||||
|  | ||||
|     // cache will help performance as IO operation are expensive | ||||
|     if (rulesDirCache[rulesDir]) { | ||||
|         return rulesDirCache[rulesDir]; | ||||
|     } | ||||
|  | ||||
|     const rules = Object.create(null); | ||||
|  | ||||
|     fs.readdirSync(rulesDir).forEach(file => { | ||||
|         if (path.extname(file) !== ".js") { | ||||
|             return; | ||||
|         } | ||||
|         rules[file.slice(0, -3)] = require(path.join(rulesDir, file)); | ||||
|     }); | ||||
|     rulesDirCache[rulesDir] = rules; | ||||
|  | ||||
|     return rules; | ||||
| }; | ||||
							
								
								
									
										34
									
								
								node_modules/eslint/lib/cli-engine/xml-escape.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										34
									
								
								node_modules/eslint/lib/cli-engine/xml-escape.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,34 @@ | ||||
| /** | ||||
|  * @fileoverview XML character escaper | ||||
|  * @author George Chung | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Returns the escaped value for a character | ||||
|  * @param {string} s string to examine | ||||
|  * @returns {string} severity level | ||||
|  * @private | ||||
|  */ | ||||
| module.exports = function(s) { | ||||
|     return (`${s}`).replace(/[<>&"'\x00-\x1F\x7F\u0080-\uFFFF]/gu, c => { // eslint-disable-line no-control-regex -- Converting controls to entities | ||||
|         switch (c) { | ||||
|             case "<": | ||||
|                 return "<"; | ||||
|             case ">": | ||||
|                 return ">"; | ||||
|             case "&": | ||||
|                 return "&"; | ||||
|             case "\"": | ||||
|                 return """; | ||||
|             case "'": | ||||
|                 return "'"; | ||||
|             default: | ||||
|                 return `&#${c.charCodeAt(0)};`; | ||||
|         } | ||||
|     }); | ||||
| }; | ||||
							
								
								
									
										471
									
								
								node_modules/eslint/lib/cli.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										471
									
								
								node_modules/eslint/lib/cli.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,471 @@ | ||||
| /** | ||||
|  * @fileoverview Main CLI object. | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| /* | ||||
|  * NOTE: The CLI object should *not* call process.exit() directly. It should only return | ||||
|  * exit codes. This allows other programs to use the CLI object and still control | ||||
|  * when the program exits. | ||||
|  */ | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const fs = require("fs"), | ||||
|     path = require("path"), | ||||
|     { promisify } = require("util"), | ||||
|     { ESLint } = require("./eslint"), | ||||
|     { FlatESLint, shouldUseFlatConfig } = require("./eslint/flat-eslint"), | ||||
|     createCLIOptions = require("./options"), | ||||
|     log = require("./shared/logging"), | ||||
|     RuntimeInfo = require("./shared/runtime-info"), | ||||
|     { normalizeSeverityToString } = require("./shared/severity"); | ||||
| const { Legacy: { naming } } = require("@eslint/eslintrc"); | ||||
| const { ModuleImporter } = require("@humanwhocodes/module-importer"); | ||||
|  | ||||
| const debug = require("debug")("eslint:cli"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Types | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @typedef {import("./eslint/eslint").ESLintOptions} ESLintOptions */ | ||||
| /** @typedef {import("./eslint/eslint").LintMessage} LintMessage */ | ||||
| /** @typedef {import("./eslint/eslint").LintResult} LintResult */ | ||||
| /** @typedef {import("./options").ParsedCLIOptions} ParsedCLIOptions */ | ||||
| /** @typedef {import("./shared/types").ResultsMeta} ResultsMeta */ | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const mkdir = promisify(fs.mkdir); | ||||
| const stat = promisify(fs.stat); | ||||
| const writeFile = promisify(fs.writeFile); | ||||
|  | ||||
| /** | ||||
|  * Predicate function for whether or not to apply fixes in quiet mode. | ||||
|  * If a message is a warning, do not apply a fix. | ||||
|  * @param {LintMessage} message The lint result. | ||||
|  * @returns {boolean} True if the lint message is an error (and thus should be | ||||
|  * autofixed), false otherwise. | ||||
|  */ | ||||
| function quietFixPredicate(message) { | ||||
|     return message.severity === 2; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Translates the CLI options into the options expected by the ESLint constructor. | ||||
|  * @param {ParsedCLIOptions} cliOptions The CLI options to translate. | ||||
|  * @param {"flat"|"eslintrc"} [configType="eslintrc"] The format of the | ||||
|  *      config to generate. | ||||
|  * @returns {Promise<ESLintOptions>} The options object for the ESLint constructor. | ||||
|  * @private | ||||
|  */ | ||||
| async function translateOptions({ | ||||
|     cache, | ||||
|     cacheFile, | ||||
|     cacheLocation, | ||||
|     cacheStrategy, | ||||
|     config, | ||||
|     configLookup, | ||||
|     env, | ||||
|     errorOnUnmatchedPattern, | ||||
|     eslintrc, | ||||
|     ext, | ||||
|     fix, | ||||
|     fixDryRun, | ||||
|     fixType, | ||||
|     global, | ||||
|     ignore, | ||||
|     ignorePath, | ||||
|     ignorePattern, | ||||
|     inlineConfig, | ||||
|     parser, | ||||
|     parserOptions, | ||||
|     plugin, | ||||
|     quiet, | ||||
|     reportUnusedDisableDirectives, | ||||
|     reportUnusedDisableDirectivesSeverity, | ||||
|     resolvePluginsRelativeTo, | ||||
|     rule, | ||||
|     rulesdir, | ||||
|     warnIgnored | ||||
| }, configType) { | ||||
|  | ||||
|     let overrideConfig, overrideConfigFile; | ||||
|     const importer = new ModuleImporter(); | ||||
|  | ||||
|     if (configType === "flat") { | ||||
|         overrideConfigFile = (typeof config === "string") ? config : !configLookup; | ||||
|         if (overrideConfigFile === false) { | ||||
|             overrideConfigFile = void 0; | ||||
|         } | ||||
|  | ||||
|         let globals = {}; | ||||
|  | ||||
|         if (global) { | ||||
|             globals = global.reduce((obj, name) => { | ||||
|                 if (name.endsWith(":true")) { | ||||
|                     obj[name.slice(0, -5)] = "writable"; | ||||
|                 } else { | ||||
|                     obj[name] = "readonly"; | ||||
|                 } | ||||
|                 return obj; | ||||
|             }, globals); | ||||
|         } | ||||
|  | ||||
|         overrideConfig = [{ | ||||
|             languageOptions: { | ||||
|                 globals, | ||||
|                 parserOptions: parserOptions || {} | ||||
|             }, | ||||
|             rules: rule ? rule : {} | ||||
|         }]; | ||||
|  | ||||
|         if (reportUnusedDisableDirectives || reportUnusedDisableDirectivesSeverity !== void 0) { | ||||
|             overrideConfig[0].linterOptions = { | ||||
|                 reportUnusedDisableDirectives: reportUnusedDisableDirectives | ||||
|                     ? "error" | ||||
|                     : normalizeSeverityToString(reportUnusedDisableDirectivesSeverity) | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         if (parser) { | ||||
|             overrideConfig[0].languageOptions.parser = await importer.import(parser); | ||||
|         } | ||||
|  | ||||
|         if (plugin) { | ||||
|             const plugins = {}; | ||||
|  | ||||
|             for (const pluginName of plugin) { | ||||
|  | ||||
|                 const shortName = naming.getShorthandName(pluginName, "eslint-plugin"); | ||||
|                 const longName = naming.normalizePackageName(pluginName, "eslint-plugin"); | ||||
|  | ||||
|                 plugins[shortName] = await importer.import(longName); | ||||
|             } | ||||
|  | ||||
|             overrideConfig[0].plugins = plugins; | ||||
|         } | ||||
|  | ||||
|     } else { | ||||
|         overrideConfigFile = config; | ||||
|  | ||||
|         overrideConfig = { | ||||
|             env: env && env.reduce((obj, name) => { | ||||
|                 obj[name] = true; | ||||
|                 return obj; | ||||
|             }, {}), | ||||
|             globals: global && global.reduce((obj, name) => { | ||||
|                 if (name.endsWith(":true")) { | ||||
|                     obj[name.slice(0, -5)] = "writable"; | ||||
|                 } else { | ||||
|                     obj[name] = "readonly"; | ||||
|                 } | ||||
|                 return obj; | ||||
|             }, {}), | ||||
|             ignorePatterns: ignorePattern, | ||||
|             parser, | ||||
|             parserOptions, | ||||
|             plugins: plugin, | ||||
|             rules: rule | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     const options = { | ||||
|         allowInlineConfig: inlineConfig, | ||||
|         cache, | ||||
|         cacheLocation: cacheLocation || cacheFile, | ||||
|         cacheStrategy, | ||||
|         errorOnUnmatchedPattern, | ||||
|         fix: (fix || fixDryRun) && (quiet ? quietFixPredicate : true), | ||||
|         fixTypes: fixType, | ||||
|         ignore, | ||||
|         overrideConfig, | ||||
|         overrideConfigFile | ||||
|     }; | ||||
|  | ||||
|     if (configType === "flat") { | ||||
|         options.ignorePatterns = ignorePattern; | ||||
|         options.warnIgnored = warnIgnored; | ||||
|     } else { | ||||
|         options.resolvePluginsRelativeTo = resolvePluginsRelativeTo; | ||||
|         options.rulePaths = rulesdir; | ||||
|         options.useEslintrc = eslintrc; | ||||
|         options.extensions = ext; | ||||
|         options.ignorePath = ignorePath; | ||||
|         if (reportUnusedDisableDirectives || reportUnusedDisableDirectivesSeverity !== void 0) { | ||||
|             options.reportUnusedDisableDirectives = reportUnusedDisableDirectives | ||||
|                 ? "error" | ||||
|                 : normalizeSeverityToString(reportUnusedDisableDirectivesSeverity); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return options; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Count error messages. | ||||
|  * @param {LintResult[]} results The lint results. | ||||
|  * @returns {{errorCount:number;fatalErrorCount:number,warningCount:number}} The number of error messages. | ||||
|  */ | ||||
| function countErrors(results) { | ||||
|     let errorCount = 0; | ||||
|     let fatalErrorCount = 0; | ||||
|     let warningCount = 0; | ||||
|  | ||||
|     for (const result of results) { | ||||
|         errorCount += result.errorCount; | ||||
|         fatalErrorCount += result.fatalErrorCount; | ||||
|         warningCount += result.warningCount; | ||||
|     } | ||||
|  | ||||
|     return { errorCount, fatalErrorCount, warningCount }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check if a given file path is a directory or not. | ||||
|  * @param {string} filePath The path to a file to check. | ||||
|  * @returns {Promise<boolean>} `true` if the given path is a directory. | ||||
|  */ | ||||
| async function isDirectory(filePath) { | ||||
|     try { | ||||
|         return (await stat(filePath)).isDirectory(); | ||||
|     } catch (error) { | ||||
|         if (error.code === "ENOENT" || error.code === "ENOTDIR") { | ||||
|             return false; | ||||
|         } | ||||
|         throw error; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Outputs the results of the linting. | ||||
|  * @param {ESLint} engine The ESLint instance to use. | ||||
|  * @param {LintResult[]} results The results to print. | ||||
|  * @param {string} format The name of the formatter to use or the path to the formatter. | ||||
|  * @param {string} outputFile The path for the output file. | ||||
|  * @param {ResultsMeta} resultsMeta Warning count and max threshold. | ||||
|  * @returns {Promise<boolean>} True if the printing succeeds, false if not. | ||||
|  * @private | ||||
|  */ | ||||
| async function printResults(engine, results, format, outputFile, resultsMeta) { | ||||
|     let formatter; | ||||
|  | ||||
|     try { | ||||
|         formatter = await engine.loadFormatter(format); | ||||
|     } catch (e) { | ||||
|         log.error(e.message); | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     const output = await formatter.format(results, resultsMeta); | ||||
|  | ||||
|     if (output) { | ||||
|         if (outputFile) { | ||||
|             const filePath = path.resolve(process.cwd(), outputFile); | ||||
|  | ||||
|             if (await isDirectory(filePath)) { | ||||
|                 log.error("Cannot write to output file path, it is a directory: %s", outputFile); | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             try { | ||||
|                 await mkdir(path.dirname(filePath), { recursive: true }); | ||||
|                 await writeFile(filePath, output); | ||||
|             } catch (ex) { | ||||
|                 log.error("There was a problem writing the output file:\n%s", ex); | ||||
|                 return false; | ||||
|             } | ||||
|         } else { | ||||
|             log.info(output); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Encapsulates all CLI behavior for eslint. Makes it easier to test as well as | ||||
|  * for other Node.js programs to effectively run the CLI. | ||||
|  */ | ||||
| const cli = { | ||||
|  | ||||
|     /** | ||||
|      * Executes the CLI based on an array of arguments that is passed in. | ||||
|      * @param {string|Array|Object} args The arguments to process. | ||||
|      * @param {string} [text] The text to lint (used for TTY). | ||||
|      * @param {boolean} [allowFlatConfig] Whether or not to allow flat config. | ||||
|      * @returns {Promise<number>} The exit code for the operation. | ||||
|      */ | ||||
|     async execute(args, text, allowFlatConfig) { | ||||
|         if (Array.isArray(args)) { | ||||
|             debug("CLI args: %o", args.slice(2)); | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * Before doing anything, we need to see if we are using a | ||||
|          * flat config file. If so, then we need to change the way command | ||||
|          * line args are parsed. This is temporary, and when we fully | ||||
|          * switch to flat config we can remove this logic. | ||||
|          */ | ||||
|  | ||||
|         const usingFlatConfig = allowFlatConfig && await shouldUseFlatConfig(); | ||||
|  | ||||
|         debug("Using flat config?", usingFlatConfig); | ||||
|  | ||||
|         const CLIOptions = createCLIOptions(usingFlatConfig); | ||||
|  | ||||
|         /** @type {ParsedCLIOptions} */ | ||||
|         let options; | ||||
|  | ||||
|         try { | ||||
|             options = CLIOptions.parse(args); | ||||
|         } catch (error) { | ||||
|             debug("Error parsing CLI options:", error.message); | ||||
|  | ||||
|             let errorMessage = error.message; | ||||
|  | ||||
|             if (usingFlatConfig) { | ||||
|                 errorMessage += "\nYou're using eslint.config.js, some command line flags are no longer available. Please see https://eslint.org/docs/latest/use/command-line-interface for details."; | ||||
|             } | ||||
|  | ||||
|             log.error(errorMessage); | ||||
|             return 2; | ||||
|         } | ||||
|  | ||||
|         const files = options._; | ||||
|         const useStdin = typeof text === "string"; | ||||
|  | ||||
|         if (options.help) { | ||||
|             log.info(CLIOptions.generateHelp()); | ||||
|             return 0; | ||||
|         } | ||||
|         if (options.version) { | ||||
|             log.info(RuntimeInfo.version()); | ||||
|             return 0; | ||||
|         } | ||||
|         if (options.envInfo) { | ||||
|             try { | ||||
|                 log.info(RuntimeInfo.environment()); | ||||
|                 return 0; | ||||
|             } catch (err) { | ||||
|                 debug("Error retrieving environment info"); | ||||
|                 log.error(err.message); | ||||
|                 return 2; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (options.printConfig) { | ||||
|             if (files.length) { | ||||
|                 log.error("The --print-config option must be used with exactly one file name."); | ||||
|                 return 2; | ||||
|             } | ||||
|             if (useStdin) { | ||||
|                 log.error("The --print-config option is not available for piped-in code."); | ||||
|                 return 2; | ||||
|             } | ||||
|  | ||||
|             const engine = usingFlatConfig | ||||
|                 ? new FlatESLint(await translateOptions(options, "flat")) | ||||
|                 : new ESLint(await translateOptions(options)); | ||||
|             const fileConfig = | ||||
|                 await engine.calculateConfigForFile(options.printConfig); | ||||
|  | ||||
|             log.info(JSON.stringify(fileConfig, null, "  ")); | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         debug(`Running on ${useStdin ? "text" : "files"}`); | ||||
|  | ||||
|         if (options.fix && options.fixDryRun) { | ||||
|             log.error("The --fix option and the --fix-dry-run option cannot be used together."); | ||||
|             return 2; | ||||
|         } | ||||
|         if (useStdin && options.fix) { | ||||
|             log.error("The --fix option is not available for piped-in code; use --fix-dry-run instead."); | ||||
|             return 2; | ||||
|         } | ||||
|         if (options.fixType && !options.fix && !options.fixDryRun) { | ||||
|             log.error("The --fix-type option requires either --fix or --fix-dry-run."); | ||||
|             return 2; | ||||
|         } | ||||
|  | ||||
|         if (options.reportUnusedDisableDirectives && options.reportUnusedDisableDirectivesSeverity !== void 0) { | ||||
|             log.error("The --report-unused-disable-directives option and the --report-unused-disable-directives-severity option cannot be used together."); | ||||
|             return 2; | ||||
|         } | ||||
|  | ||||
|         const ActiveESLint = usingFlatConfig ? FlatESLint : ESLint; | ||||
|  | ||||
|         const engine = new ActiveESLint(await translateOptions(options, usingFlatConfig ? "flat" : "eslintrc")); | ||||
|         let results; | ||||
|  | ||||
|         if (useStdin) { | ||||
|             results = await engine.lintText(text, { | ||||
|                 filePath: options.stdinFilename, | ||||
|  | ||||
|                 // flatConfig respects CLI flag and constructor warnIgnored, eslintrc forces true for backwards compatibility | ||||
|                 warnIgnored: usingFlatConfig ? void 0 : true | ||||
|             }); | ||||
|         } else { | ||||
|             results = await engine.lintFiles(files); | ||||
|         } | ||||
|  | ||||
|         if (options.fix) { | ||||
|             debug("Fix mode enabled - applying fixes"); | ||||
|             await ActiveESLint.outputFixes(results); | ||||
|         } | ||||
|  | ||||
|         let resultsToPrint = results; | ||||
|  | ||||
|         if (options.quiet) { | ||||
|             debug("Quiet mode enabled - filtering out warnings"); | ||||
|             resultsToPrint = ActiveESLint.getErrorResults(resultsToPrint); | ||||
|         } | ||||
|  | ||||
|         const resultCounts = countErrors(results); | ||||
|         const tooManyWarnings = options.maxWarnings >= 0 && resultCounts.warningCount > options.maxWarnings; | ||||
|         const resultsMeta = tooManyWarnings | ||||
|             ? { | ||||
|                 maxWarningsExceeded: { | ||||
|                     maxWarnings: options.maxWarnings, | ||||
|                     foundWarnings: resultCounts.warningCount | ||||
|                 } | ||||
|             } | ||||
|             : {}; | ||||
|  | ||||
|         if (await printResults(engine, resultsToPrint, options.format, options.outputFile, resultsMeta)) { | ||||
|  | ||||
|             // Errors and warnings from the original unfiltered results should determine the exit code | ||||
|             const shouldExitForFatalErrors = | ||||
|                 options.exitOnFatalError && resultCounts.fatalErrorCount > 0; | ||||
|  | ||||
|             if (!resultCounts.errorCount && tooManyWarnings) { | ||||
|                 log.error( | ||||
|                     "ESLint found too many warnings (maximum: %s).", | ||||
|                     options.maxWarnings | ||||
|                 ); | ||||
|             } | ||||
|  | ||||
|             if (shouldExitForFatalErrors) { | ||||
|                 return 2; | ||||
|             } | ||||
|  | ||||
|             return (resultCounts.errorCount || tooManyWarnings) ? 1 : 0; | ||||
|         } | ||||
|  | ||||
|         return 2; | ||||
|     } | ||||
| }; | ||||
|  | ||||
| module.exports = cli; | ||||
							
								
								
									
										67
									
								
								node_modules/eslint/lib/config/default-config.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										67
									
								
								node_modules/eslint/lib/config/default-config.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,67 @@ | ||||
| /** | ||||
|  * @fileoverview Default configuration | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Requirements | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| const Rules = require("../rules"); | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Helpers | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| exports.defaultConfig = [ | ||||
|     { | ||||
|         plugins: { | ||||
|             "@": { | ||||
|  | ||||
|                 /* | ||||
|                  * Because we try to delay loading rules until absolutely | ||||
|                  * necessary, a proxy allows us to hook into the lazy-loading | ||||
|                  * aspect of the rules map while still keeping all of the | ||||
|                  * relevant configuration inside of the config array. | ||||
|                  */ | ||||
|                 rules: new Proxy({}, { | ||||
|                     get(target, property) { | ||||
|                         return Rules.get(property); | ||||
|                     }, | ||||
|  | ||||
|                     has(target, property) { | ||||
|                         return Rules.has(property); | ||||
|                     } | ||||
|                 }) | ||||
|             } | ||||
|         }, | ||||
|         languageOptions: { | ||||
|             sourceType: "module", | ||||
|             ecmaVersion: "latest", | ||||
|             parser: require("espree"), | ||||
|             parserOptions: {} | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     // default ignores are listed here | ||||
|     { | ||||
|         ignores: [ | ||||
|             "**/node_modules/", | ||||
|             ".git/" | ||||
|         ] | ||||
|     }, | ||||
|  | ||||
|     // intentionally empty config to ensure these files are globbed by default | ||||
|     { | ||||
|         files: ["**/*.js", "**/*.mjs"] | ||||
|     }, | ||||
|     { | ||||
|         files: ["**/*.cjs"], | ||||
|         languageOptions: { | ||||
|             sourceType: "commonjs", | ||||
|             ecmaVersion: "latest" | ||||
|         } | ||||
|     } | ||||
| ]; | ||||
							
								
								
									
										380
									
								
								node_modules/eslint/lib/config/flat-config-array.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										380
									
								
								node_modules/eslint/lib/config/flat-config-array.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,380 @@ | ||||
| /** | ||||
|  * @fileoverview Flat Config Array | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Requirements | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| const { ConfigArray, ConfigArraySymbol } = require("@humanwhocodes/config-array"); | ||||
| const { flatConfigSchema } = require("./flat-config-schema"); | ||||
| const { RuleValidator } = require("./rule-validator"); | ||||
| const { defaultConfig } = require("./default-config"); | ||||
| const jsPlugin = require("@eslint/js"); | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Helpers | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Fields that are considered metadata and not part of the config object. | ||||
|  */ | ||||
| const META_FIELDS = new Set(["name"]); | ||||
|  | ||||
| const ruleValidator = new RuleValidator(); | ||||
|  | ||||
| /** | ||||
|  * Splits a plugin identifier in the form a/b/c into two parts: a/b and c. | ||||
|  * @param {string} identifier The identifier to parse. | ||||
|  * @returns {{objectName: string, pluginName: string}} The parts of the plugin | ||||
|  *      name. | ||||
|  */ | ||||
| function splitPluginIdentifier(identifier) { | ||||
|     const parts = identifier.split("/"); | ||||
|  | ||||
|     return { | ||||
|         objectName: parts.pop(), | ||||
|         pluginName: parts.join("/") | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Returns the name of an object in the config by reading its `meta` key. | ||||
|  * @param {Object} object The object to check. | ||||
|  * @returns {string?} The name of the object if found or `null` if there | ||||
|  *      is no name. | ||||
|  */ | ||||
| function getObjectId(object) { | ||||
|  | ||||
|     // first check old-style name | ||||
|     let name = object.name; | ||||
|  | ||||
|     if (!name) { | ||||
|  | ||||
|         if (!object.meta) { | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         name = object.meta.name; | ||||
|  | ||||
|         if (!name) { | ||||
|             return null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // now check for old-style version | ||||
|     let version = object.version; | ||||
|  | ||||
|     if (!version) { | ||||
|         version = object.meta && object.meta.version; | ||||
|     } | ||||
|  | ||||
|     // if there's a version then append that | ||||
|     if (version) { | ||||
|         return `${name}@${version}`; | ||||
|     } | ||||
|  | ||||
|     return name; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Wraps a config error with details about where the error occurred. | ||||
|  * @param {Error} error The original error. | ||||
|  * @param {number} originalLength The original length of the config array. | ||||
|  * @param {number} baseLength The length of the base config. | ||||
|  * @returns {TypeError} The new error with details. | ||||
|  */ | ||||
| function wrapConfigErrorWithDetails(error, originalLength, baseLength) { | ||||
|  | ||||
|     let location = "user-defined"; | ||||
|     let configIndex = error.index; | ||||
|  | ||||
|     /* | ||||
|      * A config array is set up in this order: | ||||
|      * 1. Base config | ||||
|      * 2. Original configs | ||||
|      * 3. User-defined configs | ||||
|      * 4. CLI-defined configs | ||||
|      * | ||||
|      * So we need to adjust the index to account for the base config. | ||||
|      * | ||||
|      * - If the index is less than the base length, it's in the base config | ||||
|      *   (as specified by `baseConfig` argument to `FlatConfigArray` constructor). | ||||
|      * - If the index is greater than the base length but less than the original | ||||
|      *   length + base length, it's in the original config. The original config | ||||
|      *   is passed to the `FlatConfigArray` constructor as the first argument. | ||||
|      * - Otherwise, it's in the user-defined config, which is loaded from the | ||||
|      *   config file and merged with any command-line options. | ||||
|      */ | ||||
|     if (error.index < baseLength) { | ||||
|         location = "base"; | ||||
|     } else if (error.index < originalLength + baseLength) { | ||||
|         location = "original"; | ||||
|         configIndex = error.index - baseLength; | ||||
|     } else { | ||||
|         configIndex = error.index - originalLength - baseLength; | ||||
|     } | ||||
|  | ||||
|     return new TypeError( | ||||
|         `${error.message.slice(0, -1)} at ${location} index ${configIndex}.`, | ||||
|         { cause: error } | ||||
|     ); | ||||
| } | ||||
|  | ||||
| const originalBaseConfig = Symbol("originalBaseConfig"); | ||||
| const originalLength = Symbol("originalLength"); | ||||
| const baseLength = Symbol("baseLength"); | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Exports | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Represents an array containing configuration information for ESLint. | ||||
|  */ | ||||
| class FlatConfigArray extends ConfigArray { | ||||
|  | ||||
|     /** | ||||
|      * Creates a new instance. | ||||
|      * @param {*[]} configs An array of configuration information. | ||||
|      * @param {{basePath: string, shouldIgnore: boolean, baseConfig: FlatConfig}} options The options | ||||
|      *      to use for the config array instance. | ||||
|      */ | ||||
|     constructor(configs, { | ||||
|         basePath, | ||||
|         shouldIgnore = true, | ||||
|         baseConfig = defaultConfig | ||||
|     } = {}) { | ||||
|         super(configs, { | ||||
|             basePath, | ||||
|             schema: flatConfigSchema | ||||
|         }); | ||||
|  | ||||
|         /** | ||||
|          * The original length of the array before any modifications. | ||||
|          * @type {number} | ||||
|          */ | ||||
|         this[originalLength] = this.length; | ||||
|  | ||||
|         if (baseConfig[Symbol.iterator]) { | ||||
|             this.unshift(...baseConfig); | ||||
|         } else { | ||||
|             this.unshift(baseConfig); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * The length of the array after applying the base config. | ||||
|          * @type {number} | ||||
|          */ | ||||
|         this[baseLength] = this.length - this[originalLength]; | ||||
|  | ||||
|         /** | ||||
|          * The base config used to build the config array. | ||||
|          * @type {Array<FlatConfig>} | ||||
|          */ | ||||
|         this[originalBaseConfig] = baseConfig; | ||||
|         Object.defineProperty(this, originalBaseConfig, { writable: false }); | ||||
|  | ||||
|         /** | ||||
|          * Determines if `ignores` fields should be honored. | ||||
|          * If true, then all `ignores` fields are honored. | ||||
|          * if false, then only `ignores` fields in the baseConfig are honored. | ||||
|          * @type {boolean} | ||||
|          */ | ||||
|         this.shouldIgnore = shouldIgnore; | ||||
|         Object.defineProperty(this, "shouldIgnore", { writable: false }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Normalizes the array by calling the superclass method and catching/rethrowing | ||||
|      * any ConfigError exceptions with additional details. | ||||
|      * @param {any} [context] The context to use to normalize the array. | ||||
|      * @returns {Promise<FlatConfigArray>} A promise that resolves when the array is normalized. | ||||
|      */ | ||||
|     normalize(context) { | ||||
|         return super.normalize(context) | ||||
|             .catch(error => { | ||||
|                 if (error.name === "ConfigError") { | ||||
|                     throw wrapConfigErrorWithDetails(error, this[originalLength], this[baseLength]); | ||||
|                 } | ||||
|  | ||||
|                 throw error; | ||||
|  | ||||
|             }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Normalizes the array by calling the superclass method and catching/rethrowing | ||||
|      * any ConfigError exceptions with additional details. | ||||
|      * @param {any} [context] The context to use to normalize the array. | ||||
|      * @returns {FlatConfigArray} The current instance. | ||||
|      * @throws {TypeError} If the config is invalid. | ||||
|      */ | ||||
|     normalizeSync(context) { | ||||
|  | ||||
|         try { | ||||
|  | ||||
|             return super.normalizeSync(context); | ||||
|  | ||||
|         } catch (error) { | ||||
|  | ||||
|             if (error.name === "ConfigError") { | ||||
|                 throw wrapConfigErrorWithDetails(error, this[originalLength], this[baseLength]); | ||||
|             } | ||||
|  | ||||
|             throw error; | ||||
|  | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /* eslint-disable class-methods-use-this -- Desired as instance method */ | ||||
|     /** | ||||
|      * Replaces a config with another config to allow us to put strings | ||||
|      * in the config array that will be replaced by objects before | ||||
|      * normalization. | ||||
|      * @param {Object} config The config to preprocess. | ||||
|      * @returns {Object} The preprocessed config. | ||||
|      */ | ||||
|     [ConfigArraySymbol.preprocessConfig](config) { | ||||
|         if (config === "eslint:recommended") { | ||||
|  | ||||
|             // if we are in a Node.js environment warn the user | ||||
|             if (typeof process !== "undefined" && process.emitWarning) { | ||||
|                 process.emitWarning("The 'eslint:recommended' string configuration is deprecated and will be replaced by the @eslint/js package's 'recommended' config."); | ||||
|             } | ||||
|  | ||||
|             return jsPlugin.configs.recommended; | ||||
|         } | ||||
|  | ||||
|         if (config === "eslint:all") { | ||||
|  | ||||
|             // if we are in a Node.js environment warn the user | ||||
|             if (typeof process !== "undefined" && process.emitWarning) { | ||||
|                 process.emitWarning("The 'eslint:all' string configuration is deprecated and will be replaced by the @eslint/js package's 'all' config."); | ||||
|             } | ||||
|  | ||||
|             return jsPlugin.configs.all; | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * If a config object has `ignores` and no other non-meta fields, then it's an object | ||||
|          * for global ignores. If `shouldIgnore` is false, that object shouldn't apply, | ||||
|          * so we'll remove its `ignores`. | ||||
|          */ | ||||
|         if ( | ||||
|             !this.shouldIgnore && | ||||
|             !this[originalBaseConfig].includes(config) && | ||||
|             config.ignores && | ||||
|             Object.keys(config).filter(key => !META_FIELDS.has(key)).length === 1 | ||||
|         ) { | ||||
|             /* eslint-disable-next-line no-unused-vars -- need to strip off other keys */ | ||||
|             const { ignores, ...otherKeys } = config; | ||||
|  | ||||
|             return otherKeys; | ||||
|         } | ||||
|  | ||||
|         return config; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Finalizes the config by replacing plugin references with their objects | ||||
|      * and validating rule option schemas. | ||||
|      * @param {Object} config The config to finalize. | ||||
|      * @returns {Object} The finalized config. | ||||
|      * @throws {TypeError} If the config is invalid. | ||||
|      */ | ||||
|     [ConfigArraySymbol.finalizeConfig](config) { | ||||
|  | ||||
|         const { plugins, languageOptions, processor } = config; | ||||
|         let parserName, processorName; | ||||
|         let invalidParser = false, | ||||
|             invalidProcessor = false; | ||||
|  | ||||
|         // Check parser value | ||||
|         if (languageOptions && languageOptions.parser) { | ||||
|             const { parser } = languageOptions; | ||||
|  | ||||
|             if (typeof parser === "object") { | ||||
|                 parserName = getObjectId(parser); | ||||
|  | ||||
|                 if (!parserName) { | ||||
|                     invalidParser = true; | ||||
|                 } | ||||
|  | ||||
|             } else { | ||||
|                 invalidParser = true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // Check processor value | ||||
|         if (processor) { | ||||
|             if (typeof processor === "string") { | ||||
|                 const { pluginName, objectName: localProcessorName } = splitPluginIdentifier(processor); | ||||
|  | ||||
|                 processorName = processor; | ||||
|  | ||||
|                 if (!plugins || !plugins[pluginName] || !plugins[pluginName].processors || !plugins[pluginName].processors[localProcessorName]) { | ||||
|                     throw new TypeError(`Key "processor": Could not find "${localProcessorName}" in plugin "${pluginName}".`); | ||||
|                 } | ||||
|  | ||||
|                 config.processor = plugins[pluginName].processors[localProcessorName]; | ||||
|             } else if (typeof processor === "object") { | ||||
|                 processorName = getObjectId(processor); | ||||
|  | ||||
|                 if (!processorName) { | ||||
|                     invalidProcessor = true; | ||||
|                 } | ||||
|  | ||||
|             } else { | ||||
|                 invalidProcessor = true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         ruleValidator.validate(config); | ||||
|  | ||||
|         // apply special logic for serialization into JSON | ||||
|         /* eslint-disable object-shorthand -- shorthand would change "this" value */ | ||||
|         Object.defineProperty(config, "toJSON", { | ||||
|             value: function() { | ||||
|  | ||||
|                 if (invalidParser) { | ||||
|                     throw new Error("Could not serialize parser object (missing 'meta' object)."); | ||||
|                 } | ||||
|  | ||||
|                 if (invalidProcessor) { | ||||
|                     throw new Error("Could not serialize processor object (missing 'meta' object)."); | ||||
|                 } | ||||
|  | ||||
|                 return { | ||||
|                     ...this, | ||||
|                     plugins: Object.entries(plugins).map(([namespace, plugin]) => { | ||||
|  | ||||
|                         const pluginId = getObjectId(plugin); | ||||
|  | ||||
|                         if (!pluginId) { | ||||
|                             return namespace; | ||||
|                         } | ||||
|  | ||||
|                         return `${namespace}:${pluginId}`; | ||||
|                     }), | ||||
|                     languageOptions: { | ||||
|                         ...languageOptions, | ||||
|                         parser: parserName | ||||
|                     }, | ||||
|                     processor: processorName | ||||
|                 }; | ||||
|             } | ||||
|         }); | ||||
|         /* eslint-enable object-shorthand -- ok to enable now */ | ||||
|  | ||||
|         return config; | ||||
|     } | ||||
|     /* eslint-enable class-methods-use-this -- Desired as instance method */ | ||||
|  | ||||
| } | ||||
|  | ||||
| exports.FlatConfigArray = FlatConfigArray; | ||||
							
								
								
									
										111
									
								
								node_modules/eslint/lib/config/flat-config-helpers.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										111
									
								
								node_modules/eslint/lib/config/flat-config-helpers.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,111 @@ | ||||
| /** | ||||
|  * @fileoverview Shared functions to work with configs. | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Functions | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Parses a ruleId into its plugin and rule parts. | ||||
|  * @param {string} ruleId The rule ID to parse. | ||||
|  * @returns {{pluginName:string,ruleName:string}} The plugin and rule | ||||
|  *      parts of the ruleId; | ||||
|  */ | ||||
| function parseRuleId(ruleId) { | ||||
|     let pluginName, ruleName; | ||||
|  | ||||
|     // distinguish between core rules and plugin rules | ||||
|     if (ruleId.includes("/")) { | ||||
|  | ||||
|         // mimic scoped npm packages | ||||
|         if (ruleId.startsWith("@")) { | ||||
|             pluginName = ruleId.slice(0, ruleId.lastIndexOf("/")); | ||||
|         } else { | ||||
|             pluginName = ruleId.slice(0, ruleId.indexOf("/")); | ||||
|         } | ||||
|  | ||||
|         ruleName = ruleId.slice(pluginName.length + 1); | ||||
|     } else { | ||||
|         pluginName = "@"; | ||||
|         ruleName = ruleId; | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         pluginName, | ||||
|         ruleName | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Retrieves a rule instance from a given config based on the ruleId. | ||||
|  * @param {string} ruleId The rule ID to look for. | ||||
|  * @param {FlatConfig} config The config to search. | ||||
|  * @returns {import("../shared/types").Rule|undefined} The rule if found | ||||
|  *      or undefined if not. | ||||
|  */ | ||||
| function getRuleFromConfig(ruleId, config) { | ||||
|  | ||||
|     const { pluginName, ruleName } = parseRuleId(ruleId); | ||||
|  | ||||
|     const plugin = config.plugins && config.plugins[pluginName]; | ||||
|     let rule = plugin && plugin.rules && plugin.rules[ruleName]; | ||||
|  | ||||
|  | ||||
|     // normalize function rules into objects | ||||
|     if (rule && typeof rule === "function") { | ||||
|         rule = { | ||||
|             create: rule | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     return rule; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Gets a complete options schema for a rule. | ||||
|  * @param {{create: Function, schema: (Array|null)}} rule A new-style rule object | ||||
|  * @returns {Object} JSON Schema for the rule's options. | ||||
|  */ | ||||
| function getRuleOptionsSchema(rule) { | ||||
|  | ||||
|     if (!rule) { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     const schema = rule.schema || rule.meta && rule.meta.schema; | ||||
|  | ||||
|     if (Array.isArray(schema)) { | ||||
|         if (schema.length) { | ||||
|             return { | ||||
|                 type: "array", | ||||
|                 items: schema, | ||||
|                 minItems: 0, | ||||
|                 maxItems: schema.length | ||||
|             }; | ||||
|         } | ||||
|         return { | ||||
|             type: "array", | ||||
|             minItems: 0, | ||||
|             maxItems: 0 | ||||
|         }; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     // Given a full schema, leave it alone | ||||
|     return schema || null; | ||||
| } | ||||
|  | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Exports | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| module.exports = { | ||||
|     parseRuleId, | ||||
|     getRuleFromConfig, | ||||
|     getRuleOptionsSchema | ||||
| }; | ||||
							
								
								
									
										598
									
								
								node_modules/eslint/lib/config/flat-config-schema.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										598
									
								
								node_modules/eslint/lib/config/flat-config-schema.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,598 @@ | ||||
| /** | ||||
|  * @fileoverview Flat config schema | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Requirements | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /* | ||||
|  * Note: This can be removed in ESLint v9 because structuredClone is available globally | ||||
|  * starting in Node.js v17. | ||||
|  */ | ||||
| const structuredClone = require("@ungap/structured-clone").default; | ||||
| const { normalizeSeverityToNumber } = require("../shared/severity"); | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Type Definitions | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * @typedef ObjectPropertySchema | ||||
|  * @property {Function|string} merge The function or name of the function to call | ||||
|  *      to merge multiple objects with this property. | ||||
|  * @property {Function|string} validate The function or name of the function to call | ||||
|  *      to validate the value of this property. | ||||
|  */ | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Helpers | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| const ruleSeverities = new Map([ | ||||
|     [0, 0], ["off", 0], | ||||
|     [1, 1], ["warn", 1], | ||||
|     [2, 2], ["error", 2] | ||||
| ]); | ||||
|  | ||||
| const globalVariablesValues = new Set([ | ||||
|     true, "true", "writable", "writeable", | ||||
|     false, "false", "readonly", "readable", null, | ||||
|     "off" | ||||
| ]); | ||||
|  | ||||
| /** | ||||
|  * Check if a value is a non-null object. | ||||
|  * @param {any} value The value to check. | ||||
|  * @returns {boolean} `true` if the value is a non-null object. | ||||
|  */ | ||||
| function isNonNullObject(value) { | ||||
|     return typeof value === "object" && value !== null; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check if a value is a non-null non-array object. | ||||
|  * @param {any} value The value to check. | ||||
|  * @returns {boolean} `true` if the value is a non-null non-array object. | ||||
|  */ | ||||
| function isNonArrayObject(value) { | ||||
|     return isNonNullObject(value) && !Array.isArray(value); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check if a value is undefined. | ||||
|  * @param {any} value The value to check. | ||||
|  * @returns {boolean} `true` if the value is undefined. | ||||
|  */ | ||||
| function isUndefined(value) { | ||||
|     return typeof value === "undefined"; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Deeply merges two non-array objects. | ||||
|  * @param {Object} first The base object. | ||||
|  * @param {Object} second The overrides object. | ||||
|  * @param {Map<string, Map<string, Object>>} [mergeMap] Maps the combination of first and second arguments to a merged result. | ||||
|  * @returns {Object} An object with properties from both first and second. | ||||
|  */ | ||||
| function deepMerge(first, second, mergeMap = new Map()) { | ||||
|  | ||||
|     let secondMergeMap = mergeMap.get(first); | ||||
|  | ||||
|     if (secondMergeMap) { | ||||
|         const result = secondMergeMap.get(second); | ||||
|  | ||||
|         if (result) { | ||||
|  | ||||
|             // If this combination of first and second arguments has been already visited, return the previously created result. | ||||
|             return result; | ||||
|         } | ||||
|     } else { | ||||
|         secondMergeMap = new Map(); | ||||
|         mergeMap.set(first, secondMergeMap); | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * First create a result object where properties from the second object | ||||
|      * overwrite properties from the first. This sets up a baseline to use | ||||
|      * later rather than needing to inspect and change every property | ||||
|      * individually. | ||||
|      */ | ||||
|     const result = { | ||||
|         ...first, | ||||
|         ...second | ||||
|     }; | ||||
|  | ||||
|     delete result.__proto__; // eslint-disable-line no-proto -- don't merge own property "__proto__" | ||||
|  | ||||
|     // Store the pending result for this combination of first and second arguments. | ||||
|     secondMergeMap.set(second, result); | ||||
|  | ||||
|     for (const key of Object.keys(second)) { | ||||
|  | ||||
|         // avoid hairy edge case | ||||
|         if (key === "__proto__" || !Object.prototype.propertyIsEnumerable.call(first, key)) { | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         const firstValue = first[key]; | ||||
|         const secondValue = second[key]; | ||||
|  | ||||
|         if (isNonArrayObject(firstValue) && isNonArrayObject(secondValue)) { | ||||
|             result[key] = deepMerge(firstValue, secondValue, mergeMap); | ||||
|         } else if (isUndefined(secondValue)) { | ||||
|             result[key] = firstValue; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return result; | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Normalizes the rule options config for a given rule by ensuring that | ||||
|  * it is an array and that the first item is 0, 1, or 2. | ||||
|  * @param {Array|string|number} ruleOptions The rule options config. | ||||
|  * @returns {Array} An array of rule options. | ||||
|  */ | ||||
| function normalizeRuleOptions(ruleOptions) { | ||||
|  | ||||
|     const finalOptions = Array.isArray(ruleOptions) | ||||
|         ? ruleOptions.slice(0) | ||||
|         : [ruleOptions]; | ||||
|  | ||||
|     finalOptions[0] = ruleSeverities.get(finalOptions[0]); | ||||
|     return structuredClone(finalOptions); | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Assertions | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * The error type when a rule's options are configured with an invalid type. | ||||
|  */ | ||||
| class InvalidRuleOptionsError extends Error { | ||||
|  | ||||
|     /** | ||||
|      * @param {string} ruleId Rule name being configured. | ||||
|      * @param {any} value The invalid value. | ||||
|      */ | ||||
|     constructor(ruleId, value) { | ||||
|         super(`Key "${ruleId}": Expected severity of "off", 0, "warn", 1, "error", or 2.`); | ||||
|         this.messageTemplate = "invalid-rule-options"; | ||||
|         this.messageData = { ruleId, value }; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Validates that a value is a valid rule options entry. | ||||
|  * @param {string} ruleId Rule name being configured. | ||||
|  * @param {any} value The value to check. | ||||
|  * @returns {void} | ||||
|  * @throws {InvalidRuleOptionsError} If the value isn't a valid rule options. | ||||
|  */ | ||||
| function assertIsRuleOptions(ruleId, value) { | ||||
|     if (typeof value !== "string" && typeof value !== "number" && !Array.isArray(value)) { | ||||
|         throw new InvalidRuleOptionsError(ruleId, value); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The error type when a rule's severity is invalid. | ||||
|  */ | ||||
| class InvalidRuleSeverityError extends Error { | ||||
|  | ||||
|     /** | ||||
|      * @param {string} ruleId Rule name being configured. | ||||
|      * @param {any} value The invalid value. | ||||
|      */ | ||||
|     constructor(ruleId, value) { | ||||
|         super(`Key "${ruleId}": Expected severity of "off", 0, "warn", 1, "error", or 2.`); | ||||
|         this.messageTemplate = "invalid-rule-severity"; | ||||
|         this.messageData = { ruleId, value }; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Validates that a value is valid rule severity. | ||||
|  * @param {string} ruleId Rule name being configured. | ||||
|  * @param {any} value The value to check. | ||||
|  * @returns {void} | ||||
|  * @throws {InvalidRuleSeverityError} If the value isn't a valid rule severity. | ||||
|  */ | ||||
| function assertIsRuleSeverity(ruleId, value) { | ||||
|     const severity = ruleSeverities.get(value); | ||||
|  | ||||
|     if (typeof severity === "undefined") { | ||||
|         throw new InvalidRuleSeverityError(ruleId, value); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Validates that a given string is the form pluginName/objectName. | ||||
|  * @param {string} value The string to check. | ||||
|  * @returns {void} | ||||
|  * @throws {TypeError} If the string isn't in the correct format. | ||||
|  */ | ||||
| function assertIsPluginMemberName(value) { | ||||
|     if (!/[@a-z0-9-_$]+(?:\/(?:[a-z0-9-_$]+))+$/iu.test(value)) { | ||||
|         throw new TypeError(`Expected string in the form "pluginName/objectName" but found "${value}".`); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Validates that a value is an object. | ||||
|  * @param {any} value The value to check. | ||||
|  * @returns {void} | ||||
|  * @throws {TypeError} If the value isn't an object. | ||||
|  */ | ||||
| function assertIsObject(value) { | ||||
|     if (!isNonNullObject(value)) { | ||||
|         throw new TypeError("Expected an object."); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The error type when there's an eslintrc-style options in a flat config. | ||||
|  */ | ||||
| class IncompatibleKeyError extends Error { | ||||
|  | ||||
|     /** | ||||
|      * @param {string} key The invalid key. | ||||
|      */ | ||||
|     constructor(key) { | ||||
|         super("This appears to be in eslintrc format rather than flat config format."); | ||||
|         this.messageTemplate = "eslintrc-incompat"; | ||||
|         this.messageData = { key }; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The error type when there's an eslintrc-style plugins array found. | ||||
|  */ | ||||
| class IncompatiblePluginsError extends Error { | ||||
|  | ||||
|     /** | ||||
|      * Creates a new instance. | ||||
|      * @param {Array<string>} plugins The plugins array. | ||||
|      */ | ||||
|     constructor(plugins) { | ||||
|         super("This appears to be in eslintrc format (array of strings) rather than flat config format (object)."); | ||||
|         this.messageTemplate = "eslintrc-plugins"; | ||||
|         this.messageData = { plugins }; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Low-Level Schemas | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const booleanSchema = { | ||||
|     merge: "replace", | ||||
|     validate: "boolean" | ||||
| }; | ||||
|  | ||||
| const ALLOWED_SEVERITIES = new Set(["error", "warn", "off", 2, 1, 0]); | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const disableDirectiveSeveritySchema = { | ||||
|     merge(first, second) { | ||||
|         const value = second === void 0 ? first : second; | ||||
|  | ||||
|         if (typeof value === "boolean") { | ||||
|             return value ? "warn" : "off"; | ||||
|         } | ||||
|  | ||||
|         return normalizeSeverityToNumber(value); | ||||
|     }, | ||||
|     validate(value) { | ||||
|         if (!(ALLOWED_SEVERITIES.has(value) || typeof value === "boolean")) { | ||||
|             throw new TypeError("Expected one of: \"error\", \"warn\", \"off\", 0, 1, 2, or a boolean."); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const deepObjectAssignSchema = { | ||||
|     merge(first = {}, second = {}) { | ||||
|         return deepMerge(first, second); | ||||
|     }, | ||||
|     validate: "object" | ||||
| }; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // High-Level Schemas | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const globalsSchema = { | ||||
|     merge: "assign", | ||||
|     validate(value) { | ||||
|  | ||||
|         assertIsObject(value); | ||||
|  | ||||
|         for (const key of Object.keys(value)) { | ||||
|  | ||||
|             // avoid hairy edge case | ||||
|             if (key === "__proto__") { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if (key !== key.trim()) { | ||||
|                 throw new TypeError(`Global "${key}" has leading or trailing whitespace.`); | ||||
|             } | ||||
|  | ||||
|             if (!globalVariablesValues.has(value[key])) { | ||||
|                 throw new TypeError(`Key "${key}": Expected "readonly", "writable", or "off".`); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const parserSchema = { | ||||
|     merge: "replace", | ||||
|     validate(value) { | ||||
|  | ||||
|         if (!value || typeof value !== "object" || | ||||
|             (typeof value.parse !== "function" && typeof value.parseForESLint !== "function") | ||||
|         ) { | ||||
|             throw new TypeError("Expected object with parse() or parseForESLint() method."); | ||||
|         } | ||||
|  | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const pluginsSchema = { | ||||
|     merge(first = {}, second = {}) { | ||||
|         const keys = new Set([...Object.keys(first), ...Object.keys(second)]); | ||||
|         const result = {}; | ||||
|  | ||||
|         // manually validate that plugins are not redefined | ||||
|         for (const key of keys) { | ||||
|  | ||||
|             // avoid hairy edge case | ||||
|             if (key === "__proto__") { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if (key in first && key in second && first[key] !== second[key]) { | ||||
|                 throw new TypeError(`Cannot redefine plugin "${key}".`); | ||||
|             } | ||||
|  | ||||
|             result[key] = second[key] || first[key]; | ||||
|         } | ||||
|  | ||||
|         return result; | ||||
|     }, | ||||
|     validate(value) { | ||||
|  | ||||
|         // first check the value to be sure it's an object | ||||
|         if (value === null || typeof value !== "object") { | ||||
|             throw new TypeError("Expected an object."); | ||||
|         } | ||||
|  | ||||
|         // make sure it's not an array, which would mean eslintrc-style is used | ||||
|         if (Array.isArray(value)) { | ||||
|             throw new IncompatiblePluginsError(value); | ||||
|         } | ||||
|  | ||||
|         // second check the keys to make sure they are objects | ||||
|         for (const key of Object.keys(value)) { | ||||
|  | ||||
|             // avoid hairy edge case | ||||
|             if (key === "__proto__") { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if (value[key] === null || typeof value[key] !== "object") { | ||||
|                 throw new TypeError(`Key "${key}": Expected an object.`); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const processorSchema = { | ||||
|     merge: "replace", | ||||
|     validate(value) { | ||||
|         if (typeof value === "string") { | ||||
|             assertIsPluginMemberName(value); | ||||
|         } else if (value && typeof value === "object") { | ||||
|             if (typeof value.preprocess !== "function" || typeof value.postprocess !== "function") { | ||||
|                 throw new TypeError("Object must have a preprocess() and a postprocess() method."); | ||||
|             } | ||||
|         } else { | ||||
|             throw new TypeError("Expected an object or a string."); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const rulesSchema = { | ||||
|     merge(first = {}, second = {}) { | ||||
|  | ||||
|         const result = { | ||||
|             ...first, | ||||
|             ...second | ||||
|         }; | ||||
|  | ||||
|  | ||||
|         for (const ruleId of Object.keys(result)) { | ||||
|  | ||||
|             try { | ||||
|  | ||||
|                 // avoid hairy edge case | ||||
|                 if (ruleId === "__proto__") { | ||||
|  | ||||
|                     /* eslint-disable-next-line no-proto -- Though deprecated, may still be present */ | ||||
|                     delete result.__proto__; | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 result[ruleId] = normalizeRuleOptions(result[ruleId]); | ||||
|  | ||||
|                 /* | ||||
|                  * If either rule config is missing, then the correct | ||||
|                  * config is already present and we just need to normalize | ||||
|                  * the severity. | ||||
|                  */ | ||||
|                 if (!(ruleId in first) || !(ruleId in second)) { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 const firstRuleOptions = normalizeRuleOptions(first[ruleId]); | ||||
|                 const secondRuleOptions = normalizeRuleOptions(second[ruleId]); | ||||
|  | ||||
|                 /* | ||||
|                  * If the second rule config only has a severity (length of 1), | ||||
|                  * then use that severity and keep the rest of the options from | ||||
|                  * the first rule config. | ||||
|                  */ | ||||
|                 if (secondRuleOptions.length === 1) { | ||||
|                     result[ruleId] = [secondRuleOptions[0], ...firstRuleOptions.slice(1)]; | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 /* | ||||
|                  * In any other situation, then the second rule config takes | ||||
|                  * precedence. That means the value at `result[ruleId]` is | ||||
|                  * already correct and no further work is necessary. | ||||
|                  */ | ||||
|             } catch (ex) { | ||||
|                 throw new Error(`Key "${ruleId}": ${ex.message}`, { cause: ex }); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return result; | ||||
|  | ||||
|  | ||||
|     }, | ||||
|  | ||||
|     validate(value) { | ||||
|         assertIsObject(value); | ||||
|  | ||||
|         /* | ||||
|          * We are not checking the rule schema here because there is no | ||||
|          * guarantee that the rule definition is present at this point. Instead | ||||
|          * we wait and check the rule schema during the finalization step | ||||
|          * of calculating a config. | ||||
|          */ | ||||
|         for (const ruleId of Object.keys(value)) { | ||||
|  | ||||
|             // avoid hairy edge case | ||||
|             if (ruleId === "__proto__") { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             const ruleOptions = value[ruleId]; | ||||
|  | ||||
|             assertIsRuleOptions(ruleId, ruleOptions); | ||||
|  | ||||
|             if (Array.isArray(ruleOptions)) { | ||||
|                 assertIsRuleSeverity(ruleId, ruleOptions[0]); | ||||
|             } else { | ||||
|                 assertIsRuleSeverity(ruleId, ruleOptions); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const ecmaVersionSchema = { | ||||
|     merge: "replace", | ||||
|     validate(value) { | ||||
|         if (typeof value === "number" || value === "latest") { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         throw new TypeError("Expected a number or \"latest\"."); | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** @type {ObjectPropertySchema} */ | ||||
| const sourceTypeSchema = { | ||||
|     merge: "replace", | ||||
|     validate(value) { | ||||
|         if (typeof value !== "string" || !/^(?:script|module|commonjs)$/u.test(value)) { | ||||
|             throw new TypeError("Expected \"script\", \"module\", or \"commonjs\"."); | ||||
|         } | ||||
|     } | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Creates a schema that always throws an error. Useful for warning | ||||
|  * about eslintrc-style keys. | ||||
|  * @param {string} key The eslintrc key to create a schema for. | ||||
|  * @returns {ObjectPropertySchema} The schema. | ||||
|  */ | ||||
| function createEslintrcErrorSchema(key) { | ||||
|     return { | ||||
|         merge: "replace", | ||||
|         validate() { | ||||
|             throw new IncompatibleKeyError(key); | ||||
|         } | ||||
|     }; | ||||
| } | ||||
|  | ||||
| const eslintrcKeys = [ | ||||
|     "env", | ||||
|     "extends", | ||||
|     "globals", | ||||
|     "ignorePatterns", | ||||
|     "noInlineConfig", | ||||
|     "overrides", | ||||
|     "parser", | ||||
|     "parserOptions", | ||||
|     "reportUnusedDisableDirectives", | ||||
|     "root" | ||||
| ]; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Full schema | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| const flatConfigSchema = { | ||||
|  | ||||
|     // eslintrc-style keys that should always error | ||||
|     ...Object.fromEntries(eslintrcKeys.map(key => [key, createEslintrcErrorSchema(key)])), | ||||
|  | ||||
|     // flat config keys | ||||
|     settings: deepObjectAssignSchema, | ||||
|     linterOptions: { | ||||
|         schema: { | ||||
|             noInlineConfig: booleanSchema, | ||||
|             reportUnusedDisableDirectives: disableDirectiveSeveritySchema | ||||
|         } | ||||
|     }, | ||||
|     languageOptions: { | ||||
|         schema: { | ||||
|             ecmaVersion: ecmaVersionSchema, | ||||
|             sourceType: sourceTypeSchema, | ||||
|             globals: globalsSchema, | ||||
|             parser: parserSchema, | ||||
|             parserOptions: deepObjectAssignSchema | ||||
|         } | ||||
|     }, | ||||
|     processor: processorSchema, | ||||
|     plugins: pluginsSchema, | ||||
|     rules: rulesSchema | ||||
| }; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Exports | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| module.exports = { | ||||
|     flatConfigSchema, | ||||
|     assertIsRuleSeverity, | ||||
|     assertIsRuleOptions | ||||
| }; | ||||
							
								
								
									
										158
									
								
								node_modules/eslint/lib/config/rule-validator.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										158
									
								
								node_modules/eslint/lib/config/rule-validator.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,158 @@ | ||||
| /** | ||||
|  * @fileoverview Rule Validator | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Requirements | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| const ajvImport = require("../shared/ajv"); | ||||
| const ajv = ajvImport(); | ||||
| const { | ||||
|     parseRuleId, | ||||
|     getRuleFromConfig, | ||||
|     getRuleOptionsSchema | ||||
| } = require("./flat-config-helpers"); | ||||
| const ruleReplacements = require("../../conf/replacements.json"); | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Helpers | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Throws a helpful error when a rule cannot be found. | ||||
|  * @param {Object} ruleId The rule identifier. | ||||
|  * @param {string} ruleId.pluginName The ID of the rule to find. | ||||
|  * @param {string} ruleId.ruleName The ID of the rule to find. | ||||
|  * @param {Object} config The config to search in. | ||||
|  * @throws {TypeError} For missing plugin or rule. | ||||
|  * @returns {void} | ||||
|  */ | ||||
| function throwRuleNotFoundError({ pluginName, ruleName }, config) { | ||||
|  | ||||
|     const ruleId = pluginName === "@" ? ruleName : `${pluginName}/${ruleName}`; | ||||
|  | ||||
|     const errorMessageHeader = `Key "rules": Key "${ruleId}"`; | ||||
|     let errorMessage = `${errorMessageHeader}: Could not find plugin "${pluginName}".`; | ||||
|  | ||||
|     // if the plugin exists then we need to check if the rule exists | ||||
|     if (config.plugins && config.plugins[pluginName]) { | ||||
|         const replacementRuleName = ruleReplacements.rules[ruleName]; | ||||
|  | ||||
|         if (pluginName === "@" && replacementRuleName) { | ||||
|  | ||||
|             errorMessage = `${errorMessageHeader}: Rule "${ruleName}" was removed and replaced by "${replacementRuleName}".`; | ||||
|  | ||||
|         } else { | ||||
|  | ||||
|             errorMessage = `${errorMessageHeader}: Could not find "${ruleName}" in plugin "${pluginName}".`; | ||||
|  | ||||
|             // otherwise, let's see if we can find the rule name elsewhere | ||||
|             for (const [otherPluginName, otherPlugin] of Object.entries(config.plugins)) { | ||||
|                 if (otherPlugin.rules && otherPlugin.rules[ruleName]) { | ||||
|                     errorMessage += ` Did you mean "${otherPluginName}/${ruleName}"?`; | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         // falls through to throw error | ||||
|     } | ||||
|  | ||||
|     throw new TypeError(errorMessage); | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Exports | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Implements validation functionality for the rules portion of a config. | ||||
|  */ | ||||
| class RuleValidator { | ||||
|  | ||||
|     /** | ||||
|      * Creates a new instance. | ||||
|      */ | ||||
|     constructor() { | ||||
|  | ||||
|         /** | ||||
|          * A collection of compiled validators for rules that have already | ||||
|          * been validated. | ||||
|          * @type {WeakMap} | ||||
|          */ | ||||
|         this.validators = new WeakMap(); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Validates all of the rule configurations in a config against each | ||||
|      * rule's schema. | ||||
|      * @param {Object} config The full config to validate. This object must | ||||
|      *      contain both the rules section and the plugins section. | ||||
|      * @returns {void} | ||||
|      * @throws {Error} If a rule's configuration does not match its schema. | ||||
|      */ | ||||
|     validate(config) { | ||||
|  | ||||
|         if (!config.rules) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         for (const [ruleId, ruleOptions] of Object.entries(config.rules)) { | ||||
|  | ||||
|             // check for edge case | ||||
|             if (ruleId === "__proto__") { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             /* | ||||
|              * If a rule is disabled, we don't do any validation. This allows | ||||
|              * users to safely set any value to 0 or "off" without worrying | ||||
|              * that it will cause a validation error. | ||||
|              * | ||||
|              * Note: ruleOptions is always an array at this point because | ||||
|              * this validation occurs after FlatConfigArray has merged and | ||||
|              * normalized values. | ||||
|              */ | ||||
|             if (ruleOptions[0] === 0) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             const rule = getRuleFromConfig(ruleId, config); | ||||
|  | ||||
|             if (!rule) { | ||||
|                 throwRuleNotFoundError(parseRuleId(ruleId), config); | ||||
|             } | ||||
|  | ||||
|             // Precompile and cache validator the first time | ||||
|             if (!this.validators.has(rule)) { | ||||
|                 const schema = getRuleOptionsSchema(rule); | ||||
|  | ||||
|                 if (schema) { | ||||
|                     this.validators.set(rule, ajv.compile(schema)); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             const validateRule = this.validators.get(rule); | ||||
|  | ||||
|             if (validateRule) { | ||||
|  | ||||
|                 validateRule(ruleOptions.slice(1)); | ||||
|  | ||||
|                 if (validateRule.errors) { | ||||
|                     throw new Error(`Key "rules": Key "${ruleId}": ${ | ||||
|                         validateRule.errors.map( | ||||
|                             error => `\tValue ${JSON.stringify(error.data)} ${error.message}.\n` | ||||
|                         ).join("") | ||||
|                     }`); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| exports.RuleValidator = RuleValidator; | ||||
							
								
								
									
										932
									
								
								node_modules/eslint/lib/eslint/eslint-helpers.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										932
									
								
								node_modules/eslint/lib/eslint/eslint-helpers.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,932 @@ | ||||
| /** | ||||
|  * @fileoverview Helper functions for ESLint class | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Requirements | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| const path = require("path"); | ||||
| const fs = require("fs"); | ||||
| const fsp = fs.promises; | ||||
| const isGlob = require("is-glob"); | ||||
| const hash = require("../cli-engine/hash"); | ||||
| const minimatch = require("minimatch"); | ||||
| const fswalk = require("@nodelib/fs.walk"); | ||||
| const globParent = require("glob-parent"); | ||||
| const isPathInside = require("is-path-inside"); | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Fixup references | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| const Minimatch = minimatch.Minimatch; | ||||
| const MINIMATCH_OPTIONS = { dot: true }; | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Types | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * @typedef {Object} GlobSearch | ||||
|  * @property {Array<string>} patterns The normalized patterns to use for a search. | ||||
|  * @property {Array<string>} rawPatterns The patterns as entered by the user | ||||
|  *      before doing any normalization. | ||||
|  */ | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Errors | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * The error type when no files match a glob. | ||||
|  */ | ||||
| class NoFilesFoundError extends Error { | ||||
|  | ||||
|     /** | ||||
|      * @param {string} pattern The glob pattern which was not found. | ||||
|      * @param {boolean} globEnabled If `false` then the pattern was a glob pattern, but glob was disabled. | ||||
|      */ | ||||
|     constructor(pattern, globEnabled) { | ||||
|         super(`No files matching '${pattern}' were found${!globEnabled ? " (glob was disabled)" : ""}.`); | ||||
|         this.messageTemplate = "file-not-found"; | ||||
|         this.messageData = { pattern, globDisabled: !globEnabled }; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The error type when a search fails to match multiple patterns. | ||||
|  */ | ||||
| class UnmatchedSearchPatternsError extends Error { | ||||
|  | ||||
|     /** | ||||
|      * @param {Object} options The options for the error. | ||||
|      * @param {string} options.basePath The directory that was searched. | ||||
|      * @param {Array<string>} options.unmatchedPatterns The glob patterns | ||||
|      *      which were not found. | ||||
|      * @param {Array<string>} options.patterns The glob patterns that were | ||||
|      *      searched. | ||||
|      * @param {Array<string>} options.rawPatterns The raw glob patterns that | ||||
|      *      were searched. | ||||
|      */ | ||||
|     constructor({ basePath, unmatchedPatterns, patterns, rawPatterns }) { | ||||
|         super(`No files matching '${rawPatterns}' in '${basePath}' were found.`); | ||||
|         this.basePath = basePath; | ||||
|         this.unmatchedPatterns = unmatchedPatterns; | ||||
|         this.patterns = patterns; | ||||
|         this.rawPatterns = rawPatterns; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The error type when there are files matched by a glob, but all of them have been ignored. | ||||
|  */ | ||||
| class AllFilesIgnoredError extends Error { | ||||
|  | ||||
|     /** | ||||
|      * @param {string} pattern The glob pattern which was not found. | ||||
|      */ | ||||
|     constructor(pattern) { | ||||
|         super(`All files matched by '${pattern}' are ignored.`); | ||||
|         this.messageTemplate = "all-files-ignored"; | ||||
|         this.messageData = { pattern }; | ||||
|     } | ||||
| } | ||||
|  | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // General Helpers | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Check if a given value is a non-empty string or not. | ||||
|  * @param {any} x The value to check. | ||||
|  * @returns {boolean} `true` if `x` is a non-empty string. | ||||
|  */ | ||||
| function isNonEmptyString(x) { | ||||
|     return typeof x === "string" && x.trim() !== ""; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check if a given value is an array of non-empty strings or not. | ||||
|  * @param {any} x The value to check. | ||||
|  * @returns {boolean} `true` if `x` is an array of non-empty strings. | ||||
|  */ | ||||
| function isArrayOfNonEmptyString(x) { | ||||
|     return Array.isArray(x) && x.every(isNonEmptyString); | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // File-related Helpers | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Normalizes slashes in a file pattern to posix-style. | ||||
|  * @param {string} pattern The pattern to replace slashes in. | ||||
|  * @returns {string} The pattern with slashes normalized. | ||||
|  */ | ||||
| function normalizeToPosix(pattern) { | ||||
|     return pattern.replace(/\\/gu, "/"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check if a string is a glob pattern or not. | ||||
|  * @param {string} pattern A glob pattern. | ||||
|  * @returns {boolean} `true` if the string is a glob pattern. | ||||
|  */ | ||||
| function isGlobPattern(pattern) { | ||||
|     return isGlob(path.sep === "\\" ? normalizeToPosix(pattern) : pattern); | ||||
| } | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Determines if a given glob pattern will return any results. | ||||
|  * Used primarily to help with useful error messages. | ||||
|  * @param {Object} options The options for the function. | ||||
|  * @param {string} options.basePath The directory to search. | ||||
|  * @param {string} options.pattern A glob pattern to match. | ||||
|  * @returns {Promise<boolean>} True if there is a glob match, false if not. | ||||
|  */ | ||||
| function globMatch({ basePath, pattern }) { | ||||
|  | ||||
|     let found = false; | ||||
|     const patternToUse = path.isAbsolute(pattern) | ||||
|         ? normalizeToPosix(path.relative(basePath, pattern)) | ||||
|         : pattern; | ||||
|  | ||||
|     const matcher = new Minimatch(patternToUse, MINIMATCH_OPTIONS); | ||||
|  | ||||
|     const fsWalkSettings = { | ||||
|  | ||||
|         deepFilter(entry) { | ||||
|             const relativePath = normalizeToPosix(path.relative(basePath, entry.path)); | ||||
|  | ||||
|             return !found && matcher.match(relativePath, true); | ||||
|         }, | ||||
|  | ||||
|         entryFilter(entry) { | ||||
|             if (found || entry.dirent.isDirectory()) { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             const relativePath = normalizeToPosix(path.relative(basePath, entry.path)); | ||||
|  | ||||
|             if (matcher.match(relativePath)) { | ||||
|                 found = true; | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     return new Promise(resolve => { | ||||
|  | ||||
|         // using a stream so we can exit early because we just need one match | ||||
|         const globStream = fswalk.walkStream(basePath, fsWalkSettings); | ||||
|  | ||||
|         globStream.on("data", () => { | ||||
|             globStream.destroy(); | ||||
|             resolve(true); | ||||
|         }); | ||||
|  | ||||
|         // swallow errors as they're not important here | ||||
|         globStream.on("error", () => { }); | ||||
|  | ||||
|         globStream.on("end", () => { | ||||
|             resolve(false); | ||||
|         }); | ||||
|         globStream.read(); | ||||
|     }); | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Searches a directory looking for matching glob patterns. This uses | ||||
|  * the config array's logic to determine if a directory or file should | ||||
|  * be ignored, so it is consistent with how ignoring works throughout | ||||
|  * ESLint. | ||||
|  * @param {Object} options The options for this function. | ||||
|  * @param {string} options.basePath The directory to search. | ||||
|  * @param {Array<string>} options.patterns An array of glob patterns | ||||
|  *      to match. | ||||
|  * @param {Array<string>} options.rawPatterns An array of glob patterns | ||||
|  *      as the user inputted them. Used for errors. | ||||
|  * @param {FlatConfigArray} options.configs The config array to use for | ||||
|  *      determining what to ignore. | ||||
|  * @param {boolean} options.errorOnUnmatchedPattern Determines if an error | ||||
|  *      should be thrown when a pattern is unmatched. | ||||
|  * @returns {Promise<Array<string>>} An array of matching file paths | ||||
|  *      or an empty array if there are no matches. | ||||
|  * @throws {UnmatchedSearchPatternsError} If there is a pattern that doesn't | ||||
|  *      match any files. | ||||
|  */ | ||||
| async function globSearch({ | ||||
|     basePath, | ||||
|     patterns, | ||||
|     rawPatterns, | ||||
|     configs, | ||||
|     errorOnUnmatchedPattern | ||||
| }) { | ||||
|  | ||||
|     if (patterns.length === 0) { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * In this section we are converting the patterns into Minimatch | ||||
|      * instances for performance reasons. Because we are doing the same | ||||
|      * matches repeatedly, it's best to compile those patterns once and | ||||
|      * reuse them multiple times. | ||||
|      * | ||||
|      * To do that, we convert any patterns with an absolute path into a | ||||
|      * relative path and normalize it to Posix-style slashes. We also keep | ||||
|      * track of the relative patterns to map them back to the original | ||||
|      * patterns, which we need in order to throw an error if there are any | ||||
|      * unmatched patterns. | ||||
|      */ | ||||
|     const relativeToPatterns = new Map(); | ||||
|     const matchers = patterns.map((pattern, i) => { | ||||
|         const patternToUse = path.isAbsolute(pattern) | ||||
|             ? normalizeToPosix(path.relative(basePath, pattern)) | ||||
|             : pattern; | ||||
|  | ||||
|         relativeToPatterns.set(patternToUse, patterns[i]); | ||||
|  | ||||
|         return new Minimatch(patternToUse, MINIMATCH_OPTIONS); | ||||
|     }); | ||||
|  | ||||
|     /* | ||||
|      * We track unmatched patterns because we may want to throw an error when | ||||
|      * they occur. To start, this set is initialized with all of the patterns. | ||||
|      * Every time a match occurs, the pattern is removed from the set, making | ||||
|      * it easy to tell if we have any unmatched patterns left at the end of | ||||
|      * search. | ||||
|      */ | ||||
|     const unmatchedPatterns = new Set([...relativeToPatterns.keys()]); | ||||
|  | ||||
|     const filePaths = (await new Promise((resolve, reject) => { | ||||
|  | ||||
|         let promiseRejected = false; | ||||
|  | ||||
|         /** | ||||
|          * Wraps a boolean-returning filter function. The wrapped function will reject the promise if an error occurs. | ||||
|          * @param {Function} filter A filter function to wrap. | ||||
|          * @returns {Function} A function similar to the wrapped filter that rejects the promise if an error occurs. | ||||
|          */ | ||||
|         function wrapFilter(filter) { | ||||
|             return (...args) => { | ||||
|  | ||||
|                 // No need to run the filter if an error has been thrown. | ||||
|                 if (!promiseRejected) { | ||||
|                     try { | ||||
|                         return filter(...args); | ||||
|                     } catch (error) { | ||||
|                         promiseRejected = true; | ||||
|                         reject(error); | ||||
|                     } | ||||
|                 } | ||||
|                 return false; | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         fswalk.walk( | ||||
|             basePath, | ||||
|             { | ||||
|                 deepFilter: wrapFilter(entry => { | ||||
|                     const relativePath = normalizeToPosix(path.relative(basePath, entry.path)); | ||||
|                     const matchesPattern = matchers.some(matcher => matcher.match(relativePath, true)); | ||||
|  | ||||
|                     return matchesPattern && !configs.isDirectoryIgnored(entry.path); | ||||
|                 }), | ||||
|                 entryFilter: wrapFilter(entry => { | ||||
|                     const relativePath = normalizeToPosix(path.relative(basePath, entry.path)); | ||||
|  | ||||
|                     // entries may be directories or files so filter out directories | ||||
|                     if (entry.dirent.isDirectory()) { | ||||
|                         return false; | ||||
|                     } | ||||
|  | ||||
|                     /* | ||||
|                      * Optimization: We need to track when patterns are left unmatched | ||||
|                      * and so we use `unmatchedPatterns` to do that. There is a bit of | ||||
|                      * complexity here because the same file can be matched by more than | ||||
|                      * one pattern. So, when we start, we actually need to test every | ||||
|                      * pattern against every file. Once we know there are no remaining | ||||
|                      * unmatched patterns, then we can switch to just looking for the | ||||
|                      * first matching pattern for improved speed. | ||||
|                      */ | ||||
|                     const matchesPattern = unmatchedPatterns.size > 0 | ||||
|                         ? matchers.reduce((previousValue, matcher) => { | ||||
|                             const pathMatches = matcher.match(relativePath); | ||||
|  | ||||
|                             /* | ||||
|                              * We updated the unmatched patterns set only if the path | ||||
|                              * matches and the file isn't ignored. If the file is | ||||
|                              * ignored, that means there wasn't a match for the | ||||
|                              * pattern so it should not be removed. | ||||
|                              * | ||||
|                              * Performance note: isFileIgnored() aggressively caches | ||||
|                              * results so there is no performance penalty for calling | ||||
|                              * it twice with the same argument. | ||||
|                              */ | ||||
|                             if (pathMatches && !configs.isFileIgnored(entry.path)) { | ||||
|                                 unmatchedPatterns.delete(matcher.pattern); | ||||
|                             } | ||||
|  | ||||
|                             return pathMatches || previousValue; | ||||
|                         }, false) | ||||
|                         : matchers.some(matcher => matcher.match(relativePath)); | ||||
|  | ||||
|                     return matchesPattern && !configs.isFileIgnored(entry.path); | ||||
|                 }) | ||||
|             }, | ||||
|             (error, entries) => { | ||||
|  | ||||
|                 // If the promise is already rejected, calling `resolve` or `reject` will do nothing. | ||||
|                 if (error) { | ||||
|                     reject(error); | ||||
|                 } else { | ||||
|                     resolve(entries); | ||||
|                 } | ||||
|             } | ||||
|         ); | ||||
|     })).map(entry => entry.path); | ||||
|  | ||||
|     // now check to see if we have any unmatched patterns | ||||
|     if (errorOnUnmatchedPattern && unmatchedPatterns.size > 0) { | ||||
|         throw new UnmatchedSearchPatternsError({ | ||||
|             basePath, | ||||
|             unmatchedPatterns: [...unmatchedPatterns].map( | ||||
|                 pattern => relativeToPatterns.get(pattern) | ||||
|             ), | ||||
|             patterns, | ||||
|             rawPatterns | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     return filePaths; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Throws an error for unmatched patterns. The error will only contain information about the first one. | ||||
|  * Checks to see if there are any ignored results for a given search. | ||||
|  * @param {Object} options The options for this function. | ||||
|  * @param {string} options.basePath The directory to search. | ||||
|  * @param {Array<string>} options.patterns An array of glob patterns | ||||
|  *      that were used in the original search. | ||||
|  * @param {Array<string>} options.rawPatterns An array of glob patterns | ||||
|  *      as the user inputted them. Used for errors. | ||||
|  * @param {Array<string>} options.unmatchedPatterns A non-empty array of glob patterns | ||||
|  *      that were unmatched in the original search. | ||||
|  * @returns {void} Always throws an error. | ||||
|  * @throws {NoFilesFoundError} If the first unmatched pattern | ||||
|  *      doesn't match any files even when there are no ignores. | ||||
|  * @throws {AllFilesIgnoredError} If the first unmatched pattern | ||||
|  *      matches some files when there are no ignores. | ||||
|  */ | ||||
| async function throwErrorForUnmatchedPatterns({ | ||||
|     basePath, | ||||
|     patterns, | ||||
|     rawPatterns, | ||||
|     unmatchedPatterns | ||||
| }) { | ||||
|  | ||||
|     const pattern = unmatchedPatterns[0]; | ||||
|     const rawPattern = rawPatterns[patterns.indexOf(pattern)]; | ||||
|  | ||||
|     const patternHasMatch = await globMatch({ | ||||
|         basePath, | ||||
|         pattern | ||||
|     }); | ||||
|  | ||||
|     if (patternHasMatch) { | ||||
|         throw new AllFilesIgnoredError(rawPattern); | ||||
|     } | ||||
|  | ||||
|     // if we get here there are truly no matches | ||||
|     throw new NoFilesFoundError(rawPattern, true); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Performs multiple glob searches in parallel. | ||||
|  * @param {Object} options The options for this function. | ||||
|  * @param {Map<string,GlobSearch>} options.searches | ||||
|  *      An array of glob patterns to match. | ||||
|  * @param {FlatConfigArray} options.configs The config array to use for | ||||
|  *      determining what to ignore. | ||||
|  * @param {boolean} options.errorOnUnmatchedPattern Determines if an | ||||
|  *      unmatched glob pattern should throw an error. | ||||
|  * @returns {Promise<Array<string>>} An array of matching file paths | ||||
|  *      or an empty array if there are no matches. | ||||
|  */ | ||||
| async function globMultiSearch({ searches, configs, errorOnUnmatchedPattern }) { | ||||
|  | ||||
|     /* | ||||
|      * For convenience, we normalized the search map into an array of objects. | ||||
|      * Next, we filter out all searches that have no patterns. This happens | ||||
|      * primarily for the cwd, which is prepopulated in the searches map as an | ||||
|      * optimization. However, if it has no patterns, it means all patterns | ||||
|      * occur outside of the cwd and we can safely filter out that search. | ||||
|      */ | ||||
|     const normalizedSearches = [...searches].map( | ||||
|         ([basePath, { patterns, rawPatterns }]) => ({ basePath, patterns, rawPatterns }) | ||||
|     ).filter(({ patterns }) => patterns.length > 0); | ||||
|  | ||||
|     const results = await Promise.allSettled( | ||||
|         normalizedSearches.map( | ||||
|             ({ basePath, patterns, rawPatterns }) => globSearch({ | ||||
|                 basePath, | ||||
|                 patterns, | ||||
|                 rawPatterns, | ||||
|                 configs, | ||||
|                 errorOnUnmatchedPattern | ||||
|             }) | ||||
|         ) | ||||
|     ); | ||||
|  | ||||
|     const filePaths = []; | ||||
|  | ||||
|     for (let i = 0; i < results.length; i++) { | ||||
|  | ||||
|         const result = results[i]; | ||||
|         const currentSearch = normalizedSearches[i]; | ||||
|  | ||||
|         if (result.status === "fulfilled") { | ||||
|  | ||||
|             // if the search was successful just add the results | ||||
|             if (result.value.length > 0) { | ||||
|                 filePaths.push(...result.value); | ||||
|             } | ||||
|  | ||||
|             continue; | ||||
|         } | ||||
|  | ||||
|         // if we make it here then there was an error | ||||
|         const error = result.reason; | ||||
|  | ||||
|         // unexpected errors should be re-thrown | ||||
|         if (!error.basePath) { | ||||
|             throw error; | ||||
|         } | ||||
|  | ||||
|         if (errorOnUnmatchedPattern) { | ||||
|  | ||||
|             await throwErrorForUnmatchedPatterns({ | ||||
|                 ...currentSearch, | ||||
|                 unmatchedPatterns: error.unmatchedPatterns | ||||
|             }); | ||||
|  | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     return filePaths; | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Finds all files matching the options specified. | ||||
|  * @param {Object} args The arguments objects. | ||||
|  * @param {Array<string>} args.patterns An array of glob patterns. | ||||
|  * @param {boolean} args.globInputPaths true to interpret glob patterns, | ||||
|  *      false to not interpret glob patterns. | ||||
|  * @param {string} args.cwd The current working directory to find from. | ||||
|  * @param {FlatConfigArray} args.configs The configs for the current run. | ||||
|  * @param {boolean} args.errorOnUnmatchedPattern Determines if an unmatched pattern | ||||
|  *      should throw an error. | ||||
|  * @returns {Promise<Array<string>>} The fully resolved file paths. | ||||
|  * @throws {AllFilesIgnoredError} If there are no results due to an ignore pattern. | ||||
|  * @throws {NoFilesFoundError} If no files matched the given patterns. | ||||
|  */ | ||||
| async function findFiles({ | ||||
|     patterns, | ||||
|     globInputPaths, | ||||
|     cwd, | ||||
|     configs, | ||||
|     errorOnUnmatchedPattern | ||||
| }) { | ||||
|  | ||||
|     const results = []; | ||||
|     const missingPatterns = []; | ||||
|     let globbyPatterns = []; | ||||
|     let rawPatterns = []; | ||||
|     const searches = new Map([[cwd, { patterns: globbyPatterns, rawPatterns: [] }]]); | ||||
|  | ||||
|     // check to see if we have explicit files and directories | ||||
|     const filePaths = patterns.map(filePath => path.resolve(cwd, filePath)); | ||||
|     const stats = await Promise.all( | ||||
|         filePaths.map( | ||||
|             filePath => fsp.stat(filePath).catch(() => { }) | ||||
|         ) | ||||
|     ); | ||||
|  | ||||
|     stats.forEach((stat, index) => { | ||||
|  | ||||
|         const filePath = filePaths[index]; | ||||
|         const pattern = normalizeToPosix(patterns[index]); | ||||
|  | ||||
|         if (stat) { | ||||
|  | ||||
|             // files are added directly to the list | ||||
|             if (stat.isFile()) { | ||||
|                 results.push(filePath); | ||||
|             } | ||||
|  | ||||
|             // directories need extensions attached | ||||
|             if (stat.isDirectory()) { | ||||
|  | ||||
|                 // group everything in cwd together and split out others | ||||
|                 if (isPathInside(filePath, cwd)) { | ||||
|                     ({ patterns: globbyPatterns, rawPatterns } = searches.get(cwd)); | ||||
|                 } else { | ||||
|                     if (!searches.has(filePath)) { | ||||
|                         searches.set(filePath, { patterns: [], rawPatterns: [] }); | ||||
|                     } | ||||
|                     ({ patterns: globbyPatterns, rawPatterns } = searches.get(filePath)); | ||||
|                 } | ||||
|  | ||||
|                 globbyPatterns.push(`${normalizeToPosix(filePath)}/**`); | ||||
|                 rawPatterns.push(pattern); | ||||
|             } | ||||
|  | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         // save patterns for later use based on whether globs are enabled | ||||
|         if (globInputPaths && isGlobPattern(pattern)) { | ||||
|  | ||||
|             const basePath = path.resolve(cwd, globParent(pattern)); | ||||
|  | ||||
|             // group in cwd if possible and split out others | ||||
|             if (isPathInside(basePath, cwd)) { | ||||
|                 ({ patterns: globbyPatterns, rawPatterns } = searches.get(cwd)); | ||||
|             } else { | ||||
|                 if (!searches.has(basePath)) { | ||||
|                     searches.set(basePath, { patterns: [], rawPatterns: [] }); | ||||
|                 } | ||||
|                 ({ patterns: globbyPatterns, rawPatterns } = searches.get(basePath)); | ||||
|             } | ||||
|  | ||||
|             globbyPatterns.push(filePath); | ||||
|             rawPatterns.push(pattern); | ||||
|         } else { | ||||
|             missingPatterns.push(pattern); | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     // there were patterns that didn't match anything, tell the user | ||||
|     if (errorOnUnmatchedPattern && missingPatterns.length) { | ||||
|         throw new NoFilesFoundError(missingPatterns[0], globInputPaths); | ||||
|     } | ||||
|  | ||||
|     // now we are safe to do the search | ||||
|     const globbyResults = await globMultiSearch({ | ||||
|         searches, | ||||
|         configs, | ||||
|         errorOnUnmatchedPattern | ||||
|     }); | ||||
|  | ||||
|     return [ | ||||
|         ...new Set([ | ||||
|             ...results, | ||||
|             ...globbyResults.map(filePath => path.resolve(filePath)) | ||||
|         ]) | ||||
|     ]; | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Results-related Helpers | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Checks if the given message is an error message. | ||||
|  * @param {LintMessage} message The message to check. | ||||
|  * @returns {boolean} Whether or not the message is an error message. | ||||
|  * @private | ||||
|  */ | ||||
| function isErrorMessage(message) { | ||||
|     return message.severity === 2; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Returns result with warning by ignore settings | ||||
|  * @param {string} filePath File path of checked code | ||||
|  * @param {string} baseDir Absolute path of base directory | ||||
|  * @returns {LintResult} Result with single warning | ||||
|  * @private | ||||
|  */ | ||||
| function createIgnoreResult(filePath, baseDir) { | ||||
|     let message; | ||||
|     const isInNodeModules = baseDir && path.dirname(path.relative(baseDir, filePath)).split(path.sep).includes("node_modules"); | ||||
|  | ||||
|     if (isInNodeModules) { | ||||
|         message = "File ignored by default because it is located under the node_modules directory. Use ignore pattern \"!**/node_modules/\" to disable file ignore settings or use \"--no-warn-ignored\" to suppress this warning."; | ||||
|     } else { | ||||
|         message = "File ignored because of a matching ignore pattern. Use \"--no-ignore\" to disable file ignore settings or use \"--no-warn-ignored\" to suppress this warning."; | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         filePath: path.resolve(filePath), | ||||
|         messages: [ | ||||
|             { | ||||
|                 ruleId: null, | ||||
|                 fatal: false, | ||||
|                 severity: 1, | ||||
|                 message, | ||||
|                 nodeType: null | ||||
|             } | ||||
|         ], | ||||
|         suppressedMessages: [], | ||||
|         errorCount: 0, | ||||
|         warningCount: 1, | ||||
|         fatalErrorCount: 0, | ||||
|         fixableErrorCount: 0, | ||||
|         fixableWarningCount: 0 | ||||
|     }; | ||||
| } | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Options-related Helpers | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Check if a given value is a valid fix type or not. | ||||
|  * @param {any} x The value to check. | ||||
|  * @returns {boolean} `true` if `x` is valid fix type. | ||||
|  */ | ||||
| function isFixType(x) { | ||||
|     return x === "directive" || x === "problem" || x === "suggestion" || x === "layout"; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check if a given value is an array of fix types or not. | ||||
|  * @param {any} x The value to check. | ||||
|  * @returns {boolean} `true` if `x` is an array of fix types. | ||||
|  */ | ||||
| function isFixTypeArray(x) { | ||||
|     return Array.isArray(x) && x.every(isFixType); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The error for invalid options. | ||||
|  */ | ||||
| class ESLintInvalidOptionsError extends Error { | ||||
|     constructor(messages) { | ||||
|         super(`Invalid Options:\n- ${messages.join("\n- ")}`); | ||||
|         this.code = "ESLINT_INVALID_OPTIONS"; | ||||
|         Error.captureStackTrace(this, ESLintInvalidOptionsError); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Validates and normalizes options for the wrapped CLIEngine instance. | ||||
|  * @param {FlatESLintOptions} options The options to process. | ||||
|  * @throws {ESLintInvalidOptionsError} If of any of a variety of type errors. | ||||
|  * @returns {FlatESLintOptions} The normalized options. | ||||
|  */ | ||||
| function processOptions({ | ||||
|     allowInlineConfig = true, // ← we cannot use `overrideConfig.noInlineConfig` instead because `allowInlineConfig` has side-effect that suppress warnings that show inline configs are ignored. | ||||
|     baseConfig = null, | ||||
|     cache = false, | ||||
|     cacheLocation = ".eslintcache", | ||||
|     cacheStrategy = "metadata", | ||||
|     cwd = process.cwd(), | ||||
|     errorOnUnmatchedPattern = true, | ||||
|     fix = false, | ||||
|     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. | ||||
|     globInputPaths = true, | ||||
|     ignore = true, | ||||
|     ignorePatterns = null, | ||||
|     overrideConfig = null, | ||||
|     overrideConfigFile = null, | ||||
|     plugins = {}, | ||||
|     warnIgnored = true, | ||||
|     ...unknownOptions | ||||
| }) { | ||||
|     const errors = []; | ||||
|     const unknownOptionKeys = Object.keys(unknownOptions); | ||||
|  | ||||
|     if (unknownOptionKeys.length >= 1) { | ||||
|         errors.push(`Unknown options: ${unknownOptionKeys.join(", ")}`); | ||||
|         if (unknownOptionKeys.includes("cacheFile")) { | ||||
|             errors.push("'cacheFile' has been removed. Please use the 'cacheLocation' option instead."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("configFile")) { | ||||
|             errors.push("'configFile' has been removed. Please use the 'overrideConfigFile' option instead."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("envs")) { | ||||
|             errors.push("'envs' has been removed."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("extensions")) { | ||||
|             errors.push("'extensions' has been removed."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("resolvePluginsRelativeTo")) { | ||||
|             errors.push("'resolvePluginsRelativeTo' has been removed."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("globals")) { | ||||
|             errors.push("'globals' has been removed. Please use the 'overrideConfig.languageOptions.globals' option instead."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("ignorePath")) { | ||||
|             errors.push("'ignorePath' has been removed."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("ignorePattern")) { | ||||
|             errors.push("'ignorePattern' has been removed. Please use the 'overrideConfig.ignorePatterns' option instead."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("parser")) { | ||||
|             errors.push("'parser' has been removed. Please use the 'overrideConfig.languageOptions.parser' option instead."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("parserOptions")) { | ||||
|             errors.push("'parserOptions' has been removed. Please use the 'overrideConfig.languageOptions.parserOptions' option instead."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("rules")) { | ||||
|             errors.push("'rules' has been removed. Please use the 'overrideConfig.rules' option instead."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("rulePaths")) { | ||||
|             errors.push("'rulePaths' has been removed. Please define your rules using plugins."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("reportUnusedDisableDirectives")) { | ||||
|             errors.push("'reportUnusedDisableDirectives' has been removed. Please use the 'overrideConfig.linterOptions.reportUnusedDisableDirectives' option instead."); | ||||
|         } | ||||
|     } | ||||
|     if (typeof allowInlineConfig !== "boolean") { | ||||
|         errors.push("'allowInlineConfig' must be a boolean."); | ||||
|     } | ||||
|     if (typeof baseConfig !== "object") { | ||||
|         errors.push("'baseConfig' must be an object or null."); | ||||
|     } | ||||
|     if (typeof cache !== "boolean") { | ||||
|         errors.push("'cache' must be a boolean."); | ||||
|     } | ||||
|     if (!isNonEmptyString(cacheLocation)) { | ||||
|         errors.push("'cacheLocation' must be a non-empty string."); | ||||
|     } | ||||
|     if ( | ||||
|         cacheStrategy !== "metadata" && | ||||
|         cacheStrategy !== "content" | ||||
|     ) { | ||||
|         errors.push("'cacheStrategy' must be any of \"metadata\", \"content\"."); | ||||
|     } | ||||
|     if (!isNonEmptyString(cwd) || !path.isAbsolute(cwd)) { | ||||
|         errors.push("'cwd' must be an absolute path."); | ||||
|     } | ||||
|     if (typeof errorOnUnmatchedPattern !== "boolean") { | ||||
|         errors.push("'errorOnUnmatchedPattern' must be a boolean."); | ||||
|     } | ||||
|     if (typeof fix !== "boolean" && typeof fix !== "function") { | ||||
|         errors.push("'fix' must be a boolean or a function."); | ||||
|     } | ||||
|     if (fixTypes !== null && !isFixTypeArray(fixTypes)) { | ||||
|         errors.push("'fixTypes' must be an array of any of \"directive\", \"problem\", \"suggestion\", and \"layout\"."); | ||||
|     } | ||||
|     if (typeof globInputPaths !== "boolean") { | ||||
|         errors.push("'globInputPaths' must be a boolean."); | ||||
|     } | ||||
|     if (typeof ignore !== "boolean") { | ||||
|         errors.push("'ignore' must be a boolean."); | ||||
|     } | ||||
|     if (!isArrayOfNonEmptyString(ignorePatterns) && ignorePatterns !== null) { | ||||
|         errors.push("'ignorePatterns' must be an array of non-empty strings or null."); | ||||
|     } | ||||
|     if (typeof overrideConfig !== "object") { | ||||
|         errors.push("'overrideConfig' must be an object or null."); | ||||
|     } | ||||
|     if (!isNonEmptyString(overrideConfigFile) && overrideConfigFile !== null && overrideConfigFile !== true) { | ||||
|         errors.push("'overrideConfigFile' must be a non-empty string, null, or true."); | ||||
|     } | ||||
|     if (typeof plugins !== "object") { | ||||
|         errors.push("'plugins' must be an object or null."); | ||||
|     } else if (plugins !== null && Object.keys(plugins).includes("")) { | ||||
|         errors.push("'plugins' must not include an empty string."); | ||||
|     } | ||||
|     if (Array.isArray(plugins)) { | ||||
|         errors.push("'plugins' doesn't add plugins to configuration to load. Please use the 'overrideConfig.plugins' option instead."); | ||||
|     } | ||||
|     if (typeof warnIgnored !== "boolean") { | ||||
|         errors.push("'warnIgnored' must be a boolean."); | ||||
|     } | ||||
|     if (errors.length > 0) { | ||||
|         throw new ESLintInvalidOptionsError(errors); | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         allowInlineConfig, | ||||
|         baseConfig, | ||||
|         cache, | ||||
|         cacheLocation, | ||||
|         cacheStrategy, | ||||
|  | ||||
|         // when overrideConfigFile is true that means don't do config file lookup | ||||
|         configFile: overrideConfigFile === true ? false : overrideConfigFile, | ||||
|         overrideConfig, | ||||
|         cwd: path.normalize(cwd), | ||||
|         errorOnUnmatchedPattern, | ||||
|         fix, | ||||
|         fixTypes, | ||||
|         globInputPaths, | ||||
|         ignore, | ||||
|         ignorePatterns, | ||||
|         warnIgnored | ||||
|     }; | ||||
| } | ||||
|  | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Cache-related helpers | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * return the cacheFile to be used by eslint, based on whether the provided parameter is | ||||
|  * a directory or looks like a directory (ends in `path.sep`), in which case the file | ||||
|  * name will be the `cacheFile/.cache_hashOfCWD` | ||||
|  * | ||||
|  * if cacheFile points to a file or looks like a file then in will just use that file | ||||
|  * @param {string} cacheFile The name of file to be used to store the cache | ||||
|  * @param {string} cwd Current working directory | ||||
|  * @returns {string} the resolved path to the cache file | ||||
|  */ | ||||
| function getCacheFile(cacheFile, cwd) { | ||||
|  | ||||
|     /* | ||||
|      * make sure the path separators are normalized for the environment/os | ||||
|      * keeping the trailing path separator if present | ||||
|      */ | ||||
|     const normalizedCacheFile = path.normalize(cacheFile); | ||||
|  | ||||
|     const resolvedCacheFile = path.resolve(cwd, normalizedCacheFile); | ||||
|     const looksLikeADirectory = normalizedCacheFile.slice(-1) === path.sep; | ||||
|  | ||||
|     /** | ||||
|      * return the name for the cache file in case the provided parameter is a directory | ||||
|      * @returns {string} the resolved path to the cacheFile | ||||
|      */ | ||||
|     function getCacheFileForDirectory() { | ||||
|         return path.join(resolvedCacheFile, `.cache_${hash(cwd)}`); | ||||
|     } | ||||
|  | ||||
|     let fileStats; | ||||
|  | ||||
|     try { | ||||
|         fileStats = fs.lstatSync(resolvedCacheFile); | ||||
|     } catch { | ||||
|         fileStats = null; | ||||
|     } | ||||
|  | ||||
|  | ||||
|     /* | ||||
|      * in case the file exists we need to verify if the provided path | ||||
|      * is a directory or a file. If it is a directory we want to create a file | ||||
|      * inside that directory | ||||
|      */ | ||||
|     if (fileStats) { | ||||
|  | ||||
|         /* | ||||
|          * is a directory or is a file, but the original file the user provided | ||||
|          * looks like a directory but `path.resolve` removed the `last path.sep` | ||||
|          * so we need to still treat this like a directory | ||||
|          */ | ||||
|         if (fileStats.isDirectory() || looksLikeADirectory) { | ||||
|             return getCacheFileForDirectory(); | ||||
|         } | ||||
|  | ||||
|         // is file so just use that file | ||||
|         return resolvedCacheFile; | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * here we known the file or directory doesn't exist, | ||||
|      * so we will try to infer if its a directory if it looks like a directory | ||||
|      * for the current operating system. | ||||
|      */ | ||||
|  | ||||
|     // if the last character passed is a path separator we assume is a directory | ||||
|     if (looksLikeADirectory) { | ||||
|         return getCacheFileForDirectory(); | ||||
|     } | ||||
|  | ||||
|     return resolvedCacheFile; | ||||
| } | ||||
|  | ||||
|  | ||||
| //----------------------------------------------------------------------------- | ||||
| // Exports | ||||
| //----------------------------------------------------------------------------- | ||||
|  | ||||
| module.exports = { | ||||
|     isGlobPattern, | ||||
|     findFiles, | ||||
|  | ||||
|     isNonEmptyString, | ||||
|     isArrayOfNonEmptyString, | ||||
|  | ||||
|     createIgnoreResult, | ||||
|     isErrorMessage, | ||||
|  | ||||
|     processOptions, | ||||
|  | ||||
|     getCacheFile | ||||
| }; | ||||
							
								
								
									
										707
									
								
								node_modules/eslint/lib/eslint/eslint.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										707
									
								
								node_modules/eslint/lib/eslint/eslint.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,707 @@ | ||||
| /** | ||||
|  * @fileoverview Main API Class | ||||
|  * @author Kai Cataldo | ||||
|  * @author Toru Nagashima | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const path = require("path"); | ||||
| const fs = require("fs"); | ||||
| const { promisify } = require("util"); | ||||
| const { CLIEngine, getCLIEngineInternalSlots } = require("../cli-engine/cli-engine"); | ||||
| const BuiltinRules = require("../rules"); | ||||
| const { | ||||
|     Legacy: { | ||||
|         ConfigOps: { | ||||
|             getRuleSeverity | ||||
|         } | ||||
|     } | ||||
| } = require("@eslint/eslintrc"); | ||||
| const { version } = require("../../package.json"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Typedefs | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @typedef {import("../cli-engine/cli-engine").LintReport} CLIEngineLintReport */ | ||||
| /** @typedef {import("../shared/types").DeprecatedRuleInfo} DeprecatedRuleInfo */ | ||||
| /** @typedef {import("../shared/types").ConfigData} ConfigData */ | ||||
| /** @typedef {import("../shared/types").LintMessage} LintMessage */ | ||||
| /** @typedef {import("../shared/types").SuppressedLintMessage} SuppressedLintMessage */ | ||||
| /** @typedef {import("../shared/types").Plugin} Plugin */ | ||||
| /** @typedef {import("../shared/types").Rule} Rule */ | ||||
| /** @typedef {import("../shared/types").LintResult} LintResult */ | ||||
| /** @typedef {import("../shared/types").ResultsMeta} ResultsMeta */ | ||||
|  | ||||
| /** | ||||
|  * The main formatter object. | ||||
|  * @typedef LoadedFormatter | ||||
|  * @property {(results: LintResult[], resultsMeta: ResultsMeta) => string | Promise<string>} format format function. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * The options with which to configure the ESLint instance. | ||||
|  * @typedef {Object} ESLintOptions | ||||
|  * @property {boolean} [allowInlineConfig] Enable or disable inline configuration comments. | ||||
|  * @property {ConfigData} [baseConfig] Base config object, extended by all configs used with this instance | ||||
|  * @property {boolean} [cache] Enable result caching. | ||||
|  * @property {string} [cacheLocation] The cache file to use instead of .eslintcache. | ||||
|  * @property {"metadata" | "content"} [cacheStrategy] The strategy used to detect changed files. | ||||
|  * @property {string} [cwd] The value to use for the current working directory. | ||||
|  * @property {boolean} [errorOnUnmatchedPattern] If `false` then `ESLint#lintFiles()` doesn't throw even if no target files found. Defaults to `true`. | ||||
|  * @property {string[]} [extensions] An array of file extensions to check. | ||||
|  * @property {boolean|Function} [fix] Execute in autofix mode. If a function, should return a boolean. | ||||
|  * @property {string[]} [fixTypes] Array of rule types to apply fixes for. | ||||
|  * @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. | ||||
|  * @property {boolean} [ignore] False disables use of .eslintignore. | ||||
|  * @property {string} [ignorePath] The ignore file to use instead of .eslintignore. | ||||
|  * @property {ConfigData} [overrideConfig] Override config object, overrides all configs used with this instance | ||||
|  * @property {string} [overrideConfigFile] The configuration file to use. | ||||
|  * @property {Record<string,Plugin>|null} [plugins] Preloaded plugins. This is a map-like object, keys are plugin IDs and each value is implementation. | ||||
|  * @property {"error" | "warn" | "off"} [reportUnusedDisableDirectives] the severity to report unused eslint-disable directives. | ||||
|  * @property {string} [resolvePluginsRelativeTo] The folder where plugins should be resolved from, defaulting to the CWD. | ||||
|  * @property {string[]} [rulePaths] An array of directories to load custom rules from. | ||||
|  * @property {boolean} [useEslintrc] False disables looking for .eslintrc.* files. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * A rules metadata object. | ||||
|  * @typedef {Object} RulesMeta | ||||
|  * @property {string} id The plugin ID. | ||||
|  * @property {Object} definition The plugin definition. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Private members for the `ESLint` instance. | ||||
|  * @typedef {Object} ESLintPrivateMembers | ||||
|  * @property {CLIEngine} cliEngine The wrapped CLIEngine instance. | ||||
|  * @property {ESLintOptions} options The options used to instantiate the ESLint instance. | ||||
|  */ | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const writeFile = promisify(fs.writeFile); | ||||
|  | ||||
| /** | ||||
|  * The map with which to store private class members. | ||||
|  * @type {WeakMap<ESLint, ESLintPrivateMembers>} | ||||
|  */ | ||||
| const privateMembersMap = new WeakMap(); | ||||
|  | ||||
| /** | ||||
|  * Check if a given value is a non-empty string or not. | ||||
|  * @param {any} x The value to check. | ||||
|  * @returns {boolean} `true` if `x` is a non-empty string. | ||||
|  */ | ||||
| function isNonEmptyString(x) { | ||||
|     return typeof x === "string" && x.trim() !== ""; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check if a given value is an array of non-empty strings or not. | ||||
|  * @param {any} x The value to check. | ||||
|  * @returns {boolean} `true` if `x` is an array of non-empty strings. | ||||
|  */ | ||||
| function isArrayOfNonEmptyString(x) { | ||||
|     return Array.isArray(x) && x.every(isNonEmptyString); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check if a given value is a valid fix type or not. | ||||
|  * @param {any} x The value to check. | ||||
|  * @returns {boolean} `true` if `x` is valid fix type. | ||||
|  */ | ||||
| function isFixType(x) { | ||||
|     return x === "directive" || x === "problem" || x === "suggestion" || x === "layout"; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check if a given value is an array of fix types or not. | ||||
|  * @param {any} x The value to check. | ||||
|  * @returns {boolean} `true` if `x` is an array of fix types. | ||||
|  */ | ||||
| function isFixTypeArray(x) { | ||||
|     return Array.isArray(x) && x.every(isFixType); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The error for invalid options. | ||||
|  */ | ||||
| class ESLintInvalidOptionsError extends Error { | ||||
|     constructor(messages) { | ||||
|         super(`Invalid Options:\n- ${messages.join("\n- ")}`); | ||||
|         this.code = "ESLINT_INVALID_OPTIONS"; | ||||
|         Error.captureStackTrace(this, ESLintInvalidOptionsError); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Validates and normalizes options for the wrapped CLIEngine instance. | ||||
|  * @param {ESLintOptions} options The options to process. | ||||
|  * @throws {ESLintInvalidOptionsError} If of any of a variety of type errors. | ||||
|  * @returns {ESLintOptions} The normalized options. | ||||
|  */ | ||||
| function processOptions({ | ||||
|     allowInlineConfig = true, // ← we cannot use `overrideConfig.noInlineConfig` instead because `allowInlineConfig` has side-effect that suppress warnings that show inline configs are ignored. | ||||
|     baseConfig = null, | ||||
|     cache = false, | ||||
|     cacheLocation = ".eslintcache", | ||||
|     cacheStrategy = "metadata", | ||||
|     cwd = process.cwd(), | ||||
|     errorOnUnmatchedPattern = true, | ||||
|     extensions = null, // ← should be null by default because if it's an array then it suppresses RFC20 feature. | ||||
|     fix = false, | ||||
|     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. | ||||
|     globInputPaths = true, | ||||
|     ignore = true, | ||||
|     ignorePath = null, // ← should be null by default because if it's a string then it may throw ENOENT. | ||||
|     overrideConfig = null, | ||||
|     overrideConfigFile = null, | ||||
|     plugins = {}, | ||||
|     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. | ||||
|     resolvePluginsRelativeTo = null, // ← should be null by default because if it's a string then it suppresses RFC47 feature. | ||||
|     rulePaths = [], | ||||
|     useEslintrc = true, | ||||
|     ...unknownOptions | ||||
| }) { | ||||
|     const errors = []; | ||||
|     const unknownOptionKeys = Object.keys(unknownOptions); | ||||
|  | ||||
|     if (unknownOptionKeys.length >= 1) { | ||||
|         errors.push(`Unknown options: ${unknownOptionKeys.join(", ")}`); | ||||
|         if (unknownOptionKeys.includes("cacheFile")) { | ||||
|             errors.push("'cacheFile' has been removed. Please use the 'cacheLocation' option instead."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("configFile")) { | ||||
|             errors.push("'configFile' has been removed. Please use the 'overrideConfigFile' option instead."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("envs")) { | ||||
|             errors.push("'envs' has been removed. Please use the 'overrideConfig.env' option instead."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("globals")) { | ||||
|             errors.push("'globals' has been removed. Please use the 'overrideConfig.globals' option instead."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("ignorePattern")) { | ||||
|             errors.push("'ignorePattern' has been removed. Please use the 'overrideConfig.ignorePatterns' option instead."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("parser")) { | ||||
|             errors.push("'parser' has been removed. Please use the 'overrideConfig.parser' option instead."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("parserOptions")) { | ||||
|             errors.push("'parserOptions' has been removed. Please use the 'overrideConfig.parserOptions' option instead."); | ||||
|         } | ||||
|         if (unknownOptionKeys.includes("rules")) { | ||||
|             errors.push("'rules' has been removed. Please use the 'overrideConfig.rules' option instead."); | ||||
|         } | ||||
|     } | ||||
|     if (typeof allowInlineConfig !== "boolean") { | ||||
|         errors.push("'allowInlineConfig' must be a boolean."); | ||||
|     } | ||||
|     if (typeof baseConfig !== "object") { | ||||
|         errors.push("'baseConfig' must be an object or null."); | ||||
|     } | ||||
|     if (typeof cache !== "boolean") { | ||||
|         errors.push("'cache' must be a boolean."); | ||||
|     } | ||||
|     if (!isNonEmptyString(cacheLocation)) { | ||||
|         errors.push("'cacheLocation' must be a non-empty string."); | ||||
|     } | ||||
|     if ( | ||||
|         cacheStrategy !== "metadata" && | ||||
|         cacheStrategy !== "content" | ||||
|     ) { | ||||
|         errors.push("'cacheStrategy' must be any of \"metadata\", \"content\"."); | ||||
|     } | ||||
|     if (!isNonEmptyString(cwd) || !path.isAbsolute(cwd)) { | ||||
|         errors.push("'cwd' must be an absolute path."); | ||||
|     } | ||||
|     if (typeof errorOnUnmatchedPattern !== "boolean") { | ||||
|         errors.push("'errorOnUnmatchedPattern' must be a boolean."); | ||||
|     } | ||||
|     if (!isArrayOfNonEmptyString(extensions) && extensions !== null) { | ||||
|         errors.push("'extensions' must be an array of non-empty strings or null."); | ||||
|     } | ||||
|     if (typeof fix !== "boolean" && typeof fix !== "function") { | ||||
|         errors.push("'fix' must be a boolean or a function."); | ||||
|     } | ||||
|     if (fixTypes !== null && !isFixTypeArray(fixTypes)) { | ||||
|         errors.push("'fixTypes' must be an array of any of \"directive\", \"problem\", \"suggestion\", and \"layout\"."); | ||||
|     } | ||||
|     if (typeof globInputPaths !== "boolean") { | ||||
|         errors.push("'globInputPaths' must be a boolean."); | ||||
|     } | ||||
|     if (typeof ignore !== "boolean") { | ||||
|         errors.push("'ignore' must be a boolean."); | ||||
|     } | ||||
|     if (!isNonEmptyString(ignorePath) && ignorePath !== null) { | ||||
|         errors.push("'ignorePath' must be a non-empty string or null."); | ||||
|     } | ||||
|     if (typeof overrideConfig !== "object") { | ||||
|         errors.push("'overrideConfig' must be an object or null."); | ||||
|     } | ||||
|     if (!isNonEmptyString(overrideConfigFile) && overrideConfigFile !== null) { | ||||
|         errors.push("'overrideConfigFile' must be a non-empty string or null."); | ||||
|     } | ||||
|     if (typeof plugins !== "object") { | ||||
|         errors.push("'plugins' must be an object or null."); | ||||
|     } else if (plugins !== null && Object.keys(plugins).includes("")) { | ||||
|         errors.push("'plugins' must not include an empty string."); | ||||
|     } | ||||
|     if (Array.isArray(plugins)) { | ||||
|         errors.push("'plugins' doesn't add plugins to configuration to load. Please use the 'overrideConfig.plugins' option instead."); | ||||
|     } | ||||
|     if ( | ||||
|         reportUnusedDisableDirectives !== "error" && | ||||
|         reportUnusedDisableDirectives !== "warn" && | ||||
|         reportUnusedDisableDirectives !== "off" && | ||||
|         reportUnusedDisableDirectives !== null | ||||
|     ) { | ||||
|         errors.push("'reportUnusedDisableDirectives' must be any of \"error\", \"warn\", \"off\", and null."); | ||||
|     } | ||||
|     if ( | ||||
|         !isNonEmptyString(resolvePluginsRelativeTo) && | ||||
|         resolvePluginsRelativeTo !== null | ||||
|     ) { | ||||
|         errors.push("'resolvePluginsRelativeTo' must be a non-empty string or null."); | ||||
|     } | ||||
|     if (!isArrayOfNonEmptyString(rulePaths)) { | ||||
|         errors.push("'rulePaths' must be an array of non-empty strings."); | ||||
|     } | ||||
|     if (typeof useEslintrc !== "boolean") { | ||||
|         errors.push("'useEslintrc' must be a boolean."); | ||||
|     } | ||||
|  | ||||
|     if (errors.length > 0) { | ||||
|         throw new ESLintInvalidOptionsError(errors); | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         allowInlineConfig, | ||||
|         baseConfig, | ||||
|         cache, | ||||
|         cacheLocation, | ||||
|         cacheStrategy, | ||||
|         configFile: overrideConfigFile, | ||||
|         cwd: path.normalize(cwd), | ||||
|         errorOnUnmatchedPattern, | ||||
|         extensions, | ||||
|         fix, | ||||
|         fixTypes, | ||||
|         globInputPaths, | ||||
|         ignore, | ||||
|         ignorePath, | ||||
|         reportUnusedDisableDirectives, | ||||
|         resolvePluginsRelativeTo, | ||||
|         rulePaths, | ||||
|         useEslintrc | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check if a value has one or more properties and that value is not undefined. | ||||
|  * @param {any} obj The value to check. | ||||
|  * @returns {boolean} `true` if `obj` has one or more properties that that value is not undefined. | ||||
|  */ | ||||
| function hasDefinedProperty(obj) { | ||||
|     if (typeof obj === "object" && obj !== null) { | ||||
|         for (const key in obj) { | ||||
|             if (typeof obj[key] !== "undefined") { | ||||
|                 return true; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Create rulesMeta object. | ||||
|  * @param {Map<string,Rule>} rules a map of rules from which to generate the object. | ||||
|  * @returns {Object} metadata for all enabled rules. | ||||
|  */ | ||||
| function createRulesMeta(rules) { | ||||
|     return Array.from(rules).reduce((retVal, [id, rule]) => { | ||||
|         retVal[id] = rule.meta; | ||||
|         return retVal; | ||||
|     }, {}); | ||||
| } | ||||
|  | ||||
| /** @type {WeakMap<ExtractedConfig, DeprecatedRuleInfo[]>} */ | ||||
| const usedDeprecatedRulesCache = new WeakMap(); | ||||
|  | ||||
| /** | ||||
|  * Create used deprecated rule list. | ||||
|  * @param {CLIEngine} cliEngine The CLIEngine instance. | ||||
|  * @param {string} maybeFilePath The absolute path to a lint target file or `"<text>"`. | ||||
|  * @returns {DeprecatedRuleInfo[]} The used deprecated rule list. | ||||
|  */ | ||||
| function getOrFindUsedDeprecatedRules(cliEngine, maybeFilePath) { | ||||
|     const { | ||||
|         configArrayFactory, | ||||
|         options: { cwd } | ||||
|     } = getCLIEngineInternalSlots(cliEngine); | ||||
|     const filePath = path.isAbsolute(maybeFilePath) | ||||
|         ? maybeFilePath | ||||
|         : path.join(cwd, "__placeholder__.js"); | ||||
|     const configArray = configArrayFactory.getConfigArrayForFile(filePath); | ||||
|     const config = configArray.extractConfig(filePath); | ||||
|  | ||||
|     // Most files use the same config, so cache it. | ||||
|     if (!usedDeprecatedRulesCache.has(config)) { | ||||
|         const pluginRules = configArray.pluginRules; | ||||
|         const retv = []; | ||||
|  | ||||
|         for (const [ruleId, ruleConf] of Object.entries(config.rules)) { | ||||
|             if (getRuleSeverity(ruleConf) === 0) { | ||||
|                 continue; | ||||
|             } | ||||
|             const rule = pluginRules.get(ruleId) || BuiltinRules.get(ruleId); | ||||
|             const meta = rule && rule.meta; | ||||
|  | ||||
|             if (meta && meta.deprecated) { | ||||
|                 retv.push({ ruleId, replacedBy: meta.replacedBy || [] }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         usedDeprecatedRulesCache.set(config, Object.freeze(retv)); | ||||
|     } | ||||
|  | ||||
|     return usedDeprecatedRulesCache.get(config); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Processes the linting results generated by a CLIEngine linting report to | ||||
|  * match the ESLint class's API. | ||||
|  * @param {CLIEngine} cliEngine The CLIEngine instance. | ||||
|  * @param {CLIEngineLintReport} report The CLIEngine linting report to process. | ||||
|  * @returns {LintResult[]} The processed linting results. | ||||
|  */ | ||||
| function processCLIEngineLintReport(cliEngine, { results }) { | ||||
|     const descriptor = { | ||||
|         configurable: true, | ||||
|         enumerable: true, | ||||
|         get() { | ||||
|             return getOrFindUsedDeprecatedRules(cliEngine, this.filePath); | ||||
|         } | ||||
|     }; | ||||
|  | ||||
|     for (const result of results) { | ||||
|         Object.defineProperty(result, "usedDeprecatedRules", descriptor); | ||||
|     } | ||||
|  | ||||
|     return results; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * An Array.prototype.sort() compatible compare function to order results by their file path. | ||||
|  * @param {LintResult} a The first lint result. | ||||
|  * @param {LintResult} b The second lint result. | ||||
|  * @returns {number} An integer representing the order in which the two results should occur. | ||||
|  */ | ||||
| function compareResultsByFilePath(a, b) { | ||||
|     if (a.filePath < b.filePath) { | ||||
|         return -1; | ||||
|     } | ||||
|  | ||||
|     if (a.filePath > b.filePath) { | ||||
|         return 1; | ||||
|     } | ||||
|  | ||||
|     return 0; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Main API. | ||||
|  */ | ||||
| class ESLint { | ||||
|  | ||||
|     /** | ||||
|      * Creates a new instance of the main ESLint API. | ||||
|      * @param {ESLintOptions} options The options for this instance. | ||||
|      */ | ||||
|     constructor(options = {}) { | ||||
|         const processedOptions = processOptions(options); | ||||
|         const cliEngine = new CLIEngine(processedOptions, { preloadedPlugins: options.plugins }); | ||||
|         const { | ||||
|             configArrayFactory, | ||||
|             lastConfigArrays | ||||
|         } = getCLIEngineInternalSlots(cliEngine); | ||||
|         let updated = false; | ||||
|  | ||||
|         /* | ||||
|          * Address `overrideConfig` to set override config. | ||||
|          * Operate the `configArrayFactory` internal slot directly because this | ||||
|          * functionality doesn't exist as the public API of CLIEngine. | ||||
|          */ | ||||
|         if (hasDefinedProperty(options.overrideConfig)) { | ||||
|             configArrayFactory.setOverrideConfig(options.overrideConfig); | ||||
|             updated = true; | ||||
|         } | ||||
|  | ||||
|         // Update caches. | ||||
|         if (updated) { | ||||
|             configArrayFactory.clearCache(); | ||||
|             lastConfigArrays[0] = configArrayFactory.getConfigArrayForFile(); | ||||
|         } | ||||
|  | ||||
|         // Initialize private properties. | ||||
|         privateMembersMap.set(this, { | ||||
|             cliEngine, | ||||
|             options: processedOptions | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The version text. | ||||
|      * @type {string} | ||||
|      */ | ||||
|     static get version() { | ||||
|         return version; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Outputs fixes from the given results to files. | ||||
|      * @param {LintResult[]} results The lint results. | ||||
|      * @returns {Promise<void>} Returns a promise that is used to track side effects. | ||||
|      */ | ||||
|     static async outputFixes(results) { | ||||
|         if (!Array.isArray(results)) { | ||||
|             throw new Error("'results' must be an array"); | ||||
|         } | ||||
|  | ||||
|         await Promise.all( | ||||
|             results | ||||
|                 .filter(result => { | ||||
|                     if (typeof result !== "object" || result === null) { | ||||
|                         throw new Error("'results' must include only objects"); | ||||
|                     } | ||||
|                     return ( | ||||
|                         typeof result.output === "string" && | ||||
|                         path.isAbsolute(result.filePath) | ||||
|                     ); | ||||
|                 }) | ||||
|                 .map(r => writeFile(r.filePath, r.output)) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns results that only contains errors. | ||||
|      * @param {LintResult[]} results The results to filter. | ||||
|      * @returns {LintResult[]} The filtered results. | ||||
|      */ | ||||
|     static getErrorResults(results) { | ||||
|         return CLIEngine.getErrorResults(results); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns meta objects for each rule represented in the lint results. | ||||
|      * @param {LintResult[]} results The results to fetch rules meta for. | ||||
|      * @returns {Object} A mapping of ruleIds to rule meta objects. | ||||
|      */ | ||||
|     getRulesMetaForResults(results) { | ||||
|  | ||||
|         const resultRuleIds = new Set(); | ||||
|  | ||||
|         // first gather all ruleIds from all results | ||||
|  | ||||
|         for (const result of results) { | ||||
|             for (const { ruleId } of result.messages) { | ||||
|                 resultRuleIds.add(ruleId); | ||||
|             } | ||||
|             for (const { ruleId } of result.suppressedMessages) { | ||||
|                 resultRuleIds.add(ruleId); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         // create a map of all rules in the results | ||||
|  | ||||
|         const { cliEngine } = privateMembersMap.get(this); | ||||
|         const rules = cliEngine.getRules(); | ||||
|         const resultRules = new Map(); | ||||
|  | ||||
|         for (const [ruleId, rule] of rules) { | ||||
|             if (resultRuleIds.has(ruleId)) { | ||||
|                 resultRules.set(ruleId, rule); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return createRulesMeta(resultRules); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Executes the current configuration on an array of file and directory names. | ||||
|      * @param {string[]} patterns An array of file and directory names. | ||||
|      * @returns {Promise<LintResult[]>} The results of linting the file patterns given. | ||||
|      */ | ||||
|     async lintFiles(patterns) { | ||||
|         if (!isNonEmptyString(patterns) && !isArrayOfNonEmptyString(patterns)) { | ||||
|             throw new Error("'patterns' must be a non-empty string or an array of non-empty strings"); | ||||
|         } | ||||
|         const { cliEngine } = privateMembersMap.get(this); | ||||
|  | ||||
|         return processCLIEngineLintReport( | ||||
|             cliEngine, | ||||
|             cliEngine.executeOnFiles(patterns) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Executes the current configuration on text. | ||||
|      * @param {string} code A string of JavaScript code to lint. | ||||
|      * @param {Object} [options] The options. | ||||
|      * @param {string} [options.filePath] The path to the file of the source code. | ||||
|      * @param {boolean} [options.warnIgnored] When set to true, warn if given filePath is an ignored path. | ||||
|      * @returns {Promise<LintResult[]>} The results of linting the string of code given. | ||||
|      */ | ||||
|     async lintText(code, options = {}) { | ||||
|         if (typeof code !== "string") { | ||||
|             throw new Error("'code' must be a string"); | ||||
|         } | ||||
|         if (typeof options !== "object") { | ||||
|             throw new Error("'options' must be an object, null, or undefined"); | ||||
|         } | ||||
|         const { | ||||
|             filePath, | ||||
|             warnIgnored = false, | ||||
|             ...unknownOptions | ||||
|         } = options || {}; | ||||
|  | ||||
|         const unknownOptionKeys = Object.keys(unknownOptions); | ||||
|  | ||||
|         if (unknownOptionKeys.length > 0) { | ||||
|             throw new Error(`'options' must not include the unknown option(s): ${unknownOptionKeys.join(", ")}`); | ||||
|         } | ||||
|  | ||||
|         if (filePath !== void 0 && !isNonEmptyString(filePath)) { | ||||
|             throw new Error("'options.filePath' must be a non-empty string or undefined"); | ||||
|         } | ||||
|         if (typeof warnIgnored !== "boolean") { | ||||
|             throw new Error("'options.warnIgnored' must be a boolean or undefined"); | ||||
|         } | ||||
|  | ||||
|         const { cliEngine } = privateMembersMap.get(this); | ||||
|  | ||||
|         return processCLIEngineLintReport( | ||||
|             cliEngine, | ||||
|             cliEngine.executeOnText(code, filePath, warnIgnored) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns the formatter representing the given formatter name. | ||||
|      * @param {string} [name] The name of the formatter to load. | ||||
|      * The following values are allowed: | ||||
|      * - `undefined` ... Load `stylish` builtin formatter. | ||||
|      * - A builtin formatter name ... Load the builtin formatter. | ||||
|      * - A third-party formatter name: | ||||
|      *   - `foo` → `eslint-formatter-foo` | ||||
|      *   - `@foo` → `@foo/eslint-formatter` | ||||
|      *   - `@foo/bar` → `@foo/eslint-formatter-bar` | ||||
|      * - A file path ... Load the file. | ||||
|      * @returns {Promise<LoadedFormatter>} A promise resolving to the formatter object. | ||||
|      * This promise will be rejected if the given formatter was not found or not | ||||
|      * a function. | ||||
|      */ | ||||
|     async loadFormatter(name = "stylish") { | ||||
|         if (typeof name !== "string") { | ||||
|             throw new Error("'name' must be a string"); | ||||
|         } | ||||
|  | ||||
|         const { cliEngine, options } = privateMembersMap.get(this); | ||||
|         const formatter = cliEngine.getFormatter(name); | ||||
|  | ||||
|         if (typeof formatter !== "function") { | ||||
|             throw new Error(`Formatter must be a function, but got a ${typeof formatter}.`); | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|  | ||||
|             /** | ||||
|              * The main formatter method. | ||||
|              * @param {LintResult[]} results The lint results to format. | ||||
|              * @param {ResultsMeta} resultsMeta Warning count and max threshold. | ||||
|              * @returns {string | Promise<string>} The formatted lint results. | ||||
|              */ | ||||
|             format(results, resultsMeta) { | ||||
|                 let rulesMeta = null; | ||||
|  | ||||
|                 results.sort(compareResultsByFilePath); | ||||
|  | ||||
|                 return formatter(results, { | ||||
|                     ...resultsMeta, | ||||
|                     get cwd() { | ||||
|                         return options.cwd; | ||||
|                     }, | ||||
|                     get rulesMeta() { | ||||
|                         if (!rulesMeta) { | ||||
|                             rulesMeta = createRulesMeta(cliEngine.getRules()); | ||||
|                         } | ||||
|  | ||||
|                         return rulesMeta; | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Returns a configuration object for the given file based on the CLI options. | ||||
|      * This is the same logic used by the ESLint CLI executable to determine | ||||
|      * configuration for each file it processes. | ||||
|      * @param {string} filePath The path of the file to retrieve a config object for. | ||||
|      * @returns {Promise<ConfigData>} A configuration object for the file. | ||||
|      */ | ||||
|     async calculateConfigForFile(filePath) { | ||||
|         if (!isNonEmptyString(filePath)) { | ||||
|             throw new Error("'filePath' must be a non-empty string"); | ||||
|         } | ||||
|         const { cliEngine } = privateMembersMap.get(this); | ||||
|  | ||||
|         return cliEngine.getConfigForFile(filePath); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Checks if a given path is ignored by ESLint. | ||||
|      * @param {string} filePath The path of the file to check. | ||||
|      * @returns {Promise<boolean>} Whether or not the given path is ignored. | ||||
|      */ | ||||
|     async isPathIgnored(filePath) { | ||||
|         if (!isNonEmptyString(filePath)) { | ||||
|             throw new Error("'filePath' must be a non-empty string"); | ||||
|         } | ||||
|         const { cliEngine } = privateMembersMap.get(this); | ||||
|  | ||||
|         return cliEngine.isPathIgnored(filePath); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * The type of configuration used by this class. | ||||
|  * @type {string} | ||||
|  * @static | ||||
|  */ | ||||
| ESLint.configType = "eslintrc"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = { | ||||
|     ESLint, | ||||
|  | ||||
|     /** | ||||
|      * Get the private class members of a given ESLint instance for tests. | ||||
|      * @param {ESLint} instance The ESLint instance to get. | ||||
|      * @returns {ESLintPrivateMembers} The instance's private class members. | ||||
|      */ | ||||
|     getESLintPrivateMembers(instance) { | ||||
|         return privateMembersMap.get(instance); | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										1159
									
								
								node_modules/eslint/lib/eslint/flat-eslint.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1159
									
								
								node_modules/eslint/lib/eslint/flat-eslint.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										9
									
								
								node_modules/eslint/lib/eslint/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										9
									
								
								node_modules/eslint/lib/eslint/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,9 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const { ESLint } = require("./eslint"); | ||||
| const { FlatESLint } = require("./flat-eslint"); | ||||
|  | ||||
| module.exports = { | ||||
|     ESLint, | ||||
|     FlatESLint | ||||
| }; | ||||
							
								
								
									
										465
									
								
								node_modules/eslint/lib/linter/apply-disable-directives.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										465
									
								
								node_modules/eslint/lib/linter/apply-disable-directives.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,465 @@ | ||||
| /** | ||||
|  * @fileoverview A module that filters reported problems based on `eslint-disable` and `eslint-enable` comments | ||||
|  * @author Teddy Katz | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Typedefs | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @typedef {import("../shared/types").LintMessage} LintMessage */ | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Module Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const escapeRegExp = require("escape-string-regexp"); | ||||
|  | ||||
| /** | ||||
|  * Compares the locations of two objects in a source file | ||||
|  * @param {{line: number, column: number}} itemA The first object | ||||
|  * @param {{line: number, column: number}} itemB The second object | ||||
|  * @returns {number} A value less than 1 if itemA appears before itemB in the source file, greater than 1 if | ||||
|  * itemA appears after itemB in the source file, or 0 if itemA and itemB have the same location. | ||||
|  */ | ||||
| function compareLocations(itemA, itemB) { | ||||
|     return itemA.line - itemB.line || itemA.column - itemB.column; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Groups a set of directives into sub-arrays by their parent comment. | ||||
|  * @param {Iterable<Directive>} directives Unused directives to be removed. | ||||
|  * @returns {Directive[][]} Directives grouped by their parent comment. | ||||
|  */ | ||||
| function groupByParentComment(directives) { | ||||
|     const groups = new Map(); | ||||
|  | ||||
|     for (const directive of directives) { | ||||
|         const { unprocessedDirective: { parentComment } } = directive; | ||||
|  | ||||
|         if (groups.has(parentComment)) { | ||||
|             groups.get(parentComment).push(directive); | ||||
|         } else { | ||||
|             groups.set(parentComment, [directive]); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return [...groups.values()]; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Creates removal details for a set of directives within the same comment. | ||||
|  * @param {Directive[]} directives Unused directives to be removed. | ||||
|  * @param {Token} commentToken The backing Comment token. | ||||
|  * @returns {{ description, fix, unprocessedDirective }[]} Details for later creation of output Problems. | ||||
|  */ | ||||
| function createIndividualDirectivesRemoval(directives, commentToken) { | ||||
|  | ||||
|     /* | ||||
|      * `commentToken.value` starts right after `//` or `/*`. | ||||
|      * All calculated offsets will be relative to this index. | ||||
|      */ | ||||
|     const commentValueStart = commentToken.range[0] + "//".length; | ||||
|  | ||||
|     // Find where the list of rules starts. `\S+` matches with the directive name (e.g. `eslint-disable-line`) | ||||
|     const listStartOffset = /^\s*\S+\s+/u.exec(commentToken.value)[0].length; | ||||
|  | ||||
|     /* | ||||
|      * Get the list text without any surrounding whitespace. In order to preserve the original | ||||
|      * formatting, we don't want to change that whitespace. | ||||
|      * | ||||
|      *     // eslint-disable-line rule-one , rule-two , rule-three -- comment | ||||
|      *                            ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ | ||||
|      */ | ||||
|     const listText = commentToken.value | ||||
|         .slice(listStartOffset) // remove directive name and all whitespace before the list | ||||
|         .split(/\s-{2,}\s/u)[0] // remove `-- comment`, if it exists | ||||
|         .trimEnd(); // remove all whitespace after the list | ||||
|  | ||||
|     /* | ||||
|      * We can assume that `listText` contains multiple elements. | ||||
|      * Otherwise, this function wouldn't be called - if there is | ||||
|      * only one rule in the list, then the whole comment must be removed. | ||||
|      */ | ||||
|  | ||||
|     return directives.map(directive => { | ||||
|         const { ruleId } = directive; | ||||
|  | ||||
|         const regex = new RegExp(String.raw`(?:^|\s*,\s*)(?<quote>['"]?)${escapeRegExp(ruleId)}\k<quote>(?:\s*,\s*|$)`, "u"); | ||||
|         const match = regex.exec(listText); | ||||
|         const matchedText = match[0]; | ||||
|         const matchStartOffset = listStartOffset + match.index; | ||||
|         const matchEndOffset = matchStartOffset + matchedText.length; | ||||
|  | ||||
|         const firstIndexOfComma = matchedText.indexOf(","); | ||||
|         const lastIndexOfComma = matchedText.lastIndexOf(","); | ||||
|  | ||||
|         let removalStartOffset, removalEndOffset; | ||||
|  | ||||
|         if (firstIndexOfComma !== lastIndexOfComma) { | ||||
|  | ||||
|             /* | ||||
|              * Since there are two commas, this must one of the elements in the middle of the list. | ||||
|              * Matched range starts where the previous rule name ends, and ends where the next rule name starts. | ||||
|              * | ||||
|              *     // eslint-disable-line rule-one , rule-two , rule-three -- comment | ||||
|              *                                    ^^^^^^^^^^^^^^ | ||||
|              * | ||||
|              * We want to remove only the content between the two commas, and also one of the commas. | ||||
|              * | ||||
|              *     // eslint-disable-line rule-one , rule-two , rule-three -- comment | ||||
|              *                                     ^^^^^^^^^^^ | ||||
|              */ | ||||
|             removalStartOffset = matchStartOffset + firstIndexOfComma; | ||||
|             removalEndOffset = matchStartOffset + lastIndexOfComma; | ||||
|  | ||||
|         } else { | ||||
|  | ||||
|             /* | ||||
|              * This is either the first element or the last element. | ||||
|              * | ||||
|              * If this is the first element, matched range starts where the first rule name starts | ||||
|              * and ends where the second rule name starts. This is exactly the range we want | ||||
|              * to remove so that the second rule name will start where the first one was starting | ||||
|              * and thus preserve the original formatting. | ||||
|              * | ||||
|              *     // eslint-disable-line rule-one , rule-two , rule-three -- comment | ||||
|              *                            ^^^^^^^^^^^ | ||||
|              * | ||||
|              * Similarly, if this is the last element, we've already matched the range we want to | ||||
|              * remove. The previous rule name will end where the last one was ending, relative | ||||
|              * to the content on the right side. | ||||
|              * | ||||
|              *     // eslint-disable-line rule-one , rule-two , rule-three -- comment | ||||
|              *                                               ^^^^^^^^^^^^^ | ||||
|              */ | ||||
|             removalStartOffset = matchStartOffset; | ||||
|             removalEndOffset = matchEndOffset; | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             description: `'${ruleId}'`, | ||||
|             fix: { | ||||
|                 range: [ | ||||
|                     commentValueStart + removalStartOffset, | ||||
|                     commentValueStart + removalEndOffset | ||||
|                 ], | ||||
|                 text: "" | ||||
|             }, | ||||
|             unprocessedDirective: directive.unprocessedDirective | ||||
|         }; | ||||
|     }); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Creates a description of deleting an entire unused disable comment. | ||||
|  * @param {Directive[]} directives Unused directives to be removed. | ||||
|  * @param {Token} commentToken The backing Comment token. | ||||
|  * @returns {{ description, fix, unprocessedDirective }} Details for later creation of an output Problem. | ||||
|  */ | ||||
| function createCommentRemoval(directives, commentToken) { | ||||
|     const { range } = commentToken; | ||||
|     const ruleIds = directives.filter(directive => directive.ruleId).map(directive => `'${directive.ruleId}'`); | ||||
|  | ||||
|     return { | ||||
|         description: ruleIds.length <= 2 | ||||
|             ? ruleIds.join(" or ") | ||||
|             : `${ruleIds.slice(0, ruleIds.length - 1).join(", ")}, or ${ruleIds[ruleIds.length - 1]}`, | ||||
|         fix: { | ||||
|             range, | ||||
|             text: " " | ||||
|         }, | ||||
|         unprocessedDirective: directives[0].unprocessedDirective | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Parses details from directives to create output Problems. | ||||
|  * @param {Iterable<Directive>} allDirectives Unused directives to be removed. | ||||
|  * @returns {{ description, fix, unprocessedDirective }[]} Details for later creation of output Problems. | ||||
|  */ | ||||
| function processUnusedDirectives(allDirectives) { | ||||
|     const directiveGroups = groupByParentComment(allDirectives); | ||||
|  | ||||
|     return directiveGroups.flatMap( | ||||
|         directives => { | ||||
|             const { parentComment } = directives[0].unprocessedDirective; | ||||
|             const remainingRuleIds = new Set(parentComment.ruleIds); | ||||
|  | ||||
|             for (const directive of directives) { | ||||
|                 remainingRuleIds.delete(directive.ruleId); | ||||
|             } | ||||
|  | ||||
|             return remainingRuleIds.size | ||||
|                 ? createIndividualDirectivesRemoval(directives, parentComment.commentToken) | ||||
|                 : [createCommentRemoval(directives, parentComment.commentToken)]; | ||||
|         } | ||||
|     ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Collect eslint-enable comments that are removing suppressions by eslint-disable comments. | ||||
|  * @param {Directive[]} directives The directives to check. | ||||
|  * @returns {Set<Directive>} The used eslint-enable comments | ||||
|  */ | ||||
| function collectUsedEnableDirectives(directives) { | ||||
|  | ||||
|     /** | ||||
|      * A Map of `eslint-enable` keyed by ruleIds that may be marked as used. | ||||
|      * If `eslint-enable` does not have a ruleId, the key will be `null`. | ||||
|      * @type {Map<string|null, Directive>} | ||||
|      */ | ||||
|     const enabledRules = new Map(); | ||||
|  | ||||
|     /** | ||||
|      * A Set of `eslint-enable` marked as used. | ||||
|      * It is also the return value of `collectUsedEnableDirectives` function. | ||||
|      * @type {Set<Directive>} | ||||
|      */ | ||||
|     const usedEnableDirectives = new Set(); | ||||
|  | ||||
|     /* | ||||
|      * Checks the directives backwards to see if the encountered `eslint-enable` is used by the previous `eslint-disable`, | ||||
|      * and if so, stores the `eslint-enable` in `usedEnableDirectives`. | ||||
|      */ | ||||
|     for (let index = directives.length - 1; index >= 0; index--) { | ||||
|         const directive = directives[index]; | ||||
|  | ||||
|         if (directive.type === "disable") { | ||||
|             if (enabledRules.size === 0) { | ||||
|                 continue; | ||||
|             } | ||||
|             if (directive.ruleId === null) { | ||||
|  | ||||
|                 // If encounter `eslint-disable` without ruleId, | ||||
|                 // mark all `eslint-enable` currently held in enabledRules as used. | ||||
|                 // e.g. | ||||
|                 //    /* eslint-disable */ <- current directive | ||||
|                 //    /* eslint-enable rule-id1 */ <- used | ||||
|                 //    /* eslint-enable rule-id2 */ <- used | ||||
|                 //    /* eslint-enable */ <- used | ||||
|                 for (const enableDirective of enabledRules.values()) { | ||||
|                     usedEnableDirectives.add(enableDirective); | ||||
|                 } | ||||
|                 enabledRules.clear(); | ||||
|             } else { | ||||
|                 const enableDirective = enabledRules.get(directive.ruleId); | ||||
|  | ||||
|                 if (enableDirective) { | ||||
|  | ||||
|                     // If encounter `eslint-disable` with ruleId, and there is an `eslint-enable` with the same ruleId in enabledRules, | ||||
|                     // mark `eslint-enable` with ruleId as used. | ||||
|                     // e.g. | ||||
|                     //    /* eslint-disable rule-id */ <- current directive | ||||
|                     //    /* eslint-enable rule-id */ <- used | ||||
|                     usedEnableDirectives.add(enableDirective); | ||||
|                 } else { | ||||
|                     const enabledDirectiveWithoutRuleId = enabledRules.get(null); | ||||
|  | ||||
|                     if (enabledDirectiveWithoutRuleId) { | ||||
|  | ||||
|                         // If encounter `eslint-disable` with ruleId, and there is no `eslint-enable` with the same ruleId in enabledRules, | ||||
|                         // mark `eslint-enable` without ruleId as used. | ||||
|                         // e.g. | ||||
|                         //    /* eslint-disable rule-id */ <- current directive | ||||
|                         //    /* eslint-enable */ <- used | ||||
|                         usedEnableDirectives.add(enabledDirectiveWithoutRuleId); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } else if (directive.type === "enable") { | ||||
|             if (directive.ruleId === null) { | ||||
|  | ||||
|                 // If encounter `eslint-enable` without ruleId, the `eslint-enable` that follows it are unused. | ||||
|                 // So clear enabledRules. | ||||
|                 // e.g. | ||||
|                 //    /* eslint-enable */ <- current directive | ||||
|                 //    /* eslint-enable rule-id *// <- unused | ||||
|                 //    /* eslint-enable */ <- unused | ||||
|                 enabledRules.clear(); | ||||
|                 enabledRules.set(null, directive); | ||||
|             } else { | ||||
|                 enabledRules.set(directive.ruleId, directive); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|     return usedEnableDirectives; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * This is the same as the exported function, except that it | ||||
|  * doesn't handle disable-line and disable-next-line directives, and it always reports unused | ||||
|  * disable directives. | ||||
|  * @param {Object} options options for applying directives. This is the same as the options | ||||
|  * for the exported function, except that `reportUnusedDisableDirectives` is not supported | ||||
|  * (this function always reports unused disable directives). | ||||
|  * @returns {{problems: LintMessage[], unusedDirectives: LintMessage[]}} An object with a list | ||||
|  * of problems (including suppressed ones) and unused eslint-disable directives | ||||
|  */ | ||||
| function applyDirectives(options) { | ||||
|     const problems = []; | ||||
|     const usedDisableDirectives = new Set(); | ||||
|  | ||||
|     for (const problem of options.problems) { | ||||
|         let disableDirectivesForProblem = []; | ||||
|         let nextDirectiveIndex = 0; | ||||
|  | ||||
|         while ( | ||||
|             nextDirectiveIndex < options.directives.length && | ||||
|             compareLocations(options.directives[nextDirectiveIndex], problem) <= 0 | ||||
|         ) { | ||||
|             const directive = options.directives[nextDirectiveIndex++]; | ||||
|  | ||||
|             if (directive.ruleId === null || directive.ruleId === problem.ruleId) { | ||||
|                 switch (directive.type) { | ||||
|                     case "disable": | ||||
|                         disableDirectivesForProblem.push(directive); | ||||
|                         break; | ||||
|  | ||||
|                     case "enable": | ||||
|                         disableDirectivesForProblem = []; | ||||
|                         break; | ||||
|  | ||||
|                     // no default | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         if (disableDirectivesForProblem.length > 0) { | ||||
|             const suppressions = disableDirectivesForProblem.map(directive => ({ | ||||
|                 kind: "directive", | ||||
|                 justification: directive.unprocessedDirective.justification | ||||
|             })); | ||||
|  | ||||
|             if (problem.suppressions) { | ||||
|                 problem.suppressions = problem.suppressions.concat(suppressions); | ||||
|             } else { | ||||
|                 problem.suppressions = suppressions; | ||||
|                 usedDisableDirectives.add(disableDirectivesForProblem[disableDirectivesForProblem.length - 1]); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         problems.push(problem); | ||||
|     } | ||||
|  | ||||
|     const unusedDisableDirectivesToReport = options.directives | ||||
|         .filter(directive => directive.type === "disable" && !usedDisableDirectives.has(directive)); | ||||
|  | ||||
|  | ||||
|     const unusedEnableDirectivesToReport = new Set( | ||||
|         options.directives.filter(directive => directive.unprocessedDirective.type === "enable") | ||||
|     ); | ||||
|  | ||||
|     /* | ||||
|      * If directives has the eslint-enable directive, | ||||
|      * check whether the eslint-enable comment is used. | ||||
|      */ | ||||
|     if (unusedEnableDirectivesToReport.size > 0) { | ||||
|         for (const directive of collectUsedEnableDirectives(options.directives)) { | ||||
|             unusedEnableDirectivesToReport.delete(directive); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     const processed = processUnusedDirectives(unusedDisableDirectivesToReport) | ||||
|         .concat(processUnusedDirectives(unusedEnableDirectivesToReport)); | ||||
|  | ||||
|     const unusedDirectives = processed | ||||
|         .map(({ description, fix, unprocessedDirective }) => { | ||||
|             const { parentComment, type, line, column } = unprocessedDirective; | ||||
|  | ||||
|             let message; | ||||
|  | ||||
|             if (type === "enable") { | ||||
|                 message = description | ||||
|                     ? `Unused eslint-enable directive (no matching eslint-disable directives were found for ${description}).` | ||||
|                     : "Unused eslint-enable directive (no matching eslint-disable directives were found)."; | ||||
|             } else { | ||||
|                 message = description | ||||
|                     ? `Unused eslint-disable directive (no problems were reported from ${description}).` | ||||
|                     : "Unused eslint-disable directive (no problems were reported)."; | ||||
|             } | ||||
|             return { | ||||
|                 ruleId: null, | ||||
|                 message, | ||||
|                 line: type === "disable-next-line" ? parentComment.commentToken.loc.start.line : line, | ||||
|                 column: type === "disable-next-line" ? parentComment.commentToken.loc.start.column + 1 : column, | ||||
|                 severity: options.reportUnusedDisableDirectives === "warn" ? 1 : 2, | ||||
|                 nodeType: null, | ||||
|                 ...options.disableFixes ? {} : { fix } | ||||
|             }; | ||||
|         }); | ||||
|  | ||||
|     return { problems, unusedDirectives }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Given a list of directive comments (i.e. metadata about eslint-disable and eslint-enable comments) and a list | ||||
|  * of reported problems, adds the suppression information to the problems. | ||||
|  * @param {Object} options Information about directives and problems | ||||
|  * @param {{ | ||||
|  *      type: ("disable"|"enable"|"disable-line"|"disable-next-line"), | ||||
|  *      ruleId: (string|null), | ||||
|  *      line: number, | ||||
|  *      column: number, | ||||
|  *      justification: string | ||||
|  * }} options.directives Directive comments found in the file, with one-based columns. | ||||
|  * Two directive comments can only have the same location if they also have the same type (e.g. a single eslint-disable | ||||
|  * comment for two different rules is represented as two directives). | ||||
|  * @param {{ruleId: (string|null), line: number, column: number}[]} options.problems | ||||
|  * A list of problems reported by rules, sorted by increasing location in the file, with one-based columns. | ||||
|  * @param {"off" | "warn" | "error"} options.reportUnusedDisableDirectives If `"warn"` or `"error"`, adds additional problems for unused directives | ||||
|  * @param {boolean} options.disableFixes If true, it doesn't make `fix` properties. | ||||
|  * @returns {{ruleId: (string|null), line: number, column: number, suppressions?: {kind: string, justification: string}}[]} | ||||
|  * An object with a list of reported problems, the suppressed of which contain the suppression information. | ||||
|  */ | ||||
| module.exports = ({ directives, disableFixes, problems, reportUnusedDisableDirectives = "off" }) => { | ||||
|     const blockDirectives = directives | ||||
|         .filter(directive => directive.type === "disable" || directive.type === "enable") | ||||
|         .map(directive => Object.assign({}, directive, { unprocessedDirective: directive })) | ||||
|         .sort(compareLocations); | ||||
|  | ||||
|     const lineDirectives = directives.flatMap(directive => { | ||||
|         switch (directive.type) { | ||||
|             case "disable": | ||||
|             case "enable": | ||||
|                 return []; | ||||
|  | ||||
|             case "disable-line": | ||||
|                 return [ | ||||
|                     { type: "disable", line: directive.line, column: 1, ruleId: directive.ruleId, unprocessedDirective: directive }, | ||||
|                     { type: "enable", line: directive.line + 1, column: 0, ruleId: directive.ruleId, unprocessedDirective: directive } | ||||
|                 ]; | ||||
|  | ||||
|             case "disable-next-line": | ||||
|                 return [ | ||||
|                     { type: "disable", line: directive.line + 1, column: 1, ruleId: directive.ruleId, unprocessedDirective: directive }, | ||||
|                     { type: "enable", line: directive.line + 2, column: 0, ruleId: directive.ruleId, unprocessedDirective: directive } | ||||
|                 ]; | ||||
|  | ||||
|             default: | ||||
|                 throw new TypeError(`Unrecognized directive type '${directive.type}'`); | ||||
|         } | ||||
|     }).sort(compareLocations); | ||||
|  | ||||
|     const blockDirectivesResult = applyDirectives({ | ||||
|         problems, | ||||
|         directives: blockDirectives, | ||||
|         disableFixes, | ||||
|         reportUnusedDisableDirectives | ||||
|     }); | ||||
|     const lineDirectivesResult = applyDirectives({ | ||||
|         problems: blockDirectivesResult.problems, | ||||
|         directives: lineDirectives, | ||||
|         disableFixes, | ||||
|         reportUnusedDisableDirectives | ||||
|     }); | ||||
|  | ||||
|     return reportUnusedDisableDirectives !== "off" | ||||
|         ? lineDirectivesResult.problems | ||||
|             .concat(blockDirectivesResult.unusedDirectives) | ||||
|             .concat(lineDirectivesResult.unusedDirectives) | ||||
|             .sort(compareLocations) | ||||
|         : lineDirectivesResult.problems; | ||||
| }; | ||||
							
								
								
									
										852
									
								
								node_modules/eslint/lib/linter/code-path-analysis/code-path-analyzer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										852
									
								
								node_modules/eslint/lib/linter/code-path-analysis/code-path-analyzer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,852 @@ | ||||
| /** | ||||
|  * @fileoverview A class of the code path analyzer. | ||||
|  * @author Toru Nagashima | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const assert = require("assert"), | ||||
|     { breakableTypePattern } = require("../../shared/ast-utils"), | ||||
|     CodePath = require("./code-path"), | ||||
|     CodePathSegment = require("./code-path-segment"), | ||||
|     IdGenerator = require("./id-generator"), | ||||
|     debug = require("./debug-helpers"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Checks whether or not a given node is a `case` node (not `default` node). | ||||
|  * @param {ASTNode} node A `SwitchCase` node to check. | ||||
|  * @returns {boolean} `true` if the node is a `case` node (not `default` node). | ||||
|  */ | ||||
| function isCaseNode(node) { | ||||
|     return Boolean(node.test); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks if a given node appears as the value of a PropertyDefinition node. | ||||
|  * @param {ASTNode} node THe node to check. | ||||
|  * @returns {boolean} `true` if the node is a PropertyDefinition value, | ||||
|  *      false if not. | ||||
|  */ | ||||
| function isPropertyDefinitionValue(node) { | ||||
|     const parent = node.parent; | ||||
|  | ||||
|     return parent && parent.type === "PropertyDefinition" && parent.value === node; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether the given logical operator is taken into account for the code | ||||
|  * path analysis. | ||||
|  * @param {string} operator The operator found in the LogicalExpression node | ||||
|  * @returns {boolean} `true` if the operator is "&&" or "||" or "??" | ||||
|  */ | ||||
| function isHandledLogicalOperator(operator) { | ||||
|     return operator === "&&" || operator === "||" || operator === "??"; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether the given assignment operator is a logical assignment operator. | ||||
|  * Logical assignments are taken into account for the code path analysis | ||||
|  * because of their short-circuiting semantics. | ||||
|  * @param {string} operator The operator found in the AssignmentExpression node | ||||
|  * @returns {boolean} `true` if the operator is "&&=" or "||=" or "??=" | ||||
|  */ | ||||
| function isLogicalAssignmentOperator(operator) { | ||||
|     return operator === "&&=" || operator === "||=" || operator === "??="; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Gets the label if the parent node of a given node is a LabeledStatement. | ||||
|  * @param {ASTNode} node A node to get. | ||||
|  * @returns {string|null} The label or `null`. | ||||
|  */ | ||||
| function getLabel(node) { | ||||
|     if (node.parent.type === "LabeledStatement") { | ||||
|         return node.parent.label.name; | ||||
|     } | ||||
|     return null; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether or not a given logical expression node goes different path | ||||
|  * between the `true` case and the `false` case. | ||||
|  * @param {ASTNode} node A node to check. | ||||
|  * @returns {boolean} `true` if the node is a test of a choice statement. | ||||
|  */ | ||||
| function isForkingByTrueOrFalse(node) { | ||||
|     const parent = node.parent; | ||||
|  | ||||
|     switch (parent.type) { | ||||
|         case "ConditionalExpression": | ||||
|         case "IfStatement": | ||||
|         case "WhileStatement": | ||||
|         case "DoWhileStatement": | ||||
|         case "ForStatement": | ||||
|             return parent.test === node; | ||||
|  | ||||
|         case "LogicalExpression": | ||||
|             return isHandledLogicalOperator(parent.operator); | ||||
|  | ||||
|         case "AssignmentExpression": | ||||
|             return isLogicalAssignmentOperator(parent.operator); | ||||
|  | ||||
|         default: | ||||
|             return false; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Gets the boolean value of a given literal node. | ||||
|  * | ||||
|  * This is used to detect infinity loops (e.g. `while (true) {}`). | ||||
|  * Statements preceded by an infinity loop are unreachable if the loop didn't | ||||
|  * have any `break` statement. | ||||
|  * @param {ASTNode} node A node to get. | ||||
|  * @returns {boolean|undefined} a boolean value if the node is a Literal node, | ||||
|  *   otherwise `undefined`. | ||||
|  */ | ||||
| function getBooleanValueIfSimpleConstant(node) { | ||||
|     if (node.type === "Literal") { | ||||
|         return Boolean(node.value); | ||||
|     } | ||||
|     return void 0; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks that a given identifier node is a reference or not. | ||||
|  * | ||||
|  * This is used to detect the first throwable node in a `try` block. | ||||
|  * @param {ASTNode} node An Identifier node to check. | ||||
|  * @returns {boolean} `true` if the node is a reference. | ||||
|  */ | ||||
| function isIdentifierReference(node) { | ||||
|     const parent = node.parent; | ||||
|  | ||||
|     switch (parent.type) { | ||||
|         case "LabeledStatement": | ||||
|         case "BreakStatement": | ||||
|         case "ContinueStatement": | ||||
|         case "ArrayPattern": | ||||
|         case "RestElement": | ||||
|         case "ImportSpecifier": | ||||
|         case "ImportDefaultSpecifier": | ||||
|         case "ImportNamespaceSpecifier": | ||||
|         case "CatchClause": | ||||
|             return false; | ||||
|  | ||||
|         case "FunctionDeclaration": | ||||
|         case "FunctionExpression": | ||||
|         case "ArrowFunctionExpression": | ||||
|         case "ClassDeclaration": | ||||
|         case "ClassExpression": | ||||
|         case "VariableDeclarator": | ||||
|             return parent.id !== node; | ||||
|  | ||||
|         case "Property": | ||||
|         case "PropertyDefinition": | ||||
|         case "MethodDefinition": | ||||
|             return ( | ||||
|                 parent.key !== node || | ||||
|                 parent.computed || | ||||
|                 parent.shorthand | ||||
|             ); | ||||
|  | ||||
|         case "AssignmentPattern": | ||||
|             return parent.key !== node; | ||||
|  | ||||
|         default: | ||||
|             return true; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Updates the current segment with the head segment. | ||||
|  * This is similar to local branches and tracking branches of git. | ||||
|  * | ||||
|  * To separate the current and the head is in order to not make useless segments. | ||||
|  * | ||||
|  * In this process, both "onCodePathSegmentStart" and "onCodePathSegmentEnd" | ||||
|  * events are fired. | ||||
|  * @param {CodePathAnalyzer} analyzer The instance. | ||||
|  * @param {ASTNode} node The current AST node. | ||||
|  * @returns {void} | ||||
|  */ | ||||
| function forwardCurrentToHead(analyzer, node) { | ||||
|     const codePath = analyzer.codePath; | ||||
|     const state = CodePath.getState(codePath); | ||||
|     const currentSegments = state.currentSegments; | ||||
|     const headSegments = state.headSegments; | ||||
|     const end = Math.max(currentSegments.length, headSegments.length); | ||||
|     let i, currentSegment, headSegment; | ||||
|  | ||||
|     // Fires leaving events. | ||||
|     for (i = 0; i < end; ++i) { | ||||
|         currentSegment = currentSegments[i]; | ||||
|         headSegment = headSegments[i]; | ||||
|  | ||||
|         if (currentSegment !== headSegment && currentSegment) { | ||||
|  | ||||
|             const eventName = currentSegment.reachable | ||||
|                 ? "onCodePathSegmentEnd" | ||||
|                 : "onUnreachableCodePathSegmentEnd"; | ||||
|  | ||||
|             debug.dump(`${eventName} ${currentSegment.id}`); | ||||
|  | ||||
|             analyzer.emitter.emit( | ||||
|                 eventName, | ||||
|                 currentSegment, | ||||
|                 node | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     // Update state. | ||||
|     state.currentSegments = headSegments; | ||||
|  | ||||
|     // Fires entering events. | ||||
|     for (i = 0; i < end; ++i) { | ||||
|         currentSegment = currentSegments[i]; | ||||
|         headSegment = headSegments[i]; | ||||
|  | ||||
|         if (currentSegment !== headSegment && headSegment) { | ||||
|  | ||||
|             const eventName = headSegment.reachable | ||||
|                 ? "onCodePathSegmentStart" | ||||
|                 : "onUnreachableCodePathSegmentStart"; | ||||
|  | ||||
|             debug.dump(`${eventName} ${headSegment.id}`); | ||||
|  | ||||
|             CodePathSegment.markUsed(headSegment); | ||||
|             analyzer.emitter.emit( | ||||
|                 eventName, | ||||
|                 headSegment, | ||||
|                 node | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Updates the current segment with empty. | ||||
|  * This is called at the last of functions or the program. | ||||
|  * @param {CodePathAnalyzer} analyzer The instance. | ||||
|  * @param {ASTNode} node The current AST node. | ||||
|  * @returns {void} | ||||
|  */ | ||||
| function leaveFromCurrentSegment(analyzer, node) { | ||||
|     const state = CodePath.getState(analyzer.codePath); | ||||
|     const currentSegments = state.currentSegments; | ||||
|  | ||||
|     for (let i = 0; i < currentSegments.length; ++i) { | ||||
|         const currentSegment = currentSegments[i]; | ||||
|         const eventName = currentSegment.reachable | ||||
|             ? "onCodePathSegmentEnd" | ||||
|             : "onUnreachableCodePathSegmentEnd"; | ||||
|  | ||||
|         debug.dump(`${eventName} ${currentSegment.id}`); | ||||
|  | ||||
|         analyzer.emitter.emit( | ||||
|             eventName, | ||||
|             currentSegment, | ||||
|             node | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     state.currentSegments = []; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Updates the code path due to the position of a given node in the parent node | ||||
|  * thereof. | ||||
|  * | ||||
|  * For example, if the node is `parent.consequent`, this creates a fork from the | ||||
|  * current path. | ||||
|  * @param {CodePathAnalyzer} analyzer The instance. | ||||
|  * @param {ASTNode} node The current AST node. | ||||
|  * @returns {void} | ||||
|  */ | ||||
| function preprocess(analyzer, node) { | ||||
|     const codePath = analyzer.codePath; | ||||
|     const state = CodePath.getState(codePath); | ||||
|     const parent = node.parent; | ||||
|  | ||||
|     switch (parent.type) { | ||||
|  | ||||
|         // The `arguments.length == 0` case is in `postprocess` function. | ||||
|         case "CallExpression": | ||||
|             if (parent.optional === true && parent.arguments.length >= 1 && parent.arguments[0] === node) { | ||||
|                 state.makeOptionalRight(); | ||||
|             } | ||||
|             break; | ||||
|         case "MemberExpression": | ||||
|             if (parent.optional === true && parent.property === node) { | ||||
|                 state.makeOptionalRight(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "LogicalExpression": | ||||
|             if ( | ||||
|                 parent.right === node && | ||||
|                 isHandledLogicalOperator(parent.operator) | ||||
|             ) { | ||||
|                 state.makeLogicalRight(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "AssignmentExpression": | ||||
|             if ( | ||||
|                 parent.right === node && | ||||
|                 isLogicalAssignmentOperator(parent.operator) | ||||
|             ) { | ||||
|                 state.makeLogicalRight(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "ConditionalExpression": | ||||
|         case "IfStatement": | ||||
|  | ||||
|             /* | ||||
|              * Fork if this node is at `consequent`/`alternate`. | ||||
|              * `popForkContext()` exists at `IfStatement:exit` and | ||||
|              * `ConditionalExpression:exit`. | ||||
|              */ | ||||
|             if (parent.consequent === node) { | ||||
|                 state.makeIfConsequent(); | ||||
|             } else if (parent.alternate === node) { | ||||
|                 state.makeIfAlternate(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "SwitchCase": | ||||
|             if (parent.consequent[0] === node) { | ||||
|                 state.makeSwitchCaseBody(false, !parent.test); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "TryStatement": | ||||
|             if (parent.handler === node) { | ||||
|                 state.makeCatchBlock(); | ||||
|             } else if (parent.finalizer === node) { | ||||
|                 state.makeFinallyBlock(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "WhileStatement": | ||||
|             if (parent.test === node) { | ||||
|                 state.makeWhileTest(getBooleanValueIfSimpleConstant(node)); | ||||
|             } else { | ||||
|                 assert(parent.body === node); | ||||
|                 state.makeWhileBody(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "DoWhileStatement": | ||||
|             if (parent.body === node) { | ||||
|                 state.makeDoWhileBody(); | ||||
|             } else { | ||||
|                 assert(parent.test === node); | ||||
|                 state.makeDoWhileTest(getBooleanValueIfSimpleConstant(node)); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "ForStatement": | ||||
|             if (parent.test === node) { | ||||
|                 state.makeForTest(getBooleanValueIfSimpleConstant(node)); | ||||
|             } else if (parent.update === node) { | ||||
|                 state.makeForUpdate(); | ||||
|             } else if (parent.body === node) { | ||||
|                 state.makeForBody(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "ForInStatement": | ||||
|         case "ForOfStatement": | ||||
|             if (parent.left === node) { | ||||
|                 state.makeForInOfLeft(); | ||||
|             } else if (parent.right === node) { | ||||
|                 state.makeForInOfRight(); | ||||
|             } else { | ||||
|                 assert(parent.body === node); | ||||
|                 state.makeForInOfBody(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "AssignmentPattern": | ||||
|  | ||||
|             /* | ||||
|              * Fork if this node is at `right`. | ||||
|              * `left` is executed always, so it uses the current path. | ||||
|              * `popForkContext()` exists at `AssignmentPattern:exit`. | ||||
|              */ | ||||
|             if (parent.right === node) { | ||||
|                 state.pushForkContext(); | ||||
|                 state.forkBypassPath(); | ||||
|                 state.forkPath(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Updates the code path due to the type of a given node in entering. | ||||
|  * @param {CodePathAnalyzer} analyzer The instance. | ||||
|  * @param {ASTNode} node The current AST node. | ||||
|  * @returns {void} | ||||
|  */ | ||||
| function processCodePathToEnter(analyzer, node) { | ||||
|     let codePath = analyzer.codePath; | ||||
|     let state = codePath && CodePath.getState(codePath); | ||||
|     const parent = node.parent; | ||||
|  | ||||
|     /** | ||||
|      * Creates a new code path and trigger the onCodePathStart event | ||||
|      * based on the currently selected node. | ||||
|      * @param {string} origin The reason the code path was started. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     function startCodePath(origin) { | ||||
|         if (codePath) { | ||||
|  | ||||
|             // Emits onCodePathSegmentStart events if updated. | ||||
|             forwardCurrentToHead(analyzer, node); | ||||
|             debug.dumpState(node, state, false); | ||||
|         } | ||||
|  | ||||
|         // Create the code path of this scope. | ||||
|         codePath = analyzer.codePath = new CodePath({ | ||||
|             id: analyzer.idGenerator.next(), | ||||
|             origin, | ||||
|             upper: codePath, | ||||
|             onLooped: analyzer.onLooped | ||||
|         }); | ||||
|         state = CodePath.getState(codePath); | ||||
|  | ||||
|         // Emits onCodePathStart events. | ||||
|         debug.dump(`onCodePathStart ${codePath.id}`); | ||||
|         analyzer.emitter.emit("onCodePathStart", codePath, node); | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * Special case: The right side of class field initializer is considered | ||||
|      * to be its own function, so we need to start a new code path in this | ||||
|      * case. | ||||
|      */ | ||||
|     if (isPropertyDefinitionValue(node)) { | ||||
|         startCodePath("class-field-initializer"); | ||||
|  | ||||
|         /* | ||||
|          * Intentional fall through because `node` needs to also be | ||||
|          * processed by the code below. For example, if we have: | ||||
|          * | ||||
|          * class Foo { | ||||
|          *     a = () => {} | ||||
|          * } | ||||
|          * | ||||
|          * In this case, we also need start a second code path. | ||||
|          */ | ||||
|  | ||||
|     } | ||||
|  | ||||
|     switch (node.type) { | ||||
|         case "Program": | ||||
|             startCodePath("program"); | ||||
|             break; | ||||
|  | ||||
|         case "FunctionDeclaration": | ||||
|         case "FunctionExpression": | ||||
|         case "ArrowFunctionExpression": | ||||
|             startCodePath("function"); | ||||
|             break; | ||||
|  | ||||
|         case "StaticBlock": | ||||
|             startCodePath("class-static-block"); | ||||
|             break; | ||||
|  | ||||
|         case "ChainExpression": | ||||
|             state.pushChainContext(); | ||||
|             break; | ||||
|         case "CallExpression": | ||||
|             if (node.optional === true) { | ||||
|                 state.makeOptionalNode(); | ||||
|             } | ||||
|             break; | ||||
|         case "MemberExpression": | ||||
|             if (node.optional === true) { | ||||
|                 state.makeOptionalNode(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "LogicalExpression": | ||||
|             if (isHandledLogicalOperator(node.operator)) { | ||||
|                 state.pushChoiceContext( | ||||
|                     node.operator, | ||||
|                     isForkingByTrueOrFalse(node) | ||||
|                 ); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "AssignmentExpression": | ||||
|             if (isLogicalAssignmentOperator(node.operator)) { | ||||
|                 state.pushChoiceContext( | ||||
|                     node.operator.slice(0, -1), // removes `=` from the end | ||||
|                     isForkingByTrueOrFalse(node) | ||||
|                 ); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "ConditionalExpression": | ||||
|         case "IfStatement": | ||||
|             state.pushChoiceContext("test", false); | ||||
|             break; | ||||
|  | ||||
|         case "SwitchStatement": | ||||
|             state.pushSwitchContext( | ||||
|                 node.cases.some(isCaseNode), | ||||
|                 getLabel(node) | ||||
|             ); | ||||
|             break; | ||||
|  | ||||
|         case "TryStatement": | ||||
|             state.pushTryContext(Boolean(node.finalizer)); | ||||
|             break; | ||||
|  | ||||
|         case "SwitchCase": | ||||
|  | ||||
|             /* | ||||
|              * Fork if this node is after the 2st node in `cases`. | ||||
|              * It's similar to `else` blocks. | ||||
|              * The next `test` node is processed in this path. | ||||
|              */ | ||||
|             if (parent.discriminant !== node && parent.cases[0] !== node) { | ||||
|                 state.forkPath(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "WhileStatement": | ||||
|         case "DoWhileStatement": | ||||
|         case "ForStatement": | ||||
|         case "ForInStatement": | ||||
|         case "ForOfStatement": | ||||
|             state.pushLoopContext(node.type, getLabel(node)); | ||||
|             break; | ||||
|  | ||||
|         case "LabeledStatement": | ||||
|             if (!breakableTypePattern.test(node.body.type)) { | ||||
|                 state.pushBreakContext(false, node.label.name); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
|  | ||||
|     // Emits onCodePathSegmentStart events if updated. | ||||
|     forwardCurrentToHead(analyzer, node); | ||||
|     debug.dumpState(node, state, false); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Updates the code path due to the type of a given node in leaving. | ||||
|  * @param {CodePathAnalyzer} analyzer The instance. | ||||
|  * @param {ASTNode} node The current AST node. | ||||
|  * @returns {void} | ||||
|  */ | ||||
| function processCodePathToExit(analyzer, node) { | ||||
|  | ||||
|     const codePath = analyzer.codePath; | ||||
|     const state = CodePath.getState(codePath); | ||||
|     let dontForward = false; | ||||
|  | ||||
|     switch (node.type) { | ||||
|         case "ChainExpression": | ||||
|             state.popChainContext(); | ||||
|             break; | ||||
|  | ||||
|         case "IfStatement": | ||||
|         case "ConditionalExpression": | ||||
|             state.popChoiceContext(); | ||||
|             break; | ||||
|  | ||||
|         case "LogicalExpression": | ||||
|             if (isHandledLogicalOperator(node.operator)) { | ||||
|                 state.popChoiceContext(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "AssignmentExpression": | ||||
|             if (isLogicalAssignmentOperator(node.operator)) { | ||||
|                 state.popChoiceContext(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "SwitchStatement": | ||||
|             state.popSwitchContext(); | ||||
|             break; | ||||
|  | ||||
|         case "SwitchCase": | ||||
|  | ||||
|             /* | ||||
|              * This is the same as the process at the 1st `consequent` node in | ||||
|              * `preprocess` function. | ||||
|              * Must do if this `consequent` is empty. | ||||
|              */ | ||||
|             if (node.consequent.length === 0) { | ||||
|                 state.makeSwitchCaseBody(true, !node.test); | ||||
|             } | ||||
|             if (state.forkContext.reachable) { | ||||
|                 dontForward = true; | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "TryStatement": | ||||
|             state.popTryContext(); | ||||
|             break; | ||||
|  | ||||
|         case "BreakStatement": | ||||
|             forwardCurrentToHead(analyzer, node); | ||||
|             state.makeBreak(node.label && node.label.name); | ||||
|             dontForward = true; | ||||
|             break; | ||||
|  | ||||
|         case "ContinueStatement": | ||||
|             forwardCurrentToHead(analyzer, node); | ||||
|             state.makeContinue(node.label && node.label.name); | ||||
|             dontForward = true; | ||||
|             break; | ||||
|  | ||||
|         case "ReturnStatement": | ||||
|             forwardCurrentToHead(analyzer, node); | ||||
|             state.makeReturn(); | ||||
|             dontForward = true; | ||||
|             break; | ||||
|  | ||||
|         case "ThrowStatement": | ||||
|             forwardCurrentToHead(analyzer, node); | ||||
|             state.makeThrow(); | ||||
|             dontForward = true; | ||||
|             break; | ||||
|  | ||||
|         case "Identifier": | ||||
|             if (isIdentifierReference(node)) { | ||||
|                 state.makeFirstThrowablePathInTryBlock(); | ||||
|                 dontForward = true; | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         case "CallExpression": | ||||
|         case "ImportExpression": | ||||
|         case "MemberExpression": | ||||
|         case "NewExpression": | ||||
|         case "YieldExpression": | ||||
|             state.makeFirstThrowablePathInTryBlock(); | ||||
|             break; | ||||
|  | ||||
|         case "WhileStatement": | ||||
|         case "DoWhileStatement": | ||||
|         case "ForStatement": | ||||
|         case "ForInStatement": | ||||
|         case "ForOfStatement": | ||||
|             state.popLoopContext(); | ||||
|             break; | ||||
|  | ||||
|         case "AssignmentPattern": | ||||
|             state.popForkContext(); | ||||
|             break; | ||||
|  | ||||
|         case "LabeledStatement": | ||||
|             if (!breakableTypePattern.test(node.body.type)) { | ||||
|                 state.popBreakContext(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
|  | ||||
|     // Emits onCodePathSegmentStart events if updated. | ||||
|     if (!dontForward) { | ||||
|         forwardCurrentToHead(analyzer, node); | ||||
|     } | ||||
|     debug.dumpState(node, state, true); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Updates the code path to finalize the current code path. | ||||
|  * @param {CodePathAnalyzer} analyzer The instance. | ||||
|  * @param {ASTNode} node The current AST node. | ||||
|  * @returns {void} | ||||
|  */ | ||||
| function postprocess(analyzer, node) { | ||||
|  | ||||
|     /** | ||||
|      * Ends the code path for the current node. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     function endCodePath() { | ||||
|         let codePath = analyzer.codePath; | ||||
|  | ||||
|         // Mark the current path as the final node. | ||||
|         CodePath.getState(codePath).makeFinal(); | ||||
|  | ||||
|         // Emits onCodePathSegmentEnd event of the current segments. | ||||
|         leaveFromCurrentSegment(analyzer, node); | ||||
|  | ||||
|         // Emits onCodePathEnd event of this code path. | ||||
|         debug.dump(`onCodePathEnd ${codePath.id}`); | ||||
|         analyzer.emitter.emit("onCodePathEnd", codePath, node); | ||||
|         debug.dumpDot(codePath); | ||||
|  | ||||
|         codePath = analyzer.codePath = analyzer.codePath.upper; | ||||
|         if (codePath) { | ||||
|             debug.dumpState(node, CodePath.getState(codePath), true); | ||||
|         } | ||||
|  | ||||
|     } | ||||
|  | ||||
|     switch (node.type) { | ||||
|         case "Program": | ||||
|         case "FunctionDeclaration": | ||||
|         case "FunctionExpression": | ||||
|         case "ArrowFunctionExpression": | ||||
|         case "StaticBlock": { | ||||
|             endCodePath(); | ||||
|             break; | ||||
|         } | ||||
|  | ||||
|         // The `arguments.length >= 1` case is in `preprocess` function. | ||||
|         case "CallExpression": | ||||
|             if (node.optional === true && node.arguments.length === 0) { | ||||
|                 CodePath.getState(analyzer.codePath).makeOptionalRight(); | ||||
|             } | ||||
|             break; | ||||
|  | ||||
|         default: | ||||
|             break; | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * Special case: The right side of class field initializer is considered | ||||
|      * to be its own function, so we need to end a code path in this | ||||
|      * case. | ||||
|      * | ||||
|      * We need to check after the other checks in order to close the | ||||
|      * code paths in the correct order for code like this: | ||||
|      * | ||||
|      * | ||||
|      * class Foo { | ||||
|      *     a = () => {} | ||||
|      * } | ||||
|      * | ||||
|      * In this case, The ArrowFunctionExpression code path is closed first | ||||
|      * and then we need to close the code path for the PropertyDefinition | ||||
|      * value. | ||||
|      */ | ||||
|     if (isPropertyDefinitionValue(node)) { | ||||
|         endCodePath(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * The class to analyze code paths. | ||||
|  * This class implements the EventGenerator interface. | ||||
|  */ | ||||
| class CodePathAnalyzer { | ||||
|  | ||||
|     /** | ||||
|      * @param {EventGenerator} eventGenerator An event generator to wrap. | ||||
|      */ | ||||
|     constructor(eventGenerator) { | ||||
|         this.original = eventGenerator; | ||||
|         this.emitter = eventGenerator.emitter; | ||||
|         this.codePath = null; | ||||
|         this.idGenerator = new IdGenerator("s"); | ||||
|         this.currentNode = null; | ||||
|         this.onLooped = this.onLooped.bind(this); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Does the process to enter a given AST node. | ||||
|      * This updates state of analysis and calls `enterNode` of the wrapped. | ||||
|      * @param {ASTNode} node A node which is entering. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     enterNode(node) { | ||||
|         this.currentNode = node; | ||||
|  | ||||
|         // Updates the code path due to node's position in its parent node. | ||||
|         if (node.parent) { | ||||
|             preprocess(this, node); | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * Updates the code path. | ||||
|          * And emits onCodePathStart/onCodePathSegmentStart events. | ||||
|          */ | ||||
|         processCodePathToEnter(this, node); | ||||
|  | ||||
|         // Emits node events. | ||||
|         this.original.enterNode(node); | ||||
|  | ||||
|         this.currentNode = null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Does the process to leave a given AST node. | ||||
|      * This updates state of analysis and calls `leaveNode` of the wrapped. | ||||
|      * @param {ASTNode} node A node which is leaving. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     leaveNode(node) { | ||||
|         this.currentNode = node; | ||||
|  | ||||
|         /* | ||||
|          * Updates the code path. | ||||
|          * And emits onCodePathStart/onCodePathSegmentStart events. | ||||
|          */ | ||||
|         processCodePathToExit(this, node); | ||||
|  | ||||
|         // Emits node events. | ||||
|         this.original.leaveNode(node); | ||||
|  | ||||
|         // Emits the last onCodePathStart/onCodePathSegmentStart events. | ||||
|         postprocess(this, node); | ||||
|  | ||||
|         this.currentNode = null; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * This is called on a code path looped. | ||||
|      * Then this raises a looped event. | ||||
|      * @param {CodePathSegment} fromSegment A segment of prev. | ||||
|      * @param {CodePathSegment} toSegment A segment of next. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     onLooped(fromSegment, toSegment) { | ||||
|         if (fromSegment.reachable && toSegment.reachable) { | ||||
|             debug.dump(`onCodePathSegmentLoop ${fromSegment.id} -> ${toSegment.id}`); | ||||
|             this.emitter.emit( | ||||
|                 "onCodePathSegmentLoop", | ||||
|                 fromSegment, | ||||
|                 toSegment, | ||||
|                 this.currentNode | ||||
|             ); | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = CodePathAnalyzer; | ||||
							
								
								
									
										263
									
								
								node_modules/eslint/lib/linter/code-path-analysis/code-path-segment.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										263
									
								
								node_modules/eslint/lib/linter/code-path-analysis/code-path-segment.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,263 @@ | ||||
| /** | ||||
|  * @fileoverview The CodePathSegment class. | ||||
|  * @author Toru Nagashima | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const debug = require("./debug-helpers"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Checks whether or not a given segment is reachable. | ||||
|  * @param {CodePathSegment} segment A segment to check. | ||||
|  * @returns {boolean} `true` if the segment is reachable. | ||||
|  */ | ||||
| function isReachable(segment) { | ||||
|     return segment.reachable; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * A code path segment. | ||||
|  * | ||||
|  * Each segment is arranged in a series of linked lists (implemented by arrays) | ||||
|  * that keep track of the previous and next segments in a code path. In this way, | ||||
|  * you can navigate between all segments in any code path so long as you have a | ||||
|  * reference to any segment in that code path. | ||||
|  * | ||||
|  * When first created, the segment is in a detached state, meaning that it knows the | ||||
|  * segments that came before it but those segments don't know that this new segment | ||||
|  * follows it. Only when `CodePathSegment#markUsed()` is called on a segment does it | ||||
|  * officially become part of the code path by updating the previous segments to know | ||||
|  * that this new segment follows. | ||||
|  */ | ||||
| class CodePathSegment { | ||||
|  | ||||
|     /** | ||||
|      * Creates a new instance. | ||||
|      * @param {string} id An identifier. | ||||
|      * @param {CodePathSegment[]} allPrevSegments An array of the previous segments. | ||||
|      *   This array includes unreachable segments. | ||||
|      * @param {boolean} reachable A flag which shows this is reachable. | ||||
|      */ | ||||
|     constructor(id, allPrevSegments, reachable) { | ||||
|  | ||||
|         /** | ||||
|          * The identifier of this code path. | ||||
|          * Rules use it to store additional information of each rule. | ||||
|          * @type {string} | ||||
|          */ | ||||
|         this.id = id; | ||||
|  | ||||
|         /** | ||||
|          * An array of the next reachable segments. | ||||
|          * @type {CodePathSegment[]} | ||||
|          */ | ||||
|         this.nextSegments = []; | ||||
|  | ||||
|         /** | ||||
|          * An array of the previous reachable segments. | ||||
|          * @type {CodePathSegment[]} | ||||
|          */ | ||||
|         this.prevSegments = allPrevSegments.filter(isReachable); | ||||
|  | ||||
|         /** | ||||
|          * An array of all next segments including reachable and unreachable. | ||||
|          * @type {CodePathSegment[]} | ||||
|          */ | ||||
|         this.allNextSegments = []; | ||||
|  | ||||
|         /** | ||||
|          * An array of all previous segments including reachable and unreachable. | ||||
|          * @type {CodePathSegment[]} | ||||
|          */ | ||||
|         this.allPrevSegments = allPrevSegments; | ||||
|  | ||||
|         /** | ||||
|          * A flag which shows this is reachable. | ||||
|          * @type {boolean} | ||||
|          */ | ||||
|         this.reachable = reachable; | ||||
|  | ||||
|         // Internal data. | ||||
|         Object.defineProperty(this, "internal", { | ||||
|             value: { | ||||
|  | ||||
|                 // determines if the segment has been attached to the code path | ||||
|                 used: false, | ||||
|  | ||||
|                 // array of previous segments coming from the end of a loop | ||||
|                 loopedPrevSegments: [] | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         /* c8 ignore start */ | ||||
|         if (debug.enabled) { | ||||
|             this.internal.nodes = []; | ||||
|         }/* c8 ignore stop */ | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Checks a given previous segment is coming from the end of a loop. | ||||
|      * @param {CodePathSegment} segment A previous segment to check. | ||||
|      * @returns {boolean} `true` if the segment is coming from the end of a loop. | ||||
|      */ | ||||
|     isLoopedPrevSegment(segment) { | ||||
|         return this.internal.loopedPrevSegments.includes(segment); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates the root segment. | ||||
|      * @param {string} id An identifier. | ||||
|      * @returns {CodePathSegment} The created segment. | ||||
|      */ | ||||
|     static newRoot(id) { | ||||
|         return new CodePathSegment(id, [], true); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new segment and appends it after the given segments. | ||||
|      * @param {string} id An identifier. | ||||
|      * @param {CodePathSegment[]} allPrevSegments An array of the previous segments | ||||
|      *      to append to. | ||||
|      * @returns {CodePathSegment} The created segment. | ||||
|      */ | ||||
|     static newNext(id, allPrevSegments) { | ||||
|         return new CodePathSegment( | ||||
|             id, | ||||
|             CodePathSegment.flattenUnusedSegments(allPrevSegments), | ||||
|             allPrevSegments.some(isReachable) | ||||
|         ); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates an unreachable segment and appends it after the given segments. | ||||
|      * @param {string} id An identifier. | ||||
|      * @param {CodePathSegment[]} allPrevSegments An array of the previous segments. | ||||
|      * @returns {CodePathSegment} The created segment. | ||||
|      */ | ||||
|     static newUnreachable(id, allPrevSegments) { | ||||
|         const segment = new CodePathSegment(id, CodePathSegment.flattenUnusedSegments(allPrevSegments), false); | ||||
|  | ||||
|         /* | ||||
|          * In `if (a) return a; foo();` case, the unreachable segment preceded by | ||||
|          * the return statement is not used but must not be removed. | ||||
|          */ | ||||
|         CodePathSegment.markUsed(segment); | ||||
|  | ||||
|         return segment; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a segment that follows given segments. | ||||
|      * This factory method does not connect with `allPrevSegments`. | ||||
|      * But this inherits `reachable` flag. | ||||
|      * @param {string} id An identifier. | ||||
|      * @param {CodePathSegment[]} allPrevSegments An array of the previous segments. | ||||
|      * @returns {CodePathSegment} The created segment. | ||||
|      */ | ||||
|     static newDisconnected(id, allPrevSegments) { | ||||
|         return new CodePathSegment(id, [], allPrevSegments.some(isReachable)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Marks a given segment as used. | ||||
|      * | ||||
|      * And this function registers the segment into the previous segments as a next. | ||||
|      * @param {CodePathSegment} segment A segment to mark. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     static markUsed(segment) { | ||||
|         if (segment.internal.used) { | ||||
|             return; | ||||
|         } | ||||
|         segment.internal.used = true; | ||||
|  | ||||
|         let i; | ||||
|  | ||||
|         if (segment.reachable) { | ||||
|  | ||||
|             /* | ||||
|              * If the segment is reachable, then it's officially part of the | ||||
|              * code path. This loops through all previous segments to update | ||||
|              * their list of next segments. Because the segment is reachable, | ||||
|              * it's added to both `nextSegments` and `allNextSegments`. | ||||
|              */ | ||||
|             for (i = 0; i < segment.allPrevSegments.length; ++i) { | ||||
|                 const prevSegment = segment.allPrevSegments[i]; | ||||
|  | ||||
|                 prevSegment.allNextSegments.push(segment); | ||||
|                 prevSegment.nextSegments.push(segment); | ||||
|             } | ||||
|         } else { | ||||
|  | ||||
|             /* | ||||
|              * If the segment is not reachable, then it's not officially part of the | ||||
|              * code path. This loops through all previous segments to update | ||||
|              * their list of next segments. Because the segment is not reachable, | ||||
|              * it's added only to `allNextSegments`. | ||||
|              */ | ||||
|             for (i = 0; i < segment.allPrevSegments.length; ++i) { | ||||
|                 segment.allPrevSegments[i].allNextSegments.push(segment); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Marks a previous segment as looped. | ||||
|      * @param {CodePathSegment} segment A segment. | ||||
|      * @param {CodePathSegment} prevSegment A previous segment to mark. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     static markPrevSegmentAsLooped(segment, prevSegment) { | ||||
|         segment.internal.loopedPrevSegments.push(prevSegment); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new array based on an array of segments. If any segment in the | ||||
|      * array is unused, then it is replaced by all of its previous segments. | ||||
|      * All used segments are returned as-is without replacement. | ||||
|      * @param {CodePathSegment[]} segments The array of segments to flatten. | ||||
|      * @returns {CodePathSegment[]} The flattened array. | ||||
|      */ | ||||
|     static flattenUnusedSegments(segments) { | ||||
|         const done = new Set(); | ||||
|  | ||||
|         for (let i = 0; i < segments.length; ++i) { | ||||
|             const segment = segments[i]; | ||||
|  | ||||
|             // Ignores duplicated. | ||||
|             if (done.has(segment)) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             // Use previous segments if unused. | ||||
|             if (!segment.internal.used) { | ||||
|                 for (let j = 0; j < segment.allPrevSegments.length; ++j) { | ||||
|                     const prevSegment = segment.allPrevSegments[j]; | ||||
|  | ||||
|                     if (!done.has(prevSegment)) { | ||||
|                         done.add(prevSegment); | ||||
|                     } | ||||
|                 } | ||||
|             } else { | ||||
|                 done.add(segment); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return [...done]; | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = CodePathSegment; | ||||
							
								
								
									
										2348
									
								
								node_modules/eslint/lib/linter/code-path-analysis/code-path-state.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2348
									
								
								node_modules/eslint/lib/linter/code-path-analysis/code-path-state.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										342
									
								
								node_modules/eslint/lib/linter/code-path-analysis/code-path.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										342
									
								
								node_modules/eslint/lib/linter/code-path-analysis/code-path.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,342 @@ | ||||
| /** | ||||
|  * @fileoverview A class of the code path. | ||||
|  * @author Toru Nagashima | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const CodePathState = require("./code-path-state"); | ||||
| const IdGenerator = require("./id-generator"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * A code path. | ||||
|  */ | ||||
| class CodePath { | ||||
|  | ||||
|     /** | ||||
|      * Creates a new instance. | ||||
|      * @param {Object} options Options for the function (see below). | ||||
|      * @param {string} options.id An identifier. | ||||
|      * @param {string} options.origin The type of code path origin. | ||||
|      * @param {CodePath|null} options.upper The code path of the upper function scope. | ||||
|      * @param {Function} options.onLooped A callback function to notify looping. | ||||
|      */ | ||||
|     constructor({ id, origin, upper, onLooped }) { | ||||
|  | ||||
|         /** | ||||
|          * The identifier of this code path. | ||||
|          * Rules use it to store additional information of each rule. | ||||
|          * @type {string} | ||||
|          */ | ||||
|         this.id = id; | ||||
|  | ||||
|         /** | ||||
|          * The reason that this code path was started. May be "program", | ||||
|          * "function", "class-field-initializer", or "class-static-block". | ||||
|          * @type {string} | ||||
|          */ | ||||
|         this.origin = origin; | ||||
|  | ||||
|         /** | ||||
|          * The code path of the upper function scope. | ||||
|          * @type {CodePath|null} | ||||
|          */ | ||||
|         this.upper = upper; | ||||
|  | ||||
|         /** | ||||
|          * The code paths of nested function scopes. | ||||
|          * @type {CodePath[]} | ||||
|          */ | ||||
|         this.childCodePaths = []; | ||||
|  | ||||
|         // Initializes internal state. | ||||
|         Object.defineProperty( | ||||
|             this, | ||||
|             "internal", | ||||
|             { value: new CodePathState(new IdGenerator(`${id}_`), onLooped) } | ||||
|         ); | ||||
|  | ||||
|         // Adds this into `childCodePaths` of `upper`. | ||||
|         if (upper) { | ||||
|             upper.childCodePaths.push(this); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Gets the state of a given code path. | ||||
|      * @param {CodePath} codePath A code path to get. | ||||
|      * @returns {CodePathState} The state of the code path. | ||||
|      */ | ||||
|     static getState(codePath) { | ||||
|         return codePath.internal; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The initial code path segment. This is the segment that is at the head | ||||
|      * of the code path. | ||||
|      * This is a passthrough to the underlying `CodePathState`. | ||||
|      * @type {CodePathSegment} | ||||
|      */ | ||||
|     get initialSegment() { | ||||
|         return this.internal.initialSegment; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Final code path segments. These are the terminal (tail) segments in the | ||||
|      * code path, which is the combination of `returnedSegments` and `thrownSegments`. | ||||
|      * All segments in this array are reachable. | ||||
|      * This is a passthrough to the underlying `CodePathState`. | ||||
|      * @type {CodePathSegment[]} | ||||
|      */ | ||||
|     get finalSegments() { | ||||
|         return this.internal.finalSegments; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Final code path segments that represent normal completion of the code path. | ||||
|      * For functions, this means both explicit `return` statements and implicit returns, | ||||
|      * such as the last reachable segment in a function that does not have an | ||||
|      * explicit `return` as this implicitly returns `undefined`. For scripts, | ||||
|      * modules, class field initializers, and class static blocks, this means | ||||
|      * all lines of code have been executed. | ||||
|      * These segments are also present in `finalSegments`. | ||||
|      * This is a passthrough to the underlying `CodePathState`. | ||||
|      * @type {CodePathSegment[]} | ||||
|      */ | ||||
|     get returnedSegments() { | ||||
|         return this.internal.returnedForkContext; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Final code path segments that represent `throw` statements. | ||||
|      * This is a passthrough to the underlying `CodePathState`. | ||||
|      * These segments are also present in `finalSegments`. | ||||
|      * @type {CodePathSegment[]} | ||||
|      */ | ||||
|     get thrownSegments() { | ||||
|         return this.internal.thrownForkContext; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Tracks the traversal of the code path through each segment. This array | ||||
|      * starts empty and segments are added or removed as the code path is | ||||
|      * traversed. This array always ends up empty at the end of a code path | ||||
|      * traversal. The `CodePathState` uses this to track its progress through | ||||
|      * the code path. | ||||
|      * This is a passthrough to the underlying `CodePathState`. | ||||
|      * @type {CodePathSegment[]} | ||||
|      * @deprecated | ||||
|      */ | ||||
|     get currentSegments() { | ||||
|         return this.internal.currentSegments; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Traverses all segments in this code path. | ||||
|      * | ||||
|      *     codePath.traverseSegments((segment, controller) => { | ||||
|      *         // do something. | ||||
|      *     }); | ||||
|      * | ||||
|      * This method enumerates segments in order from the head. | ||||
|      * | ||||
|      * The `controller` argument has two methods: | ||||
|      * | ||||
|      * - `skip()` - skips the following segments in this branch | ||||
|      * - `break()` - skips all following segments in the traversal | ||||
|      * | ||||
|      * A note on the parameters: the `options` argument is optional. This means | ||||
|      * the first argument might be an options object or the callback function. | ||||
|      * @param {Object} [optionsOrCallback] Optional first and last segments to traverse. | ||||
|      * @param {CodePathSegment} [optionsOrCallback.first] The first segment to traverse. | ||||
|      * @param {CodePathSegment} [optionsOrCallback.last] The last segment to traverse. | ||||
|      * @param {Function} callback A callback function. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     traverseSegments(optionsOrCallback, callback) { | ||||
|  | ||||
|         // normalize the arguments into a callback and options | ||||
|         let resolvedOptions; | ||||
|         let resolvedCallback; | ||||
|  | ||||
|         if (typeof optionsOrCallback === "function") { | ||||
|             resolvedCallback = optionsOrCallback; | ||||
|             resolvedOptions = {}; | ||||
|         } else { | ||||
|             resolvedOptions = optionsOrCallback || {}; | ||||
|             resolvedCallback = callback; | ||||
|         } | ||||
|  | ||||
|         // determine where to start traversing from based on the options | ||||
|         const startSegment = resolvedOptions.first || this.internal.initialSegment; | ||||
|         const lastSegment = resolvedOptions.last; | ||||
|  | ||||
|         // set up initial location information | ||||
|         let record = null; | ||||
|         let index = 0; | ||||
|         let end = 0; | ||||
|         let segment = null; | ||||
|  | ||||
|         // segments that have already been visited during traversal | ||||
|         const visited = new Set(); | ||||
|  | ||||
|         // tracks the traversal steps | ||||
|         const stack = [[startSegment, 0]]; | ||||
|  | ||||
|         // tracks the last skipped segment during traversal | ||||
|         let skippedSegment = null; | ||||
|  | ||||
|         // indicates if we exited early from the traversal | ||||
|         let broken = false; | ||||
|  | ||||
|         /** | ||||
|          * Maintains traversal state. | ||||
|          */ | ||||
|         const controller = { | ||||
|  | ||||
|             /** | ||||
|              * Skip the following segments in this branch. | ||||
|              * @returns {void} | ||||
|              */ | ||||
|             skip() { | ||||
|                 if (stack.length <= 1) { | ||||
|                     broken = true; | ||||
|                 } else { | ||||
|                     skippedSegment = stack[stack.length - 2][0]; | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             /** | ||||
|              * Stop traversal completely - do not traverse to any | ||||
|              * other segments. | ||||
|              * @returns {void} | ||||
|              */ | ||||
|             break() { | ||||
|                 broken = true; | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Checks if a given previous segment has been visited. | ||||
|          * @param {CodePathSegment} prevSegment A previous segment to check. | ||||
|          * @returns {boolean} `true` if the segment has been visited. | ||||
|          */ | ||||
|         function isVisited(prevSegment) { | ||||
|             return ( | ||||
|                 visited.has(prevSegment) || | ||||
|                 segment.isLoopedPrevSegment(prevSegment) | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         // the traversal | ||||
|         while (stack.length > 0) { | ||||
|  | ||||
|             /* | ||||
|              * This isn't a pure stack. We use the top record all the time | ||||
|              * but don't always pop it off. The record is popped only if | ||||
|              * one of the following is true: | ||||
|              * | ||||
|              * 1) We have already visited the segment. | ||||
|              * 2) We have not visited *all* of the previous segments. | ||||
|              * 3) We have traversed past the available next segments. | ||||
|              * | ||||
|              * Otherwise, we just read the value and sometimes modify the | ||||
|              * record as we traverse. | ||||
|              */ | ||||
|             record = stack[stack.length - 1]; | ||||
|             segment = record[0]; | ||||
|             index = record[1]; | ||||
|  | ||||
|             if (index === 0) { | ||||
|  | ||||
|                 // Skip if this segment has been visited already. | ||||
|                 if (visited.has(segment)) { | ||||
|                     stack.pop(); | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 // Skip if all previous segments have not been visited. | ||||
|                 if (segment !== startSegment && | ||||
|                     segment.prevSegments.length > 0 && | ||||
|                     !segment.prevSegments.every(isVisited) | ||||
|                 ) { | ||||
|                     stack.pop(); | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 // Reset the skipping flag if all branches have been skipped. | ||||
|                 if (skippedSegment && segment.prevSegments.includes(skippedSegment)) { | ||||
|                     skippedSegment = null; | ||||
|                 } | ||||
|                 visited.add(segment); | ||||
|  | ||||
|                 /* | ||||
|                  * If the most recent segment hasn't been skipped, then we call | ||||
|                  * the callback, passing in the segment and the controller. | ||||
|                  */ | ||||
|                 if (!skippedSegment) { | ||||
|                     resolvedCallback.call(this, segment, controller); | ||||
|  | ||||
|                     // exit if we're at the last segment | ||||
|                     if (segment === lastSegment) { | ||||
|                         controller.skip(); | ||||
|                     } | ||||
|  | ||||
|                     /* | ||||
|                      * If the previous statement was executed, or if the callback | ||||
|                      * called a method on the controller, we might need to exit the | ||||
|                      * loop, so check for that and break accordingly. | ||||
|                      */ | ||||
|                     if (broken) { | ||||
|                         break; | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             // Update the stack. | ||||
|             end = segment.nextSegments.length - 1; | ||||
|             if (index < end) { | ||||
|  | ||||
|                 /* | ||||
|                  * If we haven't yet visited all of the next segments, update | ||||
|                  * the current top record on the stack to the next index to visit | ||||
|                  * and then push a record for the current segment on top. | ||||
|                  * | ||||
|                  * Setting the current top record's index lets us know how many | ||||
|                  * times we've been here and ensures that the segment won't be | ||||
|                  * reprocessed (because we only process segments with an index | ||||
|                  * of 0). | ||||
|                  */ | ||||
|                 record[1] += 1; | ||||
|                 stack.push([segment.nextSegments[index], 0]); | ||||
|             } else if (index === end) { | ||||
|  | ||||
|                 /* | ||||
|                  * If we are at the last next segment, then reset the top record | ||||
|                  * in the stack to next segment and set its index to 0 so it will | ||||
|                  * be processed next. | ||||
|                  */ | ||||
|                 record[0] = segment.nextSegments[index]; | ||||
|                 record[1] = 0; | ||||
|             } else { | ||||
|  | ||||
|                 /* | ||||
|                  * If index > end, that means we have no more segments that need | ||||
|                  * processing. So, we pop that record off of the stack in order to | ||||
|                  * continue traversing at the next level up. | ||||
|                  */ | ||||
|                 stack.pop(); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = CodePath; | ||||
							
								
								
									
										203
									
								
								node_modules/eslint/lib/linter/code-path-analysis/debug-helpers.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										203
									
								
								node_modules/eslint/lib/linter/code-path-analysis/debug-helpers.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,203 @@ | ||||
| /** | ||||
|  * @fileoverview Helpers to debug for code path analysis. | ||||
|  * @author Toru Nagashima | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const debug = require("debug")("eslint:code-path"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Gets id of a given segment. | ||||
|  * @param {CodePathSegment} segment A segment to get. | ||||
|  * @returns {string} Id of the segment. | ||||
|  */ | ||||
| /* c8 ignore next */ | ||||
| function getId(segment) { // eslint-disable-line jsdoc/require-jsdoc -- Ignoring | ||||
|     return segment.id + (segment.reachable ? "" : "!"); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Get string for the given node and operation. | ||||
|  * @param {ASTNode} node The node to convert. | ||||
|  * @param {"enter" | "exit" | undefined} label The operation label. | ||||
|  * @returns {string} The string representation. | ||||
|  */ | ||||
| function nodeToString(node, label) { | ||||
|     const suffix = label ? `:${label}` : ""; | ||||
|  | ||||
|     switch (node.type) { | ||||
|         case "Identifier": return `${node.type}${suffix} (${node.name})`; | ||||
|         case "Literal": return `${node.type}${suffix} (${node.value})`; | ||||
|         default: return `${node.type}${suffix}`; | ||||
|     } | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = { | ||||
|  | ||||
|     /** | ||||
|      * A flag that debug dumping is enabled or not. | ||||
|      * @type {boolean} | ||||
|      */ | ||||
|     enabled: debug.enabled, | ||||
|  | ||||
|     /** | ||||
|      * Dumps given objects. | ||||
|      * @param {...any} args objects to dump. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     dump: debug, | ||||
|  | ||||
|     /** | ||||
|      * Dumps the current analyzing state. | ||||
|      * @param {ASTNode} node A node to dump. | ||||
|      * @param {CodePathState} state A state to dump. | ||||
|      * @param {boolean} leaving A flag whether or not it's leaving | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     dumpState: !debug.enabled ? debug : /* c8 ignore next */ function(node, state, leaving) { | ||||
|         for (let i = 0; i < state.currentSegments.length; ++i) { | ||||
|             const segInternal = state.currentSegments[i].internal; | ||||
|  | ||||
|             if (leaving) { | ||||
|                 const last = segInternal.nodes.length - 1; | ||||
|  | ||||
|                 if (last >= 0 && segInternal.nodes[last] === nodeToString(node, "enter")) { | ||||
|                     segInternal.nodes[last] = nodeToString(node, void 0); | ||||
|                 } else { | ||||
|                     segInternal.nodes.push(nodeToString(node, "exit")); | ||||
|                 } | ||||
|             } else { | ||||
|                 segInternal.nodes.push(nodeToString(node, "enter")); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         debug([ | ||||
|             `${state.currentSegments.map(getId).join(",")})`, | ||||
|             `${node.type}${leaving ? ":exit" : ""}` | ||||
|         ].join(" ")); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Dumps a DOT code of a given code path. | ||||
|      * The DOT code can be visualized with Graphvis. | ||||
|      * @param {CodePath} codePath A code path to dump. | ||||
|      * @returns {void} | ||||
|      * @see http://www.graphviz.org | ||||
|      * @see http://www.webgraphviz.com | ||||
|      */ | ||||
|     dumpDot: !debug.enabled ? debug : /* c8 ignore next */ function(codePath) { | ||||
|         let text = | ||||
|             "\n" + | ||||
|             "digraph {\n" + | ||||
|             "node[shape=box,style=\"rounded,filled\",fillcolor=white];\n" + | ||||
|             "initial[label=\"\",shape=circle,style=filled,fillcolor=black,width=0.25,height=0.25];\n"; | ||||
|  | ||||
|         if (codePath.returnedSegments.length > 0) { | ||||
|             text += "final[label=\"\",shape=doublecircle,style=filled,fillcolor=black,width=0.25,height=0.25];\n"; | ||||
|         } | ||||
|         if (codePath.thrownSegments.length > 0) { | ||||
|             text += "thrown[label=\"✘\",shape=circle,width=0.3,height=0.3,fixedsize=true];\n"; | ||||
|         } | ||||
|  | ||||
|         const traceMap = Object.create(null); | ||||
|         const arrows = this.makeDotArrows(codePath, traceMap); | ||||
|  | ||||
|         for (const id in traceMap) { // eslint-disable-line guard-for-in -- Want ability to traverse prototype | ||||
|             const segment = traceMap[id]; | ||||
|  | ||||
|             text += `${id}[`; | ||||
|  | ||||
|             if (segment.reachable) { | ||||
|                 text += "label=\""; | ||||
|             } else { | ||||
|                 text += "style=\"rounded,dashed,filled\",fillcolor=\"#FF9800\",label=\"<<unreachable>>\\n"; | ||||
|             } | ||||
|  | ||||
|             if (segment.internal.nodes.length > 0) { | ||||
|                 text += segment.internal.nodes.join("\\n"); | ||||
|             } else { | ||||
|                 text += "????"; | ||||
|             } | ||||
|  | ||||
|             text += "\"];\n"; | ||||
|         } | ||||
|  | ||||
|         text += `${arrows}\n`; | ||||
|         text += "}"; | ||||
|         debug("DOT", text); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Makes a DOT code of a given code path. | ||||
|      * The DOT code can be visualized with Graphvis. | ||||
|      * @param {CodePath} codePath A code path to make DOT. | ||||
|      * @param {Object} traceMap Optional. A map to check whether or not segments had been done. | ||||
|      * @returns {string} A DOT code of the code path. | ||||
|      */ | ||||
|     makeDotArrows(codePath, traceMap) { | ||||
|         const stack = [[codePath.initialSegment, 0]]; | ||||
|         const done = traceMap || Object.create(null); | ||||
|         let lastId = codePath.initialSegment.id; | ||||
|         let text = `initial->${codePath.initialSegment.id}`; | ||||
|  | ||||
|         while (stack.length > 0) { | ||||
|             const item = stack.pop(); | ||||
|             const segment = item[0]; | ||||
|             const index = item[1]; | ||||
|  | ||||
|             if (done[segment.id] && index === 0) { | ||||
|                 continue; | ||||
|             } | ||||
|             done[segment.id] = segment; | ||||
|  | ||||
|             const nextSegment = segment.allNextSegments[index]; | ||||
|  | ||||
|             if (!nextSegment) { | ||||
|                 continue; | ||||
|             } | ||||
|  | ||||
|             if (lastId === segment.id) { | ||||
|                 text += `->${nextSegment.id}`; | ||||
|             } else { | ||||
|                 text += `;\n${segment.id}->${nextSegment.id}`; | ||||
|             } | ||||
|             lastId = nextSegment.id; | ||||
|  | ||||
|             stack.unshift([segment, 1 + index]); | ||||
|             stack.push([nextSegment, 0]); | ||||
|         } | ||||
|  | ||||
|         codePath.returnedSegments.forEach(finalSegment => { | ||||
|             if (lastId === finalSegment.id) { | ||||
|                 text += "->final"; | ||||
|             } else { | ||||
|                 text += `;\n${finalSegment.id}->final`; | ||||
|             } | ||||
|             lastId = null; | ||||
|         }); | ||||
|  | ||||
|         codePath.thrownSegments.forEach(finalSegment => { | ||||
|             if (lastId === finalSegment.id) { | ||||
|                 text += "->thrown"; | ||||
|             } else { | ||||
|                 text += `;\n${finalSegment.id}->thrown`; | ||||
|             } | ||||
|             lastId = null; | ||||
|         }); | ||||
|  | ||||
|         return `${text};`; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										349
									
								
								node_modules/eslint/lib/linter/code-path-analysis/fork-context.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										349
									
								
								node_modules/eslint/lib/linter/code-path-analysis/fork-context.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,349 @@ | ||||
| /** | ||||
|  * @fileoverview A class to operate forking. | ||||
|  * | ||||
|  * This is state of forking. | ||||
|  * This has a fork list and manages it. | ||||
|  * | ||||
|  * @author Toru Nagashima | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const assert = require("assert"), | ||||
|     CodePathSegment = require("./code-path-segment"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Determines whether or not a given segment is reachable. | ||||
|  * @param {CodePathSegment} segment The segment to check. | ||||
|  * @returns {boolean} `true` if the segment is reachable. | ||||
|  */ | ||||
| function isReachable(segment) { | ||||
|     return segment.reachable; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Creates a new segment for each fork in the given context and appends it | ||||
|  * to the end of the specified range of segments. Ultimately, this ends up calling | ||||
|  * `new CodePathSegment()` for each of the forks using the `create` argument | ||||
|  * as a wrapper around special behavior. | ||||
|  * | ||||
|  * The `startIndex` and `endIndex` arguments specify a range of segments in | ||||
|  * `context` that should become `allPrevSegments` for the newly created | ||||
|  * `CodePathSegment` objects. | ||||
|  * | ||||
|  * When `context.segmentsList` is `[[a, b], [c, d], [e, f]]`, `begin` is `0`, and | ||||
|  * `end` is `-1`, this creates two new segments, `[g, h]`. This `g` is appended to | ||||
|  * the end of the path from `a`, `c`, and `e`. This `h` is appended to the end of | ||||
|  * `b`, `d`, and `f`. | ||||
|  * @param {ForkContext} context An instance from which the previous segments | ||||
|  *      will be obtained. | ||||
|  * @param {number} startIndex The index of the first segment in the context | ||||
|  *      that should be specified as previous segments for the newly created segments. | ||||
|  * @param {number} endIndex The index of the last segment in the context | ||||
|  *      that should be specified as previous segments for the newly created segments. | ||||
|  * @param {Function} create A function that creates new `CodePathSegment` | ||||
|  *      instances in a particular way. See the `CodePathSegment.new*` methods. | ||||
|  * @returns {Array<CodePathSegment>} An array of the newly-created segments. | ||||
|  */ | ||||
| function createSegments(context, startIndex, endIndex, create) { | ||||
|  | ||||
|     /** @type {Array<Array<CodePathSegment>>} */ | ||||
|     const list = context.segmentsList; | ||||
|  | ||||
|     /* | ||||
|      * Both `startIndex` and `endIndex` work the same way: if the number is zero | ||||
|      * or more, then the number is used as-is. If the number is negative, | ||||
|      * then that number is added to the length of the segments list to | ||||
|      * determine the index to use. That means -1 for either argument | ||||
|      * is the last element, -2 is the second to last, and so on. | ||||
|      * | ||||
|      * So if `startIndex` is 0, `endIndex` is -1, and `list.length` is 3, the | ||||
|      * effective `startIndex` is 0 and the effective `endIndex` is 2, so this function | ||||
|      * will include items at indices 0, 1, and 2. | ||||
|      * | ||||
|      * Therefore, if `startIndex` is -1 and `endIndex` is -1, that means we'll only | ||||
|      * be using the last segment in `list`. | ||||
|      */ | ||||
|     const normalizedBegin = startIndex >= 0 ? startIndex : list.length + startIndex; | ||||
|     const normalizedEnd = endIndex >= 0 ? endIndex : list.length + endIndex; | ||||
|  | ||||
|     /** @type {Array<CodePathSegment>} */ | ||||
|     const segments = []; | ||||
|  | ||||
|     for (let i = 0; i < context.count; ++i) { | ||||
|  | ||||
|         // this is passed into `new CodePathSegment` to add to code path. | ||||
|         const allPrevSegments = []; | ||||
|  | ||||
|         for (let j = normalizedBegin; j <= normalizedEnd; ++j) { | ||||
|             allPrevSegments.push(list[j][i]); | ||||
|         } | ||||
|  | ||||
|         // note: `create` is just a wrapper that augments `new CodePathSegment`. | ||||
|         segments.push(create(context.idGenerator.next(), allPrevSegments)); | ||||
|     } | ||||
|  | ||||
|     return segments; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Inside of a `finally` block we end up with two parallel paths. If the code path | ||||
|  * exits by a control statement (such as `break` or `continue`) from the `finally` | ||||
|  * block, then we need to merge the remaining parallel paths back into one. | ||||
|  * @param {ForkContext} context The fork context to work on. | ||||
|  * @param {Array<CodePathSegment>} segments Segments to merge. | ||||
|  * @returns {Array<CodePathSegment>} The merged segments. | ||||
|  */ | ||||
| function mergeExtraSegments(context, segments) { | ||||
|     let currentSegments = segments; | ||||
|  | ||||
|     /* | ||||
|      * We need to ensure that the array returned from this function contains no more | ||||
|      * than the number of segments that the context allows. `context.count` indicates | ||||
|      * how many items should be in the returned array to ensure that the new segment | ||||
|      * entries will line up with the already existing segment entries. | ||||
|      */ | ||||
|     while (currentSegments.length > context.count) { | ||||
|         const merged = []; | ||||
|  | ||||
|         /* | ||||
|          * Because `context.count` is a factor of 2 inside of a `finally` block, | ||||
|          * we can divide the segment count by 2 to merge the paths together. | ||||
|          * This loops through each segment in the list and creates a new `CodePathSegment` | ||||
|          * that has the segment and the segment two slots away as previous segments. | ||||
|          * | ||||
|          * If `currentSegments` is [a,b,c,d], this will create new segments e and f, such | ||||
|          * that: | ||||
|          * | ||||
|          * When `i` is 0: | ||||
|          * a->e | ||||
|          * c->e | ||||
|          * | ||||
|          * When `i` is 1: | ||||
|          * b->f | ||||
|          * d->f | ||||
|          */ | ||||
|         for (let i = 0, length = Math.floor(currentSegments.length / 2); i < length; ++i) { | ||||
|             merged.push(CodePathSegment.newNext( | ||||
|                 context.idGenerator.next(), | ||||
|                 [currentSegments[i], currentSegments[i + length]] | ||||
|             )); | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * Go through the loop condition one more time to see if we have the | ||||
|          * number of segments for the context. If not, we'll keep merging paths | ||||
|          * of the merged segments until we get there. | ||||
|          */ | ||||
|         currentSegments = merged; | ||||
|     } | ||||
|  | ||||
|     return currentSegments; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Manages the forking of code paths. | ||||
|  */ | ||||
| class ForkContext { | ||||
|  | ||||
|     /** | ||||
|      * Creates a new instance. | ||||
|      * @param {IdGenerator} idGenerator An identifier generator for segments. | ||||
|      * @param {ForkContext|null} upper The preceding fork context. | ||||
|      * @param {number} count The number of parallel segments in each element | ||||
|      *      of `segmentsList`. | ||||
|      */ | ||||
|     constructor(idGenerator, upper, count) { | ||||
|  | ||||
|         /** | ||||
|          * The ID generator that will generate segment IDs for any new | ||||
|          * segments that are created. | ||||
|          * @type {IdGenerator} | ||||
|          */ | ||||
|         this.idGenerator = idGenerator; | ||||
|  | ||||
|         /** | ||||
|          * The preceding fork context. | ||||
|          * @type {ForkContext|null} | ||||
|          */ | ||||
|         this.upper = upper; | ||||
|  | ||||
|         /** | ||||
|          * The number of elements in each element of `segmentsList`. In most | ||||
|          * cases, this is 1 but can be 2 when there is a `finally` present, | ||||
|          * which forks the code path outside of normal flow. In the case of nested | ||||
|          * `finally` blocks, this can be a multiple of 2. | ||||
|          * @type {number} | ||||
|          */ | ||||
|         this.count = count; | ||||
|  | ||||
|         /** | ||||
|          * The segments within this context. Each element in this array has | ||||
|          * `count` elements that represent one step in each fork. For example, | ||||
|          * when `segmentsList` is `[[a, b], [c, d], [e, f]]`, there is one path | ||||
|          * a->c->e and one path b->d->f, and `count` is 2 because each element | ||||
|          * is an array with two elements. | ||||
|          * @type {Array<Array<CodePathSegment>>} | ||||
|          */ | ||||
|         this.segmentsList = []; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * The segments that begin this fork context. | ||||
|      * @type {Array<CodePathSegment>} | ||||
|      */ | ||||
|     get head() { | ||||
|         const list = this.segmentsList; | ||||
|  | ||||
|         return list.length === 0 ? [] : list[list.length - 1]; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Indicates if the context contains no segments. | ||||
|      * @type {boolean} | ||||
|      */ | ||||
|     get empty() { | ||||
|         return this.segmentsList.length === 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Indicates if there are any segments that are reachable. | ||||
|      * @type {boolean} | ||||
|      */ | ||||
|     get reachable() { | ||||
|         const segments = this.head; | ||||
|  | ||||
|         return segments.length > 0 && segments.some(isReachable); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates new segments in this context and appends them to the end of the | ||||
|      * already existing `CodePathSegment`s specified by `startIndex` and | ||||
|      * `endIndex`. | ||||
|      * @param {number} startIndex The index of the first segment in the context | ||||
|      *      that should be specified as previous segments for the newly created segments. | ||||
|      * @param {number} endIndex The index of the last segment in the context | ||||
|      *      that should be specified as previous segments for the newly created segments. | ||||
|      * @returns {Array<CodePathSegment>} An array of the newly created segments. | ||||
|      */ | ||||
|     makeNext(startIndex, endIndex) { | ||||
|         return createSegments(this, startIndex, endIndex, CodePathSegment.newNext); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates new unreachable segments in this context and appends them to the end of the | ||||
|      * already existing `CodePathSegment`s specified by `startIndex` and | ||||
|      * `endIndex`. | ||||
|      * @param {number} startIndex The index of the first segment in the context | ||||
|      *      that should be specified as previous segments for the newly created segments. | ||||
|      * @param {number} endIndex The index of the last segment in the context | ||||
|      *      that should be specified as previous segments for the newly created segments. | ||||
|      * @returns {Array<CodePathSegment>} An array of the newly created segments. | ||||
|      */ | ||||
|     makeUnreachable(startIndex, endIndex) { | ||||
|         return createSegments(this, startIndex, endIndex, CodePathSegment.newUnreachable); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates new segments in this context and does not append them to the end | ||||
|      *  of the already existing `CodePathSegment`s specified by `startIndex` and | ||||
|      * `endIndex`. The `startIndex` and `endIndex` are only used to determine if | ||||
|      * the new segments should be reachable. If any of the segments in this range | ||||
|      * are reachable then the new segments are also reachable; otherwise, the new | ||||
|      * segments are unreachable. | ||||
|      * @param {number} startIndex The index of the first segment in the context | ||||
|      *      that should be considered for reachability. | ||||
|      * @param {number} endIndex The index of the last segment in the context | ||||
|      *      that should be considered for reachability. | ||||
|      * @returns {Array<CodePathSegment>} An array of the newly created segments. | ||||
|      */ | ||||
|     makeDisconnected(startIndex, endIndex) { | ||||
|         return createSegments(this, startIndex, endIndex, CodePathSegment.newDisconnected); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Adds segments to the head of this context. | ||||
|      * @param {Array<CodePathSegment>} segments The segments to add. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     add(segments) { | ||||
|         assert(segments.length >= this.count, `${segments.length} >= ${this.count}`); | ||||
|         this.segmentsList.push(mergeExtraSegments(this, segments)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Replaces the head segments with the given segments. | ||||
|      * The current head segments are removed. | ||||
|      * @param {Array<CodePathSegment>} replacementHeadSegments The new head segments. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     replaceHead(replacementHeadSegments) { | ||||
|         assert( | ||||
|             replacementHeadSegments.length >= this.count, | ||||
|             `${replacementHeadSegments.length} >= ${this.count}` | ||||
|         ); | ||||
|         this.segmentsList.splice(-1, 1, mergeExtraSegments(this, replacementHeadSegments)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Adds all segments of a given fork context into this context. | ||||
|      * @param {ForkContext} otherForkContext The fork context to add from. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     addAll(otherForkContext) { | ||||
|         assert(otherForkContext.count === this.count); | ||||
|         this.segmentsList.push(...otherForkContext.segmentsList); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Clears all segments in this context. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     clear() { | ||||
|         this.segmentsList = []; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates a new root context, meaning that there are no parent | ||||
|      * fork contexts. | ||||
|      * @param {IdGenerator} idGenerator An identifier generator for segments. | ||||
|      * @returns {ForkContext} New fork context. | ||||
|      */ | ||||
|     static newRoot(idGenerator) { | ||||
|         const context = new ForkContext(idGenerator, null, 1); | ||||
|  | ||||
|         context.add([CodePathSegment.newRoot(idGenerator.next())]); | ||||
|  | ||||
|         return context; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Creates an empty fork context preceded by a given context. | ||||
|      * @param {ForkContext} parentContext The parent fork context. | ||||
|      * @param {boolean} shouldForkLeavingPath Indicates that we are inside of | ||||
|      *      a `finally` block and should therefore fork the path that leaves | ||||
|      *      `finally`. | ||||
|      * @returns {ForkContext} New fork context. | ||||
|      */ | ||||
|     static newEmpty(parentContext, shouldForkLeavingPath) { | ||||
|         return new ForkContext( | ||||
|             parentContext.idGenerator, | ||||
|             parentContext, | ||||
|             (shouldForkLeavingPath ? 2 : 1) * parentContext.count | ||||
|         ); | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = ForkContext; | ||||
							
								
								
									
										45
									
								
								node_modules/eslint/lib/linter/code-path-analysis/id-generator.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										45
									
								
								node_modules/eslint/lib/linter/code-path-analysis/id-generator.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,45 @@ | ||||
| /** | ||||
|  * @fileoverview A class of identifiers generator for code path segments. | ||||
|  * | ||||
|  * Each rule uses the identifier of code path segments to store additional | ||||
|  * information of the code path. | ||||
|  * | ||||
|  * @author Toru Nagashima | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * A generator for unique ids. | ||||
|  */ | ||||
| class IdGenerator { | ||||
|  | ||||
|     /** | ||||
|      * @param {string} prefix Optional. A prefix of generated ids. | ||||
|      */ | ||||
|     constructor(prefix) { | ||||
|         this.prefix = String(prefix); | ||||
|         this.n = 0; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Generates id. | ||||
|      * @returns {string} A generated id. | ||||
|      */ | ||||
|     next() { | ||||
|         this.n = 1 + this.n | 0; | ||||
|  | ||||
|         /* c8 ignore start */ | ||||
|         if (this.n < 0) { | ||||
|             this.n = 1; | ||||
|         }/* c8 ignore stop */ | ||||
|  | ||||
|         return this.prefix + this.n; | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = IdGenerator; | ||||
							
								
								
									
										185
									
								
								node_modules/eslint/lib/linter/config-comment-parser.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										185
									
								
								node_modules/eslint/lib/linter/config-comment-parser.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,185 @@ | ||||
| /** | ||||
|  * @fileoverview Config Comment Parser | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| /* eslint class-methods-use-this: off -- Methods desired on instance */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const levn = require("levn"), | ||||
|     { | ||||
|         Legacy: { | ||||
|             ConfigOps | ||||
|         } | ||||
|     } = require("@eslint/eslintrc/universal"), | ||||
|     { | ||||
|         directivesPattern | ||||
|     } = require("../shared/directives"); | ||||
|  | ||||
| const debug = require("debug")("eslint:config-comment-parser"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Typedefs | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @typedef {import("../shared/types").LintMessage} LintMessage */ | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Object to parse ESLint configuration comments inside JavaScript files. | ||||
|  * @name ConfigCommentParser | ||||
|  */ | ||||
| module.exports = class ConfigCommentParser { | ||||
|  | ||||
|     /** | ||||
|      * Parses a list of "name:string_value" or/and "name" options divided by comma or | ||||
|      * whitespace. Used for "global" and "exported" comments. | ||||
|      * @param {string} string The string to parse. | ||||
|      * @param {Comment} comment The comment node which has the string. | ||||
|      * @returns {Object} Result map object of names and string values, or null values if no value was provided | ||||
|      */ | ||||
|     parseStringConfig(string, comment) { | ||||
|         debug("Parsing String config"); | ||||
|  | ||||
|         const items = {}; | ||||
|  | ||||
|         // Collapse whitespace around `:` and `,` to make parsing easier | ||||
|         const trimmedString = string.replace(/\s*([:,])\s*/gu, "$1"); | ||||
|  | ||||
|         trimmedString.split(/\s|,+/u).forEach(name => { | ||||
|             if (!name) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             // value defaults to null (if not provided), e.g: "foo" => ["foo", null] | ||||
|             const [key, value = null] = name.split(":"); | ||||
|  | ||||
|             items[key] = { value, comment }; | ||||
|         }); | ||||
|         return items; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Parses a JSON-like config. | ||||
|      * @param {string} string The string to parse. | ||||
|      * @param {Object} location Start line and column of comments for potential error message. | ||||
|      * @returns {({success: true, config: Object}|{success: false, error: LintMessage})} Result map object | ||||
|      */ | ||||
|     parseJsonConfig(string, location) { | ||||
|         debug("Parsing JSON config"); | ||||
|  | ||||
|         let items = {}; | ||||
|  | ||||
|         // Parses a JSON-like comment by the same way as parsing CLI option. | ||||
|         try { | ||||
|             items = levn.parse("Object", string) || {}; | ||||
|  | ||||
|             // Some tests say that it should ignore invalid comments such as `/*eslint no-alert:abc*/`. | ||||
|             // Also, commaless notations have invalid severity: | ||||
|             //     "no-alert: 2 no-console: 2" --> {"no-alert": "2 no-console: 2"} | ||||
|             // Should ignore that case as well. | ||||
|             if (ConfigOps.isEverySeverityValid(items)) { | ||||
|                 return { | ||||
|                     success: true, | ||||
|                     config: items | ||||
|                 }; | ||||
|             } | ||||
|         } catch { | ||||
|  | ||||
|             debug("Levn parsing failed; falling back to manual parsing."); | ||||
|  | ||||
|             // ignore to parse the string by a fallback. | ||||
|         } | ||||
|  | ||||
|         /* | ||||
|          * Optionator cannot parse commaless notations. | ||||
|          * But we are supporting that. So this is a fallback for that. | ||||
|          */ | ||||
|         items = {}; | ||||
|         const normalizedString = string.replace(/([-a-zA-Z0-9/]+):/gu, "\"$1\":").replace(/(\]|[0-9])\s+(?=")/u, "$1,"); | ||||
|  | ||||
|         try { | ||||
|             items = JSON.parse(`{${normalizedString}}`); | ||||
|         } catch (ex) { | ||||
|             debug("Manual parsing failed."); | ||||
|  | ||||
|             return { | ||||
|                 success: false, | ||||
|                 error: { | ||||
|                     ruleId: null, | ||||
|                     fatal: true, | ||||
|                     severity: 2, | ||||
|                     message: `Failed to parse JSON from '${normalizedString}': ${ex.message}`, | ||||
|                     line: location.start.line, | ||||
|                     column: location.start.column + 1, | ||||
|                     nodeType: null | ||||
|                 } | ||||
|             }; | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             success: true, | ||||
|             config: items | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Parses a config of values separated by comma. | ||||
|      * @param {string} string The string to parse. | ||||
|      * @returns {Object} Result map of values and true values | ||||
|      */ | ||||
|     parseListConfig(string) { | ||||
|         debug("Parsing list config"); | ||||
|  | ||||
|         const items = {}; | ||||
|  | ||||
|         string.split(",").forEach(name => { | ||||
|             const trimmedName = name.trim().replace(/^(?<quote>['"]?)(?<ruleId>.*)\k<quote>$/us, "$<ruleId>"); | ||||
|  | ||||
|             if (trimmedName) { | ||||
|                 items[trimmedName] = true; | ||||
|             } | ||||
|         }); | ||||
|         return items; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Extract the directive and the justification from a given directive comment and trim them. | ||||
|      * @param {string} value The comment text to extract. | ||||
|      * @returns {{directivePart: string, justificationPart: string}} The extracted directive and justification. | ||||
|      */ | ||||
|     extractDirectiveComment(value) { | ||||
|         const match = /\s-{2,}\s/u.exec(value); | ||||
|  | ||||
|         if (!match) { | ||||
|             return { directivePart: value.trim(), justificationPart: "" }; | ||||
|         } | ||||
|  | ||||
|         const directive = value.slice(0, match.index).trim(); | ||||
|         const justification = value.slice(match.index + match[0].length).trim(); | ||||
|  | ||||
|         return { directivePart: directive, justificationPart: justification }; | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Parses a directive comment into directive text and value. | ||||
|      * @param {Comment} comment The comment node with the directive to be parsed. | ||||
|      * @returns {{directiveText: string, directiveValue: string}} The directive text and value. | ||||
|      */ | ||||
|     parseDirective(comment) { | ||||
|         const { directivePart } = this.extractDirectiveComment(comment.value); | ||||
|         const match = directivesPattern.exec(directivePart); | ||||
|         const directiveText = match[1]; | ||||
|         const directiveValue = directivePart.slice(match.index + directiveText.length); | ||||
|  | ||||
|         return { directiveText, directiveValue }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										13
									
								
								node_modules/eslint/lib/linter/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								node_modules/eslint/lib/linter/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | ||||
| "use strict"; | ||||
|  | ||||
| const { Linter } = require("./linter"); | ||||
| const interpolate = require("./interpolate"); | ||||
| const SourceCodeFixer = require("./source-code-fixer"); | ||||
|  | ||||
| module.exports = { | ||||
|     Linter, | ||||
|  | ||||
|     // For testers. | ||||
|     SourceCodeFixer, | ||||
|     interpolate | ||||
| }; | ||||
							
								
								
									
										28
									
								
								node_modules/eslint/lib/linter/interpolate.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										28
									
								
								node_modules/eslint/lib/linter/interpolate.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,28 @@ | ||||
| /** | ||||
|  * @fileoverview Interpolate keys from an object into a string with {{ }} markers. | ||||
|  * @author Jed Fox | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| module.exports = (text, data) => { | ||||
|     if (!data) { | ||||
|         return text; | ||||
|     } | ||||
|  | ||||
|     // Substitution content for any {{ }} markers. | ||||
|     return text.replace(/\{\{([^{}]+?)\}\}/gu, (fullMatch, termWithWhitespace) => { | ||||
|         const term = termWithWhitespace.trim(); | ||||
|  | ||||
|         if (term in data) { | ||||
|             return data[term]; | ||||
|         } | ||||
|  | ||||
|         // Preserve old behavior: If parameter name not provided, don't replace it. | ||||
|         return fullMatch; | ||||
|     }); | ||||
| }; | ||||
							
								
								
									
										2119
									
								
								node_modules/eslint/lib/linter/linter.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										2119
									
								
								node_modules/eslint/lib/linter/linter.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										354
									
								
								node_modules/eslint/lib/linter/node-event-generator.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										354
									
								
								node_modules/eslint/lib/linter/node-event-generator.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,354 @@ | ||||
| /** | ||||
|  * @fileoverview The event generator for AST nodes. | ||||
|  * @author Toru Nagashima | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const esquery = require("esquery"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Typedefs | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * An object describing an AST selector | ||||
|  * @typedef {Object} ASTSelector | ||||
|  * @property {string} rawSelector The string that was parsed into this selector | ||||
|  * @property {boolean} isExit `true` if this should be emitted when exiting the node rather than when entering | ||||
|  * @property {Object} parsedSelector An object (from esquery) describing the matching behavior of the selector | ||||
|  * @property {string[]|null} listenerTypes A list of node types that could possibly cause the selector to match, | ||||
|  * or `null` if all node types could cause a match | ||||
|  * @property {number} attributeCount The total number of classes, pseudo-classes, and attribute queries in this selector | ||||
|  * @property {number} identifierCount The total number of identifier queries in this selector | ||||
|  */ | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Computes the union of one or more arrays | ||||
|  * @param {...any[]} arrays One or more arrays to union | ||||
|  * @returns {any[]} The union of the input arrays | ||||
|  */ | ||||
| function union(...arrays) { | ||||
|     return [...new Set(arrays.flat())]; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Computes the intersection of one or more arrays | ||||
|  * @param {...any[]} arrays One or more arrays to intersect | ||||
|  * @returns {any[]} The intersection of the input arrays | ||||
|  */ | ||||
| function intersection(...arrays) { | ||||
|     if (arrays.length === 0) { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     let result = [...new Set(arrays[0])]; | ||||
|  | ||||
|     for (const array of arrays.slice(1)) { | ||||
|         result = result.filter(x => array.includes(x)); | ||||
|     } | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Gets the possible types of a selector | ||||
|  * @param {Object} parsedSelector An object (from esquery) describing the matching behavior of the selector | ||||
|  * @returns {string[]|null} The node types that could possibly trigger this selector, or `null` if all node types could trigger it | ||||
|  */ | ||||
| function getPossibleTypes(parsedSelector) { | ||||
|     switch (parsedSelector.type) { | ||||
|         case "identifier": | ||||
|             return [parsedSelector.value]; | ||||
|  | ||||
|         case "matches": { | ||||
|             const typesForComponents = parsedSelector.selectors.map(getPossibleTypes); | ||||
|  | ||||
|             if (typesForComponents.every(Boolean)) { | ||||
|                 return union(...typesForComponents); | ||||
|             } | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         case "compound": { | ||||
|             const typesForComponents = parsedSelector.selectors.map(getPossibleTypes).filter(typesForComponent => typesForComponent); | ||||
|  | ||||
|             // If all of the components could match any type, then the compound could also match any type. | ||||
|             if (!typesForComponents.length) { | ||||
|                 return null; | ||||
|             } | ||||
|  | ||||
|             /* | ||||
|              * If at least one of the components could only match a particular type, the compound could only match | ||||
|              * the intersection of those types. | ||||
|              */ | ||||
|             return intersection(...typesForComponents); | ||||
|         } | ||||
|  | ||||
|         case "child": | ||||
|         case "descendant": | ||||
|         case "sibling": | ||||
|         case "adjacent": | ||||
|             return getPossibleTypes(parsedSelector.right); | ||||
|  | ||||
|         case "class": | ||||
|             if (parsedSelector.name === "function") { | ||||
|                 return ["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"]; | ||||
|             } | ||||
|  | ||||
|             return null; | ||||
|  | ||||
|         default: | ||||
|             return null; | ||||
|  | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Counts the number of class, pseudo-class, and attribute queries in this selector | ||||
|  * @param {Object} parsedSelector An object (from esquery) describing the selector's matching behavior | ||||
|  * @returns {number} The number of class, pseudo-class, and attribute queries in this selector | ||||
|  */ | ||||
| function countClassAttributes(parsedSelector) { | ||||
|     switch (parsedSelector.type) { | ||||
|         case "child": | ||||
|         case "descendant": | ||||
|         case "sibling": | ||||
|         case "adjacent": | ||||
|             return countClassAttributes(parsedSelector.left) + countClassAttributes(parsedSelector.right); | ||||
|  | ||||
|         case "compound": | ||||
|         case "not": | ||||
|         case "matches": | ||||
|             return parsedSelector.selectors.reduce((sum, childSelector) => sum + countClassAttributes(childSelector), 0); | ||||
|  | ||||
|         case "attribute": | ||||
|         case "field": | ||||
|         case "nth-child": | ||||
|         case "nth-last-child": | ||||
|             return 1; | ||||
|  | ||||
|         default: | ||||
|             return 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Counts the number of identifier queries in this selector | ||||
|  * @param {Object} parsedSelector An object (from esquery) describing the selector's matching behavior | ||||
|  * @returns {number} The number of identifier queries | ||||
|  */ | ||||
| function countIdentifiers(parsedSelector) { | ||||
|     switch (parsedSelector.type) { | ||||
|         case "child": | ||||
|         case "descendant": | ||||
|         case "sibling": | ||||
|         case "adjacent": | ||||
|             return countIdentifiers(parsedSelector.left) + countIdentifiers(parsedSelector.right); | ||||
|  | ||||
|         case "compound": | ||||
|         case "not": | ||||
|         case "matches": | ||||
|             return parsedSelector.selectors.reduce((sum, childSelector) => sum + countIdentifiers(childSelector), 0); | ||||
|  | ||||
|         case "identifier": | ||||
|             return 1; | ||||
|  | ||||
|         default: | ||||
|             return 0; | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Compares the specificity of two selector objects, with CSS-like rules. | ||||
|  * @param {ASTSelector} selectorA An AST selector descriptor | ||||
|  * @param {ASTSelector} selectorB Another AST selector descriptor | ||||
|  * @returns {number} | ||||
|  * a value less than 0 if selectorA is less specific than selectorB | ||||
|  * a value greater than 0 if selectorA is more specific than selectorB | ||||
|  * a value less than 0 if selectorA and selectorB have the same specificity, and selectorA <= selectorB alphabetically | ||||
|  * a value greater than 0 if selectorA and selectorB have the same specificity, and selectorA > selectorB alphabetically | ||||
|  */ | ||||
| function compareSpecificity(selectorA, selectorB) { | ||||
|     return selectorA.attributeCount - selectorB.attributeCount || | ||||
|         selectorA.identifierCount - selectorB.identifierCount || | ||||
|         (selectorA.rawSelector <= selectorB.rawSelector ? -1 : 1); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Parses a raw selector string, and throws a useful error if parsing fails. | ||||
|  * @param {string} rawSelector A raw AST selector | ||||
|  * @returns {Object} An object (from esquery) describing the matching behavior of this selector | ||||
|  * @throws {Error} An error if the selector is invalid | ||||
|  */ | ||||
| function tryParseSelector(rawSelector) { | ||||
|     try { | ||||
|         return esquery.parse(rawSelector.replace(/:exit$/u, "")); | ||||
|     } catch (err) { | ||||
|         if (err.location && err.location.start && typeof err.location.start.offset === "number") { | ||||
|             throw new SyntaxError(`Syntax error in selector "${rawSelector}" at position ${err.location.start.offset}: ${err.message}`); | ||||
|         } | ||||
|         throw err; | ||||
|     } | ||||
| } | ||||
|  | ||||
| const selectorCache = new Map(); | ||||
|  | ||||
| /** | ||||
|  * Parses a raw selector string, and returns the parsed selector along with specificity and type information. | ||||
|  * @param {string} rawSelector A raw AST selector | ||||
|  * @returns {ASTSelector} A selector descriptor | ||||
|  */ | ||||
| function parseSelector(rawSelector) { | ||||
|     if (selectorCache.has(rawSelector)) { | ||||
|         return selectorCache.get(rawSelector); | ||||
|     } | ||||
|  | ||||
|     const parsedSelector = tryParseSelector(rawSelector); | ||||
|  | ||||
|     const result = { | ||||
|         rawSelector, | ||||
|         isExit: rawSelector.endsWith(":exit"), | ||||
|         parsedSelector, | ||||
|         listenerTypes: getPossibleTypes(parsedSelector), | ||||
|         attributeCount: countClassAttributes(parsedSelector), | ||||
|         identifierCount: countIdentifiers(parsedSelector) | ||||
|     }; | ||||
|  | ||||
|     selectorCache.set(rawSelector, result); | ||||
|     return result; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * The event generator for AST nodes. | ||||
|  * This implements below interface. | ||||
|  * | ||||
|  * ```ts | ||||
|  * interface EventGenerator { | ||||
|  *     emitter: SafeEmitter; | ||||
|  *     enterNode(node: ASTNode): void; | ||||
|  *     leaveNode(node: ASTNode): void; | ||||
|  * } | ||||
|  * ``` | ||||
|  */ | ||||
| class NodeEventGenerator { | ||||
|  | ||||
|     /** | ||||
|      * @param {SafeEmitter} emitter | ||||
|      * An SafeEmitter which is the destination of events. This emitter must already | ||||
|      * have registered listeners for all of the events that it needs to listen for. | ||||
|      * (See lib/linter/safe-emitter.js for more details on `SafeEmitter`.) | ||||
|      * @param {ESQueryOptions} esqueryOptions `esquery` options for traversing custom nodes. | ||||
|      * @returns {NodeEventGenerator} new instance | ||||
|      */ | ||||
|     constructor(emitter, esqueryOptions) { | ||||
|         this.emitter = emitter; | ||||
|         this.esqueryOptions = esqueryOptions; | ||||
|         this.currentAncestry = []; | ||||
|         this.enterSelectorsByNodeType = new Map(); | ||||
|         this.exitSelectorsByNodeType = new Map(); | ||||
|         this.anyTypeEnterSelectors = []; | ||||
|         this.anyTypeExitSelectors = []; | ||||
|  | ||||
|         emitter.eventNames().forEach(rawSelector => { | ||||
|             const selector = parseSelector(rawSelector); | ||||
|  | ||||
|             if (selector.listenerTypes) { | ||||
|                 const typeMap = selector.isExit ? this.exitSelectorsByNodeType : this.enterSelectorsByNodeType; | ||||
|  | ||||
|                 selector.listenerTypes.forEach(nodeType => { | ||||
|                     if (!typeMap.has(nodeType)) { | ||||
|                         typeMap.set(nodeType, []); | ||||
|                     } | ||||
|                     typeMap.get(nodeType).push(selector); | ||||
|                 }); | ||||
|                 return; | ||||
|             } | ||||
|             const selectors = selector.isExit ? this.anyTypeExitSelectors : this.anyTypeEnterSelectors; | ||||
|  | ||||
|             selectors.push(selector); | ||||
|         }); | ||||
|  | ||||
|         this.anyTypeEnterSelectors.sort(compareSpecificity); | ||||
|         this.anyTypeExitSelectors.sort(compareSpecificity); | ||||
|         this.enterSelectorsByNodeType.forEach(selectorList => selectorList.sort(compareSpecificity)); | ||||
|         this.exitSelectorsByNodeType.forEach(selectorList => selectorList.sort(compareSpecificity)); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Checks a selector against a node, and emits it if it matches | ||||
|      * @param {ASTNode} node The node to check | ||||
|      * @param {ASTSelector} selector An AST selector descriptor | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     applySelector(node, selector) { | ||||
|         if (esquery.matches(node, selector.parsedSelector, this.currentAncestry, this.esqueryOptions)) { | ||||
|             this.emitter.emit(selector.rawSelector, node); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Applies all appropriate selectors to a node, in specificity order | ||||
|      * @param {ASTNode} node The node to check | ||||
|      * @param {boolean} isExit `false` if the node is currently being entered, `true` if it's currently being exited | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     applySelectors(node, isExit) { | ||||
|         const selectorsByNodeType = (isExit ? this.exitSelectorsByNodeType : this.enterSelectorsByNodeType).get(node.type) || []; | ||||
|         const anyTypeSelectors = isExit ? this.anyTypeExitSelectors : this.anyTypeEnterSelectors; | ||||
|  | ||||
|         /* | ||||
|          * selectorsByNodeType and anyTypeSelectors were already sorted by specificity in the constructor. | ||||
|          * Iterate through each of them, applying selectors in the right order. | ||||
|          */ | ||||
|         let selectorsByTypeIndex = 0; | ||||
|         let anyTypeSelectorsIndex = 0; | ||||
|  | ||||
|         while (selectorsByTypeIndex < selectorsByNodeType.length || anyTypeSelectorsIndex < anyTypeSelectors.length) { | ||||
|             if ( | ||||
|                 selectorsByTypeIndex >= selectorsByNodeType.length || | ||||
|                 anyTypeSelectorsIndex < anyTypeSelectors.length && | ||||
|                 compareSpecificity(anyTypeSelectors[anyTypeSelectorsIndex], selectorsByNodeType[selectorsByTypeIndex]) < 0 | ||||
|             ) { | ||||
|                 this.applySelector(node, anyTypeSelectors[anyTypeSelectorsIndex++]); | ||||
|             } else { | ||||
|                 this.applySelector(node, selectorsByNodeType[selectorsByTypeIndex++]); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Emits an event of entering AST node. | ||||
|      * @param {ASTNode} node A node which was entered. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     enterNode(node) { | ||||
|         if (node.parent) { | ||||
|             this.currentAncestry.unshift(node.parent); | ||||
|         } | ||||
|         this.applySelectors(node, false); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Emits an event of leaving AST node. | ||||
|      * @param {ASTNode} node A node which was left. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     leaveNode(node) { | ||||
|         this.applySelectors(node, true); | ||||
|         this.currentAncestry.shift(); | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = NodeEventGenerator; | ||||
							
								
								
									
										369
									
								
								node_modules/eslint/lib/linter/report-translator.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										369
									
								
								node_modules/eslint/lib/linter/report-translator.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,369 @@ | ||||
| /** | ||||
|  * @fileoverview A helper that translates context.report() calls from the rule API into generic problem objects | ||||
|  * @author Teddy Katz | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const assert = require("assert"); | ||||
| const ruleFixer = require("./rule-fixer"); | ||||
| const interpolate = require("./interpolate"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Typedefs | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @typedef {import("../shared/types").LintMessage} LintMessage */ | ||||
|  | ||||
| /** | ||||
|  * An error message description | ||||
|  * @typedef {Object} MessageDescriptor | ||||
|  * @property {ASTNode} [node] The reported node | ||||
|  * @property {Location} loc The location of the problem. | ||||
|  * @property {string} message The problem message. | ||||
|  * @property {Object} [data] Optional data to use to fill in placeholders in the | ||||
|  *      message. | ||||
|  * @property {Function} [fix] The function to call that creates a fix command. | ||||
|  * @property {Array<{desc?: string, messageId?: string, fix: Function}>} suggest Suggestion descriptions and functions to create a the associated fixes. | ||||
|  */ | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Module Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
|  | ||||
| /** | ||||
|  * Translates a multi-argument context.report() call into a single object argument call | ||||
|  * @param {...*} args A list of arguments passed to `context.report` | ||||
|  * @returns {MessageDescriptor} A normalized object containing report information | ||||
|  */ | ||||
| function normalizeMultiArgReportCall(...args) { | ||||
|  | ||||
|     // If there is one argument, it is considered to be a new-style call already. | ||||
|     if (args.length === 1) { | ||||
|  | ||||
|         // Shallow clone the object to avoid surprises if reusing the descriptor | ||||
|         return Object.assign({}, args[0]); | ||||
|     } | ||||
|  | ||||
|     // If the second argument is a string, the arguments are interpreted as [node, message, data, fix]. | ||||
|     if (typeof args[1] === "string") { | ||||
|         return { | ||||
|             node: args[0], | ||||
|             message: args[1], | ||||
|             data: args[2], | ||||
|             fix: args[3] | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     // Otherwise, the arguments are interpreted as [node, loc, message, data, fix]. | ||||
|     return { | ||||
|         node: args[0], | ||||
|         loc: args[1], | ||||
|         message: args[2], | ||||
|         data: args[3], | ||||
|         fix: args[4] | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Asserts that either a loc or a node was provided, and the node is valid if it was provided. | ||||
|  * @param {MessageDescriptor} descriptor A descriptor to validate | ||||
|  * @returns {void} | ||||
|  * @throws AssertionError if neither a node nor a loc was provided, or if the node is not an object | ||||
|  */ | ||||
| function assertValidNodeInfo(descriptor) { | ||||
|     if (descriptor.node) { | ||||
|         assert(typeof descriptor.node === "object", "Node must be an object"); | ||||
|     } else { | ||||
|         assert(descriptor.loc, "Node must be provided when reporting error if location is not provided"); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Normalizes a MessageDescriptor to always have a `loc` with `start` and `end` properties | ||||
|  * @param {MessageDescriptor} descriptor A descriptor for the report from a rule. | ||||
|  * @returns {{start: Location, end: (Location|null)}} An updated location that infers the `start` and `end` properties | ||||
|  * from the `node` of the original descriptor, or infers the `start` from the `loc` of the original descriptor. | ||||
|  */ | ||||
| function normalizeReportLoc(descriptor) { | ||||
|     if (descriptor.loc) { | ||||
|         if (descriptor.loc.start) { | ||||
|             return descriptor.loc; | ||||
|         } | ||||
|         return { start: descriptor.loc, end: null }; | ||||
|     } | ||||
|     return descriptor.node.loc; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Clones the given fix object. | ||||
|  * @param {Fix|null} fix The fix to clone. | ||||
|  * @returns {Fix|null} Deep cloned fix object or `null` if `null` or `undefined` was passed in. | ||||
|  */ | ||||
| function cloneFix(fix) { | ||||
|     if (!fix) { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         range: [fix.range[0], fix.range[1]], | ||||
|         text: fix.text | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Check that a fix has a valid range. | ||||
|  * @param {Fix|null} fix The fix to validate. | ||||
|  * @returns {void} | ||||
|  */ | ||||
| function assertValidFix(fix) { | ||||
|     if (fix) { | ||||
|         assert(fix.range && typeof fix.range[0] === "number" && typeof fix.range[1] === "number", `Fix has invalid range: ${JSON.stringify(fix, null, 2)}`); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Compares items in a fixes array by range. | ||||
|  * @param {Fix} a The first message. | ||||
|  * @param {Fix} b The second message. | ||||
|  * @returns {int} -1 if a comes before b, 1 if a comes after b, 0 if equal. | ||||
|  * @private | ||||
|  */ | ||||
| function compareFixesByRange(a, b) { | ||||
|     return a.range[0] - b.range[0] || a.range[1] - b.range[1]; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Merges the given fixes array into one. | ||||
|  * @param {Fix[]} fixes The fixes to merge. | ||||
|  * @param {SourceCode} sourceCode The source code object to get the text between fixes. | ||||
|  * @returns {{text: string, range: number[]}} The merged fixes | ||||
|  */ | ||||
| function mergeFixes(fixes, sourceCode) { | ||||
|     for (const fix of fixes) { | ||||
|         assertValidFix(fix); | ||||
|     } | ||||
|  | ||||
|     if (fixes.length === 0) { | ||||
|         return null; | ||||
|     } | ||||
|     if (fixes.length === 1) { | ||||
|         return cloneFix(fixes[0]); | ||||
|     } | ||||
|  | ||||
|     fixes.sort(compareFixesByRange); | ||||
|  | ||||
|     const originalText = sourceCode.text; | ||||
|     const start = fixes[0].range[0]; | ||||
|     const end = fixes[fixes.length - 1].range[1]; | ||||
|     let text = ""; | ||||
|     let lastPos = Number.MIN_SAFE_INTEGER; | ||||
|  | ||||
|     for (const fix of fixes) { | ||||
|         assert(fix.range[0] >= lastPos, "Fix objects must not be overlapped in a report."); | ||||
|  | ||||
|         if (fix.range[0] >= 0) { | ||||
|             text += originalText.slice(Math.max(0, start, lastPos), fix.range[0]); | ||||
|         } | ||||
|         text += fix.text; | ||||
|         lastPos = fix.range[1]; | ||||
|     } | ||||
|     text += originalText.slice(Math.max(0, start, lastPos), end); | ||||
|  | ||||
|     return { range: [start, end], text }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Gets one fix object from the given descriptor. | ||||
|  * If the descriptor retrieves multiple fixes, this merges those to one. | ||||
|  * @param {MessageDescriptor} descriptor The report descriptor. | ||||
|  * @param {SourceCode} sourceCode The source code object to get text between fixes. | ||||
|  * @returns {({text: string, range: number[]}|null)} The fix for the descriptor | ||||
|  */ | ||||
| function normalizeFixes(descriptor, sourceCode) { | ||||
|     if (typeof descriptor.fix !== "function") { | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     // @type {null | Fix | Fix[] | IterableIterator<Fix>} | ||||
|     const fix = descriptor.fix(ruleFixer); | ||||
|  | ||||
|     // Merge to one. | ||||
|     if (fix && Symbol.iterator in fix) { | ||||
|         return mergeFixes(Array.from(fix), sourceCode); | ||||
|     } | ||||
|  | ||||
|     assertValidFix(fix); | ||||
|     return cloneFix(fix); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Gets an array of suggestion objects from the given descriptor. | ||||
|  * @param {MessageDescriptor} descriptor The report descriptor. | ||||
|  * @param {SourceCode} sourceCode The source code object to get text between fixes. | ||||
|  * @param {Object} messages Object of meta messages for the rule. | ||||
|  * @returns {Array<SuggestionResult>} The suggestions for the descriptor | ||||
|  */ | ||||
| function mapSuggestions(descriptor, sourceCode, messages) { | ||||
|     if (!descriptor.suggest || !Array.isArray(descriptor.suggest)) { | ||||
|         return []; | ||||
|     } | ||||
|  | ||||
|     return descriptor.suggest | ||||
|         .map(suggestInfo => { | ||||
|             const computedDesc = suggestInfo.desc || messages[suggestInfo.messageId]; | ||||
|  | ||||
|             return { | ||||
|                 ...suggestInfo, | ||||
|                 desc: interpolate(computedDesc, suggestInfo.data), | ||||
|                 fix: normalizeFixes(suggestInfo, sourceCode) | ||||
|             }; | ||||
|         }) | ||||
|  | ||||
|         // Remove suggestions that didn't provide a fix | ||||
|         .filter(({ fix }) => fix); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Creates information about the report from a descriptor | ||||
|  * @param {Object} options Information about the problem | ||||
|  * @param {string} options.ruleId Rule ID | ||||
|  * @param {(0|1|2)} options.severity Rule severity | ||||
|  * @param {(ASTNode|null)} options.node Node | ||||
|  * @param {string} options.message Error message | ||||
|  * @param {string} [options.messageId] The error message ID. | ||||
|  * @param {{start: SourceLocation, end: (SourceLocation|null)}} options.loc Start and end location | ||||
|  * @param {{text: string, range: (number[]|null)}} options.fix The fix object | ||||
|  * @param {Array<{text: string, range: (number[]|null)}>} options.suggestions The array of suggestions objects | ||||
|  * @returns {LintMessage} Information about the report | ||||
|  */ | ||||
| function createProblem(options) { | ||||
|     const problem = { | ||||
|         ruleId: options.ruleId, | ||||
|         severity: options.severity, | ||||
|         message: options.message, | ||||
|         line: options.loc.start.line, | ||||
|         column: options.loc.start.column + 1, | ||||
|         nodeType: options.node && options.node.type || null | ||||
|     }; | ||||
|  | ||||
|     /* | ||||
|      * If this isn’t in the conditional, some of the tests fail | ||||
|      * because `messageId` is present in the problem object | ||||
|      */ | ||||
|     if (options.messageId) { | ||||
|         problem.messageId = options.messageId; | ||||
|     } | ||||
|  | ||||
|     if (options.loc.end) { | ||||
|         problem.endLine = options.loc.end.line; | ||||
|         problem.endColumn = options.loc.end.column + 1; | ||||
|     } | ||||
|  | ||||
|     if (options.fix) { | ||||
|         problem.fix = options.fix; | ||||
|     } | ||||
|  | ||||
|     if (options.suggestions && options.suggestions.length > 0) { | ||||
|         problem.suggestions = options.suggestions; | ||||
|     } | ||||
|  | ||||
|     return problem; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Validates that suggestions are properly defined. Throws if an error is detected. | ||||
|  * @param {Array<{ desc?: string, messageId?: string }>} suggest The incoming suggest data. | ||||
|  * @param {Object} messages Object of meta messages for the rule. | ||||
|  * @returns {void} | ||||
|  */ | ||||
| function validateSuggestions(suggest, messages) { | ||||
|     if (suggest && Array.isArray(suggest)) { | ||||
|         suggest.forEach(suggestion => { | ||||
|             if (suggestion.messageId) { | ||||
|                 const { messageId } = suggestion; | ||||
|  | ||||
|                 if (!messages) { | ||||
|                     throw new TypeError(`context.report() called with a suggest option with a messageId '${messageId}', but no messages were present in the rule metadata.`); | ||||
|                 } | ||||
|  | ||||
|                 if (!messages[messageId]) { | ||||
|                     throw new TypeError(`context.report() called with a suggest option with a messageId '${messageId}' which is not present in the 'messages' config: ${JSON.stringify(messages, null, 2)}`); | ||||
|                 } | ||||
|  | ||||
|                 if (suggestion.desc) { | ||||
|                     throw new TypeError("context.report() called with a suggest option that defines both a 'messageId' and an 'desc'. Please only pass one."); | ||||
|                 } | ||||
|             } else if (!suggestion.desc) { | ||||
|                 throw new TypeError("context.report() called with a suggest option that doesn't have either a `desc` or `messageId`"); | ||||
|             } | ||||
|  | ||||
|             if (typeof suggestion.fix !== "function") { | ||||
|                 throw new TypeError(`context.report() called with a suggest option without a fix function. See: ${suggestion}`); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Returns a function that converts the arguments of a `context.report` call from a rule into a reported | ||||
|  * problem for the Node.js API. | ||||
|  * @param {{ruleId: string, severity: number, sourceCode: SourceCode, messageIds: Object, disableFixes: boolean}} metadata Metadata for the reported problem | ||||
|  * @param {SourceCode} sourceCode The `SourceCode` instance for the text being linted | ||||
|  * @returns {function(...args): LintMessage} Function that returns information about the report | ||||
|  */ | ||||
|  | ||||
| module.exports = function createReportTranslator(metadata) { | ||||
|  | ||||
|     /* | ||||
|      * `createReportTranslator` gets called once per enabled rule per file. It needs to be very performant. | ||||
|      * The report translator itself (i.e. the function that `createReportTranslator` returns) gets | ||||
|      * called every time a rule reports a problem, which happens much less frequently (usually, the vast | ||||
|      * majority of rules don't report any problems for a given file). | ||||
|      */ | ||||
|     return (...args) => { | ||||
|         const descriptor = normalizeMultiArgReportCall(...args); | ||||
|         const messages = metadata.messageIds; | ||||
|  | ||||
|         assertValidNodeInfo(descriptor); | ||||
|  | ||||
|         let computedMessage; | ||||
|  | ||||
|         if (descriptor.messageId) { | ||||
|             if (!messages) { | ||||
|                 throw new TypeError("context.report() called with a messageId, but no messages were present in the rule metadata."); | ||||
|             } | ||||
|             const id = descriptor.messageId; | ||||
|  | ||||
|             if (descriptor.message) { | ||||
|                 throw new TypeError("context.report() called with a message and a messageId. Please only pass one."); | ||||
|             } | ||||
|             if (!messages || !Object.prototype.hasOwnProperty.call(messages, id)) { | ||||
|                 throw new TypeError(`context.report() called with a messageId of '${id}' which is not present in the 'messages' config: ${JSON.stringify(messages, null, 2)}`); | ||||
|             } | ||||
|             computedMessage = messages[id]; | ||||
|         } else if (descriptor.message) { | ||||
|             computedMessage = descriptor.message; | ||||
|         } else { | ||||
|             throw new TypeError("Missing `message` property in report() call; add a message that describes the linting problem."); | ||||
|         } | ||||
|  | ||||
|         validateSuggestions(descriptor.suggest, messages); | ||||
|  | ||||
|         return createProblem({ | ||||
|             ruleId: metadata.ruleId, | ||||
|             severity: metadata.severity, | ||||
|             node: descriptor.node, | ||||
|             message: interpolate(computedMessage, descriptor.data), | ||||
|             messageId: descriptor.messageId, | ||||
|             loc: normalizeReportLoc(descriptor), | ||||
|             fix: metadata.disableFixes ? null : normalizeFixes(descriptor, metadata.sourceCode), | ||||
|             suggestions: metadata.disableFixes ? [] : mapSuggestions(descriptor, metadata.sourceCode, messages) | ||||
|         }); | ||||
|     }; | ||||
| }; | ||||
							
								
								
									
										140
									
								
								node_modules/eslint/lib/linter/rule-fixer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								node_modules/eslint/lib/linter/rule-fixer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | ||||
| /** | ||||
|  * @fileoverview An object that creates fix commands for rules. | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| // none! | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Creates a fix command that inserts text at the specified index in the source text. | ||||
|  * @param {int} index The 0-based index at which to insert the new text. | ||||
|  * @param {string} text The text to insert. | ||||
|  * @returns {Object} The fix command. | ||||
|  * @private | ||||
|  */ | ||||
| function insertTextAt(index, text) { | ||||
|     return { | ||||
|         range: [index, index], | ||||
|         text | ||||
|     }; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Creates code fixing commands for rules. | ||||
|  */ | ||||
|  | ||||
| const ruleFixer = Object.freeze({ | ||||
|  | ||||
|     /** | ||||
|      * Creates a fix command that inserts text after the given node or token. | ||||
|      * The fix is not applied until applyFixes() is called. | ||||
|      * @param {ASTNode|Token} nodeOrToken The node or token to insert after. | ||||
|      * @param {string} text The text to insert. | ||||
|      * @returns {Object} The fix command. | ||||
|      */ | ||||
|     insertTextAfter(nodeOrToken, text) { | ||||
|         return this.insertTextAfterRange(nodeOrToken.range, text); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Creates a fix command that inserts text after the specified range in the source text. | ||||
|      * The fix is not applied until applyFixes() is called. | ||||
|      * @param {int[]} range The range to replace, first item is start of range, second | ||||
|      *      is end of range. | ||||
|      * @param {string} text The text to insert. | ||||
|      * @returns {Object} The fix command. | ||||
|      */ | ||||
|     insertTextAfterRange(range, text) { | ||||
|         return insertTextAt(range[1], text); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Creates a fix command that inserts text before the given node or token. | ||||
|      * The fix is not applied until applyFixes() is called. | ||||
|      * @param {ASTNode|Token} nodeOrToken The node or token to insert before. | ||||
|      * @param {string} text The text to insert. | ||||
|      * @returns {Object} The fix command. | ||||
|      */ | ||||
|     insertTextBefore(nodeOrToken, text) { | ||||
|         return this.insertTextBeforeRange(nodeOrToken.range, text); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Creates a fix command that inserts text before the specified range in the source text. | ||||
|      * The fix is not applied until applyFixes() is called. | ||||
|      * @param {int[]} range The range to replace, first item is start of range, second | ||||
|      *      is end of range. | ||||
|      * @param {string} text The text to insert. | ||||
|      * @returns {Object} The fix command. | ||||
|      */ | ||||
|     insertTextBeforeRange(range, text) { | ||||
|         return insertTextAt(range[0], text); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Creates a fix command that replaces text at the node or token. | ||||
|      * The fix is not applied until applyFixes() is called. | ||||
|      * @param {ASTNode|Token} nodeOrToken The node or token to remove. | ||||
|      * @param {string} text The text to insert. | ||||
|      * @returns {Object} The fix command. | ||||
|      */ | ||||
|     replaceText(nodeOrToken, text) { | ||||
|         return this.replaceTextRange(nodeOrToken.range, text); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Creates a fix command that replaces text at the specified range in the source text. | ||||
|      * The fix is not applied until applyFixes() is called. | ||||
|      * @param {int[]} range The range to replace, first item is start of range, second | ||||
|      *      is end of range. | ||||
|      * @param {string} text The text to insert. | ||||
|      * @returns {Object} The fix command. | ||||
|      */ | ||||
|     replaceTextRange(range, text) { | ||||
|         return { | ||||
|             range, | ||||
|             text | ||||
|         }; | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Creates a fix command that removes the node or token from the source. | ||||
|      * The fix is not applied until applyFixes() is called. | ||||
|      * @param {ASTNode|Token} nodeOrToken The node or token to remove. | ||||
|      * @returns {Object} The fix command. | ||||
|      */ | ||||
|     remove(nodeOrToken) { | ||||
|         return this.removeRange(nodeOrToken.range); | ||||
|     }, | ||||
|  | ||||
|     /** | ||||
|      * Creates a fix command that removes the specified range of text from the source. | ||||
|      * The fix is not applied until applyFixes() is called. | ||||
|      * @param {int[]} range The range to remove, first item is start of range, second | ||||
|      *      is end of range. | ||||
|      * @returns {Object} The fix command. | ||||
|      */ | ||||
|     removeRange(range) { | ||||
|         return { | ||||
|             range, | ||||
|             text: "" | ||||
|         }; | ||||
|     } | ||||
|  | ||||
| }); | ||||
|  | ||||
|  | ||||
| module.exports = ruleFixer; | ||||
							
								
								
									
										80
									
								
								node_modules/eslint/lib/linter/rules.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										80
									
								
								node_modules/eslint/lib/linter/rules.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,80 @@ | ||||
| /** | ||||
|  * @fileoverview Defines a storage for rules. | ||||
|  * @author Nicholas C. Zakas | ||||
|  * @author aladdin-add | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const builtInRules = require("../rules"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Normalizes a rule module to the new-style API | ||||
|  * @param {(Function|{create: Function})} rule A rule object, which can either be a function | ||||
|  * ("old-style") or an object with a `create` method ("new-style") | ||||
|  * @returns {{create: Function}} A new-style rule. | ||||
|  */ | ||||
| function normalizeRule(rule) { | ||||
|     return typeof rule === "function" ? Object.assign({ create: rule }, rule) : rule; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * A storage for rules. | ||||
|  */ | ||||
| class Rules { | ||||
|     constructor() { | ||||
|         this._rules = Object.create(null); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Registers a rule module for rule id in storage. | ||||
|      * @param {string} ruleId Rule id (file name). | ||||
|      * @param {Function} ruleModule Rule handler. | ||||
|      * @returns {void} | ||||
|      */ | ||||
|     define(ruleId, ruleModule) { | ||||
|         this._rules[ruleId] = normalizeRule(ruleModule); | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Access rule handler by id (file name). | ||||
|      * @param {string} ruleId Rule id (file name). | ||||
|      * @returns {{create: Function, schema: JsonSchema[]}} | ||||
|      * A rule. This is normalized to always have the new-style shape with a `create` method. | ||||
|      */ | ||||
|     get(ruleId) { | ||||
|         if (typeof this._rules[ruleId] === "string") { | ||||
|             this.define(ruleId, require(this._rules[ruleId])); | ||||
|         } | ||||
|         if (this._rules[ruleId]) { | ||||
|             return this._rules[ruleId]; | ||||
|         } | ||||
|         if (builtInRules.has(ruleId)) { | ||||
|             return builtInRules.get(ruleId); | ||||
|         } | ||||
|  | ||||
|         return null; | ||||
|     } | ||||
|  | ||||
|     *[Symbol.iterator]() { | ||||
|         yield* builtInRules; | ||||
|  | ||||
|         for (const ruleId of Object.keys(this._rules)) { | ||||
|             yield [ruleId, this.get(ruleId)]; | ||||
|         } | ||||
|     } | ||||
| } | ||||
|  | ||||
| module.exports = Rules; | ||||
							
								
								
									
										52
									
								
								node_modules/eslint/lib/linter/safe-emitter.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										52
									
								
								node_modules/eslint/lib/linter/safe-emitter.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,52 @@ | ||||
| /** | ||||
|  * @fileoverview A variant of EventEmitter which does not give listeners information about each other | ||||
|  * @author Teddy Katz | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Typedefs | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * An event emitter | ||||
|  * @typedef {Object} SafeEmitter | ||||
|  * @property {(eventName: string, listenerFunc: Function) => void} on Adds a listener for a given event name | ||||
|  * @property {(eventName: string, arg1?: any, arg2?: any, arg3?: any) => void} emit Emits an event with a given name. | ||||
|  * This calls all the listeners that were listening for that name, with `arg1`, `arg2`, and `arg3` as arguments. | ||||
|  * @property {function(): string[]} eventNames Gets the list of event names that have registered listeners. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Creates an object which can listen for and emit events. | ||||
|  * This is similar to the EventEmitter API in Node's standard library, but it has a few differences. | ||||
|  * The goal is to allow multiple modules to attach arbitrary listeners to the same emitter, without | ||||
|  * letting the modules know about each other at all. | ||||
|  * 1. It has no special keys like `error` and `newListener`, which would allow modules to detect when | ||||
|  * another module throws an error or registers a listener. | ||||
|  * 2. It calls listener functions without any `this` value. (`EventEmitter` calls listeners with a | ||||
|  * `this` value of the emitter instance, which would give listeners access to other listeners.) | ||||
|  * @returns {SafeEmitter} An emitter | ||||
|  */ | ||||
| module.exports = () => { | ||||
|     const listeners = Object.create(null); | ||||
|  | ||||
|     return Object.freeze({ | ||||
|         on(eventName, listener) { | ||||
|             if (eventName in listeners) { | ||||
|                 listeners[eventName].push(listener); | ||||
|             } else { | ||||
|                 listeners[eventName] = [listener]; | ||||
|             } | ||||
|         }, | ||||
|         emit(eventName, ...args) { | ||||
|             if (eventName in listeners) { | ||||
|                 listeners[eventName].forEach(listener => listener(...args)); | ||||
|             } | ||||
|         }, | ||||
|         eventNames() { | ||||
|             return Object.keys(listeners); | ||||
|         } | ||||
|     }); | ||||
| }; | ||||
							
								
								
									
										152
									
								
								node_modules/eslint/lib/linter/source-code-fixer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										152
									
								
								node_modules/eslint/lib/linter/source-code-fixer.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,152 @@ | ||||
| /** | ||||
|  * @fileoverview An object that caches and applies source code fixes. | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const debug = require("debug")("eslint:source-code-fixer"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const BOM = "\uFEFF"; | ||||
|  | ||||
| /** | ||||
|  * Compares items in a messages array by range. | ||||
|  * @param {Message} a The first message. | ||||
|  * @param {Message} b The second message. | ||||
|  * @returns {int} -1 if a comes before b, 1 if a comes after b, 0 if equal. | ||||
|  * @private | ||||
|  */ | ||||
| function compareMessagesByFixRange(a, b) { | ||||
|     return a.fix.range[0] - b.fix.range[0] || a.fix.range[1] - b.fix.range[1]; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Compares items in a messages array by line and column. | ||||
|  * @param {Message} a The first message. | ||||
|  * @param {Message} b The second message. | ||||
|  * @returns {int} -1 if a comes before b, 1 if a comes after b, 0 if equal. | ||||
|  * @private | ||||
|  */ | ||||
| function compareMessagesByLocation(a, b) { | ||||
|     return a.line - b.line || a.column - b.column; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Utility for apply fixes to source code. | ||||
|  * @constructor | ||||
|  */ | ||||
| function SourceCodeFixer() { | ||||
|     Object.freeze(this); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Applies the fixes specified by the messages to the given text. Tries to be | ||||
|  * smart about the fixes and won't apply fixes over the same area in the text. | ||||
|  * @param {string} sourceText The text to apply the changes to. | ||||
|  * @param {Message[]} messages The array of messages reported by ESLint. | ||||
|  * @param {boolean|Function} [shouldFix=true] Determines whether each message should be fixed | ||||
|  * @returns {Object} An object containing the fixed text and any unfixed messages. | ||||
|  */ | ||||
| SourceCodeFixer.applyFixes = function(sourceText, messages, shouldFix) { | ||||
|     debug("Applying fixes"); | ||||
|  | ||||
|     if (shouldFix === false) { | ||||
|         debug("shouldFix parameter was false, not attempting fixes"); | ||||
|         return { | ||||
|             fixed: false, | ||||
|             messages, | ||||
|             output: sourceText | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     // clone the array | ||||
|     const remainingMessages = [], | ||||
|         fixes = [], | ||||
|         bom = sourceText.startsWith(BOM) ? BOM : "", | ||||
|         text = bom ? sourceText.slice(1) : sourceText; | ||||
|     let lastPos = Number.NEGATIVE_INFINITY, | ||||
|         output = bom; | ||||
|  | ||||
|     /** | ||||
|      * Try to use the 'fix' from a problem. | ||||
|      * @param {Message} problem The message object to apply fixes from | ||||
|      * @returns {boolean} Whether fix was successfully applied | ||||
|      */ | ||||
|     function attemptFix(problem) { | ||||
|         const fix = problem.fix; | ||||
|         const start = fix.range[0]; | ||||
|         const end = fix.range[1]; | ||||
|  | ||||
|         // Remain it as a problem if it's overlapped or it's a negative range | ||||
|         if (lastPos >= start || start > end) { | ||||
|             remainingMessages.push(problem); | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         // Remove BOM. | ||||
|         if ((start < 0 && end >= 0) || (start === 0 && fix.text.startsWith(BOM))) { | ||||
|             output = ""; | ||||
|         } | ||||
|  | ||||
|         // Make output to this fix. | ||||
|         output += text.slice(Math.max(0, lastPos), Math.max(0, start)); | ||||
|         output += fix.text; | ||||
|         lastPos = end; | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     messages.forEach(problem => { | ||||
|         if (Object.prototype.hasOwnProperty.call(problem, "fix")) { | ||||
|             fixes.push(problem); | ||||
|         } else { | ||||
|             remainingMessages.push(problem); | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     if (fixes.length) { | ||||
|         debug("Found fixes to apply"); | ||||
|         let fixesWereApplied = false; | ||||
|  | ||||
|         for (const problem of fixes.sort(compareMessagesByFixRange)) { | ||||
|             if (typeof shouldFix !== "function" || shouldFix(problem)) { | ||||
|                 attemptFix(problem); | ||||
|  | ||||
|                 /* | ||||
|                  * The only time attemptFix will fail is if a previous fix was | ||||
|                  * applied which conflicts with it.  So we can mark this as true. | ||||
|                  */ | ||||
|                 fixesWereApplied = true; | ||||
|             } else { | ||||
|                 remainingMessages.push(problem); | ||||
|             } | ||||
|         } | ||||
|         output += text.slice(Math.max(0, lastPos)); | ||||
|  | ||||
|         return { | ||||
|             fixed: fixesWereApplied, | ||||
|             messages: remainingMessages.sort(compareMessagesByLocation), | ||||
|             output | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     debug("No fixes to apply"); | ||||
|     return { | ||||
|         fixed: false, | ||||
|         messages, | ||||
|         output: bom + text | ||||
|     }; | ||||
|  | ||||
| }; | ||||
|  | ||||
| module.exports = SourceCodeFixer; | ||||
							
								
								
									
										161
									
								
								node_modules/eslint/lib/linter/timing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										161
									
								
								node_modules/eslint/lib/linter/timing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,161 @@ | ||||
| /** | ||||
|  * @fileoverview Tracks performance of individual rules. | ||||
|  * @author Brandon Mills | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /* c8 ignore next */ | ||||
| /** | ||||
|  * Align the string to left | ||||
|  * @param {string} str string to evaluate | ||||
|  * @param {int} len length of the string | ||||
|  * @param {string} ch delimiter character | ||||
|  * @returns {string} modified string | ||||
|  * @private | ||||
|  */ | ||||
| function alignLeft(str, len, ch) { | ||||
|     return str + new Array(len - str.length + 1).join(ch || " "); | ||||
| } | ||||
|  | ||||
| /* c8 ignore next */ | ||||
| /** | ||||
|  * Align the string to right | ||||
|  * @param {string} str string to evaluate | ||||
|  * @param {int} len length of the string | ||||
|  * @param {string} ch delimiter character | ||||
|  * @returns {string} modified string | ||||
|  * @private | ||||
|  */ | ||||
| function alignRight(str, len, ch) { | ||||
|     return new Array(len - str.length + 1).join(ch || " ") + str; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Module definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const enabled = !!process.env.TIMING; | ||||
|  | ||||
| const HEADERS = ["Rule", "Time (ms)", "Relative"]; | ||||
| const ALIGN = [alignLeft, alignRight, alignRight]; | ||||
|  | ||||
| /** | ||||
|  * Decide how many rules to show in the output list. | ||||
|  * @returns {number} the number of rules to show | ||||
|  */ | ||||
| function getListSize() { | ||||
|     const MINIMUM_SIZE = 10; | ||||
|  | ||||
|     if (typeof process.env.TIMING !== "string") { | ||||
|         return MINIMUM_SIZE; | ||||
|     } | ||||
|  | ||||
|     if (process.env.TIMING.toLowerCase() === "all") { | ||||
|         return Number.POSITIVE_INFINITY; | ||||
|     } | ||||
|  | ||||
|     const TIMING_ENV_VAR_AS_INTEGER = Number.parseInt(process.env.TIMING, 10); | ||||
|  | ||||
|     return TIMING_ENV_VAR_AS_INTEGER > 10 ? TIMING_ENV_VAR_AS_INTEGER : MINIMUM_SIZE; | ||||
| } | ||||
|  | ||||
| /* c8 ignore next */ | ||||
| /** | ||||
|  * display the data | ||||
|  * @param {Object} data Data object to be displayed | ||||
|  * @returns {void} prints modified string with console.log | ||||
|  * @private | ||||
|  */ | ||||
| function display(data) { | ||||
|     let total = 0; | ||||
|     const rows = Object.keys(data) | ||||
|         .map(key => { | ||||
|             const time = data[key]; | ||||
|  | ||||
|             total += time; | ||||
|             return [key, time]; | ||||
|         }) | ||||
|         .sort((a, b) => b[1] - a[1]) | ||||
|         .slice(0, getListSize()); | ||||
|  | ||||
|     rows.forEach(row => { | ||||
|         row.push(`${(row[1] * 100 / total).toFixed(1)}%`); | ||||
|         row[1] = row[1].toFixed(3); | ||||
|     }); | ||||
|  | ||||
|     rows.unshift(HEADERS); | ||||
|  | ||||
|     const widths = []; | ||||
|  | ||||
|     rows.forEach(row => { | ||||
|         const len = row.length; | ||||
|  | ||||
|         for (let i = 0; i < len; i++) { | ||||
|             const n = row[i].length; | ||||
|  | ||||
|             if (!widths[i] || n > widths[i]) { | ||||
|                 widths[i] = n; | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
|  | ||||
|     const table = rows.map(row => ( | ||||
|         row | ||||
|             .map((cell, index) => ALIGN[index](cell, widths[index])) | ||||
|             .join(" | ") | ||||
|     )); | ||||
|  | ||||
|     table.splice(1, 0, widths.map((width, index) => { | ||||
|         const extraAlignment = index !== 0 && index !== widths.length - 1 ? 2 : 1; | ||||
|  | ||||
|         return ALIGN[index](":", width + extraAlignment, "-"); | ||||
|     }).join("|")); | ||||
|  | ||||
|     console.log(table.join("\n")); // eslint-disable-line no-console -- Debugging function | ||||
| } | ||||
|  | ||||
| /* c8 ignore next */ | ||||
| module.exports = (function() { | ||||
|  | ||||
|     const data = Object.create(null); | ||||
|  | ||||
|     /** | ||||
|      * Time the run | ||||
|      * @param {any} key key from the data object | ||||
|      * @param {Function} fn function to be called | ||||
|      * @returns {Function} function to be executed | ||||
|      * @private | ||||
|      */ | ||||
|     function time(key, fn) { | ||||
|         if (typeof data[key] === "undefined") { | ||||
|             data[key] = 0; | ||||
|         } | ||||
|  | ||||
|         return function(...args) { | ||||
|             let t = process.hrtime(); | ||||
|             const result = fn(...args); | ||||
|  | ||||
|             t = process.hrtime(t); | ||||
|             data[key] += t[0] * 1e3 + t[1] / 1e6; | ||||
|             return result; | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     if (enabled) { | ||||
|         process.on("exit", () => { | ||||
|             display(data); | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         time, | ||||
|         enabled, | ||||
|         getListSize | ||||
|     }; | ||||
|  | ||||
| }()); | ||||
							
								
								
									
										398
									
								
								node_modules/eslint/lib/options.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										398
									
								
								node_modules/eslint/lib/options.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,398 @@ | ||||
| /** | ||||
|  * @fileoverview Options configuration for optionator. | ||||
|  * @author George Zahariev | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const optionator = require("optionator"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Typedefs | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * The options object parsed by Optionator. | ||||
|  * @typedef {Object} ParsedCLIOptions | ||||
|  * @property {boolean} cache Only check changed files | ||||
|  * @property {string} cacheFile Path to the cache file. Deprecated: use --cache-location | ||||
|  * @property {string} [cacheLocation] Path to the cache file or directory | ||||
|  * @property {"metadata" | "content"} cacheStrategy Strategy to use for detecting changed files in the cache | ||||
|  * @property {boolean} [color] Force enabling/disabling of color | ||||
|  * @property {string} [config] Use this configuration, overriding .eslintrc.* config options if present | ||||
|  * @property {boolean} debug Output debugging information | ||||
|  * @property {string[]} [env] Specify environments | ||||
|  * @property {boolean} envInfo Output execution environment information | ||||
|  * @property {boolean} errorOnUnmatchedPattern Prevent errors when pattern is unmatched | ||||
|  * @property {boolean} eslintrc Disable use of configuration from .eslintrc.* | ||||
|  * @property {string[]} [ext] Specify JavaScript file extensions | ||||
|  * @property {boolean} fix Automatically fix problems | ||||
|  * @property {boolean} fixDryRun Automatically fix problems without saving the changes to the file system | ||||
|  * @property {("directive" | "problem" | "suggestion" | "layout")[]} [fixType] Specify the types of fixes to apply (directive, problem, suggestion, layout) | ||||
|  * @property {string} format Use a specific output format | ||||
|  * @property {string[]} [global] Define global variables | ||||
|  * @property {boolean} [help] Show help | ||||
|  * @property {boolean} ignore Disable use of ignore files and patterns | ||||
|  * @property {string} [ignorePath] Specify path of ignore file | ||||
|  * @property {string[]} [ignorePattern] Pattern of files to ignore (in addition to those in .eslintignore) | ||||
|  * @property {boolean} init Run config initialization wizard | ||||
|  * @property {boolean} inlineConfig Prevent comments from changing config or rules | ||||
|  * @property {number} maxWarnings Number of warnings to trigger nonzero exit code | ||||
|  * @property {string} [outputFile] Specify file to write report to | ||||
|  * @property {string} [parser] Specify the parser to be used | ||||
|  * @property {Object} [parserOptions] Specify parser options | ||||
|  * @property {string[]} [plugin] Specify plugins | ||||
|  * @property {string} [printConfig] Print the configuration for the given file | ||||
|  * @property {boolean | undefined} reportUnusedDisableDirectives Adds reported errors for unused eslint-disable and eslint-enable directives | ||||
|  * @property {string | undefined} reportUnusedDisableDirectivesSeverity A severity string indicating if and how unused disable and enable directives should be tracked and reported. | ||||
|  * @property {string} [resolvePluginsRelativeTo] A folder where plugins should be resolved from, CWD by default | ||||
|  * @property {Object} [rule] Specify rules | ||||
|  * @property {string[]} [rulesdir] Load additional rules from this directory. Deprecated: Use rules from plugins | ||||
|  * @property {boolean} stdin Lint code provided on <STDIN> | ||||
|  * @property {string} [stdinFilename] Specify filename to process STDIN as | ||||
|  * @property {boolean} quiet Report errors only | ||||
|  * @property {boolean} [version] Output the version number | ||||
|  * @property {boolean} warnIgnored Show warnings when the file list includes ignored files | ||||
|  * @property {string[]} _ Positional filenames or patterns | ||||
|  */ | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Initialization and Public Interface | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| // exports "parse(args)", "generateHelp()", and "generateHelpForOption(optionName)" | ||||
|  | ||||
| /** | ||||
|  * Creates the CLI options for ESLint. | ||||
|  * @param {boolean} usingFlatConfig Indicates if flat config is being used. | ||||
|  * @returns {Object} The optionator instance. | ||||
|  */ | ||||
| module.exports = function(usingFlatConfig) { | ||||
|  | ||||
|     let lookupFlag; | ||||
|  | ||||
|     if (usingFlatConfig) { | ||||
|         lookupFlag = { | ||||
|             option: "config-lookup", | ||||
|             type: "Boolean", | ||||
|             default: "true", | ||||
|             description: "Disable look up for eslint.config.js" | ||||
|         }; | ||||
|     } else { | ||||
|         lookupFlag = { | ||||
|             option: "eslintrc", | ||||
|             type: "Boolean", | ||||
|             default: "true", | ||||
|             description: "Disable use of configuration from .eslintrc.*" | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     let envFlag; | ||||
|  | ||||
|     if (!usingFlatConfig) { | ||||
|         envFlag = { | ||||
|             option: "env", | ||||
|             type: "[String]", | ||||
|             description: "Specify environments" | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     let extFlag; | ||||
|  | ||||
|     if (!usingFlatConfig) { | ||||
|         extFlag = { | ||||
|             option: "ext", | ||||
|             type: "[String]", | ||||
|             description: "Specify JavaScript file extensions" | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     let resolvePluginsFlag; | ||||
|  | ||||
|     if (!usingFlatConfig) { | ||||
|         resolvePluginsFlag = { | ||||
|             option: "resolve-plugins-relative-to", | ||||
|             type: "path::String", | ||||
|             description: "A folder where plugins should be resolved from, CWD by default" | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     let rulesDirFlag; | ||||
|  | ||||
|     if (!usingFlatConfig) { | ||||
|         rulesDirFlag = { | ||||
|             option: "rulesdir", | ||||
|             type: "[path::String]", | ||||
|             description: "Load additional rules from this directory. Deprecated: Use rules from plugins" | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     let ignorePathFlag; | ||||
|  | ||||
|     if (!usingFlatConfig) { | ||||
|         ignorePathFlag = { | ||||
|             option: "ignore-path", | ||||
|             type: "path::String", | ||||
|             description: "Specify path of ignore file" | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     let warnIgnoredFlag; | ||||
|  | ||||
|     if (usingFlatConfig) { | ||||
|         warnIgnoredFlag = { | ||||
|             option: "warn-ignored", | ||||
|             type: "Boolean", | ||||
|             default: "true", | ||||
|             description: "Suppress warnings when the file list includes ignored files" | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     return optionator({ | ||||
|         prepend: "eslint [options] file.js [file.js] [dir]", | ||||
|         defaults: { | ||||
|             concatRepeatedArrays: true, | ||||
|             mergeRepeatedObjects: true | ||||
|         }, | ||||
|         options: [ | ||||
|             { | ||||
|                 heading: "Basic configuration" | ||||
|             }, | ||||
|             lookupFlag, | ||||
|             { | ||||
|                 option: "config", | ||||
|                 alias: "c", | ||||
|                 type: "path::String", | ||||
|                 description: usingFlatConfig | ||||
|                     ? "Use this configuration instead of eslint.config.js, eslint.config.mjs, or eslint.config.cjs" | ||||
|                     : "Use this configuration, overriding .eslintrc.* config options if present" | ||||
|             }, | ||||
|             envFlag, | ||||
|             extFlag, | ||||
|             { | ||||
|                 option: "global", | ||||
|                 type: "[String]", | ||||
|                 description: "Define global variables" | ||||
|             }, | ||||
|             { | ||||
|                 option: "parser", | ||||
|                 type: "String", | ||||
|                 description: "Specify the parser to be used" | ||||
|             }, | ||||
|             { | ||||
|                 option: "parser-options", | ||||
|                 type: "Object", | ||||
|                 description: "Specify parser options" | ||||
|             }, | ||||
|             resolvePluginsFlag, | ||||
|             { | ||||
|                 heading: "Specify Rules and Plugins" | ||||
|             }, | ||||
|             { | ||||
|                 option: "plugin", | ||||
|                 type: "[String]", | ||||
|                 description: "Specify plugins" | ||||
|             }, | ||||
|             { | ||||
|                 option: "rule", | ||||
|                 type: "Object", | ||||
|                 description: "Specify rules" | ||||
|             }, | ||||
|             rulesDirFlag, | ||||
|             { | ||||
|                 heading: "Fix Problems" | ||||
|             }, | ||||
|             { | ||||
|                 option: "fix", | ||||
|                 type: "Boolean", | ||||
|                 default: false, | ||||
|                 description: "Automatically fix problems" | ||||
|             }, | ||||
|             { | ||||
|                 option: "fix-dry-run", | ||||
|                 type: "Boolean", | ||||
|                 default: false, | ||||
|                 description: "Automatically fix problems without saving the changes to the file system" | ||||
|             }, | ||||
|             { | ||||
|                 option: "fix-type", | ||||
|                 type: "Array", | ||||
|                 description: "Specify the types of fixes to apply (directive, problem, suggestion, layout)" | ||||
|             }, | ||||
|             { | ||||
|                 heading: "Ignore Files" | ||||
|             }, | ||||
|             ignorePathFlag, | ||||
|             { | ||||
|                 option: "ignore", | ||||
|                 type: "Boolean", | ||||
|                 default: "true", | ||||
|                 description: "Disable use of ignore files and patterns" | ||||
|             }, | ||||
|             { | ||||
|                 option: "ignore-pattern", | ||||
|                 type: "[String]", | ||||
|                 description: "Pattern of files to ignore (in addition to those in .eslintignore)", | ||||
|                 concatRepeatedArrays: [true, { | ||||
|                     oneValuePerFlag: true | ||||
|                 }] | ||||
|             }, | ||||
|             { | ||||
|                 heading: "Use stdin" | ||||
|             }, | ||||
|             { | ||||
|                 option: "stdin", | ||||
|                 type: "Boolean", | ||||
|                 default: "false", | ||||
|                 description: "Lint code provided on <STDIN>" | ||||
|             }, | ||||
|             { | ||||
|                 option: "stdin-filename", | ||||
|                 type: "String", | ||||
|                 description: "Specify filename to process STDIN as" | ||||
|             }, | ||||
|             { | ||||
|                 heading: "Handle Warnings" | ||||
|             }, | ||||
|             { | ||||
|                 option: "quiet", | ||||
|                 type: "Boolean", | ||||
|                 default: "false", | ||||
|                 description: "Report errors only" | ||||
|             }, | ||||
|             { | ||||
|                 option: "max-warnings", | ||||
|                 type: "Int", | ||||
|                 default: "-1", | ||||
|                 description: "Number of warnings to trigger nonzero exit code" | ||||
|             }, | ||||
|             { | ||||
|                 heading: "Output" | ||||
|             }, | ||||
|             { | ||||
|                 option: "output-file", | ||||
|                 alias: "o", | ||||
|                 type: "path::String", | ||||
|                 description: "Specify file to write report to" | ||||
|             }, | ||||
|             { | ||||
|                 option: "format", | ||||
|                 alias: "f", | ||||
|                 type: "String", | ||||
|                 default: "stylish", | ||||
|                 description: "Use a specific output format" | ||||
|             }, | ||||
|             { | ||||
|                 option: "color", | ||||
|                 type: "Boolean", | ||||
|                 alias: "no-color", | ||||
|                 description: "Force enabling/disabling of color" | ||||
|             }, | ||||
|             { | ||||
|                 heading: "Inline configuration comments" | ||||
|             }, | ||||
|             { | ||||
|                 option: "inline-config", | ||||
|                 type: "Boolean", | ||||
|                 default: "true", | ||||
|                 description: "Prevent comments from changing config or rules" | ||||
|             }, | ||||
|             { | ||||
|                 option: "report-unused-disable-directives", | ||||
|                 type: "Boolean", | ||||
|                 default: void 0, | ||||
|                 description: "Adds reported errors for unused eslint-disable and eslint-enable directives" | ||||
|             }, | ||||
|             { | ||||
|                 option: "report-unused-disable-directives-severity", | ||||
|                 type: "String", | ||||
|                 default: void 0, | ||||
|                 description: "Chooses severity level for reporting unused eslint-disable and eslint-enable directives", | ||||
|                 enum: ["off", "warn", "error", "0", "1", "2"] | ||||
|             }, | ||||
|             { | ||||
|                 heading: "Caching" | ||||
|             }, | ||||
|             { | ||||
|                 option: "cache", | ||||
|                 type: "Boolean", | ||||
|                 default: "false", | ||||
|                 description: "Only check changed files" | ||||
|             }, | ||||
|             { | ||||
|                 option: "cache-file", | ||||
|                 type: "path::String", | ||||
|                 default: ".eslintcache", | ||||
|                 description: "Path to the cache file. Deprecated: use --cache-location" | ||||
|             }, | ||||
|             { | ||||
|                 option: "cache-location", | ||||
|                 type: "path::String", | ||||
|                 description: "Path to the cache file or directory" | ||||
|             }, | ||||
|             { | ||||
|                 option: "cache-strategy", | ||||
|                 dependsOn: ["cache"], | ||||
|                 type: "String", | ||||
|                 default: "metadata", | ||||
|                 enum: ["metadata", "content"], | ||||
|                 description: "Strategy to use for detecting changed files in the cache" | ||||
|             }, | ||||
|             { | ||||
|                 heading: "Miscellaneous" | ||||
|             }, | ||||
|             { | ||||
|                 option: "init", | ||||
|                 type: "Boolean", | ||||
|                 default: "false", | ||||
|                 description: "Run config initialization wizard" | ||||
|             }, | ||||
|             { | ||||
|                 option: "env-info", | ||||
|                 type: "Boolean", | ||||
|                 default: "false", | ||||
|                 description: "Output execution environment information" | ||||
|             }, | ||||
|             { | ||||
|                 option: "error-on-unmatched-pattern", | ||||
|                 type: "Boolean", | ||||
|                 default: "true", | ||||
|                 description: "Prevent errors when pattern is unmatched" | ||||
|             }, | ||||
|             { | ||||
|                 option: "exit-on-fatal-error", | ||||
|                 type: "Boolean", | ||||
|                 default: "false", | ||||
|                 description: "Exit with exit code 2 in case of fatal error" | ||||
|             }, | ||||
|             warnIgnoredFlag, | ||||
|             { | ||||
|                 option: "debug", | ||||
|                 type: "Boolean", | ||||
|                 default: false, | ||||
|                 description: "Output debugging information" | ||||
|             }, | ||||
|             { | ||||
|                 option: "help", | ||||
|                 alias: "h", | ||||
|                 type: "Boolean", | ||||
|                 description: "Show help" | ||||
|             }, | ||||
|             { | ||||
|                 option: "version", | ||||
|                 alias: "v", | ||||
|                 type: "Boolean", | ||||
|                 description: "Output the version number" | ||||
|             }, | ||||
|             { | ||||
|                 option: "print-config", | ||||
|                 type: "path::String", | ||||
|                 description: "Print the configuration for the given file" | ||||
|             } | ||||
|         ].filter(value => !!value) | ||||
|     }); | ||||
| }; | ||||
							
								
								
									
										1131
									
								
								node_modules/eslint/lib/rule-tester/flat-rule-tester.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1131
									
								
								node_modules/eslint/lib/rule-tester/flat-rule-tester.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										5
									
								
								node_modules/eslint/lib/rule-tester/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								node_modules/eslint/lib/rule-tester/index.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| "use strict"; | ||||
|  | ||||
| module.exports = { | ||||
|     RuleTester: require("./rule-tester") | ||||
| }; | ||||
							
								
								
									
										1206
									
								
								node_modules/eslint/lib/rule-tester/rule-tester.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										1206
									
								
								node_modules/eslint/lib/rule-tester/rule-tester.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because it is too large
												Load Diff
											
										
									
								
							
							
								
								
									
										346
									
								
								node_modules/eslint/lib/rules/accessor-pairs.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										346
									
								
								node_modules/eslint/lib/rules/accessor-pairs.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,346 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to enforce getter and setter pairs in objects and classes. | ||||
|  * @author Gyandeep Singh | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Typedefs | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Property name if it can be computed statically, otherwise the list of the tokens of the key node. | ||||
|  * @typedef {string|Token[]} Key | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Accessor nodes with the same key. | ||||
|  * @typedef {Object} AccessorData | ||||
|  * @property {Key} key Accessor's key | ||||
|  * @property {ASTNode[]} getters List of getter nodes. | ||||
|  * @property {ASTNode[]} setters List of setter nodes. | ||||
|  */ | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Checks whether or not the given lists represent the equal tokens in the same order. | ||||
|  * Tokens are compared by their properties, not by instance. | ||||
|  * @param {Token[]} left First list of tokens. | ||||
|  * @param {Token[]} right Second list of tokens. | ||||
|  * @returns {boolean} `true` if the lists have same tokens. | ||||
|  */ | ||||
| function areEqualTokenLists(left, right) { | ||||
|     if (left.length !== right.length) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     for (let i = 0; i < left.length; i++) { | ||||
|         const leftToken = left[i], | ||||
|             rightToken = right[i]; | ||||
|  | ||||
|         if (leftToken.type !== rightToken.type || leftToken.value !== rightToken.value) { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether or not the given keys are equal. | ||||
|  * @param {Key} left First key. | ||||
|  * @param {Key} right Second key. | ||||
|  * @returns {boolean} `true` if the keys are equal. | ||||
|  */ | ||||
| function areEqualKeys(left, right) { | ||||
|     if (typeof left === "string" && typeof right === "string") { | ||||
|  | ||||
|         // Statically computed names. | ||||
|         return left === right; | ||||
|     } | ||||
|     if (Array.isArray(left) && Array.isArray(right)) { | ||||
|  | ||||
|         // Token lists. | ||||
|         return areEqualTokenLists(left, right); | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether or not a given node is of an accessor kind ('get' or 'set'). | ||||
|  * @param {ASTNode} node A node to check. | ||||
|  * @returns {boolean} `true` if the node is of an accessor kind. | ||||
|  */ | ||||
| function isAccessorKind(node) { | ||||
|     return node.kind === "get" || node.kind === "set"; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether or not a given node is an argument of a specified method call. | ||||
|  * @param {ASTNode} node A node to check. | ||||
|  * @param {number} index An expected index of the node in arguments. | ||||
|  * @param {string} object An expected name of the object of the method. | ||||
|  * @param {string} property An expected name of the method. | ||||
|  * @returns {boolean} `true` if the node is an argument of the specified method call. | ||||
|  */ | ||||
| function isArgumentOfMethodCall(node, index, object, property) { | ||||
|     const parent = node.parent; | ||||
|  | ||||
|     return ( | ||||
|         parent.type === "CallExpression" && | ||||
|         astUtils.isSpecificMemberAccess(parent.callee, object, property) && | ||||
|         parent.arguments[index] === node | ||||
|     ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether or not a given node is a property descriptor. | ||||
|  * @param {ASTNode} node A node to check. | ||||
|  * @returns {boolean} `true` if the node is a property descriptor. | ||||
|  */ | ||||
| function isPropertyDescriptor(node) { | ||||
|  | ||||
|     // Object.defineProperty(obj, "foo", {set: ...}) | ||||
|     if (isArgumentOfMethodCall(node, 2, "Object", "defineProperty") || | ||||
|         isArgumentOfMethodCall(node, 2, "Reflect", "defineProperty") | ||||
|     ) { | ||||
|         return true; | ||||
|     } | ||||
|  | ||||
|     /* | ||||
|      * Object.defineProperties(obj, {foo: {set: ...}}) | ||||
|      * Object.create(proto, {foo: {set: ...}}) | ||||
|      */ | ||||
|     const grandparent = node.parent.parent; | ||||
|  | ||||
|     return grandparent.type === "ObjectExpression" && ( | ||||
|         isArgumentOfMethodCall(grandparent, 1, "Object", "create") || | ||||
|         isArgumentOfMethodCall(grandparent, 1, "Object", "defineProperties") | ||||
|     ); | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce getter and setter pairs in objects and classes", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/accessor-pairs" | ||||
|         }, | ||||
|  | ||||
|         schema: [{ | ||||
|             type: "object", | ||||
|             properties: { | ||||
|                 getWithoutSet: { | ||||
|                     type: "boolean", | ||||
|                     default: false | ||||
|                 }, | ||||
|                 setWithoutGet: { | ||||
|                     type: "boolean", | ||||
|                     default: true | ||||
|                 }, | ||||
|                 enforceForClassMembers: { | ||||
|                     type: "boolean", | ||||
|                     default: true | ||||
|                 } | ||||
|             }, | ||||
|             additionalProperties: false | ||||
|         }], | ||||
|  | ||||
|         messages: { | ||||
|             missingGetterInPropertyDescriptor: "Getter is not present in property descriptor.", | ||||
|             missingSetterInPropertyDescriptor: "Setter is not present in property descriptor.", | ||||
|             missingGetterInObjectLiteral: "Getter is not present for {{ name }}.", | ||||
|             missingSetterInObjectLiteral: "Setter is not present for {{ name }}.", | ||||
|             missingGetterInClass: "Getter is not present for class {{ name }}.", | ||||
|             missingSetterInClass: "Setter is not present for class {{ name }}." | ||||
|         } | ||||
|     }, | ||||
|     create(context) { | ||||
|         const config = context.options[0] || {}; | ||||
|         const checkGetWithoutSet = config.getWithoutSet === true; | ||||
|         const checkSetWithoutGet = config.setWithoutGet !== false; | ||||
|         const enforceForClassMembers = config.enforceForClassMembers !== false; | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         /** | ||||
|          * Reports the given node. | ||||
|          * @param {ASTNode} node The node to report. | ||||
|          * @param {string} messageKind "missingGetter" or "missingSetter". | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function report(node, messageKind) { | ||||
|             if (node.type === "Property") { | ||||
|                 context.report({ | ||||
|                     node, | ||||
|                     messageId: `${messageKind}InObjectLiteral`, | ||||
|                     loc: astUtils.getFunctionHeadLoc(node.value, sourceCode), | ||||
|                     data: { name: astUtils.getFunctionNameWithKind(node.value) } | ||||
|                 }); | ||||
|             } else if (node.type === "MethodDefinition") { | ||||
|                 context.report({ | ||||
|                     node, | ||||
|                     messageId: `${messageKind}InClass`, | ||||
|                     loc: astUtils.getFunctionHeadLoc(node.value, sourceCode), | ||||
|                     data: { name: astUtils.getFunctionNameWithKind(node.value) } | ||||
|                 }); | ||||
|             } else { | ||||
|                 context.report({ | ||||
|                     node, | ||||
|                     messageId: `${messageKind}InPropertyDescriptor` | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports each of the nodes in the given list using the same messageId. | ||||
|          * @param {ASTNode[]} nodes Nodes to report. | ||||
|          * @param {string} messageKind "missingGetter" or "missingSetter". | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function reportList(nodes, messageKind) { | ||||
|             for (const node of nodes) { | ||||
|                 report(node, messageKind); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks accessor pairs in the given list of nodes. | ||||
|          * @param {ASTNode[]} nodes The list to check. | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function checkList(nodes) { | ||||
|             const accessors = []; | ||||
|             let found = false; | ||||
|  | ||||
|             for (let i = 0; i < nodes.length; i++) { | ||||
|                 const node = nodes[i]; | ||||
|  | ||||
|                 if (isAccessorKind(node)) { | ||||
|  | ||||
|                     // Creates a new `AccessorData` object for the given getter or setter node. | ||||
|                     const name = astUtils.getStaticPropertyName(node); | ||||
|                     const key = (name !== null) ? name : sourceCode.getTokens(node.key); | ||||
|  | ||||
|                     // Merges the given `AccessorData` object into the given accessors list. | ||||
|                     for (let j = 0; j < accessors.length; j++) { | ||||
|                         const accessor = accessors[j]; | ||||
|  | ||||
|                         if (areEqualKeys(accessor.key, key)) { | ||||
|                             accessor.getters.push(...node.kind === "get" ? [node] : []); | ||||
|                             accessor.setters.push(...node.kind === "set" ? [node] : []); | ||||
|                             found = true; | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|                     if (!found) { | ||||
|                         accessors.push({ | ||||
|                             key, | ||||
|                             getters: node.kind === "get" ? [node] : [], | ||||
|                             setters: node.kind === "set" ? [node] : [] | ||||
|                         }); | ||||
|                     } | ||||
|                     found = false; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             for (const { getters, setters } of accessors) { | ||||
|                 if (checkSetWithoutGet && setters.length && !getters.length) { | ||||
|                     reportList(setters, "missingGetter"); | ||||
|                 } | ||||
|                 if (checkGetWithoutSet && getters.length && !setters.length) { | ||||
|                     reportList(getters, "missingSetter"); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks accessor pairs in an object literal. | ||||
|          * @param {ASTNode} node `ObjectExpression` node to check. | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function checkObjectLiteral(node) { | ||||
|             checkList(node.properties.filter(p => p.type === "Property")); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks accessor pairs in a property descriptor. | ||||
|          * @param {ASTNode} node Property descriptor `ObjectExpression` node to check. | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function checkPropertyDescriptor(node) { | ||||
|             const namesToCheck = new Set(node.properties | ||||
|                 .filter(p => p.type === "Property" && p.kind === "init" && !p.computed) | ||||
|                 .map(({ key }) => key.name)); | ||||
|  | ||||
|             const hasGetter = namesToCheck.has("get"); | ||||
|             const hasSetter = namesToCheck.has("set"); | ||||
|  | ||||
|             if (checkSetWithoutGet && hasSetter && !hasGetter) { | ||||
|                 report(node, "missingGetter"); | ||||
|             } | ||||
|             if (checkGetWithoutSet && hasGetter && !hasSetter) { | ||||
|                 report(node, "missingSetter"); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks the given object expression as an object literal and as a possible property descriptor. | ||||
|          * @param {ASTNode} node `ObjectExpression` node to check. | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function checkObjectExpression(node) { | ||||
|             checkObjectLiteral(node); | ||||
|             if (isPropertyDescriptor(node)) { | ||||
|                 checkPropertyDescriptor(node); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks the given class body. | ||||
|          * @param {ASTNode} node `ClassBody` node to check. | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function checkClassBody(node) { | ||||
|             const methodDefinitions = node.body.filter(m => m.type === "MethodDefinition"); | ||||
|  | ||||
|             checkList(methodDefinitions.filter(m => m.static)); | ||||
|             checkList(methodDefinitions.filter(m => !m.static)); | ||||
|         } | ||||
|  | ||||
|         const listeners = {}; | ||||
|  | ||||
|         if (checkSetWithoutGet || checkGetWithoutSet) { | ||||
|             listeners.ObjectExpression = checkObjectExpression; | ||||
|             if (enforceForClassMembers) { | ||||
|                 listeners.ClassBody = checkClassBody; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return listeners; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										261
									
								
								node_modules/eslint/lib/rules/array-bracket-newline.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										261
									
								
								node_modules/eslint/lib/rules/array-bracket-newline.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,261 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to enforce linebreaks after open and before close array brackets | ||||
|  * @author Jan Peer Stöcklmair <https://github.com/JPeer264> | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce linebreaks after opening and before closing array brackets", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/array-bracket-newline" | ||||
|         }, | ||||
|  | ||||
|         fixable: "whitespace", | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 oneOf: [ | ||||
|                     { | ||||
|                         enum: ["always", "never", "consistent"] | ||||
|                     }, | ||||
|                     { | ||||
|                         type: "object", | ||||
|                         properties: { | ||||
|                             multiline: { | ||||
|                                 type: "boolean" | ||||
|                             }, | ||||
|                             minItems: { | ||||
|                                 type: ["integer", "null"], | ||||
|                                 minimum: 0 | ||||
|                             } | ||||
|                         }, | ||||
|                         additionalProperties: false | ||||
|                     } | ||||
|                 ] | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             unexpectedOpeningLinebreak: "There should be no linebreak after '['.", | ||||
|             unexpectedClosingLinebreak: "There should be no linebreak before ']'.", | ||||
|             missingOpeningLinebreak: "A linebreak is required after '['.", | ||||
|             missingClosingLinebreak: "A linebreak is required before ']'." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|  | ||||
|         //---------------------------------------------------------------------- | ||||
|         // Helpers | ||||
|         //---------------------------------------------------------------------- | ||||
|  | ||||
|         /** | ||||
|          * Normalizes a given option value. | ||||
|          * @param {string|Object|undefined} option An option value to parse. | ||||
|          * @returns {{multiline: boolean, minItems: number}} Normalized option object. | ||||
|          */ | ||||
|         function normalizeOptionValue(option) { | ||||
|             let consistent = false; | ||||
|             let multiline = false; | ||||
|             let minItems = 0; | ||||
|  | ||||
|             if (option) { | ||||
|                 if (option === "consistent") { | ||||
|                     consistent = true; | ||||
|                     minItems = Number.POSITIVE_INFINITY; | ||||
|                 } else if (option === "always" || option.minItems === 0) { | ||||
|                     minItems = 0; | ||||
|                 } else if (option === "never") { | ||||
|                     minItems = Number.POSITIVE_INFINITY; | ||||
|                 } else { | ||||
|                     multiline = Boolean(option.multiline); | ||||
|                     minItems = option.minItems || Number.POSITIVE_INFINITY; | ||||
|                 } | ||||
|             } else { | ||||
|                 consistent = false; | ||||
|                 multiline = true; | ||||
|                 minItems = Number.POSITIVE_INFINITY; | ||||
|             } | ||||
|  | ||||
|             return { consistent, multiline, minItems }; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Normalizes a given option value. | ||||
|          * @param {string|Object|undefined} options An option value to parse. | ||||
|          * @returns {{ArrayExpression: {multiline: boolean, minItems: number}, ArrayPattern: {multiline: boolean, minItems: number}}} Normalized option object. | ||||
|          */ | ||||
|         function normalizeOptions(options) { | ||||
|             const value = normalizeOptionValue(options); | ||||
|  | ||||
|             return { ArrayExpression: value, ArrayPattern: value }; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports that there shouldn't be a linebreak after the first token | ||||
|          * @param {ASTNode} node The node to report in the event of an error. | ||||
|          * @param {Token} token The token to use for the report. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportNoBeginningLinebreak(node, token) { | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 loc: token.loc, | ||||
|                 messageId: "unexpectedOpeningLinebreak", | ||||
|                 fix(fixer) { | ||||
|                     const nextToken = sourceCode.getTokenAfter(token, { includeComments: true }); | ||||
|  | ||||
|                     if (astUtils.isCommentToken(nextToken)) { | ||||
|                         return null; | ||||
|                     } | ||||
|  | ||||
|                     return fixer.removeRange([token.range[1], nextToken.range[0]]); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports that there shouldn't be a linebreak before the last token | ||||
|          * @param {ASTNode} node The node to report in the event of an error. | ||||
|          * @param {Token} token The token to use for the report. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportNoEndingLinebreak(node, token) { | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 loc: token.loc, | ||||
|                 messageId: "unexpectedClosingLinebreak", | ||||
|                 fix(fixer) { | ||||
|                     const previousToken = sourceCode.getTokenBefore(token, { includeComments: true }); | ||||
|  | ||||
|                     if (astUtils.isCommentToken(previousToken)) { | ||||
|                         return null; | ||||
|                     } | ||||
|  | ||||
|                     return fixer.removeRange([previousToken.range[1], token.range[0]]); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports that there should be a linebreak after the first token | ||||
|          * @param {ASTNode} node The node to report in the event of an error. | ||||
|          * @param {Token} token The token to use for the report. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportRequiredBeginningLinebreak(node, token) { | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 loc: token.loc, | ||||
|                 messageId: "missingOpeningLinebreak", | ||||
|                 fix(fixer) { | ||||
|                     return fixer.insertTextAfter(token, "\n"); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports that there should be a linebreak before the last token | ||||
|          * @param {ASTNode} node The node to report in the event of an error. | ||||
|          * @param {Token} token The token to use for the report. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportRequiredEndingLinebreak(node, token) { | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 loc: token.loc, | ||||
|                 messageId: "missingClosingLinebreak", | ||||
|                 fix(fixer) { | ||||
|                     return fixer.insertTextBefore(token, "\n"); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports a given node if it violated this rule. | ||||
|          * @param {ASTNode} node A node to check. This is an ArrayExpression node or an ArrayPattern node. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function check(node) { | ||||
|             const elements = node.elements; | ||||
|             const normalizedOptions = normalizeOptions(context.options[0]); | ||||
|             const options = normalizedOptions[node.type]; | ||||
|             const openBracket = sourceCode.getFirstToken(node); | ||||
|             const closeBracket = sourceCode.getLastToken(node); | ||||
|             const firstIncComment = sourceCode.getTokenAfter(openBracket, { includeComments: true }); | ||||
|             const lastIncComment = sourceCode.getTokenBefore(closeBracket, { includeComments: true }); | ||||
|             const first = sourceCode.getTokenAfter(openBracket); | ||||
|             const last = sourceCode.getTokenBefore(closeBracket); | ||||
|  | ||||
|             const needsLinebreaks = ( | ||||
|                 elements.length >= options.minItems || | ||||
|                 ( | ||||
|                     options.multiline && | ||||
|                     elements.length > 0 && | ||||
|                     firstIncComment.loc.start.line !== lastIncComment.loc.end.line | ||||
|                 ) || | ||||
|                 ( | ||||
|                     elements.length === 0 && | ||||
|                     firstIncComment.type === "Block" && | ||||
|                     firstIncComment.loc.start.line !== lastIncComment.loc.end.line && | ||||
|                     firstIncComment === lastIncComment | ||||
|                 ) || | ||||
|                 ( | ||||
|                     options.consistent && | ||||
|                     openBracket.loc.end.line !== first.loc.start.line | ||||
|                 ) | ||||
|             ); | ||||
|  | ||||
|             /* | ||||
|              * Use tokens or comments to check multiline or not. | ||||
|              * But use only tokens to check whether linebreaks are needed. | ||||
|              * This allows: | ||||
|              *     var arr = [ // eslint-disable-line foo | ||||
|              *         'a' | ||||
|              *     ] | ||||
|              */ | ||||
|  | ||||
|             if (needsLinebreaks) { | ||||
|                 if (astUtils.isTokenOnSameLine(openBracket, first)) { | ||||
|                     reportRequiredBeginningLinebreak(node, openBracket); | ||||
|                 } | ||||
|                 if (astUtils.isTokenOnSameLine(last, closeBracket)) { | ||||
|                     reportRequiredEndingLinebreak(node, closeBracket); | ||||
|                 } | ||||
|             } else { | ||||
|                 if (!astUtils.isTokenOnSameLine(openBracket, first)) { | ||||
|                     reportNoBeginningLinebreak(node, openBracket); | ||||
|                 } | ||||
|                 if (!astUtils.isTokenOnSameLine(last, closeBracket)) { | ||||
|                     reportNoEndingLinebreak(node, closeBracket); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         //---------------------------------------------------------------------- | ||||
|         // Public | ||||
|         //---------------------------------------------------------------------- | ||||
|  | ||||
|         return { | ||||
|             ArrayPattern: check, | ||||
|             ArrayExpression: check | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										244
									
								
								node_modules/eslint/lib/rules/array-bracket-spacing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										244
									
								
								node_modules/eslint/lib/rules/array-bracket-spacing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,244 @@ | ||||
| /** | ||||
|  * @fileoverview Disallows or enforces spaces inside of array brackets. | ||||
|  * @author Jamund Ferguson | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce consistent spacing inside array brackets", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/array-bracket-spacing" | ||||
|         }, | ||||
|  | ||||
|         fixable: "whitespace", | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 enum: ["always", "never"] | ||||
|             }, | ||||
|             { | ||||
|                 type: "object", | ||||
|                 properties: { | ||||
|                     singleValue: { | ||||
|                         type: "boolean" | ||||
|                     }, | ||||
|                     objectsInArrays: { | ||||
|                         type: "boolean" | ||||
|                     }, | ||||
|                     arraysInArrays: { | ||||
|                         type: "boolean" | ||||
|                     } | ||||
|                 }, | ||||
|                 additionalProperties: false | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             unexpectedSpaceAfter: "There should be no space after '{{tokenValue}}'.", | ||||
|             unexpectedSpaceBefore: "There should be no space before '{{tokenValue}}'.", | ||||
|             missingSpaceAfter: "A space is required after '{{tokenValue}}'.", | ||||
|             missingSpaceBefore: "A space is required before '{{tokenValue}}'." | ||||
|         } | ||||
|     }, | ||||
|     create(context) { | ||||
|         const spaced = context.options[0] === "always", | ||||
|             sourceCode = context.sourceCode; | ||||
|  | ||||
|         /** | ||||
|          * Determines whether an option is set, relative to the spacing option. | ||||
|          * If spaced is "always", then check whether option is set to false. | ||||
|          * If spaced is "never", then check whether option is set to true. | ||||
|          * @param {Object} option The option to exclude. | ||||
|          * @returns {boolean} Whether or not the property is excluded. | ||||
|          */ | ||||
|         function isOptionSet(option) { | ||||
|             return context.options[1] ? context.options[1][option] === !spaced : false; | ||||
|         } | ||||
|  | ||||
|         const options = { | ||||
|             spaced, | ||||
|             singleElementException: isOptionSet("singleValue"), | ||||
|             objectsInArraysException: isOptionSet("objectsInArrays"), | ||||
|             arraysInArraysException: isOptionSet("arraysInArrays") | ||||
|         }; | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Helpers | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         /** | ||||
|          * Reports that there shouldn't be a space after the first token | ||||
|          * @param {ASTNode} node The node to report in the event of an error. | ||||
|          * @param {Token} token The token to use for the report. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportNoBeginningSpace(node, token) { | ||||
|             const nextToken = sourceCode.getTokenAfter(token); | ||||
|  | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 loc: { start: token.loc.end, end: nextToken.loc.start }, | ||||
|                 messageId: "unexpectedSpaceAfter", | ||||
|                 data: { | ||||
|                     tokenValue: token.value | ||||
|                 }, | ||||
|                 fix(fixer) { | ||||
|                     return fixer.removeRange([token.range[1], nextToken.range[0]]); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports that there shouldn't be a space before the last token | ||||
|          * @param {ASTNode} node The node to report in the event of an error. | ||||
|          * @param {Token} token The token to use for the report. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportNoEndingSpace(node, token) { | ||||
|             const previousToken = sourceCode.getTokenBefore(token); | ||||
|  | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 loc: { start: previousToken.loc.end, end: token.loc.start }, | ||||
|                 messageId: "unexpectedSpaceBefore", | ||||
|                 data: { | ||||
|                     tokenValue: token.value | ||||
|                 }, | ||||
|                 fix(fixer) { | ||||
|                     return fixer.removeRange([previousToken.range[1], token.range[0]]); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports that there should be a space after the first token | ||||
|          * @param {ASTNode} node The node to report in the event of an error. | ||||
|          * @param {Token} token The token to use for the report. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportRequiredBeginningSpace(node, token) { | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 loc: token.loc, | ||||
|                 messageId: "missingSpaceAfter", | ||||
|                 data: { | ||||
|                     tokenValue: token.value | ||||
|                 }, | ||||
|                 fix(fixer) { | ||||
|                     return fixer.insertTextAfter(token, " "); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports that there should be a space before the last token | ||||
|          * @param {ASTNode} node The node to report in the event of an error. | ||||
|          * @param {Token} token The token to use for the report. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportRequiredEndingSpace(node, token) { | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 loc: token.loc, | ||||
|                 messageId: "missingSpaceBefore", | ||||
|                 data: { | ||||
|                     tokenValue: token.value | ||||
|                 }, | ||||
|                 fix(fixer) { | ||||
|                     return fixer.insertTextBefore(token, " "); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines if a node is an object type | ||||
|          * @param {ASTNode} node The node to check. | ||||
|          * @returns {boolean} Whether or not the node is an object type. | ||||
|          */ | ||||
|         function isObjectType(node) { | ||||
|             return node && (node.type === "ObjectExpression" || node.type === "ObjectPattern"); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines if a node is an array type | ||||
|          * @param {ASTNode} node The node to check. | ||||
|          * @returns {boolean} Whether or not the node is an array type. | ||||
|          */ | ||||
|         function isArrayType(node) { | ||||
|             return node && (node.type === "ArrayExpression" || node.type === "ArrayPattern"); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Validates the spacing around array brackets | ||||
|          * @param {ASTNode} node The node we're checking for spacing | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function validateArraySpacing(node) { | ||||
|             if (options.spaced && node.elements.length === 0) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             const first = sourceCode.getFirstToken(node), | ||||
|                 second = sourceCode.getFirstToken(node, 1), | ||||
|                 last = node.typeAnnotation | ||||
|                     ? sourceCode.getTokenBefore(node.typeAnnotation) | ||||
|                     : sourceCode.getLastToken(node), | ||||
|                 penultimate = sourceCode.getTokenBefore(last), | ||||
|                 firstElement = node.elements[0], | ||||
|                 lastElement = node.elements[node.elements.length - 1]; | ||||
|  | ||||
|             const openingBracketMustBeSpaced = | ||||
|                 options.objectsInArraysException && isObjectType(firstElement) || | ||||
|                 options.arraysInArraysException && isArrayType(firstElement) || | ||||
|                 options.singleElementException && node.elements.length === 1 | ||||
|                     ? !options.spaced : options.spaced; | ||||
|  | ||||
|             const closingBracketMustBeSpaced = | ||||
|                 options.objectsInArraysException && isObjectType(lastElement) || | ||||
|                 options.arraysInArraysException && isArrayType(lastElement) || | ||||
|                 options.singleElementException && node.elements.length === 1 | ||||
|                     ? !options.spaced : options.spaced; | ||||
|  | ||||
|             if (astUtils.isTokenOnSameLine(first, second)) { | ||||
|                 if (openingBracketMustBeSpaced && !sourceCode.isSpaceBetweenTokens(first, second)) { | ||||
|                     reportRequiredBeginningSpace(node, first); | ||||
|                 } | ||||
|                 if (!openingBracketMustBeSpaced && sourceCode.isSpaceBetweenTokens(first, second)) { | ||||
|                     reportNoBeginningSpace(node, first); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (first !== penultimate && astUtils.isTokenOnSameLine(penultimate, last)) { | ||||
|                 if (closingBracketMustBeSpaced && !sourceCode.isSpaceBetweenTokens(penultimate, last)) { | ||||
|                     reportRequiredEndingSpace(node, last); | ||||
|                 } | ||||
|                 if (!closingBracketMustBeSpaced && sourceCode.isSpaceBetweenTokens(penultimate, last)) { | ||||
|                     reportNoEndingSpace(node, last); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Public | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         return { | ||||
|             ArrayPattern: validateArraySpacing, | ||||
|             ArrayExpression: validateArraySpacing | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										446
									
								
								node_modules/eslint/lib/rules/array-callback-return.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										446
									
								
								node_modules/eslint/lib/rules/array-callback-return.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,446 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to enforce return statements in callbacks of array's methods | ||||
|  * @author Toru Nagashima | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/u; | ||||
| const TARGET_METHODS = /^(?:every|filter|find(?:Last)?(?:Index)?|flatMap|forEach|map|reduce(?:Right)?|some|sort|toSorted)$/u; | ||||
|  | ||||
| /** | ||||
|  * Checks a given node is a member access which has the specified name's | ||||
|  * property. | ||||
|  * @param {ASTNode} node A node to check. | ||||
|  * @returns {boolean} `true` if the node is a member access which has | ||||
|  *      the specified name's property. The node may be a `(Chain|Member)Expression` node. | ||||
|  */ | ||||
| function isTargetMethod(node) { | ||||
|     return astUtils.isSpecificMemberAccess(node, null, TARGET_METHODS); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks all segments in a set and returns true if any are reachable. | ||||
|  * @param {Set<CodePathSegment>} segments The segments to check. | ||||
|  * @returns {boolean} True if any segment is reachable; false otherwise. | ||||
|  */ | ||||
| function isAnySegmentReachable(segments) { | ||||
|  | ||||
|     for (const segment of segments) { | ||||
|         if (segment.reachable) { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Returns a human-legible description of an array method | ||||
|  * @param {string} arrayMethodName A method name to fully qualify | ||||
|  * @returns {string} the method name prefixed with `Array.` if it is a class method, | ||||
|  *      or else `Array.prototype.` if it is an instance method. | ||||
|  */ | ||||
| function fullMethodName(arrayMethodName) { | ||||
|     if (["from", "of", "isArray"].includes(arrayMethodName)) { | ||||
|         return "Array.".concat(arrayMethodName); | ||||
|     } | ||||
|     return "Array.prototype.".concat(arrayMethodName); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether or not a given node is a function expression which is the | ||||
|  * callback of an array method, returning the method name. | ||||
|  * @param {ASTNode} node A node to check. This is one of | ||||
|  *      FunctionExpression or ArrowFunctionExpression. | ||||
|  * @returns {string} The method name if the node is a callback method, | ||||
|  *      null otherwise. | ||||
|  */ | ||||
| function getArrayMethodName(node) { | ||||
|     let currentNode = node; | ||||
|  | ||||
|     while (currentNode) { | ||||
|         const parent = currentNode.parent; | ||||
|  | ||||
|         switch (parent.type) { | ||||
|  | ||||
|             /* | ||||
|              * Looks up the destination. e.g., | ||||
|              * foo.every(nativeFoo || function foo() { ... }); | ||||
|              */ | ||||
|             case "LogicalExpression": | ||||
|             case "ConditionalExpression": | ||||
|             case "ChainExpression": | ||||
|                 currentNode = parent; | ||||
|                 break; | ||||
|  | ||||
|             /* | ||||
|              * If the upper function is IIFE, checks the destination of the return value. | ||||
|              * e.g. | ||||
|              *   foo.every((function() { | ||||
|              *     // setup... | ||||
|              *     return function callback() { ... }; | ||||
|              *   })()); | ||||
|              */ | ||||
|             case "ReturnStatement": { | ||||
|                 const func = astUtils.getUpperFunction(parent); | ||||
|  | ||||
|                 if (func === null || !astUtils.isCallee(func)) { | ||||
|                     return null; | ||||
|                 } | ||||
|                 currentNode = func.parent; | ||||
|                 break; | ||||
|             } | ||||
|  | ||||
|             /* | ||||
|              * e.g. | ||||
|              *   Array.from([], function() {}); | ||||
|              *   list.every(function() {}); | ||||
|              */ | ||||
|             case "CallExpression": | ||||
|                 if (astUtils.isArrayFromMethod(parent.callee)) { | ||||
|                     if ( | ||||
|                         parent.arguments.length >= 2 && | ||||
|                         parent.arguments[1] === currentNode | ||||
|                     ) { | ||||
|                         return "from"; | ||||
|                     } | ||||
|                 } | ||||
|                 if (isTargetMethod(parent.callee)) { | ||||
|                     if ( | ||||
|                         parent.arguments.length >= 1 && | ||||
|                         parent.arguments[0] === currentNode | ||||
|                     ) { | ||||
|                         return astUtils.getStaticPropertyName(parent.callee); | ||||
|                     } | ||||
|                 } | ||||
|                 return null; | ||||
|  | ||||
|             // Otherwise this node is not target. | ||||
|             default: | ||||
|                 return null; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     /* c8 ignore next */ | ||||
|     return null; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks if the given node is a void expression. | ||||
|  * @param {ASTNode} node The node to check. | ||||
|  * @returns {boolean} - `true` if the node is a void expression | ||||
|  */ | ||||
| function isExpressionVoid(node) { | ||||
|     return node.type === "UnaryExpression" && node.operator === "void"; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Fixes the linting error by prepending "void " to the given node | ||||
|  * @param {Object} sourceCode context given by context.sourceCode | ||||
|  * @param {ASTNode} node The node to fix. | ||||
|  * @param {Object} fixer The fixer object provided by ESLint. | ||||
|  * @returns {Array<Object>} - An array of fix objects to apply to the node. | ||||
|  */ | ||||
| function voidPrependFixer(sourceCode, node, fixer) { | ||||
|  | ||||
|     const requiresParens = | ||||
|  | ||||
|         // prepending `void ` will fail if the node has a lower precedence than void | ||||
|         astUtils.getPrecedence(node) < astUtils.getPrecedence({ type: "UnaryExpression", operator: "void" }) && | ||||
|  | ||||
|         // check if there are parentheses around the node to avoid redundant parentheses | ||||
|         !astUtils.isParenthesised(sourceCode, node); | ||||
|  | ||||
|     // avoid parentheses issues | ||||
|     const returnOrArrowToken = sourceCode.getTokenBefore( | ||||
|         node, | ||||
|         node.parent.type === "ArrowFunctionExpression" | ||||
|             ? astUtils.isArrowToken | ||||
|  | ||||
|             // isReturnToken | ||||
|             : token => token.type === "Keyword" && token.value === "return" | ||||
|     ); | ||||
|  | ||||
|     const firstToken = sourceCode.getTokenAfter(returnOrArrowToken); | ||||
|  | ||||
|     const prependSpace = | ||||
|  | ||||
|         // is return token, as => allows void to be adjacent | ||||
|         returnOrArrowToken.value === "return" && | ||||
|  | ||||
|         // If two tokens (return and "(") are adjacent | ||||
|         returnOrArrowToken.range[1] === firstToken.range[0]; | ||||
|  | ||||
|     return [ | ||||
|         fixer.insertTextBefore(firstToken, `${prependSpace ? " " : ""}void ${requiresParens ? "(" : ""}`), | ||||
|         fixer.insertTextAfter(node, requiresParens ? ")" : "") | ||||
|     ]; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Fixes the linting error by `wrapping {}` around the given node's body. | ||||
|  * @param {Object} sourceCode context given by context.sourceCode | ||||
|  * @param {ASTNode} node The node to fix. | ||||
|  * @param {Object} fixer The fixer object provided by ESLint. | ||||
|  * @returns {Array<Object>} - An array of fix objects to apply to the node. | ||||
|  */ | ||||
| function curlyWrapFixer(sourceCode, node, fixer) { | ||||
|     const arrowToken = sourceCode.getTokenBefore(node.body, astUtils.isArrowToken); | ||||
|     const firstToken = sourceCode.getTokenAfter(arrowToken); | ||||
|     const lastToken = sourceCode.getLastToken(node); | ||||
|  | ||||
|     return [ | ||||
|         fixer.insertTextBefore(firstToken, "{"), | ||||
|         fixer.insertTextAfter(lastToken, "}") | ||||
|     ]; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "problem", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce `return` statements in callbacks of array methods", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/array-callback-return" | ||||
|         }, | ||||
|  | ||||
|         // eslint-disable-next-line eslint-plugin/require-meta-has-suggestions -- false positive | ||||
|         hasSuggestions: true, | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 type: "object", | ||||
|                 properties: { | ||||
|                     allowImplicit: { | ||||
|                         type: "boolean", | ||||
|                         default: false | ||||
|                     }, | ||||
|                     checkForEach: { | ||||
|                         type: "boolean", | ||||
|                         default: false | ||||
|                     }, | ||||
|                     allowVoid: { | ||||
|                         type: "boolean", | ||||
|                         default: false | ||||
|                     } | ||||
|                 }, | ||||
|                 additionalProperties: false | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             expectedAtEnd: "{{arrayMethodName}}() expects a value to be returned at the end of {{name}}.", | ||||
|             expectedInside: "{{arrayMethodName}}() expects a return value from {{name}}.", | ||||
|             expectedReturnValue: "{{arrayMethodName}}() expects a return value from {{name}}.", | ||||
|             expectedNoReturnValue: "{{arrayMethodName}}() expects no useless return value from {{name}}.", | ||||
|             wrapBraces: "Wrap the expression in `{}`.", | ||||
|             prependVoid: "Prepend `void` to the expression." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         const options = context.options[0] || { allowImplicit: false, checkForEach: false, allowVoid: false }; | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         let funcInfo = { | ||||
|             arrayMethodName: null, | ||||
|             upper: null, | ||||
|             codePath: null, | ||||
|             hasReturn: false, | ||||
|             shouldCheck: false, | ||||
|             node: null | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Checks whether or not the last code path segment is reachable. | ||||
|          * Then reports this function if the segment is reachable. | ||||
|          * | ||||
|          * If the last code path segment is reachable, there are paths which are not | ||||
|          * returned or thrown. | ||||
|          * @param {ASTNode} node A node to check. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function checkLastSegment(node) { | ||||
|  | ||||
|             if (!funcInfo.shouldCheck) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             const messageAndSuggestions = { messageId: "", suggest: [] }; | ||||
|  | ||||
|             if (funcInfo.arrayMethodName === "forEach") { | ||||
|                 if (options.checkForEach && node.type === "ArrowFunctionExpression" && node.expression) { | ||||
|  | ||||
|                     if (options.allowVoid) { | ||||
|                         if (isExpressionVoid(node.body)) { | ||||
|                             return; | ||||
|                         } | ||||
|  | ||||
|                         messageAndSuggestions.messageId = "expectedNoReturnValue"; | ||||
|                         messageAndSuggestions.suggest = [ | ||||
|                             { | ||||
|                                 messageId: "wrapBraces", | ||||
|                                 fix(fixer) { | ||||
|                                     return curlyWrapFixer(sourceCode, node, fixer); | ||||
|                                 } | ||||
|                             }, | ||||
|                             { | ||||
|                                 messageId: "prependVoid", | ||||
|                                 fix(fixer) { | ||||
|                                     return voidPrependFixer(sourceCode, node.body, fixer); | ||||
|                                 } | ||||
|                             } | ||||
|                         ]; | ||||
|                     } else { | ||||
|                         messageAndSuggestions.messageId = "expectedNoReturnValue"; | ||||
|                         messageAndSuggestions.suggest = [{ | ||||
|                             messageId: "wrapBraces", | ||||
|                             fix(fixer) { | ||||
|                                 return curlyWrapFixer(sourceCode, node, fixer); | ||||
|                             } | ||||
|                         }]; | ||||
|                     } | ||||
|                 } | ||||
|             } else { | ||||
|                 if (node.body.type === "BlockStatement" && isAnySegmentReachable(funcInfo.currentSegments)) { | ||||
|                     messageAndSuggestions.messageId = funcInfo.hasReturn ? "expectedAtEnd" : "expectedInside"; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (messageAndSuggestions.messageId) { | ||||
|                 const name = astUtils.getFunctionNameWithKind(node); | ||||
|  | ||||
|                 context.report({ | ||||
|                     node, | ||||
|                     loc: astUtils.getFunctionHeadLoc(node, sourceCode), | ||||
|                     messageId: messageAndSuggestions.messageId, | ||||
|                     data: { name, arrayMethodName: fullMethodName(funcInfo.arrayMethodName) }, | ||||
|                     suggest: messageAndSuggestions.suggest.length !== 0 ? messageAndSuggestions.suggest : null | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|  | ||||
|             // Stacks this function's information. | ||||
|             onCodePathStart(codePath, node) { | ||||
|  | ||||
|                 let methodName = null; | ||||
|  | ||||
|                 if (TARGET_NODE_TYPE.test(node.type)) { | ||||
|                     methodName = getArrayMethodName(node); | ||||
|                 } | ||||
|  | ||||
|                 funcInfo = { | ||||
|                     arrayMethodName: methodName, | ||||
|                     upper: funcInfo, | ||||
|                     codePath, | ||||
|                     hasReturn: false, | ||||
|                     shouldCheck: | ||||
|                         methodName && | ||||
|                         !node.async && | ||||
|                         !node.generator, | ||||
|                     node, | ||||
|                     currentSegments: new Set() | ||||
|                 }; | ||||
|             }, | ||||
|  | ||||
|             // Pops this function's information. | ||||
|             onCodePathEnd() { | ||||
|                 funcInfo = funcInfo.upper; | ||||
|             }, | ||||
|  | ||||
|             onUnreachableCodePathSegmentStart(segment) { | ||||
|                 funcInfo.currentSegments.add(segment); | ||||
|             }, | ||||
|  | ||||
|             onUnreachableCodePathSegmentEnd(segment) { | ||||
|                 funcInfo.currentSegments.delete(segment); | ||||
|             }, | ||||
|  | ||||
|             onCodePathSegmentStart(segment) { | ||||
|                 funcInfo.currentSegments.add(segment); | ||||
|             }, | ||||
|  | ||||
|             onCodePathSegmentEnd(segment) { | ||||
|                 funcInfo.currentSegments.delete(segment); | ||||
|             }, | ||||
|  | ||||
|  | ||||
|             // Checks the return statement is valid. | ||||
|             ReturnStatement(node) { | ||||
|  | ||||
|                 if (!funcInfo.shouldCheck) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 funcInfo.hasReturn = true; | ||||
|  | ||||
|                 const messageAndSuggestions = { messageId: "", suggest: [] }; | ||||
|  | ||||
|                 if (funcInfo.arrayMethodName === "forEach") { | ||||
|  | ||||
|                     // if checkForEach: true, returning a value at any path inside a forEach is not allowed | ||||
|                     if (options.checkForEach && node.argument) { | ||||
|  | ||||
|                         if (options.allowVoid) { | ||||
|                             if (isExpressionVoid(node.argument)) { | ||||
|                                 return; | ||||
|                             } | ||||
|  | ||||
|                             messageAndSuggestions.messageId = "expectedNoReturnValue"; | ||||
|                             messageAndSuggestions.suggest = [{ | ||||
|                                 messageId: "prependVoid", | ||||
|                                 fix(fixer) { | ||||
|                                     return voidPrependFixer(sourceCode, node.argument, fixer); | ||||
|                                 } | ||||
|                             }]; | ||||
|                         } else { | ||||
|                             messageAndSuggestions.messageId = "expectedNoReturnValue"; | ||||
|                         } | ||||
|                     } | ||||
|                 } else { | ||||
|  | ||||
|                     // if allowImplicit: false, should also check node.argument | ||||
|                     if (!options.allowImplicit && !node.argument) { | ||||
|                         messageAndSuggestions.messageId = "expectedReturnValue"; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (messageAndSuggestions.messageId) { | ||||
|                     context.report({ | ||||
|                         node, | ||||
|                         messageId: messageAndSuggestions.messageId, | ||||
|                         data: { | ||||
|                             name: astUtils.getFunctionNameWithKind(funcInfo.node), | ||||
|                             arrayMethodName: fullMethodName(funcInfo.arrayMethodName) | ||||
|                         }, | ||||
|                         suggest: messageAndSuggestions.suggest.length !== 0 ? messageAndSuggestions.suggest : null | ||||
|                     }); | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             // Reports a given function if the last path is reachable. | ||||
|             "FunctionExpression:exit": checkLastSegment, | ||||
|             "ArrowFunctionExpression:exit": checkLastSegment | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										311
									
								
								node_modules/eslint/lib/rules/array-element-newline.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										311
									
								
								node_modules/eslint/lib/rules/array-element-newline.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,311 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to enforce line breaks after each array element | ||||
|  * @author Jan Peer Stöcklmair <https://github.com/JPeer264> | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce line breaks after each array element", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/array-element-newline" | ||||
|         }, | ||||
|  | ||||
|         fixable: "whitespace", | ||||
|  | ||||
|         schema: { | ||||
|             definitions: { | ||||
|                 basicConfig: { | ||||
|                     oneOf: [ | ||||
|                         { | ||||
|                             enum: ["always", "never", "consistent"] | ||||
|                         }, | ||||
|                         { | ||||
|                             type: "object", | ||||
|                             properties: { | ||||
|                                 multiline: { | ||||
|                                     type: "boolean" | ||||
|                                 }, | ||||
|                                 minItems: { | ||||
|                                     type: ["integer", "null"], | ||||
|                                     minimum: 0 | ||||
|                                 } | ||||
|                             }, | ||||
|                             additionalProperties: false | ||||
|                         } | ||||
|                     ] | ||||
|                 } | ||||
|             }, | ||||
|             type: "array", | ||||
|             items: [ | ||||
|                 { | ||||
|                     oneOf: [ | ||||
|                         { | ||||
|                             $ref: "#/definitions/basicConfig" | ||||
|                         }, | ||||
|                         { | ||||
|                             type: "object", | ||||
|                             properties: { | ||||
|                                 ArrayExpression: { | ||||
|                                     $ref: "#/definitions/basicConfig" | ||||
|                                 }, | ||||
|                                 ArrayPattern: { | ||||
|                                     $ref: "#/definitions/basicConfig" | ||||
|                                 } | ||||
|                             }, | ||||
|                             additionalProperties: false, | ||||
|                             minProperties: 1 | ||||
|                         } | ||||
|                     ] | ||||
|                 } | ||||
|             ] | ||||
|         }, | ||||
|  | ||||
|         messages: { | ||||
|             unexpectedLineBreak: "There should be no linebreak here.", | ||||
|             missingLineBreak: "There should be a linebreak after this element." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         //---------------------------------------------------------------------- | ||||
|         // Helpers | ||||
|         //---------------------------------------------------------------------- | ||||
|  | ||||
|         /** | ||||
|          * Normalizes a given option value. | ||||
|          * @param {string|Object|undefined} providedOption An option value to parse. | ||||
|          * @returns {{multiline: boolean, minItems: number}} Normalized option object. | ||||
|          */ | ||||
|         function normalizeOptionValue(providedOption) { | ||||
|             let consistent = false; | ||||
|             let multiline = false; | ||||
|             let minItems; | ||||
|  | ||||
|             const option = providedOption || "always"; | ||||
|  | ||||
|             if (!option || option === "always" || option.minItems === 0) { | ||||
|                 minItems = 0; | ||||
|             } else if (option === "never") { | ||||
|                 minItems = Number.POSITIVE_INFINITY; | ||||
|             } else if (option === "consistent") { | ||||
|                 consistent = true; | ||||
|                 minItems = Number.POSITIVE_INFINITY; | ||||
|             } else { | ||||
|                 multiline = Boolean(option.multiline); | ||||
|                 minItems = option.minItems || Number.POSITIVE_INFINITY; | ||||
|             } | ||||
|  | ||||
|             return { consistent, multiline, minItems }; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Normalizes a given option value. | ||||
|          * @param {string|Object|undefined} options An option value to parse. | ||||
|          * @returns {{ArrayExpression: {multiline: boolean, minItems: number}, ArrayPattern: {multiline: boolean, minItems: number}}} Normalized option object. | ||||
|          */ | ||||
|         function normalizeOptions(options) { | ||||
|             if (options && (options.ArrayExpression || options.ArrayPattern)) { | ||||
|                 let expressionOptions, patternOptions; | ||||
|  | ||||
|                 if (options.ArrayExpression) { | ||||
|                     expressionOptions = normalizeOptionValue(options.ArrayExpression); | ||||
|                 } | ||||
|  | ||||
|                 if (options.ArrayPattern) { | ||||
|                     patternOptions = normalizeOptionValue(options.ArrayPattern); | ||||
|                 } | ||||
|  | ||||
|                 return { ArrayExpression: expressionOptions, ArrayPattern: patternOptions }; | ||||
|             } | ||||
|  | ||||
|             const value = normalizeOptionValue(options); | ||||
|  | ||||
|             return { ArrayExpression: value, ArrayPattern: value }; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports that there shouldn't be a line break after the first token | ||||
|          * @param {Token} token The token to use for the report. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportNoLineBreak(token) { | ||||
|             const tokenBefore = sourceCode.getTokenBefore(token, { includeComments: true }); | ||||
|  | ||||
|             context.report({ | ||||
|                 loc: { | ||||
|                     start: tokenBefore.loc.end, | ||||
|                     end: token.loc.start | ||||
|                 }, | ||||
|                 messageId: "unexpectedLineBreak", | ||||
|                 fix(fixer) { | ||||
|                     if (astUtils.isCommentToken(tokenBefore)) { | ||||
|                         return null; | ||||
|                     } | ||||
|  | ||||
|                     if (!astUtils.isTokenOnSameLine(tokenBefore, token)) { | ||||
|                         return fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], " "); | ||||
|                     } | ||||
|  | ||||
|                     /* | ||||
|                      * This will check if the comma is on the same line as the next element | ||||
|                      * Following array: | ||||
|                      * [ | ||||
|                      *     1 | ||||
|                      *     , 2 | ||||
|                      *     , 3 | ||||
|                      * ] | ||||
|                      * | ||||
|                      * will be fixed to: | ||||
|                      * [ | ||||
|                      *     1, 2, 3 | ||||
|                      * ] | ||||
|                      */ | ||||
|                     const twoTokensBefore = sourceCode.getTokenBefore(tokenBefore, { includeComments: true }); | ||||
|  | ||||
|                     if (astUtils.isCommentToken(twoTokensBefore)) { | ||||
|                         return null; | ||||
|                     } | ||||
|  | ||||
|                     return fixer.replaceTextRange([twoTokensBefore.range[1], tokenBefore.range[0]], ""); | ||||
|  | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports that there should be a line break after the first token | ||||
|          * @param {Token} token The token to use for the report. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportRequiredLineBreak(token) { | ||||
|             const tokenBefore = sourceCode.getTokenBefore(token, { includeComments: true }); | ||||
|  | ||||
|             context.report({ | ||||
|                 loc: { | ||||
|                     start: tokenBefore.loc.end, | ||||
|                     end: token.loc.start | ||||
|                 }, | ||||
|                 messageId: "missingLineBreak", | ||||
|                 fix(fixer) { | ||||
|                     return fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], "\n"); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports a given node if it violated this rule. | ||||
|          * @param {ASTNode} node A node to check. This is an ObjectExpression node or an ObjectPattern node. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function check(node) { | ||||
|             const elements = node.elements; | ||||
|             const normalizedOptions = normalizeOptions(context.options[0]); | ||||
|             const options = normalizedOptions[node.type]; | ||||
|  | ||||
|             if (!options) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             let elementBreak = false; | ||||
|  | ||||
|             /* | ||||
|              * MULTILINE: true | ||||
|              * loop through every element and check | ||||
|              * if at least one element has linebreaks inside | ||||
|              * this ensures that following is not valid (due to elements are on the same line): | ||||
|              * | ||||
|              * [ | ||||
|              *      1, | ||||
|              *      2, | ||||
|              *      3 | ||||
|              * ] | ||||
|              */ | ||||
|             if (options.multiline) { | ||||
|                 elementBreak = elements | ||||
|                     .filter(element => element !== null) | ||||
|                     .some(element => element.loc.start.line !== element.loc.end.line); | ||||
|             } | ||||
|  | ||||
|             let linebreaksCount = 0; | ||||
|  | ||||
|             for (let i = 0; i < node.elements.length; i++) { | ||||
|                 const element = node.elements[i]; | ||||
|  | ||||
|                 const previousElement = elements[i - 1]; | ||||
|  | ||||
|                 if (i === 0 || element === null || previousElement === null) { | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 const commaToken = sourceCode.getFirstTokenBetween(previousElement, element, astUtils.isCommaToken); | ||||
|                 const lastTokenOfPreviousElement = sourceCode.getTokenBefore(commaToken); | ||||
|                 const firstTokenOfCurrentElement = sourceCode.getTokenAfter(commaToken); | ||||
|  | ||||
|                 if (!astUtils.isTokenOnSameLine(lastTokenOfPreviousElement, firstTokenOfCurrentElement)) { | ||||
|                     linebreaksCount++; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             const needsLinebreaks = ( | ||||
|                 elements.length >= options.minItems || | ||||
|                 ( | ||||
|                     options.multiline && | ||||
|                     elementBreak | ||||
|                 ) || | ||||
|                 ( | ||||
|                     options.consistent && | ||||
|                     linebreaksCount > 0 && | ||||
|                     linebreaksCount < node.elements.length | ||||
|                 ) | ||||
|             ); | ||||
|  | ||||
|             elements.forEach((element, i) => { | ||||
|                 const previousElement = elements[i - 1]; | ||||
|  | ||||
|                 if (i === 0 || element === null || previousElement === null) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 const commaToken = sourceCode.getFirstTokenBetween(previousElement, element, astUtils.isCommaToken); | ||||
|                 const lastTokenOfPreviousElement = sourceCode.getTokenBefore(commaToken); | ||||
|                 const firstTokenOfCurrentElement = sourceCode.getTokenAfter(commaToken); | ||||
|  | ||||
|                 if (needsLinebreaks) { | ||||
|                     if (astUtils.isTokenOnSameLine(lastTokenOfPreviousElement, firstTokenOfCurrentElement)) { | ||||
|                         reportRequiredLineBreak(firstTokenOfCurrentElement); | ||||
|                     } | ||||
|                 } else { | ||||
|                     if (!astUtils.isTokenOnSameLine(lastTokenOfPreviousElement, firstTokenOfCurrentElement)) { | ||||
|                         reportNoLineBreak(firstTokenOfCurrentElement); | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         //---------------------------------------------------------------------- | ||||
|         // Public | ||||
|         //---------------------------------------------------------------------- | ||||
|  | ||||
|         return { | ||||
|             ArrayPattern: check, | ||||
|             ArrayExpression: check | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										296
									
								
								node_modules/eslint/lib/rules/arrow-body-style.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										296
									
								
								node_modules/eslint/lib/rules/arrow-body-style.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,296 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to require braces in arrow function body. | ||||
|  * @author Alberto Rodríguez | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require braces around arrow function bodies", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/arrow-body-style" | ||||
|         }, | ||||
|  | ||||
|         schema: { | ||||
|             anyOf: [ | ||||
|                 { | ||||
|                     type: "array", | ||||
|                     items: [ | ||||
|                         { | ||||
|                             enum: ["always", "never"] | ||||
|                         } | ||||
|                     ], | ||||
|                     minItems: 0, | ||||
|                     maxItems: 1 | ||||
|                 }, | ||||
|                 { | ||||
|                     type: "array", | ||||
|                     items: [ | ||||
|                         { | ||||
|                             enum: ["as-needed"] | ||||
|                         }, | ||||
|                         { | ||||
|                             type: "object", | ||||
|                             properties: { | ||||
|                                 requireReturnForObjectLiteral: { type: "boolean" } | ||||
|                             }, | ||||
|                             additionalProperties: false | ||||
|                         } | ||||
|                     ], | ||||
|                     minItems: 0, | ||||
|                     maxItems: 2 | ||||
|                 } | ||||
|             ] | ||||
|         }, | ||||
|  | ||||
|         fixable: "code", | ||||
|  | ||||
|         messages: { | ||||
|             unexpectedOtherBlock: "Unexpected block statement surrounding arrow body.", | ||||
|             unexpectedEmptyBlock: "Unexpected block statement surrounding arrow body; put a value of `undefined` immediately after the `=>`.", | ||||
|             unexpectedObjectBlock: "Unexpected block statement surrounding arrow body; parenthesize the returned value and move it immediately after the `=>`.", | ||||
|             unexpectedSingleBlock: "Unexpected block statement surrounding arrow body; move the returned value immediately after the `=>`.", | ||||
|             expectedBlock: "Expected block statement surrounding arrow body." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const options = context.options; | ||||
|         const always = options[0] === "always"; | ||||
|         const asNeeded = !options[0] || options[0] === "as-needed"; | ||||
|         const never = options[0] === "never"; | ||||
|         const requireReturnForObjectLiteral = options[1] && options[1].requireReturnForObjectLiteral; | ||||
|         const sourceCode = context.sourceCode; | ||||
|         let funcInfo = null; | ||||
|  | ||||
|         /** | ||||
|          * Checks whether the given node has ASI problem or not. | ||||
|          * @param {Token} token The token to check. | ||||
|          * @returns {boolean} `true` if it changes semantics if `;` or `}` followed by the token are removed. | ||||
|          */ | ||||
|         function hasASIProblem(token) { | ||||
|             return token && token.type === "Punctuator" && /^[([/`+-]/u.test(token.value); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Gets the closing parenthesis by the given node. | ||||
|          * @param {ASTNode} node first node after an opening parenthesis. | ||||
|          * @returns {Token} The found closing parenthesis token. | ||||
|          */ | ||||
|         function findClosingParen(node) { | ||||
|             let nodeToCheck = node; | ||||
|  | ||||
|             while (!astUtils.isParenthesised(sourceCode, nodeToCheck)) { | ||||
|                 nodeToCheck = nodeToCheck.parent; | ||||
|             } | ||||
|             return sourceCode.getTokenAfter(nodeToCheck); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Check whether the node is inside of a for loop's init | ||||
|          * @param {ASTNode} node node is inside for loop | ||||
|          * @returns {boolean} `true` if the node is inside of a for loop, else `false` | ||||
|          */ | ||||
|         function isInsideForLoopInitializer(node) { | ||||
|             if (node && node.parent) { | ||||
|                 if (node.parent.type === "ForStatement" && node.parent.init === node) { | ||||
|                     return true; | ||||
|                 } | ||||
|                 return isInsideForLoopInitializer(node.parent); | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines whether a arrow function body needs braces | ||||
|          * @param {ASTNode} node The arrow function node. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function validate(node) { | ||||
|             const arrowBody = node.body; | ||||
|  | ||||
|             if (arrowBody.type === "BlockStatement") { | ||||
|                 const blockBody = arrowBody.body; | ||||
|  | ||||
|                 if (blockBody.length !== 1 && !never) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 if (asNeeded && requireReturnForObjectLiteral && blockBody[0].type === "ReturnStatement" && | ||||
|                     blockBody[0].argument && blockBody[0].argument.type === "ObjectExpression") { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 if (never || asNeeded && blockBody[0].type === "ReturnStatement") { | ||||
|                     let messageId; | ||||
|  | ||||
|                     if (blockBody.length === 0) { | ||||
|                         messageId = "unexpectedEmptyBlock"; | ||||
|                     } else if (blockBody.length > 1) { | ||||
|                         messageId = "unexpectedOtherBlock"; | ||||
|                     } else if (blockBody[0].argument === null) { | ||||
|                         messageId = "unexpectedSingleBlock"; | ||||
|                     } else if (astUtils.isOpeningBraceToken(sourceCode.getFirstToken(blockBody[0], { skip: 1 }))) { | ||||
|                         messageId = "unexpectedObjectBlock"; | ||||
|                     } else { | ||||
|                         messageId = "unexpectedSingleBlock"; | ||||
|                     } | ||||
|  | ||||
|                     context.report({ | ||||
|                         node, | ||||
|                         loc: arrowBody.loc, | ||||
|                         messageId, | ||||
|                         fix(fixer) { | ||||
|                             const fixes = []; | ||||
|  | ||||
|                             if (blockBody.length !== 1 || | ||||
|                                 blockBody[0].type !== "ReturnStatement" || | ||||
|                                 !blockBody[0].argument || | ||||
|                                 hasASIProblem(sourceCode.getTokenAfter(arrowBody)) | ||||
|                             ) { | ||||
|                                 return fixes; | ||||
|                             } | ||||
|  | ||||
|                             const openingBrace = sourceCode.getFirstToken(arrowBody); | ||||
|                             const closingBrace = sourceCode.getLastToken(arrowBody); | ||||
|                             const firstValueToken = sourceCode.getFirstToken(blockBody[0], 1); | ||||
|                             const lastValueToken = sourceCode.getLastToken(blockBody[0]); | ||||
|                             const commentsExist = | ||||
|                                 sourceCode.commentsExistBetween(openingBrace, firstValueToken) || | ||||
|                                 sourceCode.commentsExistBetween(lastValueToken, closingBrace); | ||||
|  | ||||
|                             /* | ||||
|                              * Remove tokens around the return value. | ||||
|                              * If comments don't exist, remove extra spaces as well. | ||||
|                              */ | ||||
|                             if (commentsExist) { | ||||
|                                 fixes.push( | ||||
|                                     fixer.remove(openingBrace), | ||||
|                                     fixer.remove(closingBrace), | ||||
|                                     fixer.remove(sourceCode.getTokenAfter(openingBrace)) // return keyword | ||||
|                                 ); | ||||
|                             } else { | ||||
|                                 fixes.push( | ||||
|                                     fixer.removeRange([openingBrace.range[0], firstValueToken.range[0]]), | ||||
|                                     fixer.removeRange([lastValueToken.range[1], closingBrace.range[1]]) | ||||
|                                 ); | ||||
|                             } | ||||
|  | ||||
|                             /* | ||||
|                              * If the first token of the return value is `{` or the return value is a sequence expression, | ||||
|                              * enclose the return value by parentheses to avoid syntax error. | ||||
|                              */ | ||||
|                             if (astUtils.isOpeningBraceToken(firstValueToken) || blockBody[0].argument.type === "SequenceExpression" || (funcInfo.hasInOperator && isInsideForLoopInitializer(node))) { | ||||
|                                 if (!astUtils.isParenthesised(sourceCode, blockBody[0].argument)) { | ||||
|                                     fixes.push( | ||||
|                                         fixer.insertTextBefore(firstValueToken, "("), | ||||
|                                         fixer.insertTextAfter(lastValueToken, ")") | ||||
|                                     ); | ||||
|                                 } | ||||
|                             } | ||||
|  | ||||
|                             /* | ||||
|                              * If the last token of the return statement is semicolon, remove it. | ||||
|                              * Non-block arrow body is an expression, not a statement. | ||||
|                              */ | ||||
|                             if (astUtils.isSemicolonToken(lastValueToken)) { | ||||
|                                 fixes.push(fixer.remove(lastValueToken)); | ||||
|                             } | ||||
|  | ||||
|                             return fixes; | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             } else { | ||||
|                 if (always || (asNeeded && requireReturnForObjectLiteral && arrowBody.type === "ObjectExpression")) { | ||||
|                     context.report({ | ||||
|                         node, | ||||
|                         loc: arrowBody.loc, | ||||
|                         messageId: "expectedBlock", | ||||
|                         fix(fixer) { | ||||
|                             const fixes = []; | ||||
|                             const arrowToken = sourceCode.getTokenBefore(arrowBody, astUtils.isArrowToken); | ||||
|                             const [firstTokenAfterArrow, secondTokenAfterArrow] = sourceCode.getTokensAfter(arrowToken, { count: 2 }); | ||||
|                             const lastToken = sourceCode.getLastToken(node); | ||||
|  | ||||
|                             let parenthesisedObjectLiteral = null; | ||||
|  | ||||
|                             if ( | ||||
|                                 astUtils.isOpeningParenToken(firstTokenAfterArrow) && | ||||
|                                 astUtils.isOpeningBraceToken(secondTokenAfterArrow) | ||||
|                             ) { | ||||
|                                 const braceNode = sourceCode.getNodeByRangeIndex(secondTokenAfterArrow.range[0]); | ||||
|  | ||||
|                                 if (braceNode.type === "ObjectExpression") { | ||||
|                                     parenthesisedObjectLiteral = braceNode; | ||||
|                                 } | ||||
|                             } | ||||
|  | ||||
|                             // If the value is object literal, remove parentheses which were forced by syntax. | ||||
|                             if (parenthesisedObjectLiteral) { | ||||
|                                 const openingParenToken = firstTokenAfterArrow; | ||||
|                                 const openingBraceToken = secondTokenAfterArrow; | ||||
|  | ||||
|                                 if (astUtils.isTokenOnSameLine(openingParenToken, openingBraceToken)) { | ||||
|                                     fixes.push(fixer.replaceText(openingParenToken, "{return ")); | ||||
|                                 } else { | ||||
|  | ||||
|                                     // Avoid ASI | ||||
|                                     fixes.push( | ||||
|                                         fixer.replaceText(openingParenToken, "{"), | ||||
|                                         fixer.insertTextBefore(openingBraceToken, "return ") | ||||
|                                     ); | ||||
|                                 } | ||||
|  | ||||
|                                 // Closing paren for the object doesn't have to be lastToken, e.g.: () => ({}).foo() | ||||
|                                 fixes.push(fixer.remove(findClosingParen(parenthesisedObjectLiteral))); | ||||
|                                 fixes.push(fixer.insertTextAfter(lastToken, "}")); | ||||
|  | ||||
|                             } else { | ||||
|                                 fixes.push(fixer.insertTextBefore(firstTokenAfterArrow, "{return ")); | ||||
|                                 fixes.push(fixer.insertTextAfter(lastToken, "}")); | ||||
|                             } | ||||
|  | ||||
|                             return fixes; | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             "BinaryExpression[operator='in']"() { | ||||
|                 let info = funcInfo; | ||||
|  | ||||
|                 while (info) { | ||||
|                     info.hasInOperator = true; | ||||
|                     info = info.upper; | ||||
|                 } | ||||
|             }, | ||||
|             ArrowFunctionExpression() { | ||||
|                 funcInfo = { | ||||
|                     upper: funcInfo, | ||||
|                     hasInOperator: false | ||||
|                 }; | ||||
|             }, | ||||
|             "ArrowFunctionExpression:exit"(node) { | ||||
|                 validate(node); | ||||
|                 funcInfo = funcInfo.upper; | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										186
									
								
								node_modules/eslint/lib/rules/arrow-parens.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										186
									
								
								node_modules/eslint/lib/rules/arrow-parens.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,186 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to require parens in arrow function arguments. | ||||
|  * @author Jxck | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Determines if the given arrow function has block body. | ||||
|  * @param {ASTNode} node `ArrowFunctionExpression` node. | ||||
|  * @returns {boolean} `true` if the function has block body. | ||||
|  */ | ||||
| function hasBlockBody(node) { | ||||
|     return node.body.type === "BlockStatement"; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require parentheses around arrow function arguments", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/arrow-parens" | ||||
|         }, | ||||
|  | ||||
|         fixable: "code", | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 enum: ["always", "as-needed"] | ||||
|             }, | ||||
|             { | ||||
|                 type: "object", | ||||
|                 properties: { | ||||
|                     requireForBlockBody: { | ||||
|                         type: "boolean", | ||||
|                         default: false | ||||
|                     } | ||||
|                 }, | ||||
|                 additionalProperties: false | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             unexpectedParens: "Unexpected parentheses around single function argument.", | ||||
|             expectedParens: "Expected parentheses around arrow function argument.", | ||||
|  | ||||
|             unexpectedParensInline: "Unexpected parentheses around single function argument having a body with no curly braces.", | ||||
|             expectedParensBlock: "Expected parentheses around arrow function argument having a body with curly braces." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const asNeeded = context.options[0] === "as-needed"; | ||||
|         const requireForBlockBody = asNeeded && context.options[1] && context.options[1].requireForBlockBody === true; | ||||
|  | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         /** | ||||
|          * Finds opening paren of parameters for the given arrow function, if it exists. | ||||
|          * It is assumed that the given arrow function has exactly one parameter. | ||||
|          * @param {ASTNode} node `ArrowFunctionExpression` node. | ||||
|          * @returns {Token|null} the opening paren, or `null` if the given arrow function doesn't have parens of parameters. | ||||
|          */ | ||||
|         function findOpeningParenOfParams(node) { | ||||
|             const tokenBeforeParams = sourceCode.getTokenBefore(node.params[0]); | ||||
|  | ||||
|             if ( | ||||
|                 tokenBeforeParams && | ||||
|                 astUtils.isOpeningParenToken(tokenBeforeParams) && | ||||
|                 node.range[0] <= tokenBeforeParams.range[0] | ||||
|             ) { | ||||
|                 return tokenBeforeParams; | ||||
|             } | ||||
|  | ||||
|             return null; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Finds closing paren of parameters for the given arrow function. | ||||
|          * It is assumed that the given arrow function has parens of parameters and that it has exactly one parameter. | ||||
|          * @param {ASTNode} node `ArrowFunctionExpression` node. | ||||
|          * @returns {Token} the closing paren of parameters. | ||||
|          */ | ||||
|         function getClosingParenOfParams(node) { | ||||
|             return sourceCode.getTokenAfter(node.params[0], astUtils.isClosingParenToken); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines whether the given arrow function has comments inside parens of parameters. | ||||
|          * It is assumed that the given arrow function has parens of parameters. | ||||
|          * @param {ASTNode} node `ArrowFunctionExpression` node. | ||||
|          * @param {Token} openingParen Opening paren of parameters. | ||||
|          * @returns {boolean} `true` if the function has at least one comment inside of parens of parameters. | ||||
|          */ | ||||
|         function hasCommentsInParensOfParams(node, openingParen) { | ||||
|             return sourceCode.commentsExistBetween(openingParen, getClosingParenOfParams(node)); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines whether the given arrow function has unexpected tokens before opening paren of parameters, | ||||
|          * in which case it will be assumed that the existing parens of parameters are necessary. | ||||
|          * Only tokens within the range of the arrow function (tokens that are part of the arrow function) are taken into account. | ||||
|          * Example: <T>(a) => b | ||||
|          * @param {ASTNode} node `ArrowFunctionExpression` node. | ||||
|          * @param {Token} openingParen Opening paren of parameters. | ||||
|          * @returns {boolean} `true` if the function has at least one unexpected token. | ||||
|          */ | ||||
|         function hasUnexpectedTokensBeforeOpeningParen(node, openingParen) { | ||||
|             const expectedCount = node.async ? 1 : 0; | ||||
|  | ||||
|             return sourceCode.getFirstToken(node, { skip: expectedCount }) !== openingParen; | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             "ArrowFunctionExpression[params.length=1]"(node) { | ||||
|                 const shouldHaveParens = !asNeeded || requireForBlockBody && hasBlockBody(node); | ||||
|                 const openingParen = findOpeningParenOfParams(node); | ||||
|                 const hasParens = openingParen !== null; | ||||
|                 const [param] = node.params; | ||||
|  | ||||
|                 if (shouldHaveParens && !hasParens) { | ||||
|                     context.report({ | ||||
|                         node, | ||||
|                         messageId: requireForBlockBody ? "expectedParensBlock" : "expectedParens", | ||||
|                         loc: param.loc, | ||||
|                         *fix(fixer) { | ||||
|                             yield fixer.insertTextBefore(param, "("); | ||||
|                             yield fixer.insertTextAfter(param, ")"); | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|  | ||||
|                 if ( | ||||
|                     !shouldHaveParens && | ||||
|                     hasParens && | ||||
|                     param.type === "Identifier" && | ||||
|                     !param.typeAnnotation && | ||||
|                     !node.returnType && | ||||
|                     !hasCommentsInParensOfParams(node, openingParen) && | ||||
|                     !hasUnexpectedTokensBeforeOpeningParen(node, openingParen) | ||||
|                 ) { | ||||
|                     context.report({ | ||||
|                         node, | ||||
|                         messageId: requireForBlockBody ? "unexpectedParensInline" : "unexpectedParens", | ||||
|                         loc: param.loc, | ||||
|                         *fix(fixer) { | ||||
|                             const tokenBeforeOpeningParen = sourceCode.getTokenBefore(openingParen); | ||||
|                             const closingParen = getClosingParenOfParams(node); | ||||
|  | ||||
|                             if ( | ||||
|                                 tokenBeforeOpeningParen && | ||||
|                                 tokenBeforeOpeningParen.range[1] === openingParen.range[0] && | ||||
|                                 !astUtils.canTokensBeAdjacent(tokenBeforeOpeningParen, sourceCode.getFirstToken(param)) | ||||
|                             ) { | ||||
|                                 yield fixer.insertTextBefore(openingParen, " "); | ||||
|                             } | ||||
|  | ||||
|                             // remove parens, whitespace inside parens, and possible trailing comma | ||||
|                             yield fixer.removeRange([openingParen.range[0], param.range[0]]); | ||||
|                             yield fixer.removeRange([param.range[1], closingParen.range[1]]); | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										164
									
								
								node_modules/eslint/lib/rules/arrow-spacing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										164
									
								
								node_modules/eslint/lib/rules/arrow-spacing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,164 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to define spacing before/after arrow function's arrow. | ||||
|  * @author Jxck | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce consistent spacing before and after the arrow in arrow functions", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/arrow-spacing" | ||||
|         }, | ||||
|  | ||||
|         fixable: "whitespace", | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 type: "object", | ||||
|                 properties: { | ||||
|                     before: { | ||||
|                         type: "boolean", | ||||
|                         default: true | ||||
|                     }, | ||||
|                     after: { | ||||
|                         type: "boolean", | ||||
|                         default: true | ||||
|                     } | ||||
|                 }, | ||||
|                 additionalProperties: false | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             expectedBefore: "Missing space before =>.", | ||||
|             unexpectedBefore: "Unexpected space before =>.", | ||||
|  | ||||
|             expectedAfter: "Missing space after =>.", | ||||
|             unexpectedAfter: "Unexpected space after =>." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         // merge rules with default | ||||
|         const rule = Object.assign({}, context.options[0]); | ||||
|  | ||||
|         rule.before = rule.before !== false; | ||||
|         rule.after = rule.after !== false; | ||||
|  | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         /** | ||||
|          * Get tokens of arrow(`=>`) and before/after arrow. | ||||
|          * @param {ASTNode} node The arrow function node. | ||||
|          * @returns {Object} Tokens of arrow and before/after arrow. | ||||
|          */ | ||||
|         function getTokens(node) { | ||||
|             const arrow = sourceCode.getTokenBefore(node.body, astUtils.isArrowToken); | ||||
|  | ||||
|             return { | ||||
|                 before: sourceCode.getTokenBefore(arrow), | ||||
|                 arrow, | ||||
|                 after: sourceCode.getTokenAfter(arrow) | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Count spaces before/after arrow(`=>`) token. | ||||
|          * @param {Object} tokens Tokens before/after arrow. | ||||
|          * @returns {Object} count of space before/after arrow. | ||||
|          */ | ||||
|         function countSpaces(tokens) { | ||||
|             const before = tokens.arrow.range[0] - tokens.before.range[1]; | ||||
|             const after = tokens.after.range[0] - tokens.arrow.range[1]; | ||||
|  | ||||
|             return { before, after }; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines whether space(s) before after arrow(`=>`) is satisfy rule. | ||||
|          * if before/after value is `true`, there should be space(s). | ||||
|          * if before/after value is `false`, there should be no space. | ||||
|          * @param {ASTNode} node The arrow function node. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function spaces(node) { | ||||
|             const tokens = getTokens(node); | ||||
|             const countSpace = countSpaces(tokens); | ||||
|  | ||||
|             if (rule.before) { | ||||
|  | ||||
|                 // should be space(s) before arrow | ||||
|                 if (countSpace.before === 0) { | ||||
|                     context.report({ | ||||
|                         node: tokens.before, | ||||
|                         messageId: "expectedBefore", | ||||
|                         fix(fixer) { | ||||
|                             return fixer.insertTextBefore(tokens.arrow, " "); | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             } else { | ||||
|  | ||||
|                 // should be no space before arrow | ||||
|                 if (countSpace.before > 0) { | ||||
|                     context.report({ | ||||
|                         node: tokens.before, | ||||
|                         messageId: "unexpectedBefore", | ||||
|                         fix(fixer) { | ||||
|                             return fixer.removeRange([tokens.before.range[1], tokens.arrow.range[0]]); | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (rule.after) { | ||||
|  | ||||
|                 // should be space(s) after arrow | ||||
|                 if (countSpace.after === 0) { | ||||
|                     context.report({ | ||||
|                         node: tokens.after, | ||||
|                         messageId: "expectedAfter", | ||||
|                         fix(fixer) { | ||||
|                             return fixer.insertTextAfter(tokens.arrow, " "); | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             } else { | ||||
|  | ||||
|                 // should be no space after arrow | ||||
|                 if (countSpace.after > 0) { | ||||
|                     context.report({ | ||||
|                         node: tokens.after, | ||||
|                         messageId: "unexpectedAfter", | ||||
|                         fix(fixer) { | ||||
|                             return fixer.removeRange([tokens.arrow.range[1], tokens.after.range[0]]); | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             ArrowFunctionExpression: spaces | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										135
									
								
								node_modules/eslint/lib/rules/block-scoped-var.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										135
									
								
								node_modules/eslint/lib/rules/block-scoped-var.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,135 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to check for "block scoped" variables by binding context | ||||
|  * @author Matt DuVall <http://www.mattduvall.com> | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce the use of variables within the scope they are defined", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/block-scoped-var" | ||||
|         }, | ||||
|  | ||||
|         schema: [], | ||||
|  | ||||
|         messages: { | ||||
|             outOfScope: "'{{name}}' declared on line {{definitionLine}} column {{definitionColumn}} is used outside of binding context." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         let stack = []; | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         /** | ||||
|          * Makes a block scope. | ||||
|          * @param {ASTNode} node A node of a scope. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function enterScope(node) { | ||||
|             stack.push(node.range); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Pops the last block scope. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function exitScope() { | ||||
|             stack.pop(); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports a given reference. | ||||
|          * @param {eslint-scope.Reference} reference A reference to report. | ||||
|          * @param {eslint-scope.Definition} definition A definition for which to report reference. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function report(reference, definition) { | ||||
|             const identifier = reference.identifier; | ||||
|             const definitionPosition = definition.name.loc.start; | ||||
|  | ||||
|             context.report({ | ||||
|                 node: identifier, | ||||
|                 messageId: "outOfScope", | ||||
|                 data: { | ||||
|                     name: identifier.name, | ||||
|                     definitionLine: definitionPosition.line, | ||||
|                     definitionColumn: definitionPosition.column + 1 | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Finds and reports references which are outside of valid scopes. | ||||
|          * @param {ASTNode} node A node to get variables. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function checkForVariables(node) { | ||||
|             if (node.kind !== "var") { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             // Defines a predicate to check whether or not a given reference is outside of valid scope. | ||||
|             const scopeRange = stack[stack.length - 1]; | ||||
|  | ||||
|             /** | ||||
|              * Check if a reference is out of scope | ||||
|              * @param {ASTNode} reference node to examine | ||||
|              * @returns {boolean} True is its outside the scope | ||||
|              * @private | ||||
|              */ | ||||
|             function isOutsideOfScope(reference) { | ||||
|                 const idRange = reference.identifier.range; | ||||
|  | ||||
|                 return idRange[0] < scopeRange[0] || idRange[1] > scopeRange[1]; | ||||
|             } | ||||
|  | ||||
|             // Gets declared variables, and checks its references. | ||||
|             const variables = sourceCode.getDeclaredVariables(node); | ||||
|  | ||||
|             for (let i = 0; i < variables.length; ++i) { | ||||
|  | ||||
|                 // Reports. | ||||
|                 variables[i] | ||||
|                     .references | ||||
|                     .filter(isOutsideOfScope) | ||||
|                     .forEach(ref => report(ref, variables[i].defs.find(def => def.parent === node))); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             Program(node) { | ||||
|                 stack = [node.range]; | ||||
|             }, | ||||
|  | ||||
|             // Manages scopes. | ||||
|             BlockStatement: enterScope, | ||||
|             "BlockStatement:exit": exitScope, | ||||
|             ForStatement: enterScope, | ||||
|             "ForStatement:exit": exitScope, | ||||
|             ForInStatement: enterScope, | ||||
|             "ForInStatement:exit": exitScope, | ||||
|             ForOfStatement: enterScope, | ||||
|             "ForOfStatement:exit": exitScope, | ||||
|             SwitchStatement: enterScope, | ||||
|             "SwitchStatement:exit": exitScope, | ||||
|             CatchClause: enterScope, | ||||
|             "CatchClause:exit": exitScope, | ||||
|             StaticBlock: enterScope, | ||||
|             "StaticBlock:exit": exitScope, | ||||
|  | ||||
|             // Finds and reports references which are outside of valid scope. | ||||
|             VariableDeclaration: checkForVariables | ||||
|         }; | ||||
|  | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										174
									
								
								node_modules/eslint/lib/rules/block-spacing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								node_modules/eslint/lib/rules/block-spacing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,174 @@ | ||||
| /** | ||||
|  * @fileoverview A rule to disallow or enforce spaces inside of single line blocks. | ||||
|  * @author Toru Nagashima | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| const util = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Disallow or enforce spaces inside of blocks after opening block and before closing block", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/block-spacing" | ||||
|         }, | ||||
|  | ||||
|         fixable: "whitespace", | ||||
|  | ||||
|         schema: [ | ||||
|             { enum: ["always", "never"] } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             missing: "Requires a space {{location}} '{{token}}'.", | ||||
|             extra: "Unexpected space(s) {{location}} '{{token}}'." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const always = (context.options[0] !== "never"), | ||||
|             messageId = always ? "missing" : "extra", | ||||
|             sourceCode = context.sourceCode; | ||||
|  | ||||
|         /** | ||||
|          * Gets the open brace token from a given node. | ||||
|          * @param {ASTNode} node A BlockStatement/StaticBlock/SwitchStatement node to get. | ||||
|          * @returns {Token} The token of the open brace. | ||||
|          */ | ||||
|         function getOpenBrace(node) { | ||||
|             if (node.type === "SwitchStatement") { | ||||
|                 if (node.cases.length > 0) { | ||||
|                     return sourceCode.getTokenBefore(node.cases[0]); | ||||
|                 } | ||||
|                 return sourceCode.getLastToken(node, 1); | ||||
|             } | ||||
|  | ||||
|             if (node.type === "StaticBlock") { | ||||
|                 return sourceCode.getFirstToken(node, { skip: 1 }); // skip the `static` token | ||||
|             } | ||||
|  | ||||
|             // "BlockStatement" | ||||
|             return sourceCode.getFirstToken(node); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks whether or not: | ||||
|          *   - given tokens are on same line. | ||||
|          *   - there is/isn't a space between given tokens. | ||||
|          * @param {Token} left A token to check. | ||||
|          * @param {Token} right The token which is next to `left`. | ||||
|          * @returns {boolean} | ||||
|          *    When the option is `"always"`, `true` if there are one or more spaces between given tokens. | ||||
|          *    When the option is `"never"`, `true` if there are not any spaces between given tokens. | ||||
|          *    If given tokens are not on same line, it's always `true`. | ||||
|          */ | ||||
|         function isValid(left, right) { | ||||
|             return ( | ||||
|                 !util.isTokenOnSameLine(left, right) || | ||||
|                 sourceCode.isSpaceBetweenTokens(left, right) === always | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks and reports invalid spacing style inside braces. | ||||
|          * @param {ASTNode} node A BlockStatement/StaticBlock/SwitchStatement node to check. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function checkSpacingInsideBraces(node) { | ||||
|  | ||||
|             // Gets braces and the first/last token of content. | ||||
|             const openBrace = getOpenBrace(node); | ||||
|             const closeBrace = sourceCode.getLastToken(node); | ||||
|             const firstToken = sourceCode.getTokenAfter(openBrace, { includeComments: true }); | ||||
|             const lastToken = sourceCode.getTokenBefore(closeBrace, { includeComments: true }); | ||||
|  | ||||
|             // Skip if the node is invalid or empty. | ||||
|             if (openBrace.type !== "Punctuator" || | ||||
|                 openBrace.value !== "{" || | ||||
|                 closeBrace.type !== "Punctuator" || | ||||
|                 closeBrace.value !== "}" || | ||||
|                 firstToken === closeBrace | ||||
|             ) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             // Skip line comments for option never | ||||
|             if (!always && firstToken.type === "Line") { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             // Check. | ||||
|             if (!isValid(openBrace, firstToken)) { | ||||
|                 let loc = openBrace.loc; | ||||
|  | ||||
|                 if (messageId === "extra") { | ||||
|                     loc = { | ||||
|                         start: openBrace.loc.end, | ||||
|                         end: firstToken.loc.start | ||||
|                     }; | ||||
|                 } | ||||
|  | ||||
|                 context.report({ | ||||
|                     node, | ||||
|                     loc, | ||||
|                     messageId, | ||||
|                     data: { | ||||
|                         location: "after", | ||||
|                         token: openBrace.value | ||||
|                     }, | ||||
|                     fix(fixer) { | ||||
|                         if (always) { | ||||
|                             return fixer.insertTextBefore(firstToken, " "); | ||||
|                         } | ||||
|  | ||||
|                         return fixer.removeRange([openBrace.range[1], firstToken.range[0]]); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|             if (!isValid(lastToken, closeBrace)) { | ||||
|                 let loc = closeBrace.loc; | ||||
|  | ||||
|                 if (messageId === "extra") { | ||||
|                     loc = { | ||||
|                         start: lastToken.loc.end, | ||||
|                         end: closeBrace.loc.start | ||||
|                     }; | ||||
|                 } | ||||
|                 context.report({ | ||||
|                     node, | ||||
|                     loc, | ||||
|                     messageId, | ||||
|                     data: { | ||||
|                         location: "before", | ||||
|                         token: closeBrace.value | ||||
|                     }, | ||||
|                     fix(fixer) { | ||||
|                         if (always) { | ||||
|                             return fixer.insertTextAfter(lastToken, " "); | ||||
|                         } | ||||
|  | ||||
|                         return fixer.removeRange([lastToken.range[1], closeBrace.range[0]]); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             BlockStatement: checkSpacingInsideBraces, | ||||
|             StaticBlock: checkSpacingInsideBraces, | ||||
|             SwitchStatement: checkSpacingInsideBraces | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										197
									
								
								node_modules/eslint/lib/rules/brace-style.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										197
									
								
								node_modules/eslint/lib/rules/brace-style.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,197 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to flag block statements that do not use the one true brace style | ||||
|  * @author Ian Christian Myers | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce consistent brace style for blocks", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/brace-style" | ||||
|         }, | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 enum: ["1tbs", "stroustrup", "allman"] | ||||
|             }, | ||||
|             { | ||||
|                 type: "object", | ||||
|                 properties: { | ||||
|                     allowSingleLine: { | ||||
|                         type: "boolean", | ||||
|                         default: false | ||||
|                     } | ||||
|                 }, | ||||
|                 additionalProperties: false | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         fixable: "whitespace", | ||||
|  | ||||
|         messages: { | ||||
|             nextLineOpen: "Opening curly brace does not appear on the same line as controlling statement.", | ||||
|             sameLineOpen: "Opening curly brace appears on the same line as controlling statement.", | ||||
|             blockSameLine: "Statement inside of curly braces should be on next line.", | ||||
|             nextLineClose: "Closing curly brace does not appear on the same line as the subsequent block.", | ||||
|             singleLineClose: "Closing curly brace should be on the same line as opening curly brace or on the line after the previous block.", | ||||
|             sameLineClose: "Closing curly brace appears on the same line as the subsequent block." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const style = context.options[0] || "1tbs", | ||||
|             params = context.options[1] || {}, | ||||
|             sourceCode = context.sourceCode; | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Helpers | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         /** | ||||
|          * Fixes a place where a newline unexpectedly appears | ||||
|          * @param {Token} firstToken The token before the unexpected newline | ||||
|          * @param {Token} secondToken The token after the unexpected newline | ||||
|          * @returns {Function} A fixer function to remove the newlines between the tokens | ||||
|          */ | ||||
|         function removeNewlineBetween(firstToken, secondToken) { | ||||
|             const textRange = [firstToken.range[1], secondToken.range[0]]; | ||||
|             const textBetween = sourceCode.text.slice(textRange[0], textRange[1]); | ||||
|  | ||||
|             // Don't do a fix if there is a comment between the tokens | ||||
|             if (textBetween.trim()) { | ||||
|                 return null; | ||||
|             } | ||||
|             return fixer => fixer.replaceTextRange(textRange, " "); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Validates a pair of curly brackets based on the user's config | ||||
|          * @param {Token} openingCurly The opening curly bracket | ||||
|          * @param {Token} closingCurly The closing curly bracket | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function validateCurlyPair(openingCurly, closingCurly) { | ||||
|             const tokenBeforeOpeningCurly = sourceCode.getTokenBefore(openingCurly); | ||||
|             const tokenAfterOpeningCurly = sourceCode.getTokenAfter(openingCurly); | ||||
|             const tokenBeforeClosingCurly = sourceCode.getTokenBefore(closingCurly); | ||||
|             const singleLineException = params.allowSingleLine && astUtils.isTokenOnSameLine(openingCurly, closingCurly); | ||||
|  | ||||
|             if (style !== "allman" && !astUtils.isTokenOnSameLine(tokenBeforeOpeningCurly, openingCurly)) { | ||||
|                 context.report({ | ||||
|                     node: openingCurly, | ||||
|                     messageId: "nextLineOpen", | ||||
|                     fix: removeNewlineBetween(tokenBeforeOpeningCurly, openingCurly) | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             if (style === "allman" && astUtils.isTokenOnSameLine(tokenBeforeOpeningCurly, openingCurly) && !singleLineException) { | ||||
|                 context.report({ | ||||
|                     node: openingCurly, | ||||
|                     messageId: "sameLineOpen", | ||||
|                     fix: fixer => fixer.insertTextBefore(openingCurly, "\n") | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             if (astUtils.isTokenOnSameLine(openingCurly, tokenAfterOpeningCurly) && tokenAfterOpeningCurly !== closingCurly && !singleLineException) { | ||||
|                 context.report({ | ||||
|                     node: openingCurly, | ||||
|                     messageId: "blockSameLine", | ||||
|                     fix: fixer => fixer.insertTextAfter(openingCurly, "\n") | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             if (tokenBeforeClosingCurly !== openingCurly && !singleLineException && astUtils.isTokenOnSameLine(tokenBeforeClosingCurly, closingCurly)) { | ||||
|                 context.report({ | ||||
|                     node: closingCurly, | ||||
|                     messageId: "singleLineClose", | ||||
|                     fix: fixer => fixer.insertTextBefore(closingCurly, "\n") | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Validates the location of a token that appears before a keyword (e.g. a newline before `else`) | ||||
|          * @param {Token} curlyToken The closing curly token. This is assumed to precede a keyword token (such as `else` or `finally`). | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function validateCurlyBeforeKeyword(curlyToken) { | ||||
|             const keywordToken = sourceCode.getTokenAfter(curlyToken); | ||||
|  | ||||
|             if (style === "1tbs" && !astUtils.isTokenOnSameLine(curlyToken, keywordToken)) { | ||||
|                 context.report({ | ||||
|                     node: curlyToken, | ||||
|                     messageId: "nextLineClose", | ||||
|                     fix: removeNewlineBetween(curlyToken, keywordToken) | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             if (style !== "1tbs" && astUtils.isTokenOnSameLine(curlyToken, keywordToken)) { | ||||
|                 context.report({ | ||||
|                     node: curlyToken, | ||||
|                     messageId: "sameLineClose", | ||||
|                     fix: fixer => fixer.insertTextAfter(curlyToken, "\n") | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Public API | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         return { | ||||
|             BlockStatement(node) { | ||||
|                 if (!astUtils.STATEMENT_LIST_PARENTS.has(node.parent.type)) { | ||||
|                     validateCurlyPair(sourceCode.getFirstToken(node), sourceCode.getLastToken(node)); | ||||
|                 } | ||||
|             }, | ||||
|             StaticBlock(node) { | ||||
|                 validateCurlyPair( | ||||
|                     sourceCode.getFirstToken(node, { skip: 1 }), // skip the `static` token | ||||
|                     sourceCode.getLastToken(node) | ||||
|                 ); | ||||
|             }, | ||||
|             ClassBody(node) { | ||||
|                 validateCurlyPair(sourceCode.getFirstToken(node), sourceCode.getLastToken(node)); | ||||
|             }, | ||||
|             SwitchStatement(node) { | ||||
|                 const closingCurly = sourceCode.getLastToken(node); | ||||
|                 const openingCurly = sourceCode.getTokenBefore(node.cases.length ? node.cases[0] : closingCurly); | ||||
|  | ||||
|                 validateCurlyPair(openingCurly, closingCurly); | ||||
|             }, | ||||
|             IfStatement(node) { | ||||
|                 if (node.consequent.type === "BlockStatement" && node.alternate) { | ||||
|  | ||||
|                     // Handle the keyword after the `if` block (before `else`) | ||||
|                     validateCurlyBeforeKeyword(sourceCode.getLastToken(node.consequent)); | ||||
|                 } | ||||
|             }, | ||||
|             TryStatement(node) { | ||||
|  | ||||
|                 // Handle the keyword after the `try` block (before `catch` or `finally`) | ||||
|                 validateCurlyBeforeKeyword(sourceCode.getLastToken(node.block)); | ||||
|  | ||||
|                 if (node.handler && node.finalizer) { | ||||
|  | ||||
|                     // Handle the keyword after the `catch` block (before `finally`) | ||||
|                     validateCurlyBeforeKeyword(sourceCode.getLastToken(node.handler.body)); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										187
									
								
								node_modules/eslint/lib/rules/callback-return.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								node_modules/eslint/lib/rules/callback-return.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,187 @@ | ||||
| /** | ||||
|  * @fileoverview Enforce return after a callback. | ||||
|  * @author Jamund Ferguson | ||||
|  * @deprecated in ESLint v7.0.0 | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|  | ||||
|         replacedBy: [], | ||||
|  | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require `return` statements after callbacks", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/callback-return" | ||||
|         }, | ||||
|  | ||||
|         schema: [{ | ||||
|             type: "array", | ||||
|             items: { type: "string" } | ||||
|         }], | ||||
|  | ||||
|         messages: { | ||||
|             missingReturn: "Expected return with your callback function." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         const callbacks = context.options[0] || ["callback", "cb", "next"], | ||||
|             sourceCode = context.sourceCode; | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Helpers | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         /** | ||||
|          * Find the closest parent matching a list of types. | ||||
|          * @param {ASTNode} node The node whose parents we are searching | ||||
|          * @param {Array} types The node types to match | ||||
|          * @returns {ASTNode} The matched node or undefined. | ||||
|          */ | ||||
|         function findClosestParentOfType(node, types) { | ||||
|             if (!node.parent) { | ||||
|                 return null; | ||||
|             } | ||||
|             if (!types.includes(node.parent.type)) { | ||||
|                 return findClosestParentOfType(node.parent, types); | ||||
|             } | ||||
|             return node.parent; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Check to see if a node contains only identifiers | ||||
|          * @param {ASTNode} node The node to check | ||||
|          * @returns {boolean} Whether or not the node contains only identifiers | ||||
|          */ | ||||
|         function containsOnlyIdentifiers(node) { | ||||
|             if (node.type === "Identifier") { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             if (node.type === "MemberExpression") { | ||||
|                 if (node.object.type === "Identifier") { | ||||
|                     return true; | ||||
|                 } | ||||
|                 if (node.object.type === "MemberExpression") { | ||||
|                     return containsOnlyIdentifiers(node.object); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Check to see if a CallExpression is in our callback list. | ||||
|          * @param {ASTNode} node The node to check against our callback names list. | ||||
|          * @returns {boolean} Whether or not this function matches our callback name. | ||||
|          */ | ||||
|         function isCallback(node) { | ||||
|             return containsOnlyIdentifiers(node.callee) && callbacks.includes(sourceCode.getText(node.callee)); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines whether or not the callback is part of a callback expression. | ||||
|          * @param {ASTNode} node The callback node | ||||
|          * @param {ASTNode} parentNode The expression node | ||||
|          * @returns {boolean} Whether or not this is part of a callback expression | ||||
|          */ | ||||
|         function isCallbackExpression(node, parentNode) { | ||||
|  | ||||
|             // ensure the parent node exists and is an expression | ||||
|             if (!parentNode || parentNode.type !== "ExpressionStatement") { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             // cb() | ||||
|             if (parentNode.expression === node) { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             // special case for cb && cb() and similar | ||||
|             if (parentNode.expression.type === "BinaryExpression" || parentNode.expression.type === "LogicalExpression") { | ||||
|                 if (parentNode.expression.right === node) { | ||||
|                     return true; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Public | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         return { | ||||
|             CallExpression(node) { | ||||
|  | ||||
|                 // if we're not a callback we can return | ||||
|                 if (!isCallback(node)) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // find the closest block, return or loop | ||||
|                 const closestBlock = findClosestParentOfType(node, ["BlockStatement", "ReturnStatement", "ArrowFunctionExpression"]) || {}; | ||||
|  | ||||
|                 // if our parent is a return we know we're ok | ||||
|                 if (closestBlock.type === "ReturnStatement") { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // arrow functions don't always have blocks and implicitly return | ||||
|                 if (closestBlock.type === "ArrowFunctionExpression") { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // block statements are part of functions and most if statements | ||||
|                 if (closestBlock.type === "BlockStatement") { | ||||
|  | ||||
|                     // find the last item in the block | ||||
|                     const lastItem = closestBlock.body[closestBlock.body.length - 1]; | ||||
|  | ||||
|                     // if the callback is the last thing in a block that might be ok | ||||
|                     if (isCallbackExpression(node, lastItem)) { | ||||
|  | ||||
|                         const parentType = closestBlock.parent.type; | ||||
|  | ||||
|                         // but only if the block is part of a function | ||||
|                         if (parentType === "FunctionExpression" || | ||||
|                             parentType === "FunctionDeclaration" || | ||||
|                             parentType === "ArrowFunctionExpression" | ||||
|                         ) { | ||||
|                             return; | ||||
|                         } | ||||
|  | ||||
|                     } | ||||
|  | ||||
|                     // ending a block with a return is also ok | ||||
|                     if (lastItem.type === "ReturnStatement") { | ||||
|  | ||||
|                         // but only if the callback is immediately before | ||||
|                         if (isCallbackExpression(node, closestBlock.body[closestBlock.body.length - 2])) { | ||||
|                             return; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                 } | ||||
|  | ||||
|                 // as long as you're the child of a function at this point you should be asked to return | ||||
|                 if (findClosestParentOfType(node, ["FunctionDeclaration", "FunctionExpression", "ArrowFunctionExpression"])) { | ||||
|                     context.report({ node, messageId: "missingReturn" }); | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|  | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										399
									
								
								node_modules/eslint/lib/rules/camelcase.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										399
									
								
								node_modules/eslint/lib/rules/camelcase.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,399 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to flag non-camelcased identifiers | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce camelcase naming convention", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/camelcase" | ||||
|         }, | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 type: "object", | ||||
|                 properties: { | ||||
|                     ignoreDestructuring: { | ||||
|                         type: "boolean", | ||||
|                         default: false | ||||
|                     }, | ||||
|                     ignoreImports: { | ||||
|                         type: "boolean", | ||||
|                         default: false | ||||
|                     }, | ||||
|                     ignoreGlobals: { | ||||
|                         type: "boolean", | ||||
|                         default: false | ||||
|                     }, | ||||
|                     properties: { | ||||
|                         enum: ["always", "never"] | ||||
|                     }, | ||||
|                     allow: { | ||||
|                         type: "array", | ||||
|                         items: [ | ||||
|                             { | ||||
|                                 type: "string" | ||||
|                             } | ||||
|                         ], | ||||
|                         minItems: 0, | ||||
|                         uniqueItems: true | ||||
|                     } | ||||
|                 }, | ||||
|                 additionalProperties: false | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             notCamelCase: "Identifier '{{name}}' is not in camel case.", | ||||
|             notCamelCasePrivate: "#{{name}} is not in camel case." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const options = context.options[0] || {}; | ||||
|         const properties = options.properties === "never" ? "never" : "always"; | ||||
|         const ignoreDestructuring = options.ignoreDestructuring; | ||||
|         const ignoreImports = options.ignoreImports; | ||||
|         const ignoreGlobals = options.ignoreGlobals; | ||||
|         const allow = options.allow || []; | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Helpers | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         // contains reported nodes to avoid reporting twice on destructuring with shorthand notation | ||||
|         const reported = new Set(); | ||||
|  | ||||
|         /** | ||||
|          * Checks if a string contains an underscore and isn't all upper-case | ||||
|          * @param {string} name The string to check. | ||||
|          * @returns {boolean} if the string is underscored | ||||
|          * @private | ||||
|          */ | ||||
|         function isUnderscored(name) { | ||||
|             const nameBody = name.replace(/^_+|_+$/gu, ""); | ||||
|  | ||||
|             // if there's an underscore, it might be A_CONSTANT, which is okay | ||||
|             return nameBody.includes("_") && nameBody !== nameBody.toUpperCase(); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks if a string match the ignore list | ||||
|          * @param {string} name The string to check. | ||||
|          * @returns {boolean} if the string is ignored | ||||
|          * @private | ||||
|          */ | ||||
|         function isAllowed(name) { | ||||
|             return allow.some( | ||||
|                 entry => name === entry || name.match(new RegExp(entry, "u")) | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks if a given name is good or not. | ||||
|          * @param {string} name The name to check. | ||||
|          * @returns {boolean} `true` if the name is good. | ||||
|          * @private | ||||
|          */ | ||||
|         function isGoodName(name) { | ||||
|             return !isUnderscored(name) || isAllowed(name); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks if a given identifier reference or member expression is an assignment | ||||
|          * target. | ||||
|          * @param {ASTNode} node The node to check. | ||||
|          * @returns {boolean} `true` if the node is an assignment target. | ||||
|          */ | ||||
|         function isAssignmentTarget(node) { | ||||
|             const parent = node.parent; | ||||
|  | ||||
|             switch (parent.type) { | ||||
|                 case "AssignmentExpression": | ||||
|                 case "AssignmentPattern": | ||||
|                     return parent.left === node; | ||||
|  | ||||
|                 case "Property": | ||||
|                     return ( | ||||
|                         parent.parent.type === "ObjectPattern" && | ||||
|                         parent.value === node | ||||
|                     ); | ||||
|                 case "ArrayPattern": | ||||
|                 case "RestElement": | ||||
|                     return true; | ||||
|  | ||||
|                 default: | ||||
|                     return false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks if a given binding identifier uses the original name as-is. | ||||
|          * - If it's in object destructuring or object expression, the original name is its property name. | ||||
|          * - If it's in import declaration, the original name is its exported name. | ||||
|          * @param {ASTNode} node The `Identifier` node to check. | ||||
|          * @returns {boolean} `true` if the identifier uses the original name as-is. | ||||
|          */ | ||||
|         function equalsToOriginalName(node) { | ||||
|             const localName = node.name; | ||||
|             const valueNode = node.parent.type === "AssignmentPattern" | ||||
|                 ? node.parent | ||||
|                 : node; | ||||
|             const parent = valueNode.parent; | ||||
|  | ||||
|             switch (parent.type) { | ||||
|                 case "Property": | ||||
|                     return ( | ||||
|                         (parent.parent.type === "ObjectPattern" || parent.parent.type === "ObjectExpression") && | ||||
|                         parent.value === valueNode && | ||||
|                         !parent.computed && | ||||
|                         parent.key.type === "Identifier" && | ||||
|                         parent.key.name === localName | ||||
|                     ); | ||||
|  | ||||
|                 case "ImportSpecifier": | ||||
|                     return ( | ||||
|                         parent.local === node && | ||||
|                         astUtils.getModuleExportName(parent.imported) === localName | ||||
|                     ); | ||||
|  | ||||
|                 default: | ||||
|                     return false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports an AST node as a rule violation. | ||||
|          * @param {ASTNode} node The node to report. | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function report(node) { | ||||
|             if (reported.has(node.range[0])) { | ||||
|                 return; | ||||
|             } | ||||
|             reported.add(node.range[0]); | ||||
|  | ||||
|             // Report it. | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 messageId: node.type === "PrivateIdentifier" | ||||
|                     ? "notCamelCasePrivate" | ||||
|                     : "notCamelCase", | ||||
|                 data: { name: node.name } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports an identifier reference or a binding identifier. | ||||
|          * @param {ASTNode} node The `Identifier` node to report. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportReferenceId(node) { | ||||
|  | ||||
|             /* | ||||
|              * For backward compatibility, if it's in callings then ignore it. | ||||
|              * Not sure why it is. | ||||
|              */ | ||||
|             if ( | ||||
|                 node.parent.type === "CallExpression" || | ||||
|                 node.parent.type === "NewExpression" | ||||
|             ) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             /* | ||||
|              * For backward compatibility, if it's a default value of | ||||
|              * destructuring/parameters then ignore it. | ||||
|              * Not sure why it is. | ||||
|              */ | ||||
|             if ( | ||||
|                 node.parent.type === "AssignmentPattern" && | ||||
|                 node.parent.right === node | ||||
|             ) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             /* | ||||
|              * The `ignoreDestructuring` flag skips the identifiers that uses | ||||
|              * the property name as-is. | ||||
|              */ | ||||
|             if (ignoreDestructuring && equalsToOriginalName(node)) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             report(node); | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|  | ||||
|             // Report camelcase of global variable references ------------------ | ||||
|             Program(node) { | ||||
|                 const scope = sourceCode.getScope(node); | ||||
|  | ||||
|                 if (!ignoreGlobals) { | ||||
|  | ||||
|                     // Defined globals in config files or directive comments. | ||||
|                     for (const variable of scope.variables) { | ||||
|                         if ( | ||||
|                             variable.identifiers.length > 0 || | ||||
|                             isGoodName(variable.name) | ||||
|                         ) { | ||||
|                             continue; | ||||
|                         } | ||||
|                         for (const reference of variable.references) { | ||||
|  | ||||
|                             /* | ||||
|                              * For backward compatibility, this rule reports read-only | ||||
|                              * references as well. | ||||
|                              */ | ||||
|                             reportReferenceId(reference.identifier); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 // Undefined globals. | ||||
|                 for (const reference of scope.through) { | ||||
|                     const id = reference.identifier; | ||||
|  | ||||
|                     if (isGoodName(id.name)) { | ||||
|                         continue; | ||||
|                     } | ||||
|  | ||||
|                     /* | ||||
|                      * For backward compatibility, this rule reports read-only | ||||
|                      * references as well. | ||||
|                      */ | ||||
|                     reportReferenceId(id); | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             // Report camelcase of declared variables -------------------------- | ||||
|             [[ | ||||
|                 "VariableDeclaration", | ||||
|                 "FunctionDeclaration", | ||||
|                 "FunctionExpression", | ||||
|                 "ArrowFunctionExpression", | ||||
|                 "ClassDeclaration", | ||||
|                 "ClassExpression", | ||||
|                 "CatchClause" | ||||
|             ]](node) { | ||||
|                 for (const variable of sourceCode.getDeclaredVariables(node)) { | ||||
|                     if (isGoodName(variable.name)) { | ||||
|                         continue; | ||||
|                     } | ||||
|                     const id = variable.identifiers[0]; | ||||
|  | ||||
|                     // Report declaration. | ||||
|                     if (!(ignoreDestructuring && equalsToOriginalName(id))) { | ||||
|                         report(id); | ||||
|                     } | ||||
|  | ||||
|                     /* | ||||
|                      * For backward compatibility, report references as well. | ||||
|                      * It looks unnecessary because declarations are reported. | ||||
|                      */ | ||||
|                     for (const reference of variable.references) { | ||||
|                         if (reference.init) { | ||||
|                             continue; // Skip the write references of initializers. | ||||
|                         } | ||||
|                         reportReferenceId(reference.identifier); | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             // Report camelcase in properties ---------------------------------- | ||||
|             [[ | ||||
|                 "ObjectExpression > Property[computed!=true] > Identifier.key", | ||||
|                 "MethodDefinition[computed!=true] > Identifier.key", | ||||
|                 "PropertyDefinition[computed!=true] > Identifier.key", | ||||
|                 "MethodDefinition > PrivateIdentifier.key", | ||||
|                 "PropertyDefinition > PrivateIdentifier.key" | ||||
|             ]](node) { | ||||
|                 if (properties === "never" || isGoodName(node.name)) { | ||||
|                     return; | ||||
|                 } | ||||
|                 report(node); | ||||
|             }, | ||||
|             "MemberExpression[computed!=true] > Identifier.property"(node) { | ||||
|                 if ( | ||||
|                     properties === "never" || | ||||
|                     !isAssignmentTarget(node.parent) || // ← ignore read-only references. | ||||
|                     isGoodName(node.name) | ||||
|                 ) { | ||||
|                     return; | ||||
|                 } | ||||
|                 report(node); | ||||
|             }, | ||||
|  | ||||
|             // Report camelcase in import -------------------------------------- | ||||
|             ImportDeclaration(node) { | ||||
|                 for (const variable of sourceCode.getDeclaredVariables(node)) { | ||||
|                     if (isGoodName(variable.name)) { | ||||
|                         continue; | ||||
|                     } | ||||
|                     const id = variable.identifiers[0]; | ||||
|  | ||||
|                     // Report declaration. | ||||
|                     if (!(ignoreImports && equalsToOriginalName(id))) { | ||||
|                         report(id); | ||||
|                     } | ||||
|  | ||||
|                     /* | ||||
|                      * For backward compatibility, report references as well. | ||||
|                      * It looks unnecessary because declarations are reported. | ||||
|                      */ | ||||
|                     for (const reference of variable.references) { | ||||
|                         reportReferenceId(reference.identifier); | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             // Report camelcase in re-export ----------------------------------- | ||||
|             [[ | ||||
|                 "ExportAllDeclaration > Identifier.exported", | ||||
|                 "ExportSpecifier > Identifier.exported" | ||||
|             ]](node) { | ||||
|                 if (isGoodName(node.name)) { | ||||
|                     return; | ||||
|                 } | ||||
|                 report(node); | ||||
|             }, | ||||
|  | ||||
|             // Report camelcase in labels -------------------------------------- | ||||
|             [[ | ||||
|                 "LabeledStatement > Identifier.label", | ||||
|  | ||||
|                 /* | ||||
|                  * For backward compatibility, report references as well. | ||||
|                  * It looks unnecessary because declarations are reported. | ||||
|                  */ | ||||
|                 "BreakStatement > Identifier.label", | ||||
|                 "ContinueStatement > Identifier.label" | ||||
|             ]](node) { | ||||
|                 if (isGoodName(node.name)) { | ||||
|                     return; | ||||
|                 } | ||||
|                 report(node); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										300
									
								
								node_modules/eslint/lib/rules/capitalized-comments.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										300
									
								
								node_modules/eslint/lib/rules/capitalized-comments.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,300 @@ | ||||
| /** | ||||
|  * @fileoverview enforce or disallow capitalization of the first letter of a comment | ||||
|  * @author Kevin Partington | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const LETTER_PATTERN = require("./utils/patterns/letters"); | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const DEFAULT_IGNORE_PATTERN = astUtils.COMMENTS_IGNORE_PATTERN, | ||||
|     WHITESPACE = /\s/gu, | ||||
|     MAYBE_URL = /^\s*[^:/?#\s]+:\/\/[^?#]/u; // TODO: Combine w/ max-len pattern? | ||||
|  | ||||
| /* | ||||
|  * Base schema body for defining the basic capitalization rule, ignorePattern, | ||||
|  * and ignoreInlineComments values. | ||||
|  * This can be used in a few different ways in the actual schema. | ||||
|  */ | ||||
| const SCHEMA_BODY = { | ||||
|     type: "object", | ||||
|     properties: { | ||||
|         ignorePattern: { | ||||
|             type: "string" | ||||
|         }, | ||||
|         ignoreInlineComments: { | ||||
|             type: "boolean" | ||||
|         }, | ||||
|         ignoreConsecutiveComments: { | ||||
|             type: "boolean" | ||||
|         } | ||||
|     }, | ||||
|     additionalProperties: false | ||||
| }; | ||||
| const DEFAULTS = { | ||||
|     ignorePattern: "", | ||||
|     ignoreInlineComments: false, | ||||
|     ignoreConsecutiveComments: false | ||||
| }; | ||||
|  | ||||
| /** | ||||
|  * Get normalized options for either block or line comments from the given | ||||
|  * user-provided options. | ||||
|  * - If the user-provided options is just a string, returns a normalized | ||||
|  *   set of options using default values for all other options. | ||||
|  * - If the user-provided options is an object, then a normalized option | ||||
|  *   set is returned. Options specified in overrides will take priority | ||||
|  *   over options specified in the main options object, which will in | ||||
|  *   turn take priority over the rule's defaults. | ||||
|  * @param {Object|string} rawOptions The user-provided options. | ||||
|  * @param {string} which Either "line" or "block". | ||||
|  * @returns {Object} The normalized options. | ||||
|  */ | ||||
| function getNormalizedOptions(rawOptions, which) { | ||||
|     return Object.assign({}, DEFAULTS, rawOptions[which] || rawOptions); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Get normalized options for block and line comments. | ||||
|  * @param {Object|string} rawOptions The user-provided options. | ||||
|  * @returns {Object} An object with "Line" and "Block" keys and corresponding | ||||
|  * normalized options objects. | ||||
|  */ | ||||
| function getAllNormalizedOptions(rawOptions = {}) { | ||||
|     return { | ||||
|         Line: getNormalizedOptions(rawOptions, "line"), | ||||
|         Block: getNormalizedOptions(rawOptions, "block") | ||||
|     }; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Creates a regular expression for each ignorePattern defined in the rule | ||||
|  * options. | ||||
|  * | ||||
|  * This is done in order to avoid invoking the RegExp constructor repeatedly. | ||||
|  * @param {Object} normalizedOptions The normalized rule options. | ||||
|  * @returns {void} | ||||
|  */ | ||||
| function createRegExpForIgnorePatterns(normalizedOptions) { | ||||
|     Object.keys(normalizedOptions).forEach(key => { | ||||
|         const ignorePatternStr = normalizedOptions[key].ignorePattern; | ||||
|  | ||||
|         if (ignorePatternStr) { | ||||
|             const regExp = RegExp(`^\\s*(?:${ignorePatternStr})`, "u"); | ||||
|  | ||||
|             normalizedOptions[key].ignorePatternRegExp = regExp; | ||||
|         } | ||||
|     }); | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce or disallow capitalization of the first letter of a comment", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/capitalized-comments" | ||||
|         }, | ||||
|  | ||||
|         fixable: "code", | ||||
|  | ||||
|         schema: [ | ||||
|             { enum: ["always", "never"] }, | ||||
|             { | ||||
|                 oneOf: [ | ||||
|                     SCHEMA_BODY, | ||||
|                     { | ||||
|                         type: "object", | ||||
|                         properties: { | ||||
|                             line: SCHEMA_BODY, | ||||
|                             block: SCHEMA_BODY | ||||
|                         }, | ||||
|                         additionalProperties: false | ||||
|                     } | ||||
|                 ] | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             unexpectedLowercaseComment: "Comments should not begin with a lowercase character.", | ||||
|             unexpectedUppercaseComment: "Comments should not begin with an uppercase character." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         const capitalize = context.options[0] || "always", | ||||
|             normalizedOptions = getAllNormalizedOptions(context.options[1]), | ||||
|             sourceCode = context.sourceCode; | ||||
|  | ||||
|         createRegExpForIgnorePatterns(normalizedOptions); | ||||
|  | ||||
|         //---------------------------------------------------------------------- | ||||
|         // Helpers | ||||
|         //---------------------------------------------------------------------- | ||||
|  | ||||
|         /** | ||||
|          * Checks whether a comment is an inline comment. | ||||
|          * | ||||
|          * For the purpose of this rule, a comment is inline if: | ||||
|          * 1. The comment is preceded by a token on the same line; and | ||||
|          * 2. The command is followed by a token on the same line. | ||||
|          * | ||||
|          * Note that the comment itself need not be single-line! | ||||
|          * | ||||
|          * Also, it follows from this definition that only block comments can | ||||
|          * be considered as possibly inline. This is because line comments | ||||
|          * would consume any following tokens on the same line as the comment. | ||||
|          * @param {ASTNode} comment The comment node to check. | ||||
|          * @returns {boolean} True if the comment is an inline comment, false | ||||
|          * otherwise. | ||||
|          */ | ||||
|         function isInlineComment(comment) { | ||||
|             const previousToken = sourceCode.getTokenBefore(comment, { includeComments: true }), | ||||
|                 nextToken = sourceCode.getTokenAfter(comment, { includeComments: true }); | ||||
|  | ||||
|             return Boolean( | ||||
|                 previousToken && | ||||
|                 nextToken && | ||||
|                 comment.loc.start.line === previousToken.loc.end.line && | ||||
|                 comment.loc.end.line === nextToken.loc.start.line | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determine if a comment follows another comment. | ||||
|          * @param {ASTNode} comment The comment to check. | ||||
|          * @returns {boolean} True if the comment follows a valid comment. | ||||
|          */ | ||||
|         function isConsecutiveComment(comment) { | ||||
|             const previousTokenOrComment = sourceCode.getTokenBefore(comment, { includeComments: true }); | ||||
|  | ||||
|             return Boolean( | ||||
|                 previousTokenOrComment && | ||||
|                 ["Block", "Line"].includes(previousTokenOrComment.type) | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Check a comment to determine if it is valid for this rule. | ||||
|          * @param {ASTNode} comment The comment node to process. | ||||
|          * @param {Object} options The options for checking this comment. | ||||
|          * @returns {boolean} True if the comment is valid, false otherwise. | ||||
|          */ | ||||
|         function isCommentValid(comment, options) { | ||||
|  | ||||
|             // 1. Check for default ignore pattern. | ||||
|             if (DEFAULT_IGNORE_PATTERN.test(comment.value)) { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             // 2. Check for custom ignore pattern. | ||||
|             const commentWithoutAsterisks = comment.value | ||||
|                 .replace(/\*/gu, ""); | ||||
|  | ||||
|             if (options.ignorePatternRegExp && options.ignorePatternRegExp.test(commentWithoutAsterisks)) { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             // 3. Check for inline comments. | ||||
|             if (options.ignoreInlineComments && isInlineComment(comment)) { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             // 4. Is this a consecutive comment (and are we tolerating those)? | ||||
|             if (options.ignoreConsecutiveComments && isConsecutiveComment(comment)) { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             // 5. Does the comment start with a possible URL? | ||||
|             if (MAYBE_URL.test(commentWithoutAsterisks)) { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             // 6. Is the initial word character a letter? | ||||
|             const commentWordCharsOnly = commentWithoutAsterisks | ||||
|                 .replace(WHITESPACE, ""); | ||||
|  | ||||
|             if (commentWordCharsOnly.length === 0) { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             const firstWordChar = commentWordCharsOnly[0]; | ||||
|  | ||||
|             if (!LETTER_PATTERN.test(firstWordChar)) { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             // 7. Check the case of the initial word character. | ||||
|             const isUppercase = firstWordChar !== firstWordChar.toLocaleLowerCase(), | ||||
|                 isLowercase = firstWordChar !== firstWordChar.toLocaleUpperCase(); | ||||
|  | ||||
|             if (capitalize === "always" && isLowercase) { | ||||
|                 return false; | ||||
|             } | ||||
|             if (capitalize === "never" && isUppercase) { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Process a comment to determine if it needs to be reported. | ||||
|          * @param {ASTNode} comment The comment node to process. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function processComment(comment) { | ||||
|             const options = normalizedOptions[comment.type], | ||||
|                 commentValid = isCommentValid(comment, options); | ||||
|  | ||||
|             if (!commentValid) { | ||||
|                 const messageId = capitalize === "always" | ||||
|                     ? "unexpectedLowercaseComment" | ||||
|                     : "unexpectedUppercaseComment"; | ||||
|  | ||||
|                 context.report({ | ||||
|                     node: null, // Intentionally using loc instead | ||||
|                     loc: comment.loc, | ||||
|                     messageId, | ||||
|                     fix(fixer) { | ||||
|                         const match = comment.value.match(LETTER_PATTERN); | ||||
|  | ||||
|                         return fixer.replaceTextRange( | ||||
|  | ||||
|                             // Offset match.index by 2 to account for the first 2 characters that start the comment (// or /*) | ||||
|                             [comment.range[0] + match.index + 2, comment.range[0] + match.index + 3], | ||||
|                             capitalize === "always" ? match[0].toLocaleUpperCase() : match[0].toLocaleLowerCase() | ||||
|                         ); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         //---------------------------------------------------------------------- | ||||
|         // Public | ||||
|         //---------------------------------------------------------------------- | ||||
|  | ||||
|         return { | ||||
|             Program() { | ||||
|                 const comments = sourceCode.getAllComments(); | ||||
|  | ||||
|                 comments.filter(token => token.type !== "Shebang").forEach(processComment); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										187
									
								
								node_modules/eslint/lib/rules/class-methods-use-this.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										187
									
								
								node_modules/eslint/lib/rules/class-methods-use-this.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,187 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to enforce that all class methods use 'this'. | ||||
|  * @author Patrick Williams | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce that class methods utilize `this`", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/class-methods-use-this" | ||||
|         }, | ||||
|  | ||||
|         schema: [{ | ||||
|             type: "object", | ||||
|             properties: { | ||||
|                 exceptMethods: { | ||||
|                     type: "array", | ||||
|                     items: { | ||||
|                         type: "string" | ||||
|                     } | ||||
|                 }, | ||||
|                 enforceForClassFields: { | ||||
|                     type: "boolean", | ||||
|                     default: true | ||||
|                 } | ||||
|             }, | ||||
|             additionalProperties: false | ||||
|         }], | ||||
|  | ||||
|         messages: { | ||||
|             missingThis: "Expected 'this' to be used by class {{name}}." | ||||
|         } | ||||
|     }, | ||||
|     create(context) { | ||||
|         const config = Object.assign({}, context.options[0]); | ||||
|         const enforceForClassFields = config.enforceForClassFields !== false; | ||||
|         const exceptMethods = new Set(config.exceptMethods || []); | ||||
|  | ||||
|         const stack = []; | ||||
|  | ||||
|         /** | ||||
|          * Push `this` used flag initialized with `false` onto the stack. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function pushContext() { | ||||
|             stack.push(false); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Pop `this` used flag from the stack. | ||||
|          * @returns {boolean | undefined} `this` used flag | ||||
|          */ | ||||
|         function popContext() { | ||||
|             return stack.pop(); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Initializes the current context to false and pushes it onto the stack. | ||||
|          * These booleans represent whether 'this' has been used in the context. | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function enterFunction() { | ||||
|             pushContext(); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Check if the node is an instance method | ||||
|          * @param {ASTNode} node node to check | ||||
|          * @returns {boolean} True if its an instance method | ||||
|          * @private | ||||
|          */ | ||||
|         function isInstanceMethod(node) { | ||||
|             switch (node.type) { | ||||
|                 case "MethodDefinition": | ||||
|                     return !node.static && node.kind !== "constructor"; | ||||
|                 case "PropertyDefinition": | ||||
|                     return !node.static && enforceForClassFields; | ||||
|                 default: | ||||
|                     return false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Check if the node is an instance method not excluded by config | ||||
|          * @param {ASTNode} node node to check | ||||
|          * @returns {boolean} True if it is an instance method, and not excluded by config | ||||
|          * @private | ||||
|          */ | ||||
|         function isIncludedInstanceMethod(node) { | ||||
|             if (isInstanceMethod(node)) { | ||||
|                 if (node.computed) { | ||||
|                     return true; | ||||
|                 } | ||||
|  | ||||
|                 const hashIfNeeded = node.key.type === "PrivateIdentifier" ? "#" : ""; | ||||
|                 const name = node.key.type === "Literal" | ||||
|                     ? astUtils.getStaticStringValue(node.key) | ||||
|                     : (node.key.name || ""); | ||||
|  | ||||
|                 return !exceptMethods.has(hashIfNeeded + name); | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks if we are leaving a function that is a method, and reports if 'this' has not been used. | ||||
|          * Static methods and the constructor are exempt. | ||||
|          * Then pops the context off the stack. | ||||
|          * @param {ASTNode} node A function node that was entered. | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function exitFunction(node) { | ||||
|             const methodUsesThis = popContext(); | ||||
|  | ||||
|             if (isIncludedInstanceMethod(node.parent) && !methodUsesThis) { | ||||
|                 context.report({ | ||||
|                     node, | ||||
|                     loc: astUtils.getFunctionHeadLoc(node, context.sourceCode), | ||||
|                     messageId: "missingThis", | ||||
|                     data: { | ||||
|                         name: astUtils.getFunctionNameWithKind(node) | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Mark the current context as having used 'this'. | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function markThisUsed() { | ||||
|             if (stack.length) { | ||||
|                 stack[stack.length - 1] = true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             FunctionDeclaration: enterFunction, | ||||
|             "FunctionDeclaration:exit": exitFunction, | ||||
|             FunctionExpression: enterFunction, | ||||
|             "FunctionExpression:exit": exitFunction, | ||||
|  | ||||
|             /* | ||||
|              * Class field value are implicit functions. | ||||
|              */ | ||||
|             "PropertyDefinition > *.key:exit": pushContext, | ||||
|             "PropertyDefinition:exit": popContext, | ||||
|  | ||||
|             /* | ||||
|              * Class static blocks are implicit functions. They aren't required to use `this`, | ||||
|              * but we have to push context so that it captures any use of `this` in the static block | ||||
|              * separately from enclosing contexts, because static blocks have their own `this` and it | ||||
|              * shouldn't count as used `this` in enclosing contexts. | ||||
|              */ | ||||
|             StaticBlock: pushContext, | ||||
|             "StaticBlock:exit": popContext, | ||||
|  | ||||
|             ThisExpression: markThisUsed, | ||||
|             Super: markThisUsed, | ||||
|             ...( | ||||
|                 enforceForClassFields && { | ||||
|                     "PropertyDefinition > ArrowFunctionExpression.value": enterFunction, | ||||
|                     "PropertyDefinition > ArrowFunctionExpression.value:exit": exitFunction | ||||
|                 } | ||||
|             ) | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										373
									
								
								node_modules/eslint/lib/rules/comma-dangle.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										373
									
								
								node_modules/eslint/lib/rules/comma-dangle.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,373 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to forbid or enforce dangling commas. | ||||
|  * @author Ian Christian Myers | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const DEFAULT_OPTIONS = Object.freeze({ | ||||
|     arrays: "never", | ||||
|     objects: "never", | ||||
|     imports: "never", | ||||
|     exports: "never", | ||||
|     functions: "never" | ||||
| }); | ||||
|  | ||||
| /** | ||||
|  * Checks whether or not a trailing comma is allowed in a given node. | ||||
|  * If the `lastItem` is `RestElement` or `RestProperty`, it disallows trailing commas. | ||||
|  * @param {ASTNode} lastItem The node of the last element in the given node. | ||||
|  * @returns {boolean} `true` if a trailing comma is allowed. | ||||
|  */ | ||||
| function isTrailingCommaAllowed(lastItem) { | ||||
|     return !( | ||||
|         lastItem.type === "RestElement" || | ||||
|         lastItem.type === "RestProperty" || | ||||
|         lastItem.type === "ExperimentalRestProperty" | ||||
|     ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Normalize option value. | ||||
|  * @param {string|Object|undefined} optionValue The 1st option value to normalize. | ||||
|  * @param {number} ecmaVersion The normalized ECMAScript version. | ||||
|  * @returns {Object} The normalized option value. | ||||
|  */ | ||||
| function normalizeOptions(optionValue, ecmaVersion) { | ||||
|     if (typeof optionValue === "string") { | ||||
|         return { | ||||
|             arrays: optionValue, | ||||
|             objects: optionValue, | ||||
|             imports: optionValue, | ||||
|             exports: optionValue, | ||||
|             functions: ecmaVersion < 2017 ? "ignore" : optionValue | ||||
|         }; | ||||
|     } | ||||
|     if (typeof optionValue === "object" && optionValue !== null) { | ||||
|         return { | ||||
|             arrays: optionValue.arrays || DEFAULT_OPTIONS.arrays, | ||||
|             objects: optionValue.objects || DEFAULT_OPTIONS.objects, | ||||
|             imports: optionValue.imports || DEFAULT_OPTIONS.imports, | ||||
|             exports: optionValue.exports || DEFAULT_OPTIONS.exports, | ||||
|             functions: optionValue.functions || DEFAULT_OPTIONS.functions | ||||
|         }; | ||||
|     } | ||||
|  | ||||
|     return DEFAULT_OPTIONS; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require or disallow trailing commas", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/comma-dangle" | ||||
|         }, | ||||
|  | ||||
|         fixable: "code", | ||||
|  | ||||
|         schema: { | ||||
|             definitions: { | ||||
|                 value: { | ||||
|                     enum: [ | ||||
|                         "always-multiline", | ||||
|                         "always", | ||||
|                         "never", | ||||
|                         "only-multiline" | ||||
|                     ] | ||||
|                 }, | ||||
|                 valueWithIgnore: { | ||||
|                     enum: [ | ||||
|                         "always-multiline", | ||||
|                         "always", | ||||
|                         "ignore", | ||||
|                         "never", | ||||
|                         "only-multiline" | ||||
|                     ] | ||||
|                 } | ||||
|             }, | ||||
|             type: "array", | ||||
|             items: [ | ||||
|                 { | ||||
|                     oneOf: [ | ||||
|                         { | ||||
|                             $ref: "#/definitions/value" | ||||
|                         }, | ||||
|                         { | ||||
|                             type: "object", | ||||
|                             properties: { | ||||
|                                 arrays: { $ref: "#/definitions/valueWithIgnore" }, | ||||
|                                 objects: { $ref: "#/definitions/valueWithIgnore" }, | ||||
|                                 imports: { $ref: "#/definitions/valueWithIgnore" }, | ||||
|                                 exports: { $ref: "#/definitions/valueWithIgnore" }, | ||||
|                                 functions: { $ref: "#/definitions/valueWithIgnore" } | ||||
|                             }, | ||||
|                             additionalProperties: false | ||||
|                         } | ||||
|                     ] | ||||
|                 } | ||||
|             ], | ||||
|             additionalItems: false | ||||
|         }, | ||||
|  | ||||
|         messages: { | ||||
|             unexpected: "Unexpected trailing comma.", | ||||
|             missing: "Missing trailing comma." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const options = normalizeOptions(context.options[0], context.languageOptions.ecmaVersion); | ||||
|  | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         /** | ||||
|          * Gets the last item of the given node. | ||||
|          * @param {ASTNode} node The node to get. | ||||
|          * @returns {ASTNode|null} The last node or null. | ||||
|          */ | ||||
|         function getLastItem(node) { | ||||
|  | ||||
|             /** | ||||
|              * Returns the last element of an array | ||||
|              * @param {any[]} array The input array | ||||
|              * @returns {any} The last element | ||||
|              */ | ||||
|             function last(array) { | ||||
|                 return array[array.length - 1]; | ||||
|             } | ||||
|  | ||||
|             switch (node.type) { | ||||
|                 case "ObjectExpression": | ||||
|                 case "ObjectPattern": | ||||
|                     return last(node.properties); | ||||
|                 case "ArrayExpression": | ||||
|                 case "ArrayPattern": | ||||
|                     return last(node.elements); | ||||
|                 case "ImportDeclaration": | ||||
|                 case "ExportNamedDeclaration": | ||||
|                     return last(node.specifiers); | ||||
|                 case "FunctionDeclaration": | ||||
|                 case "FunctionExpression": | ||||
|                 case "ArrowFunctionExpression": | ||||
|                     return last(node.params); | ||||
|                 case "CallExpression": | ||||
|                 case "NewExpression": | ||||
|                     return last(node.arguments); | ||||
|                 default: | ||||
|                     return null; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Gets the trailing comma token of the given node. | ||||
|          * If the trailing comma does not exist, this returns the token which is | ||||
|          * the insertion point of the trailing comma token. | ||||
|          * @param {ASTNode} node The node to get. | ||||
|          * @param {ASTNode} lastItem The last item of the node. | ||||
|          * @returns {Token} The trailing comma token or the insertion point. | ||||
|          */ | ||||
|         function getTrailingToken(node, lastItem) { | ||||
|             switch (node.type) { | ||||
|                 case "ObjectExpression": | ||||
|                 case "ArrayExpression": | ||||
|                 case "CallExpression": | ||||
|                 case "NewExpression": | ||||
|                     return sourceCode.getLastToken(node, 1); | ||||
|                 default: { | ||||
|                     const nextToken = sourceCode.getTokenAfter(lastItem); | ||||
|  | ||||
|                     if (astUtils.isCommaToken(nextToken)) { | ||||
|                         return nextToken; | ||||
|                     } | ||||
|                     return sourceCode.getLastToken(lastItem); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks whether or not a given node is multiline. | ||||
|          * This rule handles a given node as multiline when the closing parenthesis | ||||
|          * and the last element are not on the same line. | ||||
|          * @param {ASTNode} node A node to check. | ||||
|          * @returns {boolean} `true` if the node is multiline. | ||||
|          */ | ||||
|         function isMultiline(node) { | ||||
|             const lastItem = getLastItem(node); | ||||
|  | ||||
|             if (!lastItem) { | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             const penultimateToken = getTrailingToken(node, lastItem); | ||||
|             const lastToken = sourceCode.getTokenAfter(penultimateToken); | ||||
|  | ||||
|             return lastToken.loc.end.line !== penultimateToken.loc.end.line; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports a trailing comma if it exists. | ||||
|          * @param {ASTNode} node A node to check. Its type is one of | ||||
|          *   ObjectExpression, ObjectPattern, ArrayExpression, ArrayPattern, | ||||
|          *   ImportDeclaration, and ExportNamedDeclaration. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function forbidTrailingComma(node) { | ||||
|             const lastItem = getLastItem(node); | ||||
|  | ||||
|             if (!lastItem || (node.type === "ImportDeclaration" && lastItem.type !== "ImportSpecifier")) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             const trailingToken = getTrailingToken(node, lastItem); | ||||
|  | ||||
|             if (astUtils.isCommaToken(trailingToken)) { | ||||
|                 context.report({ | ||||
|                     node: lastItem, | ||||
|                     loc: trailingToken.loc, | ||||
|                     messageId: "unexpected", | ||||
|                     *fix(fixer) { | ||||
|                         yield fixer.remove(trailingToken); | ||||
|  | ||||
|                         /* | ||||
|                          * Extend the range of the fix to include surrounding tokens to ensure | ||||
|                          * that the element after which the comma is removed stays _last_. | ||||
|                          * This intentionally makes conflicts in fix ranges with rules that may be | ||||
|                          * adding or removing elements in the same autofix pass. | ||||
|                          * https://github.com/eslint/eslint/issues/15660 | ||||
|                          */ | ||||
|                         yield fixer.insertTextBefore(sourceCode.getTokenBefore(trailingToken), ""); | ||||
|                         yield fixer.insertTextAfter(sourceCode.getTokenAfter(trailingToken), ""); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports the last element of a given node if it does not have a trailing | ||||
|          * comma. | ||||
|          * | ||||
|          * If a given node is `ArrayPattern` which has `RestElement`, the trailing | ||||
|          * comma is disallowed, so report if it exists. | ||||
|          * @param {ASTNode} node A node to check. Its type is one of | ||||
|          *   ObjectExpression, ObjectPattern, ArrayExpression, ArrayPattern, | ||||
|          *   ImportDeclaration, and ExportNamedDeclaration. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function forceTrailingComma(node) { | ||||
|             const lastItem = getLastItem(node); | ||||
|  | ||||
|             if (!lastItem || (node.type === "ImportDeclaration" && lastItem.type !== "ImportSpecifier")) { | ||||
|                 return; | ||||
|             } | ||||
|             if (!isTrailingCommaAllowed(lastItem)) { | ||||
|                 forbidTrailingComma(node); | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             const trailingToken = getTrailingToken(node, lastItem); | ||||
|  | ||||
|             if (trailingToken.value !== ",") { | ||||
|                 context.report({ | ||||
|                     node: lastItem, | ||||
|                     loc: { | ||||
|                         start: trailingToken.loc.end, | ||||
|                         end: astUtils.getNextLocation(sourceCode, trailingToken.loc.end) | ||||
|                     }, | ||||
|                     messageId: "missing", | ||||
|                     *fix(fixer) { | ||||
|                         yield fixer.insertTextAfter(trailingToken, ","); | ||||
|  | ||||
|                         /* | ||||
|                          * Extend the range of the fix to include surrounding tokens to ensure | ||||
|                          * that the element after which the comma is inserted stays _last_. | ||||
|                          * This intentionally makes conflicts in fix ranges with rules that may be | ||||
|                          * adding or removing elements in the same autofix pass. | ||||
|                          * https://github.com/eslint/eslint/issues/15660 | ||||
|                          */ | ||||
|                         yield fixer.insertTextBefore(trailingToken, ""); | ||||
|                         yield fixer.insertTextAfter(sourceCode.getTokenAfter(trailingToken), ""); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * If a given node is multiline, reports the last element of a given node | ||||
|          * when it does not have a trailing comma. | ||||
|          * Otherwise, reports a trailing comma if it exists. | ||||
|          * @param {ASTNode} node A node to check. Its type is one of | ||||
|          *   ObjectExpression, ObjectPattern, ArrayExpression, ArrayPattern, | ||||
|          *   ImportDeclaration, and ExportNamedDeclaration. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function forceTrailingCommaIfMultiline(node) { | ||||
|             if (isMultiline(node)) { | ||||
|                 forceTrailingComma(node); | ||||
|             } else { | ||||
|                 forbidTrailingComma(node); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Only if a given node is not multiline, reports the last element of a given node | ||||
|          * when it does not have a trailing comma. | ||||
|          * Otherwise, reports a trailing comma if it exists. | ||||
|          * @param {ASTNode} node A node to check. Its type is one of | ||||
|          *   ObjectExpression, ObjectPattern, ArrayExpression, ArrayPattern, | ||||
|          *   ImportDeclaration, and ExportNamedDeclaration. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function allowTrailingCommaIfMultiline(node) { | ||||
|             if (!isMultiline(node)) { | ||||
|                 forbidTrailingComma(node); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         const predicate = { | ||||
|             always: forceTrailingComma, | ||||
|             "always-multiline": forceTrailingCommaIfMultiline, | ||||
|             "only-multiline": allowTrailingCommaIfMultiline, | ||||
|             never: forbidTrailingComma, | ||||
|             ignore() {} | ||||
|         }; | ||||
|  | ||||
|         return { | ||||
|             ObjectExpression: predicate[options.objects], | ||||
|             ObjectPattern: predicate[options.objects], | ||||
|  | ||||
|             ArrayExpression: predicate[options.arrays], | ||||
|             ArrayPattern: predicate[options.arrays], | ||||
|  | ||||
|             ImportDeclaration: predicate[options.imports], | ||||
|  | ||||
|             ExportNamedDeclaration: predicate[options.exports], | ||||
|  | ||||
|             FunctionDeclaration: predicate[options.functions], | ||||
|             FunctionExpression: predicate[options.functions], | ||||
|             ArrowFunctionExpression: predicate[options.functions], | ||||
|             CallExpression: predicate[options.functions], | ||||
|             NewExpression: predicate[options.functions] | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										192
									
								
								node_modules/eslint/lib/rules/comma-spacing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										192
									
								
								node_modules/eslint/lib/rules/comma-spacing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,192 @@ | ||||
| /** | ||||
|  * @fileoverview Comma spacing - validates spacing before and after comma | ||||
|  * @author Vignesh Anand aka vegetableman. | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce consistent spacing before and after commas", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/comma-spacing" | ||||
|         }, | ||||
|  | ||||
|         fixable: "whitespace", | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 type: "object", | ||||
|                 properties: { | ||||
|                     before: { | ||||
|                         type: "boolean", | ||||
|                         default: false | ||||
|                     }, | ||||
|                     after: { | ||||
|                         type: "boolean", | ||||
|                         default: true | ||||
|                     } | ||||
|                 }, | ||||
|                 additionalProperties: false | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             missing: "A space is required {{loc}} ','.", | ||||
|             unexpected: "There should be no space {{loc}} ','." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         const sourceCode = context.sourceCode; | ||||
|         const tokensAndComments = sourceCode.tokensAndComments; | ||||
|  | ||||
|         const options = { | ||||
|             before: context.options[0] ? context.options[0].before : false, | ||||
|             after: context.options[0] ? context.options[0].after : true | ||||
|         }; | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Helpers | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         // list of comma tokens to ignore for the check of leading whitespace | ||||
|         const commaTokensToIgnore = []; | ||||
|  | ||||
|         /** | ||||
|          * Reports a spacing error with an appropriate message. | ||||
|          * @param {ASTNode} node The binary expression node to report. | ||||
|          * @param {string} loc Is the error "before" or "after" the comma? | ||||
|          * @param {ASTNode} otherNode The node at the left or right of `node` | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function report(node, loc, otherNode) { | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 fix(fixer) { | ||||
|                     if (options[loc]) { | ||||
|                         if (loc === "before") { | ||||
|                             return fixer.insertTextBefore(node, " "); | ||||
|                         } | ||||
|                         return fixer.insertTextAfter(node, " "); | ||||
|  | ||||
|                     } | ||||
|                     let start, end; | ||||
|                     const newText = ""; | ||||
|  | ||||
|                     if (loc === "before") { | ||||
|                         start = otherNode.range[1]; | ||||
|                         end = node.range[0]; | ||||
|                     } else { | ||||
|                         start = node.range[1]; | ||||
|                         end = otherNode.range[0]; | ||||
|                     } | ||||
|  | ||||
|                     return fixer.replaceTextRange([start, end], newText); | ||||
|  | ||||
|                 }, | ||||
|                 messageId: options[loc] ? "missing" : "unexpected", | ||||
|                 data: { | ||||
|                     loc | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Adds null elements of the given ArrayExpression or ArrayPattern node to the ignore list. | ||||
|          * @param {ASTNode} node An ArrayExpression or ArrayPattern node. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function addNullElementsToIgnoreList(node) { | ||||
|             let previousToken = sourceCode.getFirstToken(node); | ||||
|  | ||||
|             node.elements.forEach(element => { | ||||
|                 let token; | ||||
|  | ||||
|                 if (element === null) { | ||||
|                     token = sourceCode.getTokenAfter(previousToken); | ||||
|  | ||||
|                     if (astUtils.isCommaToken(token)) { | ||||
|                         commaTokensToIgnore.push(token); | ||||
|                     } | ||||
|                 } else { | ||||
|                     token = sourceCode.getTokenAfter(element); | ||||
|                 } | ||||
|  | ||||
|                 previousToken = token; | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Public | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         return { | ||||
|             "Program:exit"() { | ||||
|                 tokensAndComments.forEach((token, i) => { | ||||
|  | ||||
|                     if (!astUtils.isCommaToken(token)) { | ||||
|                         return; | ||||
|                     } | ||||
|  | ||||
|                     const previousToken = tokensAndComments[i - 1]; | ||||
|                     const nextToken = tokensAndComments[i + 1]; | ||||
|  | ||||
|                     if ( | ||||
|                         previousToken && | ||||
|                         !astUtils.isCommaToken(previousToken) && // ignore spacing between two commas | ||||
|  | ||||
|                         /* | ||||
|                          * `commaTokensToIgnore` are ending commas of `null` elements (array holes/elisions). | ||||
|                          * In addition to spacing between two commas, this can also ignore: | ||||
|                          * | ||||
|                          *   - Spacing after `[` (controlled by array-bracket-spacing) | ||||
|                          *       Example: [ , ] | ||||
|                          *                 ^ | ||||
|                          *   - Spacing after a comment (for backwards compatibility, this was possibly unintentional) | ||||
|                          *       Example: [a, /* * / ,] | ||||
|                          *                          ^ | ||||
|                          */ | ||||
|                         !commaTokensToIgnore.includes(token) && | ||||
|  | ||||
|                         astUtils.isTokenOnSameLine(previousToken, token) && | ||||
|                         options.before !== sourceCode.isSpaceBetweenTokens(previousToken, token) | ||||
|                     ) { | ||||
|                         report(token, "before", previousToken); | ||||
|                     } | ||||
|  | ||||
|                     if ( | ||||
|                         nextToken && | ||||
|                         !astUtils.isCommaToken(nextToken) && // ignore spacing between two commas | ||||
|                         !astUtils.isClosingParenToken(nextToken) && // controlled by space-in-parens | ||||
|                         !astUtils.isClosingBracketToken(nextToken) && // controlled by array-bracket-spacing | ||||
|                         !astUtils.isClosingBraceToken(nextToken) && // controlled by object-curly-spacing | ||||
|                         !(!options.after && nextToken.type === "Line") && // special case, allow space before line comment | ||||
|                         astUtils.isTokenOnSameLine(token, nextToken) && | ||||
|                         options.after !== sourceCode.isSpaceBetweenTokens(token, nextToken) | ||||
|                     ) { | ||||
|                         report(token, "after", nextToken); | ||||
|                     } | ||||
|                 }); | ||||
|             }, | ||||
|             ArrayExpression: addNullElementsToIgnoreList, | ||||
|             ArrayPattern: addNullElementsToIgnoreList | ||||
|  | ||||
|         }; | ||||
|  | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										314
									
								
								node_modules/eslint/lib/rules/comma-style.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										314
									
								
								node_modules/eslint/lib/rules/comma-style.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,314 @@ | ||||
| /** | ||||
|  * @fileoverview Comma style - enforces comma styles of two types: last and first | ||||
|  * @author Vignesh Anand aka vegetableman | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce consistent comma style", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/comma-style" | ||||
|         }, | ||||
|  | ||||
|         fixable: "code", | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 enum: ["first", "last"] | ||||
|             }, | ||||
|             { | ||||
|                 type: "object", | ||||
|                 properties: { | ||||
|                     exceptions: { | ||||
|                         type: "object", | ||||
|                         additionalProperties: { | ||||
|                             type: "boolean" | ||||
|                         } | ||||
|                     } | ||||
|                 }, | ||||
|                 additionalProperties: false | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             unexpectedLineBeforeAndAfterComma: "Bad line breaking before and after ','.", | ||||
|             expectedCommaFirst: "',' should be placed first.", | ||||
|             expectedCommaLast: "',' should be placed last." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const style = context.options[0] || "last", | ||||
|             sourceCode = context.sourceCode; | ||||
|         const exceptions = { | ||||
|             ArrayPattern: true, | ||||
|             ArrowFunctionExpression: true, | ||||
|             CallExpression: true, | ||||
|             FunctionDeclaration: true, | ||||
|             FunctionExpression: true, | ||||
|             ImportDeclaration: true, | ||||
|             ObjectPattern: true, | ||||
|             NewExpression: true | ||||
|         }; | ||||
|  | ||||
|         if (context.options.length === 2 && Object.prototype.hasOwnProperty.call(context.options[1], "exceptions")) { | ||||
|             const keys = Object.keys(context.options[1].exceptions); | ||||
|  | ||||
|             for (let i = 0; i < keys.length; i++) { | ||||
|                 exceptions[keys[i]] = context.options[1].exceptions[keys[i]]; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Helpers | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         /** | ||||
|          * Modified text based on the style | ||||
|          * @param {string} styleType Style type | ||||
|          * @param {string} text Source code text | ||||
|          * @returns {string} modified text | ||||
|          * @private | ||||
|          */ | ||||
|         function getReplacedText(styleType, text) { | ||||
|             switch (styleType) { | ||||
|                 case "between": | ||||
|                     return `,${text.replace(astUtils.LINEBREAK_MATCHER, "")}`; | ||||
|  | ||||
|                 case "first": | ||||
|                     return `${text},`; | ||||
|  | ||||
|                 case "last": | ||||
|                     return `,${text}`; | ||||
|  | ||||
|                 default: | ||||
|                     return ""; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines the fixer function for a given style. | ||||
|          * @param {string} styleType comma style | ||||
|          * @param {ASTNode} previousItemToken The token to check. | ||||
|          * @param {ASTNode} commaToken The token to check. | ||||
|          * @param {ASTNode} currentItemToken The token to check. | ||||
|          * @returns {Function} Fixer function | ||||
|          * @private | ||||
|          */ | ||||
|         function getFixerFunction(styleType, previousItemToken, commaToken, currentItemToken) { | ||||
|             const text = | ||||
|                 sourceCode.text.slice(previousItemToken.range[1], commaToken.range[0]) + | ||||
|                 sourceCode.text.slice(commaToken.range[1], currentItemToken.range[0]); | ||||
|             const range = [previousItemToken.range[1], currentItemToken.range[0]]; | ||||
|  | ||||
|             return function(fixer) { | ||||
|                 return fixer.replaceTextRange(range, getReplacedText(styleType, text)); | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Validates the spacing around single items in lists. | ||||
|          * @param {Token} previousItemToken The last token from the previous item. | ||||
|          * @param {Token} commaToken The token representing the comma. | ||||
|          * @param {Token} currentItemToken The first token of the current item. | ||||
|          * @param {Token} reportItem The item to use when reporting an error. | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function validateCommaItemSpacing(previousItemToken, commaToken, currentItemToken, reportItem) { | ||||
|  | ||||
|             // if single line | ||||
|             if (astUtils.isTokenOnSameLine(commaToken, currentItemToken) && | ||||
|                     astUtils.isTokenOnSameLine(previousItemToken, commaToken)) { | ||||
|  | ||||
|                 // do nothing. | ||||
|  | ||||
|             } else if (!astUtils.isTokenOnSameLine(commaToken, currentItemToken) && | ||||
|                     !astUtils.isTokenOnSameLine(previousItemToken, commaToken)) { | ||||
|  | ||||
|                 const comment = sourceCode.getCommentsAfter(commaToken)[0]; | ||||
|                 const styleType = comment && comment.type === "Block" && astUtils.isTokenOnSameLine(commaToken, comment) | ||||
|                     ? style | ||||
|                     : "between"; | ||||
|  | ||||
|                 // lone comma | ||||
|                 context.report({ | ||||
|                     node: reportItem, | ||||
|                     loc: commaToken.loc, | ||||
|                     messageId: "unexpectedLineBeforeAndAfterComma", | ||||
|                     fix: getFixerFunction(styleType, previousItemToken, commaToken, currentItemToken) | ||||
|                 }); | ||||
|  | ||||
|             } else if (style === "first" && !astUtils.isTokenOnSameLine(commaToken, currentItemToken)) { | ||||
|  | ||||
|                 context.report({ | ||||
|                     node: reportItem, | ||||
|                     loc: commaToken.loc, | ||||
|                     messageId: "expectedCommaFirst", | ||||
|                     fix: getFixerFunction(style, previousItemToken, commaToken, currentItemToken) | ||||
|                 }); | ||||
|  | ||||
|             } else if (style === "last" && astUtils.isTokenOnSameLine(commaToken, currentItemToken)) { | ||||
|  | ||||
|                 context.report({ | ||||
|                     node: reportItem, | ||||
|                     loc: commaToken.loc, | ||||
|                     messageId: "expectedCommaLast", | ||||
|                     fix: getFixerFunction(style, previousItemToken, commaToken, currentItemToken) | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks the comma placement with regards to a declaration/property/element | ||||
|          * @param {ASTNode} node The binary expression node to check | ||||
|          * @param {string} property The property of the node containing child nodes. | ||||
|          * @private | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function validateComma(node, property) { | ||||
|             const items = node[property], | ||||
|                 arrayLiteral = (node.type === "ArrayExpression" || node.type === "ArrayPattern"); | ||||
|  | ||||
|             if (items.length > 1 || arrayLiteral) { | ||||
|  | ||||
|                 // seed as opening [ | ||||
|                 let previousItemToken = sourceCode.getFirstToken(node); | ||||
|  | ||||
|                 items.forEach(item => { | ||||
|                     const commaToken = item ? sourceCode.getTokenBefore(item) : previousItemToken, | ||||
|                         currentItemToken = item ? sourceCode.getFirstToken(item) : sourceCode.getTokenAfter(commaToken), | ||||
|                         reportItem = item || currentItemToken; | ||||
|  | ||||
|                     /* | ||||
|                      * This works by comparing three token locations: | ||||
|                      * - previousItemToken is the last token of the previous item | ||||
|                      * - commaToken is the location of the comma before the current item | ||||
|                      * - currentItemToken is the first token of the current item | ||||
|                      * | ||||
|                      * These values get switched around if item is undefined. | ||||
|                      * previousItemToken will refer to the last token not belonging | ||||
|                      * to the current item, which could be a comma or an opening | ||||
|                      * square bracket. currentItemToken could be a comma. | ||||
|                      * | ||||
|                      * All comparisons are done based on these tokens directly, so | ||||
|                      * they are always valid regardless of an undefined item. | ||||
|                      */ | ||||
|                     if (astUtils.isCommaToken(commaToken)) { | ||||
|                         validateCommaItemSpacing(previousItemToken, commaToken, currentItemToken, reportItem); | ||||
|                     } | ||||
|  | ||||
|                     if (item) { | ||||
|                         const tokenAfterItem = sourceCode.getTokenAfter(item, astUtils.isNotClosingParenToken); | ||||
|  | ||||
|                         previousItemToken = tokenAfterItem | ||||
|                             ? sourceCode.getTokenBefore(tokenAfterItem) | ||||
|                             : sourceCode.ast.tokens[sourceCode.ast.tokens.length - 1]; | ||||
|                     } else { | ||||
|                         previousItemToken = currentItemToken; | ||||
|                     } | ||||
|                 }); | ||||
|  | ||||
|                 /* | ||||
|                  * Special case for array literals that have empty last items, such | ||||
|                  * as [ 1, 2, ]. These arrays only have two items show up in the | ||||
|                  * AST, so we need to look at the token to verify that there's no | ||||
|                  * dangling comma. | ||||
|                  */ | ||||
|                 if (arrayLiteral) { | ||||
|  | ||||
|                     const lastToken = sourceCode.getLastToken(node), | ||||
|                         nextToLastToken = sourceCode.getTokenBefore(lastToken); | ||||
|  | ||||
|                     if (astUtils.isCommaToken(nextToLastToken)) { | ||||
|                         validateCommaItemSpacing( | ||||
|                             sourceCode.getTokenBefore(nextToLastToken), | ||||
|                             nextToLastToken, | ||||
|                             lastToken, | ||||
|                             lastToken | ||||
|                         ); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Public | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         const nodes = {}; | ||||
|  | ||||
|         if (!exceptions.VariableDeclaration) { | ||||
|             nodes.VariableDeclaration = function(node) { | ||||
|                 validateComma(node, "declarations"); | ||||
|             }; | ||||
|         } | ||||
|         if (!exceptions.ObjectExpression) { | ||||
|             nodes.ObjectExpression = function(node) { | ||||
|                 validateComma(node, "properties"); | ||||
|             }; | ||||
|         } | ||||
|         if (!exceptions.ObjectPattern) { | ||||
|             nodes.ObjectPattern = function(node) { | ||||
|                 validateComma(node, "properties"); | ||||
|             }; | ||||
|         } | ||||
|         if (!exceptions.ArrayExpression) { | ||||
|             nodes.ArrayExpression = function(node) { | ||||
|                 validateComma(node, "elements"); | ||||
|             }; | ||||
|         } | ||||
|         if (!exceptions.ArrayPattern) { | ||||
|             nodes.ArrayPattern = function(node) { | ||||
|                 validateComma(node, "elements"); | ||||
|             }; | ||||
|         } | ||||
|         if (!exceptions.FunctionDeclaration) { | ||||
|             nodes.FunctionDeclaration = function(node) { | ||||
|                 validateComma(node, "params"); | ||||
|             }; | ||||
|         } | ||||
|         if (!exceptions.FunctionExpression) { | ||||
|             nodes.FunctionExpression = function(node) { | ||||
|                 validateComma(node, "params"); | ||||
|             }; | ||||
|         } | ||||
|         if (!exceptions.ArrowFunctionExpression) { | ||||
|             nodes.ArrowFunctionExpression = function(node) { | ||||
|                 validateComma(node, "params"); | ||||
|             }; | ||||
|         } | ||||
|         if (!exceptions.CallExpression) { | ||||
|             nodes.CallExpression = function(node) { | ||||
|                 validateComma(node, "arguments"); | ||||
|             }; | ||||
|         } | ||||
|         if (!exceptions.ImportDeclaration) { | ||||
|             nodes.ImportDeclaration = function(node) { | ||||
|                 validateComma(node, "specifiers"); | ||||
|             }; | ||||
|         } | ||||
|         if (!exceptions.NewExpression) { | ||||
|             nodes.NewExpression = function(node) { | ||||
|                 validateComma(node, "arguments"); | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         return nodes; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										165
									
								
								node_modules/eslint/lib/rules/complexity.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										165
									
								
								node_modules/eslint/lib/rules/complexity.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,165 @@ | ||||
| /** | ||||
|  * @fileoverview Counts the cyclomatic complexity of each function of the script. See http://en.wikipedia.org/wiki/Cyclomatic_complexity. | ||||
|  * Counts the number of if, conditional, for, while, try, switch/case, | ||||
|  * @author Patrick Brosset | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
| const { upperCaseFirst } = require("../shared/string-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce a maximum cyclomatic complexity allowed in a program", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/complexity" | ||||
|         }, | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 oneOf: [ | ||||
|                     { | ||||
|                         type: "integer", | ||||
|                         minimum: 0 | ||||
|                     }, | ||||
|                     { | ||||
|                         type: "object", | ||||
|                         properties: { | ||||
|                             maximum: { | ||||
|                                 type: "integer", | ||||
|                                 minimum: 0 | ||||
|                             }, | ||||
|                             max: { | ||||
|                                 type: "integer", | ||||
|                                 minimum: 0 | ||||
|                             } | ||||
|                         }, | ||||
|                         additionalProperties: false | ||||
|                     } | ||||
|                 ] | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             complex: "{{name}} has a complexity of {{complexity}}. Maximum allowed is {{max}}." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const option = context.options[0]; | ||||
|         let THRESHOLD = 20; | ||||
|  | ||||
|         if ( | ||||
|             typeof option === "object" && | ||||
|             (Object.prototype.hasOwnProperty.call(option, "maximum") || Object.prototype.hasOwnProperty.call(option, "max")) | ||||
|         ) { | ||||
|             THRESHOLD = option.maximum || option.max; | ||||
|         } else if (typeof option === "number") { | ||||
|             THRESHOLD = option; | ||||
|         } | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Helpers | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         // Using a stack to store complexity per code path | ||||
|         const complexities = []; | ||||
|  | ||||
|         /** | ||||
|          * Increase the complexity of the code path in context | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function increaseComplexity() { | ||||
|             complexities[complexities.length - 1]++; | ||||
|         } | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Public API | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         return { | ||||
|  | ||||
|             onCodePathStart() { | ||||
|  | ||||
|                 // The initial complexity is 1, representing one execution path in the CodePath | ||||
|                 complexities.push(1); | ||||
|             }, | ||||
|  | ||||
|             // Each branching in the code adds 1 to the complexity | ||||
|             CatchClause: increaseComplexity, | ||||
|             ConditionalExpression: increaseComplexity, | ||||
|             LogicalExpression: increaseComplexity, | ||||
|             ForStatement: increaseComplexity, | ||||
|             ForInStatement: increaseComplexity, | ||||
|             ForOfStatement: increaseComplexity, | ||||
|             IfStatement: increaseComplexity, | ||||
|             WhileStatement: increaseComplexity, | ||||
|             DoWhileStatement: increaseComplexity, | ||||
|  | ||||
|             // Avoid `default` | ||||
|             "SwitchCase[test]": increaseComplexity, | ||||
|  | ||||
|             // Logical assignment operators have short-circuiting behavior | ||||
|             AssignmentExpression(node) { | ||||
|                 if (astUtils.isLogicalAssignmentOperator(node.operator)) { | ||||
|                     increaseComplexity(); | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             onCodePathEnd(codePath, node) { | ||||
|                 const complexity = complexities.pop(); | ||||
|  | ||||
|                 /* | ||||
|                  * This rule only evaluates complexity of functions, so "program" is excluded. | ||||
|                  * Class field initializers and class static blocks are implicit functions. Therefore, | ||||
|                  * they shouldn't contribute to the enclosing function's complexity, but their | ||||
|                  * own complexity should be evaluated. | ||||
|                  */ | ||||
|                 if ( | ||||
|                     codePath.origin !== "function" && | ||||
|                     codePath.origin !== "class-field-initializer" && | ||||
|                     codePath.origin !== "class-static-block" | ||||
|                 ) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 if (complexity > THRESHOLD) { | ||||
|                     let name; | ||||
|  | ||||
|                     if (codePath.origin === "class-field-initializer") { | ||||
|                         name = "class field initializer"; | ||||
|                     } else if (codePath.origin === "class-static-block") { | ||||
|                         name = "class static block"; | ||||
|                     } else { | ||||
|                         name = astUtils.getFunctionNameWithKind(node); | ||||
|                     } | ||||
|  | ||||
|                     context.report({ | ||||
|                         node, | ||||
|                         messageId: "complex", | ||||
|                         data: { | ||||
|                             name: upperCaseFirst(name), | ||||
|                             complexity, | ||||
|                             max: THRESHOLD | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										208
									
								
								node_modules/eslint/lib/rules/computed-property-spacing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										208
									
								
								node_modules/eslint/lib/rules/computed-property-spacing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,208 @@ | ||||
| /** | ||||
|  * @fileoverview Disallows or enforces spaces inside computed properties. | ||||
|  * @author Jamund Ferguson | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce consistent spacing inside computed property brackets", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/computed-property-spacing" | ||||
|         }, | ||||
|  | ||||
|         fixable: "whitespace", | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 enum: ["always", "never"] | ||||
|             }, | ||||
|             { | ||||
|                 type: "object", | ||||
|                 properties: { | ||||
|                     enforceForClassMembers: { | ||||
|                         type: "boolean", | ||||
|                         default: true | ||||
|                     } | ||||
|                 }, | ||||
|                 additionalProperties: false | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             unexpectedSpaceBefore: "There should be no space before '{{tokenValue}}'.", | ||||
|             unexpectedSpaceAfter: "There should be no space after '{{tokenValue}}'.", | ||||
|  | ||||
|             missingSpaceBefore: "A space is required before '{{tokenValue}}'.", | ||||
|             missingSpaceAfter: "A space is required after '{{tokenValue}}'." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const sourceCode = context.sourceCode; | ||||
|         const propertyNameMustBeSpaced = context.options[0] === "always"; // default is "never" | ||||
|         const enforceForClassMembers = !context.options[1] || context.options[1].enforceForClassMembers; | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Helpers | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         /** | ||||
|          * Reports that there shouldn't be a space after the first token | ||||
|          * @param {ASTNode} node The node to report in the event of an error. | ||||
|          * @param {Token} token The token to use for the report. | ||||
|          * @param {Token} tokenAfter The token after `token`. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportNoBeginningSpace(node, token, tokenAfter) { | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 loc: { start: token.loc.end, end: tokenAfter.loc.start }, | ||||
|                 messageId: "unexpectedSpaceAfter", | ||||
|                 data: { | ||||
|                     tokenValue: token.value | ||||
|                 }, | ||||
|                 fix(fixer) { | ||||
|                     return fixer.removeRange([token.range[1], tokenAfter.range[0]]); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports that there shouldn't be a space before the last token | ||||
|          * @param {ASTNode} node The node to report in the event of an error. | ||||
|          * @param {Token} token The token to use for the report. | ||||
|          * @param {Token} tokenBefore The token before `token`. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportNoEndingSpace(node, token, tokenBefore) { | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 loc: { start: tokenBefore.loc.end, end: token.loc.start }, | ||||
|                 messageId: "unexpectedSpaceBefore", | ||||
|                 data: { | ||||
|                     tokenValue: token.value | ||||
|                 }, | ||||
|                 fix(fixer) { | ||||
|                     return fixer.removeRange([tokenBefore.range[1], token.range[0]]); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports that there should be a space after the first token | ||||
|          * @param {ASTNode} node The node to report in the event of an error. | ||||
|          * @param {Token} token The token to use for the report. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportRequiredBeginningSpace(node, token) { | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 loc: token.loc, | ||||
|                 messageId: "missingSpaceAfter", | ||||
|                 data: { | ||||
|                     tokenValue: token.value | ||||
|                 }, | ||||
|                 fix(fixer) { | ||||
|                     return fixer.insertTextAfter(token, " "); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports that there should be a space before the last token | ||||
|          * @param {ASTNode} node The node to report in the event of an error. | ||||
|          * @param {Token} token The token to use for the report. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportRequiredEndingSpace(node, token) { | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 loc: token.loc, | ||||
|                 messageId: "missingSpaceBefore", | ||||
|                 data: { | ||||
|                     tokenValue: token.value | ||||
|                 }, | ||||
|                 fix(fixer) { | ||||
|                     return fixer.insertTextBefore(token, " "); | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Returns a function that checks the spacing of a node on the property name | ||||
|          * that was passed in. | ||||
|          * @param {string} propertyName The property on the node to check for spacing | ||||
|          * @returns {Function} A function that will check spacing on a node | ||||
|          */ | ||||
|         function checkSpacing(propertyName) { | ||||
|             return function(node) { | ||||
|                 if (!node.computed) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 const property = node[propertyName]; | ||||
|  | ||||
|                 const before = sourceCode.getTokenBefore(property, astUtils.isOpeningBracketToken), | ||||
|                     first = sourceCode.getTokenAfter(before, { includeComments: true }), | ||||
|                     after = sourceCode.getTokenAfter(property, astUtils.isClosingBracketToken), | ||||
|                     last = sourceCode.getTokenBefore(after, { includeComments: true }); | ||||
|  | ||||
|                 if (astUtils.isTokenOnSameLine(before, first)) { | ||||
|                     if (propertyNameMustBeSpaced) { | ||||
|                         if (!sourceCode.isSpaceBetweenTokens(before, first) && astUtils.isTokenOnSameLine(before, first)) { | ||||
|                             reportRequiredBeginningSpace(node, before); | ||||
|                         } | ||||
|                     } else { | ||||
|                         if (sourceCode.isSpaceBetweenTokens(before, first)) { | ||||
|                             reportNoBeginningSpace(node, before, first); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (astUtils.isTokenOnSameLine(last, after)) { | ||||
|                     if (propertyNameMustBeSpaced) { | ||||
|                         if (!sourceCode.isSpaceBetweenTokens(last, after) && astUtils.isTokenOnSameLine(last, after)) { | ||||
|                             reportRequiredEndingSpace(node, after); | ||||
|                         } | ||||
|                     } else { | ||||
|                         if (sourceCode.isSpaceBetweenTokens(last, after)) { | ||||
|                             reportNoEndingSpace(node, after, last); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Public | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         const listeners = { | ||||
|             Property: checkSpacing("key"), | ||||
|             MemberExpression: checkSpacing("property") | ||||
|         }; | ||||
|  | ||||
|         if (enforceForClassMembers) { | ||||
|             listeners.MethodDefinition = | ||||
|                 listeners.PropertyDefinition = listeners.Property; | ||||
|         } | ||||
|  | ||||
|         return listeners; | ||||
|  | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										210
									
								
								node_modules/eslint/lib/rules/consistent-return.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										210
									
								
								node_modules/eslint/lib/rules/consistent-return.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,210 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to flag consistent return values | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
| const { upperCaseFirst } = require("../shared/string-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Checks all segments in a set and returns true if all are unreachable. | ||||
|  * @param {Set<CodePathSegment>} segments The segments to check. | ||||
|  * @returns {boolean} True if all segments are unreachable; false otherwise. | ||||
|  */ | ||||
| function areAllSegmentsUnreachable(segments) { | ||||
|  | ||||
|     for (const segment of segments) { | ||||
|         if (segment.reachable) { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether a given node is a `constructor` method in an ES6 class | ||||
|  * @param {ASTNode} node A node to check | ||||
|  * @returns {boolean} `true` if the node is a `constructor` method | ||||
|  */ | ||||
| function isClassConstructor(node) { | ||||
|     return node.type === "FunctionExpression" && | ||||
|         node.parent && | ||||
|         node.parent.type === "MethodDefinition" && | ||||
|         node.parent.kind === "constructor"; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require `return` statements to either always or never specify values", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/consistent-return" | ||||
|         }, | ||||
|  | ||||
|         schema: [{ | ||||
|             type: "object", | ||||
|             properties: { | ||||
|                 treatUndefinedAsUnspecified: { | ||||
|                     type: "boolean", | ||||
|                     default: false | ||||
|                 } | ||||
|             }, | ||||
|             additionalProperties: false | ||||
|         }], | ||||
|  | ||||
|         messages: { | ||||
|             missingReturn: "Expected to return a value at the end of {{name}}.", | ||||
|             missingReturnValue: "{{name}} expected a return value.", | ||||
|             unexpectedReturnValue: "{{name}} expected no return value." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const options = context.options[0] || {}; | ||||
|         const treatUndefinedAsUnspecified = options.treatUndefinedAsUnspecified === true; | ||||
|         let funcInfo = null; | ||||
|  | ||||
|         /** | ||||
|          * Checks whether of not the implicit returning is consistent if the last | ||||
|          * code path segment is reachable. | ||||
|          * @param {ASTNode} node A program/function node to check. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function checkLastSegment(node) { | ||||
|             let loc, name; | ||||
|  | ||||
|             /* | ||||
|              * Skip if it expected no return value or unreachable. | ||||
|              * When unreachable, all paths are returned or thrown. | ||||
|              */ | ||||
|             if (!funcInfo.hasReturnValue || | ||||
|                 areAllSegmentsUnreachable(funcInfo.currentSegments) || | ||||
|                 astUtils.isES5Constructor(node) || | ||||
|                 isClassConstructor(node) | ||||
|             ) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             // Adjust a location and a message. | ||||
|             if (node.type === "Program") { | ||||
|  | ||||
|                 // The head of program. | ||||
|                 loc = { line: 1, column: 0 }; | ||||
|                 name = "program"; | ||||
|             } else if (node.type === "ArrowFunctionExpression") { | ||||
|  | ||||
|                 // `=>` token | ||||
|                 loc = context.sourceCode.getTokenBefore(node.body, astUtils.isArrowToken).loc; | ||||
|             } else if ( | ||||
|                 node.parent.type === "MethodDefinition" || | ||||
|                 (node.parent.type === "Property" && node.parent.method) | ||||
|             ) { | ||||
|  | ||||
|                 // Method name. | ||||
|                 loc = node.parent.key.loc; | ||||
|             } else { | ||||
|  | ||||
|                 // Function name or `function` keyword. | ||||
|                 loc = (node.id || context.sourceCode.getFirstToken(node)).loc; | ||||
|             } | ||||
|  | ||||
|             if (!name) { | ||||
|                 name = astUtils.getFunctionNameWithKind(node); | ||||
|             } | ||||
|  | ||||
|             // Reports. | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 loc, | ||||
|                 messageId: "missingReturn", | ||||
|                 data: { name } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|  | ||||
|             // Initializes/Disposes state of each code path. | ||||
|             onCodePathStart(codePath, node) { | ||||
|                 funcInfo = { | ||||
|                     upper: funcInfo, | ||||
|                     codePath, | ||||
|                     hasReturn: false, | ||||
|                     hasReturnValue: false, | ||||
|                     messageId: "", | ||||
|                     node, | ||||
|                     currentSegments: new Set() | ||||
|                 }; | ||||
|             }, | ||||
|             onCodePathEnd() { | ||||
|                 funcInfo = funcInfo.upper; | ||||
|             }, | ||||
|  | ||||
|             onUnreachableCodePathSegmentStart(segment) { | ||||
|                 funcInfo.currentSegments.add(segment); | ||||
|             }, | ||||
|  | ||||
|             onUnreachableCodePathSegmentEnd(segment) { | ||||
|                 funcInfo.currentSegments.delete(segment); | ||||
|             }, | ||||
|  | ||||
|             onCodePathSegmentStart(segment) { | ||||
|                 funcInfo.currentSegments.add(segment); | ||||
|             }, | ||||
|  | ||||
|             onCodePathSegmentEnd(segment) { | ||||
|                 funcInfo.currentSegments.delete(segment); | ||||
|             }, | ||||
|  | ||||
|  | ||||
|             // Reports a given return statement if it's inconsistent. | ||||
|             ReturnStatement(node) { | ||||
|                 const argument = node.argument; | ||||
|                 let hasReturnValue = Boolean(argument); | ||||
|  | ||||
|                 if (treatUndefinedAsUnspecified && hasReturnValue) { | ||||
|                     hasReturnValue = !astUtils.isSpecificId(argument, "undefined") && argument.operator !== "void"; | ||||
|                 } | ||||
|  | ||||
|                 if (!funcInfo.hasReturn) { | ||||
|                     funcInfo.hasReturn = true; | ||||
|                     funcInfo.hasReturnValue = hasReturnValue; | ||||
|                     funcInfo.messageId = hasReturnValue ? "missingReturnValue" : "unexpectedReturnValue"; | ||||
|                     funcInfo.data = { | ||||
|                         name: funcInfo.node.type === "Program" | ||||
|                             ? "Program" | ||||
|                             : upperCaseFirst(astUtils.getFunctionNameWithKind(funcInfo.node)) | ||||
|                     }; | ||||
|                 } else if (funcInfo.hasReturnValue !== hasReturnValue) { | ||||
|                     context.report({ | ||||
|                         node, | ||||
|                         messageId: funcInfo.messageId, | ||||
|                         data: funcInfo.data | ||||
|                     }); | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             // Reports a given program/function if the implicit returning is not consistent. | ||||
|             "Program:exit": checkLastSegment, | ||||
|             "FunctionDeclaration:exit": checkLastSegment, | ||||
|             "FunctionExpression:exit": checkLastSegment, | ||||
|             "ArrowFunctionExpression:exit": checkLastSegment | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										153
									
								
								node_modules/eslint/lib/rules/consistent-this.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										153
									
								
								node_modules/eslint/lib/rules/consistent-this.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,153 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to enforce consistent naming of "this" context variables | ||||
|  * @author Raphael Pigulla | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce consistent naming when capturing the current execution context", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/consistent-this" | ||||
|         }, | ||||
|  | ||||
|         schema: { | ||||
|             type: "array", | ||||
|             items: { | ||||
|                 type: "string", | ||||
|                 minLength: 1 | ||||
|             }, | ||||
|             uniqueItems: true | ||||
|         }, | ||||
|  | ||||
|         messages: { | ||||
|             aliasNotAssignedToThis: "Designated alias '{{name}}' is not assigned to 'this'.", | ||||
|             unexpectedAlias: "Unexpected alias '{{name}}' for 'this'." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         let aliases = []; | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         if (context.options.length === 0) { | ||||
|             aliases.push("that"); | ||||
|         } else { | ||||
|             aliases = context.options; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports that a variable declarator or assignment expression is assigning | ||||
|          * a non-'this' value to the specified alias. | ||||
|          * @param {ASTNode} node The assigning node. | ||||
|          * @param {string} name the name of the alias that was incorrectly used. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportBadAssignment(node, name) { | ||||
|             context.report({ node, messageId: "aliasNotAssignedToThis", data: { name } }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks that an assignment to an identifier only assigns 'this' to the | ||||
|          * appropriate alias, and the alias is only assigned to 'this'. | ||||
|          * @param {ASTNode} node The assigning node. | ||||
|          * @param {Identifier} name The name of the variable assigned to. | ||||
|          * @param {Expression} value The value of the assignment. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function checkAssignment(node, name, value) { | ||||
|             const isThis = value.type === "ThisExpression"; | ||||
|  | ||||
|             if (aliases.includes(name)) { | ||||
|                 if (!isThis || node.operator && node.operator !== "=") { | ||||
|                     reportBadAssignment(node, name); | ||||
|                 } | ||||
|             } else if (isThis) { | ||||
|                 context.report({ node, messageId: "unexpectedAlias", data: { name } }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Ensures that a variable declaration of the alias in a program or function | ||||
|          * is assigned to the correct value. | ||||
|          * @param {string} alias alias the check the assignment of. | ||||
|          * @param {Object} scope scope of the current code we are checking. | ||||
|          * @private | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function checkWasAssigned(alias, scope) { | ||||
|             const variable = scope.set.get(alias); | ||||
|  | ||||
|             if (!variable) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             if (variable.defs.some(def => def.node.type === "VariableDeclarator" && | ||||
|                 def.node.init !== null)) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             /* | ||||
|              * The alias has been declared and not assigned: check it was | ||||
|              * assigned later in the same scope. | ||||
|              */ | ||||
|             if (!variable.references.some(reference => { | ||||
|                 const write = reference.writeExpr; | ||||
|  | ||||
|                 return ( | ||||
|                     reference.from === scope && | ||||
|                     write && write.type === "ThisExpression" && | ||||
|                     write.parent.operator === "=" | ||||
|                 ); | ||||
|             })) { | ||||
|                 variable.defs.map(def => def.node).forEach(node => { | ||||
|                     reportBadAssignment(node, alias); | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Check each alias to ensure that is was assigned to the correct value. | ||||
|          * @param {ASTNode} node The node that represents the scope to check. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function ensureWasAssigned(node) { | ||||
|             const scope = sourceCode.getScope(node); | ||||
|  | ||||
|             aliases.forEach(alias => { | ||||
|                 checkWasAssigned(alias, scope); | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             "Program:exit": ensureWasAssigned, | ||||
|             "FunctionExpression:exit": ensureWasAssigned, | ||||
|             "FunctionDeclaration:exit": ensureWasAssigned, | ||||
|  | ||||
|             VariableDeclarator(node) { | ||||
|                 const id = node.id; | ||||
|                 const isDestructuring = | ||||
|                     id.type === "ArrayPattern" || id.type === "ObjectPattern"; | ||||
|  | ||||
|                 if (node.init !== null && !isDestructuring) { | ||||
|                     checkAssignment(node, id.name, node.init); | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             AssignmentExpression(node) { | ||||
|                 if (node.left.type === "Identifier") { | ||||
|                     checkAssignment(node, node.left.name, node.right); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										446
									
								
								node_modules/eslint/lib/rules/constructor-super.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										446
									
								
								node_modules/eslint/lib/rules/constructor-super.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,446 @@ | ||||
| /** | ||||
|  * @fileoverview A rule to verify `super()` callings in constructor. | ||||
|  * @author Toru Nagashima | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Checks all segments in a set and returns true if any are reachable. | ||||
|  * @param {Set<CodePathSegment>} segments The segments to check. | ||||
|  * @returns {boolean} True if any segment is reachable; false otherwise. | ||||
|  */ | ||||
| function isAnySegmentReachable(segments) { | ||||
|  | ||||
|     for (const segment of segments) { | ||||
|         if (segment.reachable) { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether or not a given node is a constructor. | ||||
|  * @param {ASTNode} node A node to check. This node type is one of | ||||
|  *   `Program`, `FunctionDeclaration`, `FunctionExpression`, and | ||||
|  *   `ArrowFunctionExpression`. | ||||
|  * @returns {boolean} `true` if the node is a constructor. | ||||
|  */ | ||||
| function isConstructorFunction(node) { | ||||
|     return ( | ||||
|         node.type === "FunctionExpression" && | ||||
|         node.parent.type === "MethodDefinition" && | ||||
|         node.parent.kind === "constructor" | ||||
|     ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether a given node can be a constructor or not. | ||||
|  * @param {ASTNode} node A node to check. | ||||
|  * @returns {boolean} `true` if the node can be a constructor. | ||||
|  */ | ||||
| function isPossibleConstructor(node) { | ||||
|     if (!node) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     switch (node.type) { | ||||
|         case "ClassExpression": | ||||
|         case "FunctionExpression": | ||||
|         case "ThisExpression": | ||||
|         case "MemberExpression": | ||||
|         case "CallExpression": | ||||
|         case "NewExpression": | ||||
|         case "ChainExpression": | ||||
|         case "YieldExpression": | ||||
|         case "TaggedTemplateExpression": | ||||
|         case "MetaProperty": | ||||
|             return true; | ||||
|  | ||||
|         case "Identifier": | ||||
|             return node.name !== "undefined"; | ||||
|  | ||||
|         case "AssignmentExpression": | ||||
|             if (["=", "&&="].includes(node.operator)) { | ||||
|                 return isPossibleConstructor(node.right); | ||||
|             } | ||||
|  | ||||
|             if (["||=", "??="].includes(node.operator)) { | ||||
|                 return ( | ||||
|                     isPossibleConstructor(node.left) || | ||||
|                     isPossibleConstructor(node.right) | ||||
|                 ); | ||||
|             } | ||||
|  | ||||
|             /** | ||||
|              * All other assignment operators are mathematical assignment operators (arithmetic or bitwise). | ||||
|              * An assignment expression with a mathematical operator can either evaluate to a primitive value, | ||||
|              * or throw, depending on the operands. Thus, it cannot evaluate to a constructor function. | ||||
|              */ | ||||
|             return false; | ||||
|  | ||||
|         case "LogicalExpression": | ||||
|  | ||||
|             /* | ||||
|              * If the && operator short-circuits, the left side was falsy and therefore not a constructor, and if | ||||
|              * it doesn't short-circuit, it takes the value from the right side, so the right side must always be a | ||||
|              * possible constructor. A future improvement could verify that the left side could be truthy by | ||||
|              * excluding falsy literals. | ||||
|              */ | ||||
|             if (node.operator === "&&") { | ||||
|                 return isPossibleConstructor(node.right); | ||||
|             } | ||||
|  | ||||
|             return ( | ||||
|                 isPossibleConstructor(node.left) || | ||||
|                 isPossibleConstructor(node.right) | ||||
|             ); | ||||
|  | ||||
|         case "ConditionalExpression": | ||||
|             return ( | ||||
|                 isPossibleConstructor(node.alternate) || | ||||
|                 isPossibleConstructor(node.consequent) | ||||
|             ); | ||||
|  | ||||
|         case "SequenceExpression": { | ||||
|             const lastExpression = node.expressions[node.expressions.length - 1]; | ||||
|  | ||||
|             return isPossibleConstructor(lastExpression); | ||||
|         } | ||||
|  | ||||
|         default: | ||||
|             return false; | ||||
|     } | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "problem", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require `super()` calls in constructors", | ||||
|             recommended: true, | ||||
|             url: "https://eslint.org/docs/latest/rules/constructor-super" | ||||
|         }, | ||||
|  | ||||
|         schema: [], | ||||
|  | ||||
|         messages: { | ||||
|             missingSome: "Lacked a call of 'super()' in some code paths.", | ||||
|             missingAll: "Expected to call 'super()'.", | ||||
|  | ||||
|             duplicate: "Unexpected duplicate 'super()'.", | ||||
|             badSuper: "Unexpected 'super()' because 'super' is not a constructor.", | ||||
|             unexpected: "Unexpected 'super()'." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         /* | ||||
|          * {{hasExtends: boolean, scope: Scope, codePath: CodePath}[]} | ||||
|          * Information for each constructor. | ||||
|          * - upper:      Information of the upper constructor. | ||||
|          * - hasExtends: A flag which shows whether own class has a valid `extends` | ||||
|          *               part. | ||||
|          * - scope:      The scope of own class. | ||||
|          * - codePath:   The code path object of the constructor. | ||||
|          */ | ||||
|         let funcInfo = null; | ||||
|  | ||||
|         /* | ||||
|          * {Map<string, {calledInSomePaths: boolean, calledInEveryPaths: boolean}>} | ||||
|          * Information for each code path segment. | ||||
|          * - calledInSomePaths:  A flag of be called `super()` in some code paths. | ||||
|          * - calledInEveryPaths: A flag of be called `super()` in all code paths. | ||||
|          * - validNodes: | ||||
|          */ | ||||
|         let segInfoMap = Object.create(null); | ||||
|  | ||||
|         /** | ||||
|          * Gets the flag which shows `super()` is called in some paths. | ||||
|          * @param {CodePathSegment} segment A code path segment to get. | ||||
|          * @returns {boolean} The flag which shows `super()` is called in some paths | ||||
|          */ | ||||
|         function isCalledInSomePath(segment) { | ||||
|             return segment.reachable && segInfoMap[segment.id].calledInSomePaths; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Gets the flag which shows `super()` is called in all paths. | ||||
|          * @param {CodePathSegment} segment A code path segment to get. | ||||
|          * @returns {boolean} The flag which shows `super()` is called in all paths. | ||||
|          */ | ||||
|         function isCalledInEveryPath(segment) { | ||||
|  | ||||
|             /* | ||||
|              * If specific segment is the looped segment of the current segment, | ||||
|              * skip the segment. | ||||
|              * If not skipped, this never becomes true after a loop. | ||||
|              */ | ||||
|             if (segment.nextSegments.length === 1 && | ||||
|                 segment.nextSegments[0].isLoopedPrevSegment(segment) | ||||
|             ) { | ||||
|                 return true; | ||||
|             } | ||||
|             return segment.reachable && segInfoMap[segment.id].calledInEveryPaths; | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|  | ||||
|             /** | ||||
|              * Stacks a constructor information. | ||||
|              * @param {CodePath} codePath A code path which was started. | ||||
|              * @param {ASTNode} node The current node. | ||||
|              * @returns {void} | ||||
|              */ | ||||
|             onCodePathStart(codePath, node) { | ||||
|                 if (isConstructorFunction(node)) { | ||||
|  | ||||
|                     // Class > ClassBody > MethodDefinition > FunctionExpression | ||||
|                     const classNode = node.parent.parent.parent; | ||||
|                     const superClass = classNode.superClass; | ||||
|  | ||||
|                     funcInfo = { | ||||
|                         upper: funcInfo, | ||||
|                         isConstructor: true, | ||||
|                         hasExtends: Boolean(superClass), | ||||
|                         superIsConstructor: isPossibleConstructor(superClass), | ||||
|                         codePath, | ||||
|                         currentSegments: new Set() | ||||
|                     }; | ||||
|                 } else { | ||||
|                     funcInfo = { | ||||
|                         upper: funcInfo, | ||||
|                         isConstructor: false, | ||||
|                         hasExtends: false, | ||||
|                         superIsConstructor: false, | ||||
|                         codePath, | ||||
|                         currentSegments: new Set() | ||||
|                     }; | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             /** | ||||
|              * Pops a constructor information. | ||||
|              * And reports if `super()` lacked. | ||||
|              * @param {CodePath} codePath A code path which was ended. | ||||
|              * @param {ASTNode} node The current node. | ||||
|              * @returns {void} | ||||
|              */ | ||||
|             onCodePathEnd(codePath, node) { | ||||
|                 const hasExtends = funcInfo.hasExtends; | ||||
|  | ||||
|                 // Pop. | ||||
|                 funcInfo = funcInfo.upper; | ||||
|  | ||||
|                 if (!hasExtends) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // Reports if `super()` lacked. | ||||
|                 const segments = codePath.returnedSegments; | ||||
|                 const calledInEveryPaths = segments.every(isCalledInEveryPath); | ||||
|                 const calledInSomePaths = segments.some(isCalledInSomePath); | ||||
|  | ||||
|                 if (!calledInEveryPaths) { | ||||
|                     context.report({ | ||||
|                         messageId: calledInSomePaths | ||||
|                             ? "missingSome" | ||||
|                             : "missingAll", | ||||
|                         node: node.parent | ||||
|                     }); | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             /** | ||||
|              * Initialize information of a given code path segment. | ||||
|              * @param {CodePathSegment} segment A code path segment to initialize. | ||||
|              * @returns {void} | ||||
|              */ | ||||
|             onCodePathSegmentStart(segment) { | ||||
|  | ||||
|                 funcInfo.currentSegments.add(segment); | ||||
|  | ||||
|                 if (!(funcInfo && funcInfo.isConstructor && funcInfo.hasExtends)) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // Initialize info. | ||||
|                 const info = segInfoMap[segment.id] = { | ||||
|                     calledInSomePaths: false, | ||||
|                     calledInEveryPaths: false, | ||||
|                     validNodes: [] | ||||
|                 }; | ||||
|  | ||||
|                 // When there are previous segments, aggregates these. | ||||
|                 const prevSegments = segment.prevSegments; | ||||
|  | ||||
|                 if (prevSegments.length > 0) { | ||||
|                     info.calledInSomePaths = prevSegments.some(isCalledInSomePath); | ||||
|                     info.calledInEveryPaths = prevSegments.every(isCalledInEveryPath); | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             onUnreachableCodePathSegmentStart(segment) { | ||||
|                 funcInfo.currentSegments.add(segment); | ||||
|             }, | ||||
|  | ||||
|             onUnreachableCodePathSegmentEnd(segment) { | ||||
|                 funcInfo.currentSegments.delete(segment); | ||||
|             }, | ||||
|  | ||||
|             onCodePathSegmentEnd(segment) { | ||||
|                 funcInfo.currentSegments.delete(segment); | ||||
|             }, | ||||
|  | ||||
|  | ||||
|             /** | ||||
|              * Update information of the code path segment when a code path was | ||||
|              * looped. | ||||
|              * @param {CodePathSegment} fromSegment The code path segment of the | ||||
|              *      end of a loop. | ||||
|              * @param {CodePathSegment} toSegment A code path segment of the head | ||||
|              *      of a loop. | ||||
|              * @returns {void} | ||||
|              */ | ||||
|             onCodePathSegmentLoop(fromSegment, toSegment) { | ||||
|                 if (!(funcInfo && funcInfo.isConstructor && funcInfo.hasExtends)) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // Update information inside of the loop. | ||||
|                 const isRealLoop = toSegment.prevSegments.length >= 2; | ||||
|  | ||||
|                 funcInfo.codePath.traverseSegments( | ||||
|                     { first: toSegment, last: fromSegment }, | ||||
|                     segment => { | ||||
|                         const info = segInfoMap[segment.id]; | ||||
|                         const prevSegments = segment.prevSegments; | ||||
|  | ||||
|                         // Updates flags. | ||||
|                         info.calledInSomePaths = prevSegments.some(isCalledInSomePath); | ||||
|                         info.calledInEveryPaths = prevSegments.every(isCalledInEveryPath); | ||||
|  | ||||
|                         // If flags become true anew, reports the valid nodes. | ||||
|                         if (info.calledInSomePaths || isRealLoop) { | ||||
|                             const nodes = info.validNodes; | ||||
|  | ||||
|                             info.validNodes = []; | ||||
|  | ||||
|                             for (let i = 0; i < nodes.length; ++i) { | ||||
|                                 const node = nodes[i]; | ||||
|  | ||||
|                                 context.report({ | ||||
|                                     messageId: "duplicate", | ||||
|                                     node | ||||
|                                 }); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 ); | ||||
|             }, | ||||
|  | ||||
|             /** | ||||
|              * Checks for a call of `super()`. | ||||
|              * @param {ASTNode} node A CallExpression node to check. | ||||
|              * @returns {void} | ||||
|              */ | ||||
|             "CallExpression:exit"(node) { | ||||
|                 if (!(funcInfo && funcInfo.isConstructor)) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // Skips except `super()`. | ||||
|                 if (node.callee.type !== "Super") { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // Reports if needed. | ||||
|                 if (funcInfo.hasExtends) { | ||||
|                     const segments = funcInfo.currentSegments; | ||||
|                     let duplicate = false; | ||||
|                     let info = null; | ||||
|  | ||||
|                     for (const segment of segments) { | ||||
|  | ||||
|                         if (segment.reachable) { | ||||
|                             info = segInfoMap[segment.id]; | ||||
|  | ||||
|                             duplicate = duplicate || info.calledInSomePaths; | ||||
|                             info.calledInSomePaths = info.calledInEveryPaths = true; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     if (info) { | ||||
|                         if (duplicate) { | ||||
|                             context.report({ | ||||
|                                 messageId: "duplicate", | ||||
|                                 node | ||||
|                             }); | ||||
|                         } else if (!funcInfo.superIsConstructor) { | ||||
|                             context.report({ | ||||
|                                 messageId: "badSuper", | ||||
|                                 node | ||||
|                             }); | ||||
|                         } else { | ||||
|                             info.validNodes.push(node); | ||||
|                         } | ||||
|                     } | ||||
|                 } else if (isAnySegmentReachable(funcInfo.currentSegments)) { | ||||
|                     context.report({ | ||||
|                         messageId: "unexpected", | ||||
|                         node | ||||
|                     }); | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             /** | ||||
|              * Set the mark to the returned path as `super()` was called. | ||||
|              * @param {ASTNode} node A ReturnStatement node to check. | ||||
|              * @returns {void} | ||||
|              */ | ||||
|             ReturnStatement(node) { | ||||
|                 if (!(funcInfo && funcInfo.isConstructor && funcInfo.hasExtends)) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // Skips if no argument. | ||||
|                 if (!node.argument) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // Returning argument is a substitute of 'super()'. | ||||
|                 const segments = funcInfo.currentSegments; | ||||
|  | ||||
|                 for (const segment of segments) { | ||||
|  | ||||
|                     if (segment.reachable) { | ||||
|                         const info = segInfoMap[segment.id]; | ||||
|  | ||||
|                         info.calledInSomePaths = info.calledInEveryPaths = true; | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             /** | ||||
|              * Resets state. | ||||
|              * @returns {void} | ||||
|              */ | ||||
|             "Program:exit"() { | ||||
|                 segInfoMap = Object.create(null); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										486
									
								
								node_modules/eslint/lib/rules/curly.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										486
									
								
								node_modules/eslint/lib/rules/curly.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,486 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to flag statements without curly braces | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce consistent brace style for all control statements", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/curly" | ||||
|         }, | ||||
|  | ||||
|         schema: { | ||||
|             anyOf: [ | ||||
|                 { | ||||
|                     type: "array", | ||||
|                     items: [ | ||||
|                         { | ||||
|                             enum: ["all"] | ||||
|                         } | ||||
|                     ], | ||||
|                     minItems: 0, | ||||
|                     maxItems: 1 | ||||
|                 }, | ||||
|                 { | ||||
|                     type: "array", | ||||
|                     items: [ | ||||
|                         { | ||||
|                             enum: ["multi", "multi-line", "multi-or-nest"] | ||||
|                         }, | ||||
|                         { | ||||
|                             enum: ["consistent"] | ||||
|                         } | ||||
|                     ], | ||||
|                     minItems: 0, | ||||
|                     maxItems: 2 | ||||
|                 } | ||||
|             ] | ||||
|         }, | ||||
|  | ||||
|         fixable: "code", | ||||
|  | ||||
|         messages: { | ||||
|             missingCurlyAfter: "Expected { after '{{name}}'.", | ||||
|             missingCurlyAfterCondition: "Expected { after '{{name}}' condition.", | ||||
|             unexpectedCurlyAfter: "Unnecessary { after '{{name}}'.", | ||||
|             unexpectedCurlyAfterCondition: "Unnecessary { after '{{name}}' condition." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         const multiOnly = (context.options[0] === "multi"); | ||||
|         const multiLine = (context.options[0] === "multi-line"); | ||||
|         const multiOrNest = (context.options[0] === "multi-or-nest"); | ||||
|         const consistent = (context.options[1] === "consistent"); | ||||
|  | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Helpers | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         /** | ||||
|          * Determines if a given node is a one-liner that's on the same line as it's preceding code. | ||||
|          * @param {ASTNode} node The node to check. | ||||
|          * @returns {boolean} True if the node is a one-liner that's on the same line as it's preceding code. | ||||
|          * @private | ||||
|          */ | ||||
|         function isCollapsedOneLiner(node) { | ||||
|             const before = sourceCode.getTokenBefore(node); | ||||
|             const last = sourceCode.getLastToken(node); | ||||
|             const lastExcludingSemicolon = astUtils.isSemicolonToken(last) ? sourceCode.getTokenBefore(last) : last; | ||||
|  | ||||
|             return before.loc.start.line === lastExcludingSemicolon.loc.end.line; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines if a given node is a one-liner. | ||||
|          * @param {ASTNode} node The node to check. | ||||
|          * @returns {boolean} True if the node is a one-liner. | ||||
|          * @private | ||||
|          */ | ||||
|         function isOneLiner(node) { | ||||
|             if (node.type === "EmptyStatement") { | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             const first = sourceCode.getFirstToken(node); | ||||
|             const last = sourceCode.getLastToken(node); | ||||
|             const lastExcludingSemicolon = astUtils.isSemicolonToken(last) ? sourceCode.getTokenBefore(last) : last; | ||||
|  | ||||
|             return first.loc.start.line === lastExcludingSemicolon.loc.end.line; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines if the given node is a lexical declaration (let, const, function, or class) | ||||
|          * @param {ASTNode} node The node to check | ||||
|          * @returns {boolean} True if the node is a lexical declaration | ||||
|          * @private | ||||
|          */ | ||||
|         function isLexicalDeclaration(node) { | ||||
|             if (node.type === "VariableDeclaration") { | ||||
|                 return node.kind === "const" || node.kind === "let"; | ||||
|             } | ||||
|  | ||||
|             return node.type === "FunctionDeclaration" || node.type === "ClassDeclaration"; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks if the given token is an `else` token or not. | ||||
|          * @param {Token} token The token to check. | ||||
|          * @returns {boolean} `true` if the token is an `else` token. | ||||
|          */ | ||||
|         function isElseKeywordToken(token) { | ||||
|             return token.value === "else" && token.type === "Keyword"; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines whether the given node has an `else` keyword token as the first token after. | ||||
|          * @param {ASTNode} node The node to check. | ||||
|          * @returns {boolean} `true` if the node is followed by an `else` keyword token. | ||||
|          */ | ||||
|         function isFollowedByElseKeyword(node) { | ||||
|             const nextToken = sourceCode.getTokenAfter(node); | ||||
|  | ||||
|             return Boolean(nextToken) && isElseKeywordToken(nextToken); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines if a semicolon needs to be inserted after removing a set of curly brackets, in order to avoid a SyntaxError. | ||||
|          * @param {Token} closingBracket The } token | ||||
|          * @returns {boolean} `true` if a semicolon needs to be inserted after the last statement in the block. | ||||
|          */ | ||||
|         function needsSemicolon(closingBracket) { | ||||
|             const tokenBefore = sourceCode.getTokenBefore(closingBracket); | ||||
|             const tokenAfter = sourceCode.getTokenAfter(closingBracket); | ||||
|             const lastBlockNode = sourceCode.getNodeByRangeIndex(tokenBefore.range[0]); | ||||
|  | ||||
|             if (astUtils.isSemicolonToken(tokenBefore)) { | ||||
|  | ||||
|                 // If the last statement already has a semicolon, don't add another one. | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             if (!tokenAfter) { | ||||
|  | ||||
|                 // If there are no statements after this block, there is no need to add a semicolon. | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             if (lastBlockNode.type === "BlockStatement" && lastBlockNode.parent.type !== "FunctionExpression" && lastBlockNode.parent.type !== "ArrowFunctionExpression") { | ||||
|  | ||||
|                 /* | ||||
|                  * If the last node surrounded by curly brackets is a BlockStatement (other than a FunctionExpression or an ArrowFunctionExpression), | ||||
|                  * don't insert a semicolon. Otherwise, the semicolon would be parsed as a separate statement, which would cause | ||||
|                  * a SyntaxError if it was followed by `else`. | ||||
|                  */ | ||||
|                 return false; | ||||
|             } | ||||
|  | ||||
|             if (tokenBefore.loc.end.line === tokenAfter.loc.start.line) { | ||||
|  | ||||
|                 // If the next token is on the same line, insert a semicolon. | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             if (/^[([/`+-]/u.test(tokenAfter.value)) { | ||||
|  | ||||
|                 // If the next token starts with a character that would disrupt ASI, insert a semicolon. | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             if (tokenBefore.type === "Punctuator" && (tokenBefore.value === "++" || tokenBefore.value === "--")) { | ||||
|  | ||||
|                 // If the last token is ++ or --, insert a semicolon to avoid disrupting ASI. | ||||
|                 return true; | ||||
|             } | ||||
|  | ||||
|             // Otherwise, do not insert a semicolon. | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines whether the code represented by the given node contains an `if` statement | ||||
|          * that would become associated with an `else` keyword directly appended to that code. | ||||
|          * | ||||
|          * Examples where it returns `true`: | ||||
|          * | ||||
|          *    if (a) | ||||
|          *        foo(); | ||||
|          * | ||||
|          *    if (a) { | ||||
|          *        foo(); | ||||
|          *    } | ||||
|          * | ||||
|          *    if (a) | ||||
|          *        foo(); | ||||
|          *    else if (b) | ||||
|          *        bar(); | ||||
|          * | ||||
|          *    while (a) | ||||
|          *        if (b) | ||||
|          *            if(c) | ||||
|          *                foo(); | ||||
|          *            else | ||||
|          *                bar(); | ||||
|          * | ||||
|          * Examples where it returns `false`: | ||||
|          * | ||||
|          *    if (a) | ||||
|          *        foo(); | ||||
|          *    else | ||||
|          *        bar(); | ||||
|          * | ||||
|          *    while (a) { | ||||
|          *        if (b) | ||||
|          *            if(c) | ||||
|          *                foo(); | ||||
|          *            else | ||||
|          *                bar(); | ||||
|          *    } | ||||
|          * | ||||
|          *    while (a) | ||||
|          *        if (b) { | ||||
|          *            if(c) | ||||
|          *                foo(); | ||||
|          *        } | ||||
|          *        else | ||||
|          *            bar(); | ||||
|          * @param {ASTNode} node Node representing the code to check. | ||||
|          * @returns {boolean} `true` if an `if` statement within the code would become associated with an `else` appended to that code. | ||||
|          */ | ||||
|         function hasUnsafeIf(node) { | ||||
|             switch (node.type) { | ||||
|                 case "IfStatement": | ||||
|                     if (!node.alternate) { | ||||
|                         return true; | ||||
|                     } | ||||
|                     return hasUnsafeIf(node.alternate); | ||||
|                 case "ForStatement": | ||||
|                 case "ForInStatement": | ||||
|                 case "ForOfStatement": | ||||
|                 case "LabeledStatement": | ||||
|                 case "WithStatement": | ||||
|                 case "WhileStatement": | ||||
|                     return hasUnsafeIf(node.body); | ||||
|                 default: | ||||
|                     return false; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines whether the existing curly braces around the single statement are necessary to preserve the semantics of the code. | ||||
|          * The braces, which make the given block body, are necessary in either of the following situations: | ||||
|          * | ||||
|          * 1. The statement is a lexical declaration. | ||||
|          * 2. Without the braces, an `if` within the statement would become associated with an `else` after the closing brace: | ||||
|          * | ||||
|          *     if (a) { | ||||
|          *         if (b) | ||||
|          *             foo(); | ||||
|          *     } | ||||
|          *     else | ||||
|          *         bar(); | ||||
|          * | ||||
|          *     if (a) | ||||
|          *         while (b) | ||||
|          *             while (c) { | ||||
|          *                 while (d) | ||||
|          *                     if (e) | ||||
|          *                         while(f) | ||||
|          *                             foo(); | ||||
|          *            } | ||||
|          *     else | ||||
|          *         bar(); | ||||
|          * @param {ASTNode} node `BlockStatement` body with exactly one statement directly inside. The statement can have its own nested statements. | ||||
|          * @returns {boolean} `true` if the braces are necessary - removing them (replacing the given `BlockStatement` body with its single statement content) | ||||
|          * would change the semantics of the code or produce a syntax error. | ||||
|          */ | ||||
|         function areBracesNecessary(node) { | ||||
|             const statement = node.body[0]; | ||||
|  | ||||
|             return isLexicalDeclaration(statement) || | ||||
|                 hasUnsafeIf(statement) && isFollowedByElseKeyword(node); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Prepares to check the body of a node to see if it's a block statement. | ||||
|          * @param {ASTNode} node The node to report if there's a problem. | ||||
|          * @param {ASTNode} body The body node to check for blocks. | ||||
|          * @param {string} name The name to report if there's a problem. | ||||
|          * @param {{ condition: boolean }} opts Options to pass to the report functions | ||||
|          * @returns {Object} a prepared check object, with "actual", "expected", "check" properties. | ||||
|          *   "actual" will be `true` or `false` whether the body is already a block statement. | ||||
|          *   "expected" will be `true` or `false` if the body should be a block statement or not, or | ||||
|          *   `null` if it doesn't matter, depending on the rule options. It can be modified to change | ||||
|          *   the final behavior of "check". | ||||
|          *   "check" will be a function reporting appropriate problems depending on the other | ||||
|          *   properties. | ||||
|          */ | ||||
|         function prepareCheck(node, body, name, opts) { | ||||
|             const hasBlock = (body.type === "BlockStatement"); | ||||
|             let expected = null; | ||||
|  | ||||
|             if (hasBlock && (body.body.length !== 1 || areBracesNecessary(body))) { | ||||
|                 expected = true; | ||||
|             } else if (multiOnly) { | ||||
|                 expected = false; | ||||
|             } else if (multiLine) { | ||||
|                 if (!isCollapsedOneLiner(body)) { | ||||
|                     expected = true; | ||||
|                 } | ||||
|  | ||||
|                 // otherwise, the body is allowed to have braces or not to have braces | ||||
|  | ||||
|             } else if (multiOrNest) { | ||||
|                 if (hasBlock) { | ||||
|                     const statement = body.body[0]; | ||||
|                     const leadingCommentsInBlock = sourceCode.getCommentsBefore(statement); | ||||
|  | ||||
|                     expected = !isOneLiner(statement) || leadingCommentsInBlock.length > 0; | ||||
|                 } else { | ||||
|                     expected = !isOneLiner(body); | ||||
|                 } | ||||
|             } else { | ||||
|  | ||||
|                 // default "all" | ||||
|                 expected = true; | ||||
|             } | ||||
|  | ||||
|             return { | ||||
|                 actual: hasBlock, | ||||
|                 expected, | ||||
|                 check() { | ||||
|                     if (this.expected !== null && this.expected !== this.actual) { | ||||
|                         if (this.expected) { | ||||
|                             context.report({ | ||||
|                                 node, | ||||
|                                 loc: body.loc, | ||||
|                                 messageId: opts && opts.condition ? "missingCurlyAfterCondition" : "missingCurlyAfter", | ||||
|                                 data: { | ||||
|                                     name | ||||
|                                 }, | ||||
|                                 fix: fixer => fixer.replaceText(body, `{${sourceCode.getText(body)}}`) | ||||
|                             }); | ||||
|                         } else { | ||||
|                             context.report({ | ||||
|                                 node, | ||||
|                                 loc: body.loc, | ||||
|                                 messageId: opts && opts.condition ? "unexpectedCurlyAfterCondition" : "unexpectedCurlyAfter", | ||||
|                                 data: { | ||||
|                                     name | ||||
|                                 }, | ||||
|                                 fix(fixer) { | ||||
|  | ||||
|                                     /* | ||||
|                                      * `do while` expressions sometimes need a space to be inserted after `do`. | ||||
|                                      * e.g. `do{foo()} while (bar)` should be corrected to `do foo() while (bar)` | ||||
|                                      */ | ||||
|                                     const needsPrecedingSpace = node.type === "DoWhileStatement" && | ||||
|                                         sourceCode.getTokenBefore(body).range[1] === body.range[0] && | ||||
|                                         !astUtils.canTokensBeAdjacent("do", sourceCode.getFirstToken(body, { skip: 1 })); | ||||
|  | ||||
|                                     const openingBracket = sourceCode.getFirstToken(body); | ||||
|                                     const closingBracket = sourceCode.getLastToken(body); | ||||
|                                     const lastTokenInBlock = sourceCode.getTokenBefore(closingBracket); | ||||
|  | ||||
|                                     if (needsSemicolon(closingBracket)) { | ||||
|  | ||||
|                                         /* | ||||
|                                          * If removing braces would cause a SyntaxError due to multiple statements on the same line (or | ||||
|                                          * change the semantics of the code due to ASI), don't perform a fix. | ||||
|                                          */ | ||||
|                                         return null; | ||||
|                                     } | ||||
|  | ||||
|                                     const resultingBodyText = sourceCode.getText().slice(openingBracket.range[1], lastTokenInBlock.range[0]) + | ||||
|                                         sourceCode.getText(lastTokenInBlock) + | ||||
|                                         sourceCode.getText().slice(lastTokenInBlock.range[1], closingBracket.range[0]); | ||||
|  | ||||
|                                     return fixer.replaceText(body, (needsPrecedingSpace ? " " : "") + resultingBodyText); | ||||
|                                 } | ||||
|                             }); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Prepares to check the bodies of a "if", "else if" and "else" chain. | ||||
|          * @param {ASTNode} node The first IfStatement node of the chain. | ||||
|          * @returns {Object[]} prepared checks for each body of the chain. See `prepareCheck` for more | ||||
|          *   information. | ||||
|          */ | ||||
|         function prepareIfChecks(node) { | ||||
|             const preparedChecks = []; | ||||
|  | ||||
|             for (let currentNode = node; currentNode; currentNode = currentNode.alternate) { | ||||
|                 preparedChecks.push(prepareCheck(currentNode, currentNode.consequent, "if", { condition: true })); | ||||
|                 if (currentNode.alternate && currentNode.alternate.type !== "IfStatement") { | ||||
|                     preparedChecks.push(prepareCheck(currentNode, currentNode.alternate, "else")); | ||||
|                     break; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             if (consistent) { | ||||
|  | ||||
|                 /* | ||||
|                  * If any node should have or already have braces, make sure they | ||||
|                  * all have braces. | ||||
|                  * If all nodes shouldn't have braces, make sure they don't. | ||||
|                  */ | ||||
|                 const expected = preparedChecks.some(preparedCheck => { | ||||
|                     if (preparedCheck.expected !== null) { | ||||
|                         return preparedCheck.expected; | ||||
|                     } | ||||
|                     return preparedCheck.actual; | ||||
|                 }); | ||||
|  | ||||
|                 preparedChecks.forEach(preparedCheck => { | ||||
|                     preparedCheck.expected = expected; | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             return preparedChecks; | ||||
|         } | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Public | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         return { | ||||
|             IfStatement(node) { | ||||
|                 const parent = node.parent; | ||||
|                 const isElseIf = parent.type === "IfStatement" && parent.alternate === node; | ||||
|  | ||||
|                 if (!isElseIf) { | ||||
|  | ||||
|                     // This is a top `if`, check the whole `if-else-if` chain | ||||
|                     prepareIfChecks(node).forEach(preparedCheck => { | ||||
|                         preparedCheck.check(); | ||||
|                     }); | ||||
|                 } | ||||
|  | ||||
|                 // Skip `else if`, it's already checked (when the top `if` was visited) | ||||
|             }, | ||||
|  | ||||
|             WhileStatement(node) { | ||||
|                 prepareCheck(node, node.body, "while", { condition: true }).check(); | ||||
|             }, | ||||
|  | ||||
|             DoWhileStatement(node) { | ||||
|                 prepareCheck(node, node.body, "do").check(); | ||||
|             }, | ||||
|  | ||||
|             ForStatement(node) { | ||||
|                 prepareCheck(node, node.body, "for", { condition: true }).check(); | ||||
|             }, | ||||
|  | ||||
|             ForInStatement(node) { | ||||
|                 prepareCheck(node, node.body, "for-in").check(); | ||||
|             }, | ||||
|  | ||||
|             ForOfStatement(node) { | ||||
|                 prepareCheck(node, node.body, "for-of").check(); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										44
									
								
								node_modules/eslint/lib/rules/default-case-last.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										44
									
								
								node_modules/eslint/lib/rules/default-case-last.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,44 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to enforce default clauses in switch statements to be last | ||||
|  * @author Milos Djermanovic | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce default clauses in switch statements to be last", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/default-case-last" | ||||
|         }, | ||||
|  | ||||
|         schema: [], | ||||
|  | ||||
|         messages: { | ||||
|             notLast: "Default clause should be the last clause." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         return { | ||||
|             SwitchStatement(node) { | ||||
|                 const cases = node.cases, | ||||
|                     indexOfDefault = cases.findIndex(c => c.test === null); | ||||
|  | ||||
|                 if (indexOfDefault !== -1 && indexOfDefault !== cases.length - 1) { | ||||
|                     const defaultClause = cases[indexOfDefault]; | ||||
|  | ||||
|                     context.report({ node: defaultClause, messageId: "notLast" }); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										97
									
								
								node_modules/eslint/lib/rules/default-case.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										97
									
								
								node_modules/eslint/lib/rules/default-case.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,97 @@ | ||||
| /** | ||||
|  * @fileoverview require default case in switch statements | ||||
|  * @author Aliaksei Shytkin | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| const DEFAULT_COMMENT_PATTERN = /^no default$/iu; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require `default` cases in `switch` statements", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/default-case" | ||||
|         }, | ||||
|  | ||||
|         schema: [{ | ||||
|             type: "object", | ||||
|             properties: { | ||||
|                 commentPattern: { | ||||
|                     type: "string" | ||||
|                 } | ||||
|             }, | ||||
|             additionalProperties: false | ||||
|         }], | ||||
|  | ||||
|         messages: { | ||||
|             missingDefaultCase: "Expected a default case." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const options = context.options[0] || {}; | ||||
|         const commentPattern = options.commentPattern | ||||
|             ? new RegExp(options.commentPattern, "u") | ||||
|             : DEFAULT_COMMENT_PATTERN; | ||||
|  | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Helpers | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         /** | ||||
|          * Shortcut to get last element of array | ||||
|          * @param {*[]} collection Array | ||||
|          * @returns {any} Last element | ||||
|          */ | ||||
|         function last(collection) { | ||||
|             return collection[collection.length - 1]; | ||||
|         } | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Public | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         return { | ||||
|  | ||||
|             SwitchStatement(node) { | ||||
|  | ||||
|                 if (!node.cases.length) { | ||||
|  | ||||
|                     /* | ||||
|                      * skip check of empty switch because there is no easy way | ||||
|                      * to extract comments inside it now | ||||
|                      */ | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 const hasDefault = node.cases.some(v => v.test === null); | ||||
|  | ||||
|                 if (!hasDefault) { | ||||
|  | ||||
|                     let comment; | ||||
|  | ||||
|                     const lastCase = last(node.cases); | ||||
|                     const comments = sourceCode.getCommentsAfter(lastCase); | ||||
|  | ||||
|                     if (comments.length) { | ||||
|                         comment = last(comments); | ||||
|                     } | ||||
|  | ||||
|                     if (!comment || !commentPattern.test(comment.value.trim())) { | ||||
|                         context.report({ node, messageId: "missingDefaultCase" }); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										62
									
								
								node_modules/eslint/lib/rules/default-param-last.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										62
									
								
								node_modules/eslint/lib/rules/default-param-last.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,62 @@ | ||||
| /** | ||||
|  * @fileoverview enforce default parameters to be last | ||||
|  * @author Chiawen Chen | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce default parameters to be last", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/default-param-last" | ||||
|         }, | ||||
|  | ||||
|         schema: [], | ||||
|  | ||||
|         messages: { | ||||
|             shouldBeLast: "Default parameters should be last." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         /** | ||||
|          * Handler for function contexts. | ||||
|          * @param {ASTNode} node function node | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function handleFunction(node) { | ||||
|             let hasSeenPlainParam = false; | ||||
|  | ||||
|             for (let i = node.params.length - 1; i >= 0; i -= 1) { | ||||
|                 const param = node.params[i]; | ||||
|  | ||||
|                 if ( | ||||
|                     param.type !== "AssignmentPattern" && | ||||
|                     param.type !== "RestElement" | ||||
|                 ) { | ||||
|                     hasSeenPlainParam = true; | ||||
|                     continue; | ||||
|                 } | ||||
|  | ||||
|                 if (hasSeenPlainParam && param.type === "AssignmentPattern") { | ||||
|                     context.report({ | ||||
|                         node: param, | ||||
|                         messageId: "shouldBeLast" | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             FunctionDeclaration: handleFunction, | ||||
|             FunctionExpression: handleFunction, | ||||
|             ArrowFunctionExpression: handleFunction | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										108
									
								
								node_modules/eslint/lib/rules/dot-location.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										108
									
								
								node_modules/eslint/lib/rules/dot-location.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,108 @@ | ||||
| /** | ||||
|  * @fileoverview Validates newlines before and after dots | ||||
|  * @author Greg Cochard | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce consistent newlines before and after dots", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/dot-location" | ||||
|         }, | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 enum: ["object", "property"] | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         fixable: "code", | ||||
|  | ||||
|         messages: { | ||||
|             expectedDotAfterObject: "Expected dot to be on same line as object.", | ||||
|             expectedDotBeforeProperty: "Expected dot to be on same line as property." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         const config = context.options[0]; | ||||
|  | ||||
|         // default to onObject if no preference is passed | ||||
|         const onObject = config === "object" || !config; | ||||
|  | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         /** | ||||
|          * Reports if the dot between object and property is on the correct location. | ||||
|          * @param {ASTNode} node The `MemberExpression` node. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function checkDotLocation(node) { | ||||
|             const property = node.property; | ||||
|             const dotToken = sourceCode.getTokenBefore(property); | ||||
|  | ||||
|             if (onObject) { | ||||
|  | ||||
|                 // `obj` expression can be parenthesized, but those paren tokens are not a part of the `obj` node. | ||||
|                 const tokenBeforeDot = sourceCode.getTokenBefore(dotToken); | ||||
|  | ||||
|                 if (!astUtils.isTokenOnSameLine(tokenBeforeDot, dotToken)) { | ||||
|                     context.report({ | ||||
|                         node, | ||||
|                         loc: dotToken.loc, | ||||
|                         messageId: "expectedDotAfterObject", | ||||
|                         *fix(fixer) { | ||||
|                             if (dotToken.value.startsWith(".") && astUtils.isDecimalIntegerNumericToken(tokenBeforeDot)) { | ||||
|                                 yield fixer.insertTextAfter(tokenBeforeDot, ` ${dotToken.value}`); | ||||
|                             } else { | ||||
|                                 yield fixer.insertTextAfter(tokenBeforeDot, dotToken.value); | ||||
|                             } | ||||
|                             yield fixer.remove(dotToken); | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             } else if (!astUtils.isTokenOnSameLine(dotToken, property)) { | ||||
|                 context.report({ | ||||
|                     node, | ||||
|                     loc: dotToken.loc, | ||||
|                     messageId: "expectedDotBeforeProperty", | ||||
|                     *fix(fixer) { | ||||
|                         yield fixer.remove(dotToken); | ||||
|                         yield fixer.insertTextBefore(property, dotToken.value); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks the spacing of the dot within a member expression. | ||||
|          * @param {ASTNode} node The node to check. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function checkNode(node) { | ||||
|             if (!node.computed) { | ||||
|                 checkDotLocation(node); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             MemberExpression: checkNode | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										176
									
								
								node_modules/eslint/lib/rules/dot-notation.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										176
									
								
								node_modules/eslint/lib/rules/dot-notation.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,176 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to warn about using dot notation instead of square bracket notation when possible. | ||||
|  * @author Josh Perez | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
| const keywords = require("./utils/keywords"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const validIdentifier = /^[a-zA-Z_$][a-zA-Z0-9_$]*$/u; | ||||
|  | ||||
| // `null` literal must be handled separately. | ||||
| const literalTypesToCheck = new Set(["string", "boolean"]); | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce dot notation whenever possible", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/dot-notation" | ||||
|         }, | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 type: "object", | ||||
|                 properties: { | ||||
|                     allowKeywords: { | ||||
|                         type: "boolean", | ||||
|                         default: true | ||||
|                     }, | ||||
|                     allowPattern: { | ||||
|                         type: "string", | ||||
|                         default: "" | ||||
|                     } | ||||
|                 }, | ||||
|                 additionalProperties: false | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         fixable: "code", | ||||
|  | ||||
|         messages: { | ||||
|             useDot: "[{{key}}] is better written in dot notation.", | ||||
|             useBrackets: ".{{key}} is a syntax error." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const options = context.options[0] || {}; | ||||
|         const allowKeywords = options.allowKeywords === void 0 || options.allowKeywords; | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         let allowPattern; | ||||
|  | ||||
|         if (options.allowPattern) { | ||||
|             allowPattern = new RegExp(options.allowPattern, "u"); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Check if the property is valid dot notation | ||||
|          * @param {ASTNode} node The dot notation node | ||||
|          * @param {string} value Value which is to be checked | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function checkComputedProperty(node, value) { | ||||
|             if ( | ||||
|                 validIdentifier.test(value) && | ||||
|                 (allowKeywords || !keywords.includes(String(value))) && | ||||
|                 !(allowPattern && allowPattern.test(value)) | ||||
|             ) { | ||||
|                 const formattedValue = node.property.type === "Literal" ? JSON.stringify(value) : `\`${value}\``; | ||||
|  | ||||
|                 context.report({ | ||||
|                     node: node.property, | ||||
|                     messageId: "useDot", | ||||
|                     data: { | ||||
|                         key: formattedValue | ||||
|                     }, | ||||
|                     *fix(fixer) { | ||||
|                         const leftBracket = sourceCode.getTokenAfter(node.object, astUtils.isOpeningBracketToken); | ||||
|                         const rightBracket = sourceCode.getLastToken(node); | ||||
|                         const nextToken = sourceCode.getTokenAfter(node); | ||||
|  | ||||
|                         // Don't perform any fixes if there are comments inside the brackets. | ||||
|                         if (sourceCode.commentsExistBetween(leftBracket, rightBracket)) { | ||||
|                             return; | ||||
|                         } | ||||
|  | ||||
|                         // Replace the brackets by an identifier. | ||||
|                         if (!node.optional) { | ||||
|                             yield fixer.insertTextBefore( | ||||
|                                 leftBracket, | ||||
|                                 astUtils.isDecimalInteger(node.object) ? " ." : "." | ||||
|                             ); | ||||
|                         } | ||||
|                         yield fixer.replaceTextRange( | ||||
|                             [leftBracket.range[0], rightBracket.range[1]], | ||||
|                             value | ||||
|                         ); | ||||
|  | ||||
|                         // Insert a space after the property if it will be connected to the next token. | ||||
|                         if ( | ||||
|                             nextToken && | ||||
|                             rightBracket.range[1] === nextToken.range[0] && | ||||
|                             !astUtils.canTokensBeAdjacent(String(value), nextToken) | ||||
|                         ) { | ||||
|                             yield fixer.insertTextAfter(node, " "); | ||||
|                         } | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             MemberExpression(node) { | ||||
|                 if ( | ||||
|                     node.computed && | ||||
|                     node.property.type === "Literal" && | ||||
|                     (literalTypesToCheck.has(typeof node.property.value) || astUtils.isNullLiteral(node.property)) | ||||
|                 ) { | ||||
|                     checkComputedProperty(node, node.property.value); | ||||
|                 } | ||||
|                 if ( | ||||
|                     node.computed && | ||||
|                     astUtils.isStaticTemplateLiteral(node.property) | ||||
|                 ) { | ||||
|                     checkComputedProperty(node, node.property.quasis[0].value.cooked); | ||||
|                 } | ||||
|                 if ( | ||||
|                     !allowKeywords && | ||||
|                     !node.computed && | ||||
|                     node.property.type === "Identifier" && | ||||
|                     keywords.includes(String(node.property.name)) | ||||
|                 ) { | ||||
|                     context.report({ | ||||
|                         node: node.property, | ||||
|                         messageId: "useBrackets", | ||||
|                         data: { | ||||
|                             key: node.property.name | ||||
|                         }, | ||||
|                         *fix(fixer) { | ||||
|                             const dotToken = sourceCode.getTokenBefore(node.property); | ||||
|  | ||||
|                             // A statement that starts with `let[` is parsed as a destructuring variable declaration, not a MemberExpression. | ||||
|                             if (node.object.type === "Identifier" && node.object.name === "let" && !node.optional) { | ||||
|                                 return; | ||||
|                             } | ||||
|  | ||||
|                             // Don't perform any fixes if there are comments between the dot and the property name. | ||||
|                             if (sourceCode.commentsExistBetween(dotToken, node.property)) { | ||||
|                                 return; | ||||
|                             } | ||||
|  | ||||
|                             // Replace the identifier to brackets. | ||||
|                             if (!node.optional) { | ||||
|                                 yield fixer.remove(dotToken); | ||||
|                             } | ||||
|                             yield fixer.replaceText(node.property, `["${node.property.name}"]`); | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										115
									
								
								node_modules/eslint/lib/rules/eol-last.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										115
									
								
								node_modules/eslint/lib/rules/eol-last.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,115 @@ | ||||
| /** | ||||
|  * @fileoverview Require or disallow newline at the end of files | ||||
|  * @author Nodeca Team <https://github.com/nodeca> | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require or disallow newline at the end of files", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/eol-last" | ||||
|         }, | ||||
|  | ||||
|         fixable: "whitespace", | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 enum: ["always", "never", "unix", "windows"] | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             missing: "Newline required at end of file but not found.", | ||||
|             unexpected: "Newline not allowed at end of file." | ||||
|         } | ||||
|     }, | ||||
|     create(context) { | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Public | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         return { | ||||
|             Program: function checkBadEOF(node) { | ||||
|                 const sourceCode = context.sourceCode, | ||||
|                     src = sourceCode.getText(), | ||||
|                     lastLine = sourceCode.lines[sourceCode.lines.length - 1], | ||||
|                     location = { | ||||
|                         column: lastLine.length, | ||||
|                         line: sourceCode.lines.length | ||||
|                     }, | ||||
|                     LF = "\n", | ||||
|                     CRLF = `\r${LF}`, | ||||
|                     endsWithNewline = src.endsWith(LF); | ||||
|  | ||||
|                 /* | ||||
|                  * Empty source is always valid: No content in file so we don't | ||||
|                  * need to lint for a newline on the last line of content. | ||||
|                  */ | ||||
|                 if (!src.length) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 let mode = context.options[0] || "always", | ||||
|                     appendCRLF = false; | ||||
|  | ||||
|                 if (mode === "unix") { | ||||
|  | ||||
|                     // `"unix"` should behave exactly as `"always"` | ||||
|                     mode = "always"; | ||||
|                 } | ||||
|                 if (mode === "windows") { | ||||
|  | ||||
|                     // `"windows"` should behave exactly as `"always"`, but append CRLF in the fixer for backwards compatibility | ||||
|                     mode = "always"; | ||||
|                     appendCRLF = true; | ||||
|                 } | ||||
|                 if (mode === "always" && !endsWithNewline) { | ||||
|  | ||||
|                     // File is not newline-terminated, but should be | ||||
|                     context.report({ | ||||
|                         node, | ||||
|                         loc: location, | ||||
|                         messageId: "missing", | ||||
|                         fix(fixer) { | ||||
|                             return fixer.insertTextAfterRange([0, src.length], appendCRLF ? CRLF : LF); | ||||
|                         } | ||||
|                     }); | ||||
|                 } else if (mode === "never" && endsWithNewline) { | ||||
|  | ||||
|                     const secondLastLine = sourceCode.lines[sourceCode.lines.length - 2]; | ||||
|  | ||||
|                     // File is newline-terminated, but shouldn't be | ||||
|                     context.report({ | ||||
|                         node, | ||||
|                         loc: { | ||||
|                             start: { line: sourceCode.lines.length - 1, column: secondLastLine.length }, | ||||
|                             end: { line: sourceCode.lines.length, column: 0 } | ||||
|                         }, | ||||
|                         messageId: "unexpected", | ||||
|                         fix(fixer) { | ||||
|                             const finalEOLs = /(?:\r?\n)+$/u, | ||||
|                                 match = finalEOLs.exec(sourceCode.text), | ||||
|                                 start = match.index, | ||||
|                                 end = sourceCode.text.length; | ||||
|  | ||||
|                             return fixer.replaceTextRange([start, end], ""); | ||||
|                         } | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										174
									
								
								node_modules/eslint/lib/rules/eqeqeq.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										174
									
								
								node_modules/eslint/lib/rules/eqeqeq.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,174 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to flag statements that use != and == instead of !== and === | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require the use of `===` and `!==`", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/eqeqeq" | ||||
|         }, | ||||
|  | ||||
|         schema: { | ||||
|             anyOf: [ | ||||
|                 { | ||||
|                     type: "array", | ||||
|                     items: [ | ||||
|                         { | ||||
|                             enum: ["always"] | ||||
|                         }, | ||||
|                         { | ||||
|                             type: "object", | ||||
|                             properties: { | ||||
|                                 null: { | ||||
|                                     enum: ["always", "never", "ignore"] | ||||
|                                 } | ||||
|                             }, | ||||
|                             additionalProperties: false | ||||
|                         } | ||||
|                     ], | ||||
|                     additionalItems: false | ||||
|                 }, | ||||
|                 { | ||||
|                     type: "array", | ||||
|                     items: [ | ||||
|                         { | ||||
|                             enum: ["smart", "allow-null"] | ||||
|                         } | ||||
|                     ], | ||||
|                     additionalItems: false | ||||
|                 } | ||||
|             ] | ||||
|         }, | ||||
|  | ||||
|         fixable: "code", | ||||
|  | ||||
|         messages: { | ||||
|             unexpected: "Expected '{{expectedOperator}}' and instead saw '{{actualOperator}}'." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const config = context.options[0] || "always"; | ||||
|         const options = context.options[1] || {}; | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         const nullOption = (config === "always") | ||||
|             ? options.null || "always" | ||||
|             : "ignore"; | ||||
|         const enforceRuleForNull = (nullOption === "always"); | ||||
|         const enforceInverseRuleForNull = (nullOption === "never"); | ||||
|  | ||||
|         /** | ||||
|          * Checks if an expression is a typeof expression | ||||
|          * @param {ASTNode} node The node to check | ||||
|          * @returns {boolean} if the node is a typeof expression | ||||
|          */ | ||||
|         function isTypeOf(node) { | ||||
|             return node.type === "UnaryExpression" && node.operator === "typeof"; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks if either operand of a binary expression is a typeof operation | ||||
|          * @param {ASTNode} node The node to check | ||||
|          * @returns {boolean} if one of the operands is typeof | ||||
|          * @private | ||||
|          */ | ||||
|         function isTypeOfBinary(node) { | ||||
|             return isTypeOf(node.left) || isTypeOf(node.right); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks if operands are literals of the same type (via typeof) | ||||
|          * @param {ASTNode} node The node to check | ||||
|          * @returns {boolean} if operands are of same type | ||||
|          * @private | ||||
|          */ | ||||
|         function areLiteralsAndSameType(node) { | ||||
|             return node.left.type === "Literal" && node.right.type === "Literal" && | ||||
|                     typeof node.left.value === typeof node.right.value; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks if one of the operands is a literal null | ||||
|          * @param {ASTNode} node The node to check | ||||
|          * @returns {boolean} if operands are null | ||||
|          * @private | ||||
|          */ | ||||
|         function isNullCheck(node) { | ||||
|             return astUtils.isNullLiteral(node.right) || astUtils.isNullLiteral(node.left); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports a message for this rule. | ||||
|          * @param {ASTNode} node The binary expression node that was checked | ||||
|          * @param {string} expectedOperator The operator that was expected (either '==', '!=', '===', or '!==') | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function report(node, expectedOperator) { | ||||
|             const operatorToken = sourceCode.getFirstTokenBetween( | ||||
|                 node.left, | ||||
|                 node.right, | ||||
|                 token => token.value === node.operator | ||||
|             ); | ||||
|  | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 loc: operatorToken.loc, | ||||
|                 messageId: "unexpected", | ||||
|                 data: { expectedOperator, actualOperator: node.operator }, | ||||
|                 fix(fixer) { | ||||
|  | ||||
|                     // If the comparison is a `typeof` comparison or both sides are literals with the same type, then it's safe to fix. | ||||
|                     if (isTypeOfBinary(node) || areLiteralsAndSameType(node)) { | ||||
|                         return fixer.replaceText(operatorToken, expectedOperator); | ||||
|                     } | ||||
|                     return null; | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             BinaryExpression(node) { | ||||
|                 const isNull = isNullCheck(node); | ||||
|  | ||||
|                 if (node.operator !== "==" && node.operator !== "!=") { | ||||
|                     if (enforceInverseRuleForNull && isNull) { | ||||
|                         report(node, node.operator.slice(0, -1)); | ||||
|                     } | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 if (config === "smart" && (isTypeOfBinary(node) || | ||||
|                         areLiteralsAndSameType(node) || isNull)) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 if (!enforceRuleForNull && isNull) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 report(node, `${node.operator}=`); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										140
									
								
								node_modules/eslint/lib/rules/for-direction.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										140
									
								
								node_modules/eslint/lib/rules/for-direction.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,140 @@ | ||||
| /** | ||||
|  * @fileoverview enforce "for" loop update clause moving the counter in the right direction.(for-direction) | ||||
|  * @author Aladdin-ADD<hh_2013@foxmail.com> | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const { getStaticValue } = require("@eslint-community/eslint-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "problem", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce \"for\" loop update clause moving the counter in the right direction", | ||||
|             recommended: true, | ||||
|             url: "https://eslint.org/docs/latest/rules/for-direction" | ||||
|         }, | ||||
|  | ||||
|         fixable: null, | ||||
|         schema: [], | ||||
|  | ||||
|         messages: { | ||||
|             incorrectDirection: "The update clause in this loop moves the variable in the wrong direction." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const { sourceCode } = context; | ||||
|  | ||||
|         /** | ||||
|          * report an error. | ||||
|          * @param {ASTNode} node the node to report. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function report(node) { | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 messageId: "incorrectDirection" | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * check the right side of the assignment | ||||
|          * @param {ASTNode} update UpdateExpression to check | ||||
|          * @param {int} dir expected direction that could either be turned around or invalidated | ||||
|          * @returns {int} return dir, the negated dir, or zero if the counter does not change or the direction is not clear | ||||
|          */ | ||||
|         function getRightDirection(update, dir) { | ||||
|             const staticValue = getStaticValue(update.right, sourceCode.getScope(update)); | ||||
|  | ||||
|             if (staticValue && ["bigint", "boolean", "number"].includes(typeof staticValue.value)) { | ||||
|                 const sign = Math.sign(Number(staticValue.value)) || 0; // convert NaN to 0 | ||||
|  | ||||
|                 return dir * sign; | ||||
|             } | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * check UpdateExpression add/sub the counter | ||||
|          * @param {ASTNode} update UpdateExpression to check | ||||
|          * @param {string} counter variable name to check | ||||
|          * @returns {int} if add return 1, if sub return -1, if nochange, return 0 | ||||
|          */ | ||||
|         function getUpdateDirection(update, counter) { | ||||
|             if (update.argument.type === "Identifier" && update.argument.name === counter) { | ||||
|                 if (update.operator === "++") { | ||||
|                     return 1; | ||||
|                 } | ||||
|                 if (update.operator === "--") { | ||||
|                     return -1; | ||||
|                 } | ||||
|             } | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * check AssignmentExpression add/sub the counter | ||||
|          * @param {ASTNode} update AssignmentExpression to check | ||||
|          * @param {string} counter variable name to check | ||||
|          * @returns {int} if add return 1, if sub return -1, if nochange, return 0 | ||||
|          */ | ||||
|         function getAssignmentDirection(update, counter) { | ||||
|             if (update.left.name === counter) { | ||||
|                 if (update.operator === "+=") { | ||||
|                     return getRightDirection(update, 1); | ||||
|                 } | ||||
|                 if (update.operator === "-=") { | ||||
|                     return getRightDirection(update, -1); | ||||
|                 } | ||||
|             } | ||||
|             return 0; | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             ForStatement(node) { | ||||
|  | ||||
|                 if (node.test && node.test.type === "BinaryExpression" && node.update) { | ||||
|                     for (const counterPosition of ["left", "right"]) { | ||||
|                         if (node.test[counterPosition].type !== "Identifier") { | ||||
|                             continue; | ||||
|                         } | ||||
|  | ||||
|                         const counter = node.test[counterPosition].name; | ||||
|                         const operator = node.test.operator; | ||||
|                         const update = node.update; | ||||
|  | ||||
|                         let wrongDirection; | ||||
|  | ||||
|                         if (operator === "<" || operator === "<=") { | ||||
|                             wrongDirection = counterPosition === "left" ? -1 : 1; | ||||
|                         } else if (operator === ">" || operator === ">=") { | ||||
|                             wrongDirection = counterPosition === "left" ? 1 : -1; | ||||
|                         } else { | ||||
|                             return; | ||||
|                         } | ||||
|  | ||||
|                         if (update.type === "UpdateExpression") { | ||||
|                             if (getUpdateDirection(update, counter) === wrongDirection) { | ||||
|                                 report(node); | ||||
|                             } | ||||
|                         } else if (update.type === "AssignmentExpression" && getAssignmentDirection(update, counter) === wrongDirection) { | ||||
|                             report(node); | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										233
									
								
								node_modules/eslint/lib/rules/func-call-spacing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										233
									
								
								node_modules/eslint/lib/rules/func-call-spacing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,233 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to control spacing within function calls | ||||
|  * @author Matt DuVall <http://www.mattduvall.com> | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require or disallow spacing between function identifiers and their invocations", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/func-call-spacing" | ||||
|         }, | ||||
|  | ||||
|         fixable: "whitespace", | ||||
|  | ||||
|         schema: { | ||||
|             anyOf: [ | ||||
|                 { | ||||
|                     type: "array", | ||||
|                     items: [ | ||||
|                         { | ||||
|                             enum: ["never"] | ||||
|                         } | ||||
|                     ], | ||||
|                     minItems: 0, | ||||
|                     maxItems: 1 | ||||
|                 }, | ||||
|                 { | ||||
|                     type: "array", | ||||
|                     items: [ | ||||
|                         { | ||||
|                             enum: ["always"] | ||||
|                         }, | ||||
|                         { | ||||
|                             type: "object", | ||||
|                             properties: { | ||||
|                                 allowNewlines: { | ||||
|                                     type: "boolean" | ||||
|                                 } | ||||
|                             }, | ||||
|                             additionalProperties: false | ||||
|                         } | ||||
|                     ], | ||||
|                     minItems: 0, | ||||
|                     maxItems: 2 | ||||
|                 } | ||||
|             ] | ||||
|         }, | ||||
|  | ||||
|         messages: { | ||||
|             unexpectedWhitespace: "Unexpected whitespace between function name and paren.", | ||||
|             unexpectedNewline: "Unexpected newline between function name and paren.", | ||||
|             missing: "Missing space between function name and paren." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         const never = context.options[0] !== "always"; | ||||
|         const allowNewlines = !never && context.options[1] && context.options[1].allowNewlines; | ||||
|         const sourceCode = context.sourceCode; | ||||
|         const text = sourceCode.getText(); | ||||
|  | ||||
|         /** | ||||
|          * Check if open space is present in a function name | ||||
|          * @param {ASTNode} node node to evaluate | ||||
|          * @param {Token} leftToken The last token of the callee. This may be the closing parenthesis that encloses the callee. | ||||
|          * @param {Token} rightToken Tha first token of the arguments. this is the opening parenthesis that encloses the arguments. | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function checkSpacing(node, leftToken, rightToken) { | ||||
|             const textBetweenTokens = text.slice(leftToken.range[1], rightToken.range[0]).replace(/\/\*.*?\*\//gu, ""); | ||||
|             const hasWhitespace = /\s/u.test(textBetweenTokens); | ||||
|             const hasNewline = hasWhitespace && astUtils.LINEBREAK_MATCHER.test(textBetweenTokens); | ||||
|  | ||||
|             /* | ||||
|              * never allowNewlines hasWhitespace hasNewline message | ||||
|              * F     F             F             F          Missing space between function name and paren. | ||||
|              * F     F             F             T          (Invalid `!hasWhitespace && hasNewline`) | ||||
|              * F     F             T             T          Unexpected newline between function name and paren. | ||||
|              * F     F             T             F          (OK) | ||||
|              * F     T             T             F          (OK) | ||||
|              * F     T             T             T          (OK) | ||||
|              * F     T             F             T          (Invalid `!hasWhitespace && hasNewline`) | ||||
|              * F     T             F             F          Missing space between function name and paren. | ||||
|              * T     T             F             F          (Invalid `never && allowNewlines`) | ||||
|              * T     T             F             T          (Invalid `!hasWhitespace && hasNewline`) | ||||
|              * T     T             T             T          (Invalid `never && allowNewlines`) | ||||
|              * T     T             T             F          (Invalid `never && allowNewlines`) | ||||
|              * T     F             T             F          Unexpected space between function name and paren. | ||||
|              * T     F             T             T          Unexpected space between function name and paren. | ||||
|              * T     F             F             T          (Invalid `!hasWhitespace && hasNewline`) | ||||
|              * T     F             F             F          (OK) | ||||
|              * | ||||
|              * T                   T                        Unexpected space between function name and paren. | ||||
|              * F                   F                        Missing space between function name and paren. | ||||
|              * F     F                           T          Unexpected newline between function name and paren. | ||||
|              */ | ||||
|  | ||||
|             if (never && hasWhitespace) { | ||||
|                 context.report({ | ||||
|                     node, | ||||
|                     loc: { | ||||
|                         start: leftToken.loc.end, | ||||
|                         end: { | ||||
|                             line: rightToken.loc.start.line, | ||||
|                             column: rightToken.loc.start.column - 1 | ||||
|                         } | ||||
|                     }, | ||||
|                     messageId: "unexpectedWhitespace", | ||||
|                     fix(fixer) { | ||||
|  | ||||
|                         // Don't remove comments. | ||||
|                         if (sourceCode.commentsExistBetween(leftToken, rightToken)) { | ||||
|                             return null; | ||||
|                         } | ||||
|  | ||||
|                         // If `?.` exists, it doesn't hide no-unexpected-multiline errors | ||||
|                         if (node.optional) { | ||||
|                             return fixer.replaceTextRange([leftToken.range[1], rightToken.range[0]], "?."); | ||||
|                         } | ||||
|  | ||||
|                         /* | ||||
|                          * Only autofix if there is no newline | ||||
|                          * https://github.com/eslint/eslint/issues/7787 | ||||
|                          */ | ||||
|                         if (hasNewline) { | ||||
|                             return null; | ||||
|                         } | ||||
|                         return fixer.removeRange([leftToken.range[1], rightToken.range[0]]); | ||||
|                     } | ||||
|                 }); | ||||
|             } else if (!never && !hasWhitespace) { | ||||
|                 context.report({ | ||||
|                     node, | ||||
|                     loc: { | ||||
|                         start: { | ||||
|                             line: leftToken.loc.end.line, | ||||
|                             column: leftToken.loc.end.column - 1 | ||||
|                         }, | ||||
|                         end: rightToken.loc.start | ||||
|                     }, | ||||
|                     messageId: "missing", | ||||
|                     fix(fixer) { | ||||
|                         if (node.optional) { | ||||
|                             return null; // Not sure if inserting a space to either before/after `?.` token. | ||||
|                         } | ||||
|                         return fixer.insertTextBefore(rightToken, " "); | ||||
|                     } | ||||
|                 }); | ||||
|             } else if (!never && !allowNewlines && hasNewline) { | ||||
|                 context.report({ | ||||
|                     node, | ||||
|                     loc: { | ||||
|                         start: leftToken.loc.end, | ||||
|                         end: rightToken.loc.start | ||||
|                     }, | ||||
|                     messageId: "unexpectedNewline", | ||||
|                     fix(fixer) { | ||||
|  | ||||
|                         /* | ||||
|                          * Only autofix if there is no newline | ||||
|                          * https://github.com/eslint/eslint/issues/7787 | ||||
|                          * But if `?.` exists, it doesn't hide no-unexpected-multiline errors | ||||
|                          */ | ||||
|                         if (!node.optional) { | ||||
|                             return null; | ||||
|                         } | ||||
|  | ||||
|                         // Don't remove comments. | ||||
|                         if (sourceCode.commentsExistBetween(leftToken, rightToken)) { | ||||
|                             return null; | ||||
|                         } | ||||
|  | ||||
|                         const range = [leftToken.range[1], rightToken.range[0]]; | ||||
|                         const qdToken = sourceCode.getTokenAfter(leftToken); | ||||
|  | ||||
|                         if (qdToken.range[0] === leftToken.range[1]) { | ||||
|                             return fixer.replaceTextRange(range, "?. "); | ||||
|                         } | ||||
|                         if (qdToken.range[1] === rightToken.range[0]) { | ||||
|                             return fixer.replaceTextRange(range, " ?."); | ||||
|                         } | ||||
|                         return fixer.replaceTextRange(range, " ?. "); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             "CallExpression, NewExpression"(node) { | ||||
|                 const lastToken = sourceCode.getLastToken(node); | ||||
|                 const lastCalleeToken = sourceCode.getLastToken(node.callee); | ||||
|                 const parenToken = sourceCode.getFirstTokenBetween(lastCalleeToken, lastToken, astUtils.isOpeningParenToken); | ||||
|                 const prevToken = parenToken && sourceCode.getTokenBefore(parenToken, astUtils.isNotQuestionDotToken); | ||||
|  | ||||
|                 // Parens in NewExpression are optional | ||||
|                 if (!(parenToken && parenToken.range[1] < node.range[1])) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 checkSpacing(node, prevToken, parenToken); | ||||
|             }, | ||||
|  | ||||
|             ImportExpression(node) { | ||||
|                 const leftToken = sourceCode.getFirstToken(node); | ||||
|                 const rightToken = sourceCode.getTokenAfter(leftToken); | ||||
|  | ||||
|                 checkSpacing(node, leftToken, rightToken); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										253
									
								
								node_modules/eslint/lib/rules/func-name-matching.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										253
									
								
								node_modules/eslint/lib/rules/func-name-matching.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,253 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to require function names to match the name of the variable or property to which they are assigned. | ||||
|  * @author Annie Zhang, Pavel Strashkin | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //-------------------------------------------------------------------------- | ||||
| // Requirements | ||||
| //-------------------------------------------------------------------------- | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
| const esutils = require("esutils"); | ||||
|  | ||||
| //-------------------------------------------------------------------------- | ||||
| // Helpers | ||||
| //-------------------------------------------------------------------------- | ||||
|  | ||||
| /** | ||||
|  * Determines if a pattern is `module.exports` or `module["exports"]` | ||||
|  * @param {ASTNode} pattern The left side of the AssignmentExpression | ||||
|  * @returns {boolean} True if the pattern is `module.exports` or `module["exports"]` | ||||
|  */ | ||||
| function isModuleExports(pattern) { | ||||
|     if (pattern.type === "MemberExpression" && pattern.object.type === "Identifier" && pattern.object.name === "module") { | ||||
|  | ||||
|         // module.exports | ||||
|         if (pattern.property.type === "Identifier" && pattern.property.name === "exports") { | ||||
|             return true; | ||||
|         } | ||||
|  | ||||
|         // module["exports"] | ||||
|         if (pattern.property.type === "Literal" && pattern.property.value === "exports") { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Determines if a string name is a valid identifier | ||||
|  * @param {string} name The string to be checked | ||||
|  * @param {int} ecmaVersion The ECMAScript version if specified in the parserOptions config | ||||
|  * @returns {boolean} True if the string is a valid identifier | ||||
|  */ | ||||
| function isIdentifier(name, ecmaVersion) { | ||||
|     if (ecmaVersion >= 2015) { | ||||
|         return esutils.keyword.isIdentifierES6(name); | ||||
|     } | ||||
|     return esutils.keyword.isIdentifierES5(name); | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const alwaysOrNever = { enum: ["always", "never"] }; | ||||
| const optionsObject = { | ||||
|     type: "object", | ||||
|     properties: { | ||||
|         considerPropertyDescriptor: { | ||||
|             type: "boolean" | ||||
|         }, | ||||
|         includeCommonJSModuleExports: { | ||||
|             type: "boolean" | ||||
|         } | ||||
|     }, | ||||
|     additionalProperties: false | ||||
| }; | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require function names to match the name of the variable or property to which they are assigned", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/func-name-matching" | ||||
|         }, | ||||
|  | ||||
|         schema: { | ||||
|             anyOf: [{ | ||||
|                 type: "array", | ||||
|                 additionalItems: false, | ||||
|                 items: [alwaysOrNever, optionsObject] | ||||
|             }, { | ||||
|                 type: "array", | ||||
|                 additionalItems: false, | ||||
|                 items: [optionsObject] | ||||
|             }] | ||||
|         }, | ||||
|  | ||||
|         messages: { | ||||
|             matchProperty: "Function name `{{funcName}}` should match property name `{{name}}`.", | ||||
|             matchVariable: "Function name `{{funcName}}` should match variable name `{{name}}`.", | ||||
|             notMatchProperty: "Function name `{{funcName}}` should not match property name `{{name}}`.", | ||||
|             notMatchVariable: "Function name `{{funcName}}` should not match variable name `{{name}}`." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const options = (typeof context.options[0] === "object" ? context.options[0] : context.options[1]) || {}; | ||||
|         const nameMatches = typeof context.options[0] === "string" ? context.options[0] : "always"; | ||||
|         const considerPropertyDescriptor = options.considerPropertyDescriptor; | ||||
|         const includeModuleExports = options.includeCommonJSModuleExports; | ||||
|         const ecmaVersion = context.languageOptions.ecmaVersion; | ||||
|  | ||||
|         /** | ||||
|          * Check whether node is a certain CallExpression. | ||||
|          * @param {string} objName object name | ||||
|          * @param {string} funcName function name | ||||
|          * @param {ASTNode} node The node to check | ||||
|          * @returns {boolean} `true` if node matches CallExpression | ||||
|          */ | ||||
|         function isPropertyCall(objName, funcName, node) { | ||||
|             if (!node) { | ||||
|                 return false; | ||||
|             } | ||||
|             return node.type === "CallExpression" && astUtils.isSpecificMemberAccess(node.callee, objName, funcName); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Compares identifiers based on the nameMatches option | ||||
|          * @param {string} x the first identifier | ||||
|          * @param {string} y the second identifier | ||||
|          * @returns {boolean} whether the two identifiers should warn. | ||||
|          */ | ||||
|         function shouldWarn(x, y) { | ||||
|             return (nameMatches === "always" && x !== y) || (nameMatches === "never" && x === y); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports | ||||
|          * @param {ASTNode} node The node to report | ||||
|          * @param {string} name The variable or property name | ||||
|          * @param {string} funcName The function name | ||||
|          * @param {boolean} isProp True if the reported node is a property assignment | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function report(node, name, funcName, isProp) { | ||||
|             let messageId; | ||||
|  | ||||
|             if (nameMatches === "always" && isProp) { | ||||
|                 messageId = "matchProperty"; | ||||
|             } else if (nameMatches === "always") { | ||||
|                 messageId = "matchVariable"; | ||||
|             } else if (isProp) { | ||||
|                 messageId = "notMatchProperty"; | ||||
|             } else { | ||||
|                 messageId = "notMatchVariable"; | ||||
|             } | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 messageId, | ||||
|                 data: { | ||||
|                     name, | ||||
|                     funcName | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines whether a given node is a string literal | ||||
|          * @param {ASTNode} node The node to check | ||||
|          * @returns {boolean} `true` if the node is a string literal | ||||
|          */ | ||||
|         function isStringLiteral(node) { | ||||
|             return node.type === "Literal" && typeof node.value === "string"; | ||||
|         } | ||||
|  | ||||
|         //-------------------------------------------------------------------------- | ||||
|         // Public | ||||
|         //-------------------------------------------------------------------------- | ||||
|  | ||||
|         return { | ||||
|             VariableDeclarator(node) { | ||||
|                 if (!node.init || node.init.type !== "FunctionExpression" || node.id.type !== "Identifier") { | ||||
|                     return; | ||||
|                 } | ||||
|                 if (node.init.id && shouldWarn(node.id.name, node.init.id.name)) { | ||||
|                     report(node, node.id.name, node.init.id.name, false); | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             AssignmentExpression(node) { | ||||
|                 if ( | ||||
|                     node.right.type !== "FunctionExpression" || | ||||
|                     (node.left.computed && node.left.property.type !== "Literal") || | ||||
|                     (!includeModuleExports && isModuleExports(node.left)) || | ||||
|                     (node.left.type !== "Identifier" && node.left.type !== "MemberExpression") | ||||
|                 ) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 const isProp = node.left.type === "MemberExpression"; | ||||
|                 const name = isProp ? astUtils.getStaticPropertyName(node.left) : node.left.name; | ||||
|  | ||||
|                 if (node.right.id && name && isIdentifier(name) && shouldWarn(name, node.right.id.name)) { | ||||
|                     report(node, name, node.right.id.name, isProp); | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             "Property, PropertyDefinition[value]"(node) { | ||||
|                 if (!(node.value.type === "FunctionExpression" && node.value.id)) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 if (node.key.type === "Identifier" && !node.computed) { | ||||
|                     const functionName = node.value.id.name; | ||||
|                     let propertyName = node.key.name; | ||||
|  | ||||
|                     if ( | ||||
|                         considerPropertyDescriptor && | ||||
|                         propertyName === "value" && | ||||
|                         node.parent.type === "ObjectExpression" | ||||
|                     ) { | ||||
|                         if (isPropertyCall("Object", "defineProperty", node.parent.parent) || isPropertyCall("Reflect", "defineProperty", node.parent.parent)) { | ||||
|                             const property = node.parent.parent.arguments[1]; | ||||
|  | ||||
|                             if (isStringLiteral(property) && shouldWarn(property.value, functionName)) { | ||||
|                                 report(node, property.value, functionName, true); | ||||
|                             } | ||||
|                         } else if (isPropertyCall("Object", "defineProperties", node.parent.parent.parent.parent)) { | ||||
|                             propertyName = node.parent.parent.key.name; | ||||
|                             if (!node.parent.parent.computed && shouldWarn(propertyName, functionName)) { | ||||
|                                 report(node, propertyName, functionName, true); | ||||
|                             } | ||||
|                         } else if (isPropertyCall("Object", "create", node.parent.parent.parent.parent)) { | ||||
|                             propertyName = node.parent.parent.key.name; | ||||
|                             if (!node.parent.parent.computed && shouldWarn(propertyName, functionName)) { | ||||
|                                 report(node, propertyName, functionName, true); | ||||
|                             } | ||||
|                         } else if (shouldWarn(propertyName, functionName)) { | ||||
|                             report(node, propertyName, functionName, true); | ||||
|                         } | ||||
|                     } else if (shouldWarn(propertyName, functionName)) { | ||||
|                         report(node, propertyName, functionName, true); | ||||
|                     } | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 if ( | ||||
|                     isStringLiteral(node.key) && | ||||
|                     isIdentifier(node.key.value, ecmaVersion) && | ||||
|                     shouldWarn(node.key.value, node.value.id.name) | ||||
|                 ) { | ||||
|                     report(node, node.key.value, node.value.id.name, true); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										191
									
								
								node_modules/eslint/lib/rules/func-names.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										191
									
								
								node_modules/eslint/lib/rules/func-names.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,191 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to warn when a function expression does not have a name. | ||||
|  * @author Kyle T. Nunery | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| /** | ||||
|  * Checks whether or not a given variable is a function name. | ||||
|  * @param {eslint-scope.Variable} variable A variable to check. | ||||
|  * @returns {boolean} `true` if the variable is a function name. | ||||
|  */ | ||||
| function isFunctionName(variable) { | ||||
|     return variable && variable.defs[0].type === "FunctionName"; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require or disallow named `function` expressions", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/func-names" | ||||
|         }, | ||||
|  | ||||
|         schema: { | ||||
|             definitions: { | ||||
|                 value: { | ||||
|                     enum: [ | ||||
|                         "always", | ||||
|                         "as-needed", | ||||
|                         "never" | ||||
|                     ] | ||||
|                 } | ||||
|             }, | ||||
|             items: [ | ||||
|                 { | ||||
|                     $ref: "#/definitions/value" | ||||
|                 }, | ||||
|                 { | ||||
|                     type: "object", | ||||
|                     properties: { | ||||
|                         generators: { | ||||
|                             $ref: "#/definitions/value" | ||||
|                         } | ||||
|                     }, | ||||
|                     additionalProperties: false | ||||
|                 } | ||||
|             ] | ||||
|         }, | ||||
|  | ||||
|         messages: { | ||||
|             unnamed: "Unexpected unnamed {{name}}.", | ||||
|             named: "Unexpected named {{name}}." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         /** | ||||
|          * Returns the config option for the given node. | ||||
|          * @param {ASTNode} node A node to get the config for. | ||||
|          * @returns {string} The config option. | ||||
|          */ | ||||
|         function getConfigForNode(node) { | ||||
|             if ( | ||||
|                 node.generator && | ||||
|                 context.options.length > 1 && | ||||
|                 context.options[1].generators | ||||
|             ) { | ||||
|                 return context.options[1].generators; | ||||
|             } | ||||
|  | ||||
|             return context.options[0] || "always"; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines whether the current FunctionExpression node is a get, set, or | ||||
|          * shorthand method in an object literal or a class. | ||||
|          * @param {ASTNode} node A node to check. | ||||
|          * @returns {boolean} True if the node is a get, set, or shorthand method. | ||||
|          */ | ||||
|         function isObjectOrClassMethod(node) { | ||||
|             const parent = node.parent; | ||||
|  | ||||
|             return (parent.type === "MethodDefinition" || ( | ||||
|                 parent.type === "Property" && ( | ||||
|                     parent.method || | ||||
|                     parent.kind === "get" || | ||||
|                     parent.kind === "set" | ||||
|                 ) | ||||
|             )); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines whether the current FunctionExpression node has a name that would be | ||||
|          * inferred from context in a conforming ES6 environment. | ||||
|          * @param {ASTNode} node A node to check. | ||||
|          * @returns {boolean} True if the node would have a name assigned automatically. | ||||
|          */ | ||||
|         function hasInferredName(node) { | ||||
|             const parent = node.parent; | ||||
|  | ||||
|             return isObjectOrClassMethod(node) || | ||||
|                 (parent.type === "VariableDeclarator" && parent.id.type === "Identifier" && parent.init === node) || | ||||
|                 (parent.type === "Property" && parent.value === node) || | ||||
|                 (parent.type === "PropertyDefinition" && parent.value === node) || | ||||
|                 (parent.type === "AssignmentExpression" && parent.left.type === "Identifier" && parent.right === node) || | ||||
|                 (parent.type === "AssignmentPattern" && parent.left.type === "Identifier" && parent.right === node); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports that an unnamed function should be named | ||||
|          * @param {ASTNode} node The node to report in the event of an error. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportUnexpectedUnnamedFunction(node) { | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 messageId: "unnamed", | ||||
|                 loc: astUtils.getFunctionHeadLoc(node, sourceCode), | ||||
|                 data: { name: astUtils.getFunctionNameWithKind(node) } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports that a named function should be unnamed | ||||
|          * @param {ASTNode} node The node to report in the event of an error. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function reportUnexpectedNamedFunction(node) { | ||||
|             context.report({ | ||||
|                 node, | ||||
|                 messageId: "named", | ||||
|                 loc: astUtils.getFunctionHeadLoc(node, sourceCode), | ||||
|                 data: { name: astUtils.getFunctionNameWithKind(node) } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * The listener for function nodes. | ||||
|          * @param {ASTNode} node function node | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function handleFunction(node) { | ||||
|  | ||||
|             // Skip recursive functions. | ||||
|             const nameVar = sourceCode.getDeclaredVariables(node)[0]; | ||||
|  | ||||
|             if (isFunctionName(nameVar) && nameVar.references.length > 0) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             const hasName = Boolean(node.id && node.id.name); | ||||
|             const config = getConfigForNode(node); | ||||
|  | ||||
|             if (config === "never") { | ||||
|                 if (hasName && node.type !== "FunctionDeclaration") { | ||||
|                     reportUnexpectedNamedFunction(node); | ||||
|                 } | ||||
|             } else if (config === "as-needed") { | ||||
|                 if (!hasName && !hasInferredName(node)) { | ||||
|                     reportUnexpectedUnnamedFunction(node); | ||||
|                 } | ||||
|             } else { | ||||
|                 if (!hasName && !isObjectOrClassMethod(node)) { | ||||
|                     reportUnexpectedUnnamedFunction(node); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             "FunctionExpression:exit": handleFunction, | ||||
|             "ExportDefaultDeclaration > FunctionDeclaration": handleFunction | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										98
									
								
								node_modules/eslint/lib/rules/func-style.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										98
									
								
								node_modules/eslint/lib/rules/func-style.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,98 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to enforce a particular function style | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce the consistent use of either `function` declarations or expressions", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/func-style" | ||||
|         }, | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 enum: ["declaration", "expression"] | ||||
|             }, | ||||
|             { | ||||
|                 type: "object", | ||||
|                 properties: { | ||||
|                     allowArrowFunctions: { | ||||
|                         type: "boolean", | ||||
|                         default: false | ||||
|                     } | ||||
|                 }, | ||||
|                 additionalProperties: false | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             expression: "Expected a function expression.", | ||||
|             declaration: "Expected a function declaration." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         const style = context.options[0], | ||||
|             allowArrowFunctions = context.options[1] && context.options[1].allowArrowFunctions, | ||||
|             enforceDeclarations = (style === "declaration"), | ||||
|             stack = []; | ||||
|  | ||||
|         const nodesToCheck = { | ||||
|             FunctionDeclaration(node) { | ||||
|                 stack.push(false); | ||||
|  | ||||
|                 if (!enforceDeclarations && node.parent.type !== "ExportDefaultDeclaration") { | ||||
|                     context.report({ node, messageId: "expression" }); | ||||
|                 } | ||||
|             }, | ||||
|             "FunctionDeclaration:exit"() { | ||||
|                 stack.pop(); | ||||
|             }, | ||||
|  | ||||
|             FunctionExpression(node) { | ||||
|                 stack.push(false); | ||||
|  | ||||
|                 if (enforceDeclarations && node.parent.type === "VariableDeclarator") { | ||||
|                     context.report({ node: node.parent, messageId: "declaration" }); | ||||
|                 } | ||||
|             }, | ||||
|             "FunctionExpression:exit"() { | ||||
|                 stack.pop(); | ||||
|             }, | ||||
|  | ||||
|             ThisExpression() { | ||||
|                 if (stack.length > 0) { | ||||
|                     stack[stack.length - 1] = true; | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         if (!allowArrowFunctions) { | ||||
|             nodesToCheck.ArrowFunctionExpression = function() { | ||||
|                 stack.push(false); | ||||
|             }; | ||||
|  | ||||
|             nodesToCheck["ArrowFunctionExpression:exit"] = function(node) { | ||||
|                 const hasThisExpr = stack.pop(); | ||||
|  | ||||
|                 if (enforceDeclarations && !hasThisExpr && node.parent.type === "VariableDeclarator") { | ||||
|                     context.report({ node: node.parent, messageId: "declaration" }); | ||||
|                 } | ||||
|             }; | ||||
|         } | ||||
|  | ||||
|         return nodesToCheck; | ||||
|  | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										125
									
								
								node_modules/eslint/lib/rules/function-call-argument-newline.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										125
									
								
								node_modules/eslint/lib/rules/function-call-argument-newline.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,125 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to enforce line breaks between arguments of a function call | ||||
|  * @author Alexey Gonchar <https://github.com/finico> | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce line breaks between arguments of a function call", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/function-call-argument-newline" | ||||
|         }, | ||||
|  | ||||
|         fixable: "whitespace", | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 enum: ["always", "never", "consistent"] | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             unexpectedLineBreak: "There should be no line break here.", | ||||
|             missingLineBreak: "There should be a line break after this argument." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         const checkers = { | ||||
|             unexpected: { | ||||
|                 messageId: "unexpectedLineBreak", | ||||
|                 check: (prevToken, currentToken) => prevToken.loc.end.line !== currentToken.loc.start.line, | ||||
|                 createFix: (token, tokenBefore) => fixer => | ||||
|                     fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], " ") | ||||
|             }, | ||||
|             missing: { | ||||
|                 messageId: "missingLineBreak", | ||||
|                 check: (prevToken, currentToken) => prevToken.loc.end.line === currentToken.loc.start.line, | ||||
|                 createFix: (token, tokenBefore) => fixer => | ||||
|                     fixer.replaceTextRange([tokenBefore.range[1], token.range[0]], "\n") | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Check all arguments for line breaks in the CallExpression | ||||
|          * @param {CallExpression} node node to evaluate | ||||
|          * @param {{ messageId: string, check: Function }} checker selected checker | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function checkArguments(node, checker) { | ||||
|             for (let i = 1; i < node.arguments.length; i++) { | ||||
|                 const prevArgToken = sourceCode.getLastToken(node.arguments[i - 1]); | ||||
|                 const currentArgToken = sourceCode.getFirstToken(node.arguments[i]); | ||||
|  | ||||
|                 if (checker.check(prevArgToken, currentArgToken)) { | ||||
|                     const tokenBefore = sourceCode.getTokenBefore( | ||||
|                         currentArgToken, | ||||
|                         { includeComments: true } | ||||
|                     ); | ||||
|  | ||||
|                     const hasLineCommentBefore = tokenBefore.type === "Line"; | ||||
|  | ||||
|                     context.report({ | ||||
|                         node, | ||||
|                         loc: { | ||||
|                             start: tokenBefore.loc.end, | ||||
|                             end: currentArgToken.loc.start | ||||
|                         }, | ||||
|                         messageId: checker.messageId, | ||||
|                         fix: hasLineCommentBefore ? null : checker.createFix(currentArgToken, tokenBefore) | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Check if open space is present in a function name | ||||
|          * @param {CallExpression} node node to evaluate | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function check(node) { | ||||
|             if (node.arguments.length < 2) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             const option = context.options[0] || "always"; | ||||
|  | ||||
|             if (option === "never") { | ||||
|                 checkArguments(node, checkers.unexpected); | ||||
|             } else if (option === "always") { | ||||
|                 checkArguments(node, checkers.missing); | ||||
|             } else if (option === "consistent") { | ||||
|                 const firstArgToken = sourceCode.getLastToken(node.arguments[0]); | ||||
|                 const secondArgToken = sourceCode.getFirstToken(node.arguments[1]); | ||||
|  | ||||
|                 if (firstArgToken.loc.end.line === secondArgToken.loc.start.line) { | ||||
|                     checkArguments(node, checkers.unexpected); | ||||
|                 } else { | ||||
|                     checkArguments(node, checkers.missing); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             CallExpression: check, | ||||
|             NewExpression: check | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										292
									
								
								node_modules/eslint/lib/rules/function-paren-newline.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										292
									
								
								node_modules/eslint/lib/rules/function-paren-newline.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,292 @@ | ||||
| /** | ||||
|  * @fileoverview enforce consistent line breaks inside function parentheses | ||||
|  * @author Teddy Katz | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce consistent line breaks inside function parentheses", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/function-paren-newline" | ||||
|         }, | ||||
|  | ||||
|         fixable: "whitespace", | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 oneOf: [ | ||||
|                     { | ||||
|                         enum: ["always", "never", "consistent", "multiline", "multiline-arguments"] | ||||
|                     }, | ||||
|                     { | ||||
|                         type: "object", | ||||
|                         properties: { | ||||
|                             minItems: { | ||||
|                                 type: "integer", | ||||
|                                 minimum: 0 | ||||
|                             } | ||||
|                         }, | ||||
|                         additionalProperties: false | ||||
|                     } | ||||
|                 ] | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             expectedBefore: "Expected newline before ')'.", | ||||
|             expectedAfter: "Expected newline after '('.", | ||||
|             expectedBetween: "Expected newline between arguments/params.", | ||||
|             unexpectedBefore: "Unexpected newline before ')'.", | ||||
|             unexpectedAfter: "Unexpected newline after '('." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const sourceCode = context.sourceCode; | ||||
|         const rawOption = context.options[0] || "multiline"; | ||||
|         const multilineOption = rawOption === "multiline"; | ||||
|         const multilineArgumentsOption = rawOption === "multiline-arguments"; | ||||
|         const consistentOption = rawOption === "consistent"; | ||||
|         let minItems; | ||||
|  | ||||
|         if (typeof rawOption === "object") { | ||||
|             minItems = rawOption.minItems; | ||||
|         } else if (rawOption === "always") { | ||||
|             minItems = 0; | ||||
|         } else if (rawOption === "never") { | ||||
|             minItems = Infinity; | ||||
|         } else { | ||||
|             minItems = null; | ||||
|         } | ||||
|  | ||||
|         //---------------------------------------------------------------------- | ||||
|         // Helpers | ||||
|         //---------------------------------------------------------------------- | ||||
|  | ||||
|         /** | ||||
|          * Determines whether there should be newlines inside function parens | ||||
|          * @param {ASTNode[]} elements The arguments or parameters in the list | ||||
|          * @param {boolean} hasLeftNewline `true` if the left paren has a newline in the current code. | ||||
|          * @returns {boolean} `true` if there should be newlines inside the function parens | ||||
|          */ | ||||
|         function shouldHaveNewlines(elements, hasLeftNewline) { | ||||
|             if (multilineArgumentsOption && elements.length === 1) { | ||||
|                 return hasLeftNewline; | ||||
|             } | ||||
|             if (multilineOption || multilineArgumentsOption) { | ||||
|                 return elements.some((element, index) => index !== elements.length - 1 && element.loc.end.line !== elements[index + 1].loc.start.line); | ||||
|             } | ||||
|             if (consistentOption) { | ||||
|                 return hasLeftNewline; | ||||
|             } | ||||
|             return elements.length >= minItems; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Validates parens | ||||
|          * @param {Object} parens An object with keys `leftParen` for the left paren token, and `rightParen` for the right paren token | ||||
|          * @param {ASTNode[]} elements The arguments or parameters in the list | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function validateParens(parens, elements) { | ||||
|             const leftParen = parens.leftParen; | ||||
|             const rightParen = parens.rightParen; | ||||
|             const tokenAfterLeftParen = sourceCode.getTokenAfter(leftParen); | ||||
|             const tokenBeforeRightParen = sourceCode.getTokenBefore(rightParen); | ||||
|             const hasLeftNewline = !astUtils.isTokenOnSameLine(leftParen, tokenAfterLeftParen); | ||||
|             const hasRightNewline = !astUtils.isTokenOnSameLine(tokenBeforeRightParen, rightParen); | ||||
|             const needsNewlines = shouldHaveNewlines(elements, hasLeftNewline); | ||||
|  | ||||
|             if (hasLeftNewline && !needsNewlines) { | ||||
|                 context.report({ | ||||
|                     node: leftParen, | ||||
|                     messageId: "unexpectedAfter", | ||||
|                     fix(fixer) { | ||||
|                         return sourceCode.getText().slice(leftParen.range[1], tokenAfterLeftParen.range[0]).trim() | ||||
|  | ||||
|                             // If there is a comment between the ( and the first element, don't do a fix. | ||||
|                             ? null | ||||
|                             : fixer.removeRange([leftParen.range[1], tokenAfterLeftParen.range[0]]); | ||||
|                     } | ||||
|                 }); | ||||
|             } else if (!hasLeftNewline && needsNewlines) { | ||||
|                 context.report({ | ||||
|                     node: leftParen, | ||||
|                     messageId: "expectedAfter", | ||||
|                     fix: fixer => fixer.insertTextAfter(leftParen, "\n") | ||||
|                 }); | ||||
|             } | ||||
|  | ||||
|             if (hasRightNewline && !needsNewlines) { | ||||
|                 context.report({ | ||||
|                     node: rightParen, | ||||
|                     messageId: "unexpectedBefore", | ||||
|                     fix(fixer) { | ||||
|                         return sourceCode.getText().slice(tokenBeforeRightParen.range[1], rightParen.range[0]).trim() | ||||
|  | ||||
|                             // If there is a comment between the last element and the ), don't do a fix. | ||||
|                             ? null | ||||
|                             : fixer.removeRange([tokenBeforeRightParen.range[1], rightParen.range[0]]); | ||||
|                     } | ||||
|                 }); | ||||
|             } else if (!hasRightNewline && needsNewlines) { | ||||
|                 context.report({ | ||||
|                     node: rightParen, | ||||
|                     messageId: "expectedBefore", | ||||
|                     fix: fixer => fixer.insertTextBefore(rightParen, "\n") | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Validates a list of arguments or parameters | ||||
|          * @param {Object} parens An object with keys `leftParen` for the left paren token, and `rightParen` for the right paren token | ||||
|          * @param {ASTNode[]} elements The arguments or parameters in the list | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function validateArguments(parens, elements) { | ||||
|             const leftParen = parens.leftParen; | ||||
|             const tokenAfterLeftParen = sourceCode.getTokenAfter(leftParen); | ||||
|             const hasLeftNewline = !astUtils.isTokenOnSameLine(leftParen, tokenAfterLeftParen); | ||||
|             const needsNewlines = shouldHaveNewlines(elements, hasLeftNewline); | ||||
|  | ||||
|             for (let i = 0; i <= elements.length - 2; i++) { | ||||
|                 const currentElement = elements[i]; | ||||
|                 const nextElement = elements[i + 1]; | ||||
|                 const hasNewLine = currentElement.loc.end.line !== nextElement.loc.start.line; | ||||
|  | ||||
|                 if (!hasNewLine && needsNewlines) { | ||||
|                     context.report({ | ||||
|                         node: currentElement, | ||||
|                         messageId: "expectedBetween", | ||||
|                         fix: fixer => fixer.insertTextBefore(nextElement, "\n") | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Gets the left paren and right paren tokens of a node. | ||||
|          * @param {ASTNode} node The node with parens | ||||
|          * @throws {TypeError} Unexpected node type. | ||||
|          * @returns {Object} An object with keys `leftParen` for the left paren token, and `rightParen` for the right paren token. | ||||
|          * Can also return `null` if an expression has no parens (e.g. a NewExpression with no arguments, or an ArrowFunctionExpression | ||||
|          * with a single parameter) | ||||
|          */ | ||||
|         function getParenTokens(node) { | ||||
|             switch (node.type) { | ||||
|                 case "NewExpression": | ||||
|                     if (!node.arguments.length && | ||||
|                         !( | ||||
|                             astUtils.isOpeningParenToken(sourceCode.getLastToken(node, { skip: 1 })) && | ||||
|                             astUtils.isClosingParenToken(sourceCode.getLastToken(node)) && | ||||
|                             node.callee.range[1] < node.range[1] | ||||
|                         ) | ||||
|                     ) { | ||||
|  | ||||
|                         // If the NewExpression does not have parens (e.g. `new Foo`), return null. | ||||
|                         return null; | ||||
|                     } | ||||
|  | ||||
|                     // falls through | ||||
|  | ||||
|                 case "CallExpression": | ||||
|                     return { | ||||
|                         leftParen: sourceCode.getTokenAfter(node.callee, astUtils.isOpeningParenToken), | ||||
|                         rightParen: sourceCode.getLastToken(node) | ||||
|                     }; | ||||
|  | ||||
|                 case "FunctionDeclaration": | ||||
|                 case "FunctionExpression": { | ||||
|                     const leftParen = sourceCode.getFirstToken(node, astUtils.isOpeningParenToken); | ||||
|                     const rightParen = node.params.length | ||||
|                         ? sourceCode.getTokenAfter(node.params[node.params.length - 1], astUtils.isClosingParenToken) | ||||
|                         : sourceCode.getTokenAfter(leftParen); | ||||
|  | ||||
|                     return { leftParen, rightParen }; | ||||
|                 } | ||||
|  | ||||
|                 case "ArrowFunctionExpression": { | ||||
|                     const firstToken = sourceCode.getFirstToken(node, { skip: (node.async ? 1 : 0) }); | ||||
|  | ||||
|                     if (!astUtils.isOpeningParenToken(firstToken)) { | ||||
|  | ||||
|                         // If the ArrowFunctionExpression has a single param without parens, return null. | ||||
|                         return null; | ||||
|                     } | ||||
|  | ||||
|                     const rightParen = node.params.length | ||||
|                         ? sourceCode.getTokenAfter(node.params[node.params.length - 1], astUtils.isClosingParenToken) | ||||
|                         : sourceCode.getTokenAfter(firstToken); | ||||
|  | ||||
|                     return { | ||||
|                         leftParen: firstToken, | ||||
|                         rightParen | ||||
|                     }; | ||||
|                 } | ||||
|  | ||||
|                 case "ImportExpression": { | ||||
|                     const leftParen = sourceCode.getFirstToken(node, 1); | ||||
|                     const rightParen = sourceCode.getLastToken(node); | ||||
|  | ||||
|                     return { leftParen, rightParen }; | ||||
|                 } | ||||
|  | ||||
|                 default: | ||||
|                     throw new TypeError(`unexpected node with type ${node.type}`); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         //---------------------------------------------------------------------- | ||||
|         // Public | ||||
|         //---------------------------------------------------------------------- | ||||
|  | ||||
|         return { | ||||
|             [[ | ||||
|                 "ArrowFunctionExpression", | ||||
|                 "CallExpression", | ||||
|                 "FunctionDeclaration", | ||||
|                 "FunctionExpression", | ||||
|                 "ImportExpression", | ||||
|                 "NewExpression" | ||||
|             ]](node) { | ||||
|                 const parens = getParenTokens(node); | ||||
|                 let params; | ||||
|  | ||||
|                 if (node.type === "ImportExpression") { | ||||
|                     params = [node.source]; | ||||
|                 } else if (astUtils.isFunction(node)) { | ||||
|                     params = node.params; | ||||
|                 } else { | ||||
|                     params = node.arguments; | ||||
|                 } | ||||
|  | ||||
|                 if (parens) { | ||||
|                     validateParens(parens, params); | ||||
|  | ||||
|                     if (multilineArgumentsOption) { | ||||
|                         validateArguments(parens, params); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										209
									
								
								node_modules/eslint/lib/rules/generator-star-spacing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										209
									
								
								node_modules/eslint/lib/rules/generator-star-spacing.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,209 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to check the spacing around the * in generator functions. | ||||
|  * @author Jamund Ferguson | ||||
|  * @deprecated in ESLint v8.53.0 | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const OVERRIDE_SCHEMA = { | ||||
|     oneOf: [ | ||||
|         { | ||||
|             enum: ["before", "after", "both", "neither"] | ||||
|         }, | ||||
|         { | ||||
|             type: "object", | ||||
|             properties: { | ||||
|                 before: { type: "boolean" }, | ||||
|                 after: { type: "boolean" } | ||||
|             }, | ||||
|             additionalProperties: false | ||||
|         } | ||||
|     ] | ||||
| }; | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: [], | ||||
|         type: "layout", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce consistent spacing around `*` operators in generator functions", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/generator-star-spacing" | ||||
|         }, | ||||
|  | ||||
|         fixable: "whitespace", | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 oneOf: [ | ||||
|                     { | ||||
|                         enum: ["before", "after", "both", "neither"] | ||||
|                     }, | ||||
|                     { | ||||
|                         type: "object", | ||||
|                         properties: { | ||||
|                             before: { type: "boolean" }, | ||||
|                             after: { type: "boolean" }, | ||||
|                             named: OVERRIDE_SCHEMA, | ||||
|                             anonymous: OVERRIDE_SCHEMA, | ||||
|                             method: OVERRIDE_SCHEMA | ||||
|                         }, | ||||
|                         additionalProperties: false | ||||
|                     } | ||||
|                 ] | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             missingBefore: "Missing space before *.", | ||||
|             missingAfter: "Missing space after *.", | ||||
|             unexpectedBefore: "Unexpected space before *.", | ||||
|             unexpectedAfter: "Unexpected space after *." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         const optionDefinitions = { | ||||
|             before: { before: true, after: false }, | ||||
|             after: { before: false, after: true }, | ||||
|             both: { before: true, after: true }, | ||||
|             neither: { before: false, after: false } | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Returns resolved option definitions based on an option and defaults | ||||
|          * @param {any} option The option object or string value | ||||
|          * @param {Object} defaults The defaults to use if options are not present | ||||
|          * @returns {Object} the resolved object definition | ||||
|          */ | ||||
|         function optionToDefinition(option, defaults) { | ||||
|             if (!option) { | ||||
|                 return defaults; | ||||
|             } | ||||
|  | ||||
|             return typeof option === "string" | ||||
|                 ? optionDefinitions[option] | ||||
|                 : Object.assign({}, defaults, option); | ||||
|         } | ||||
|  | ||||
|         const modes = (function(option) { | ||||
|             const defaults = optionToDefinition(option, optionDefinitions.before); | ||||
|  | ||||
|             return { | ||||
|                 named: optionToDefinition(option.named, defaults), | ||||
|                 anonymous: optionToDefinition(option.anonymous, defaults), | ||||
|                 method: optionToDefinition(option.method, defaults) | ||||
|             }; | ||||
|         }(context.options[0] || {})); | ||||
|  | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         /** | ||||
|          * Checks if the given token is a star token or not. | ||||
|          * @param {Token} token The token to check. | ||||
|          * @returns {boolean} `true` if the token is a star token. | ||||
|          */ | ||||
|         function isStarToken(token) { | ||||
|             return token.value === "*" && token.type === "Punctuator"; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Gets the generator star token of the given function node. | ||||
|          * @param {ASTNode} node The function node to get. | ||||
|          * @returns {Token} Found star token. | ||||
|          */ | ||||
|         function getStarToken(node) { | ||||
|             return sourceCode.getFirstToken( | ||||
|                 (node.parent.method || node.parent.type === "MethodDefinition") ? node.parent : node, | ||||
|                 isStarToken | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * capitalize a given string. | ||||
|          * @param {string} str the given string. | ||||
|          * @returns {string} the capitalized string. | ||||
|          */ | ||||
|         function capitalize(str) { | ||||
|             return str[0].toUpperCase() + str.slice(1); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks the spacing between two tokens before or after the star token. | ||||
|          * @param {string} kind Either "named", "anonymous", or "method" | ||||
|          * @param {string} side Either "before" or "after". | ||||
|          * @param {Token} leftToken `function` keyword token if side is "before", or | ||||
|          *     star token if side is "after". | ||||
|          * @param {Token} rightToken Star token if side is "before", or identifier | ||||
|          *     token if side is "after". | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function checkSpacing(kind, side, leftToken, rightToken) { | ||||
|             if (!!(rightToken.range[0] - leftToken.range[1]) !== modes[kind][side]) { | ||||
|                 const after = leftToken.value === "*"; | ||||
|                 const spaceRequired = modes[kind][side]; | ||||
|                 const node = after ? leftToken : rightToken; | ||||
|                 const messageId = `${spaceRequired ? "missing" : "unexpected"}${capitalize(side)}`; | ||||
|  | ||||
|                 context.report({ | ||||
|                     node, | ||||
|                     messageId, | ||||
|                     fix(fixer) { | ||||
|                         if (spaceRequired) { | ||||
|                             if (after) { | ||||
|                                 return fixer.insertTextAfter(node, " "); | ||||
|                             } | ||||
|                             return fixer.insertTextBefore(node, " "); | ||||
|                         } | ||||
|                         return fixer.removeRange([leftToken.range[1], rightToken.range[0]]); | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Enforces the spacing around the star if node is a generator function. | ||||
|          * @param {ASTNode} node A function expression or declaration node. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function checkFunction(node) { | ||||
|             if (!node.generator) { | ||||
|                 return; | ||||
|             } | ||||
|  | ||||
|             const starToken = getStarToken(node); | ||||
|             const prevToken = sourceCode.getTokenBefore(starToken); | ||||
|             const nextToken = sourceCode.getTokenAfter(starToken); | ||||
|  | ||||
|             let kind = "named"; | ||||
|  | ||||
|             if (node.parent.type === "MethodDefinition" || (node.parent.type === "Property" && node.parent.method)) { | ||||
|                 kind = "method"; | ||||
|             } else if (!node.id) { | ||||
|                 kind = "anonymous"; | ||||
|             } | ||||
|  | ||||
|             // Only check before when preceded by `function`|`static` keyword | ||||
|             if (!(kind === "method" && starToken === sourceCode.getFirstToken(node.parent))) { | ||||
|                 checkSpacing(kind, "before", prevToken, starToken); | ||||
|             } | ||||
|  | ||||
|             checkSpacing(kind, "after", starToken, nextToken); | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             FunctionDeclaration: checkFunction, | ||||
|             FunctionExpression: checkFunction | ||||
|         }; | ||||
|  | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										204
									
								
								node_modules/eslint/lib/rules/getter-return.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										204
									
								
								node_modules/eslint/lib/rules/getter-return.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,204 @@ | ||||
| /** | ||||
|  * @fileoverview Enforces that a return statement is present in property getters. | ||||
|  * @author Aladdin-ADD(hh_2013@foxmail.com) | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const TARGET_NODE_TYPE = /^(?:Arrow)?FunctionExpression$/u; | ||||
|  | ||||
| /** | ||||
|  * Checks all segments in a set and returns true if any are reachable. | ||||
|  * @param {Set<CodePathSegment>} segments The segments to check. | ||||
|  * @returns {boolean} True if any segment is reachable; false otherwise. | ||||
|  */ | ||||
| function isAnySegmentReachable(segments) { | ||||
|  | ||||
|     for (const segment of segments) { | ||||
|         if (segment.reachable) { | ||||
|             return true; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "problem", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce `return` statements in getters", | ||||
|             recommended: true, | ||||
|             url: "https://eslint.org/docs/latest/rules/getter-return" | ||||
|         }, | ||||
|  | ||||
|         fixable: null, | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 type: "object", | ||||
|                 properties: { | ||||
|                     allowImplicit: { | ||||
|                         type: "boolean", | ||||
|                         default: false | ||||
|                     } | ||||
|                 }, | ||||
|                 additionalProperties: false | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             expected: "Expected to return a value in {{name}}.", | ||||
|             expectedAlways: "Expected {{name}} to always return a value." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         const options = context.options[0] || { allowImplicit: false }; | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         let funcInfo = { | ||||
|             upper: null, | ||||
|             codePath: null, | ||||
|             hasReturn: false, | ||||
|             shouldCheck: false, | ||||
|             node: null, | ||||
|             currentSegments: [] | ||||
|         }; | ||||
|  | ||||
|         /** | ||||
|          * Checks whether or not the last code path segment is reachable. | ||||
|          * Then reports this function if the segment is reachable. | ||||
|          * | ||||
|          * If the last code path segment is reachable, there are paths which are not | ||||
|          * returned or thrown. | ||||
|          * @param {ASTNode} node A node to check. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function checkLastSegment(node) { | ||||
|             if (funcInfo.shouldCheck && | ||||
|                 isAnySegmentReachable(funcInfo.currentSegments) | ||||
|             ) { | ||||
|                 context.report({ | ||||
|                     node, | ||||
|                     loc: astUtils.getFunctionHeadLoc(node, sourceCode), | ||||
|                     messageId: funcInfo.hasReturn ? "expectedAlways" : "expected", | ||||
|                     data: { | ||||
|                         name: astUtils.getFunctionNameWithKind(funcInfo.node) | ||||
|                     } | ||||
|                 }); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks whether a node means a getter function. | ||||
|          * @param {ASTNode} node a node to check. | ||||
|          * @returns {boolean} if node means a getter, return true; else return false. | ||||
|          */ | ||||
|         function isGetter(node) { | ||||
|             const parent = node.parent; | ||||
|  | ||||
|             if (TARGET_NODE_TYPE.test(node.type) && node.body.type === "BlockStatement") { | ||||
|                 if (parent.kind === "get") { | ||||
|                     return true; | ||||
|                 } | ||||
|                 if (parent.type === "Property" && astUtils.getStaticPropertyName(parent) === "get" && parent.parent.type === "ObjectExpression") { | ||||
|  | ||||
|                     // Object.defineProperty() or Reflect.defineProperty() | ||||
|                     if (parent.parent.parent.type === "CallExpression") { | ||||
|                         const callNode = parent.parent.parent.callee; | ||||
|  | ||||
|                         if (astUtils.isSpecificMemberAccess(callNode, "Object", "defineProperty") || | ||||
|                             astUtils.isSpecificMemberAccess(callNode, "Reflect", "defineProperty")) { | ||||
|                             return true; | ||||
|                         } | ||||
|                     } | ||||
|  | ||||
|                     // Object.defineProperties() or Object.create() | ||||
|                     if (parent.parent.parent.type === "Property" && | ||||
|                         parent.parent.parent.parent.type === "ObjectExpression" && | ||||
|                         parent.parent.parent.parent.parent.type === "CallExpression") { | ||||
|                         const callNode = parent.parent.parent.parent.parent.callee; | ||||
|  | ||||
|                         return astUtils.isSpecificMemberAccess(callNode, "Object", "defineProperties") || | ||||
|                                astUtils.isSpecificMemberAccess(callNode, "Object", "create"); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|         return { | ||||
|  | ||||
|             // Stacks this function's information. | ||||
|             onCodePathStart(codePath, node) { | ||||
|                 funcInfo = { | ||||
|                     upper: funcInfo, | ||||
|                     codePath, | ||||
|                     hasReturn: false, | ||||
|                     shouldCheck: isGetter(node), | ||||
|                     node, | ||||
|                     currentSegments: new Set() | ||||
|                 }; | ||||
|             }, | ||||
|  | ||||
|             // Pops this function's information. | ||||
|             onCodePathEnd() { | ||||
|                 funcInfo = funcInfo.upper; | ||||
|             }, | ||||
|             onUnreachableCodePathSegmentStart(segment) { | ||||
|                 funcInfo.currentSegments.add(segment); | ||||
|             }, | ||||
|  | ||||
|             onUnreachableCodePathSegmentEnd(segment) { | ||||
|                 funcInfo.currentSegments.delete(segment); | ||||
|             }, | ||||
|  | ||||
|             onCodePathSegmentStart(segment) { | ||||
|                 funcInfo.currentSegments.add(segment); | ||||
|             }, | ||||
|  | ||||
|             onCodePathSegmentEnd(segment) { | ||||
|                 funcInfo.currentSegments.delete(segment); | ||||
|             }, | ||||
|  | ||||
|             // Checks the return statement is valid. | ||||
|             ReturnStatement(node) { | ||||
|                 if (funcInfo.shouldCheck) { | ||||
|                     funcInfo.hasReturn = true; | ||||
|  | ||||
|                     // if allowImplicit: false, should also check node.argument | ||||
|                     if (!options.allowImplicit && !node.argument) { | ||||
|                         context.report({ | ||||
|                             node, | ||||
|                             messageId: "expected", | ||||
|                             data: { | ||||
|                                 name: astUtils.getFunctionNameWithKind(funcInfo.node) | ||||
|                             } | ||||
|                         }); | ||||
|                     } | ||||
|                 } | ||||
|             }, | ||||
|  | ||||
|             // Reports a given function if the last path is reachable. | ||||
|             "FunctionExpression:exit": checkLastSegment, | ||||
|             "ArrowFunctionExpression:exit": checkLastSegment | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										90
									
								
								node_modules/eslint/lib/rules/global-require.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								node_modules/eslint/lib/rules/global-require.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| /** | ||||
|  * @fileoverview Rule for disallowing require() outside of the top-level module context | ||||
|  * @author Jamund Ferguson | ||||
|  * @deprecated in ESLint v7.0.0 | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| const ACCEPTABLE_PARENTS = new Set([ | ||||
|     "AssignmentExpression", | ||||
|     "VariableDeclarator", | ||||
|     "MemberExpression", | ||||
|     "ExpressionStatement", | ||||
|     "CallExpression", | ||||
|     "ConditionalExpression", | ||||
|     "Program", | ||||
|     "VariableDeclaration", | ||||
|     "ChainExpression" | ||||
| ]); | ||||
|  | ||||
| /** | ||||
|  * Finds the eslint-scope reference in the given scope. | ||||
|  * @param {Object} scope The scope to search. | ||||
|  * @param {ASTNode} node The identifier node. | ||||
|  * @returns {Reference|null} Returns the found reference or null if none were found. | ||||
|  */ | ||||
| function findReference(scope, node) { | ||||
|     const references = scope.references.filter(reference => reference.identifier.range[0] === node.range[0] && | ||||
|             reference.identifier.range[1] === node.range[1]); | ||||
|  | ||||
|     if (references.length === 1) { | ||||
|         return references[0]; | ||||
|     } | ||||
|  | ||||
|     /* c8 ignore next */ | ||||
|     return null; | ||||
|  | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks if the given identifier node is shadowed in the given scope. | ||||
|  * @param {Object} scope The current scope. | ||||
|  * @param {ASTNode} node The identifier node to check. | ||||
|  * @returns {boolean} Whether or not the name is shadowed. | ||||
|  */ | ||||
| function isShadowed(scope, node) { | ||||
|     const reference = findReference(scope, node); | ||||
|  | ||||
|     return reference && reference.resolved && reference.resolved.defs.length > 0; | ||||
| } | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|  | ||||
|         replacedBy: [], | ||||
|  | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require `require()` calls to be placed at top-level module scope", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/global-require" | ||||
|         }, | ||||
|  | ||||
|         schema: [], | ||||
|         messages: { | ||||
|             unexpected: "Unexpected require()." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         return { | ||||
|             CallExpression(node) { | ||||
|                 const currentScope = sourceCode.getScope(node); | ||||
|  | ||||
|                 if (node.callee.name === "require" && !isShadowed(currentScope, node.callee)) { | ||||
|                     const isGoodRequire = sourceCode.getAncestors(node).every(parent => ACCEPTABLE_PARENTS.has(parent.type)); | ||||
|  | ||||
|                     if (!isGoodRequire) { | ||||
|                         context.report({ node, messageId: "unexpected" }); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										215
									
								
								node_modules/eslint/lib/rules/grouped-accessor-pairs.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										215
									
								
								node_modules/eslint/lib/rules/grouped-accessor-pairs.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,215 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to require grouped accessor pairs in object literals and classes | ||||
|  * @author Milos Djermanovic | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const astUtils = require("./utils/ast-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Typedefs | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Property name if it can be computed statically, otherwise the list of the tokens of the key node. | ||||
|  * @typedef {string|Token[]} Key | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Accessor nodes with the same key. | ||||
|  * @typedef {Object} AccessorData | ||||
|  * @property {Key} key Accessor's key | ||||
|  * @property {ASTNode[]} getters List of getter nodes. | ||||
|  * @property {ASTNode[]} setters List of setter nodes. | ||||
|  */ | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Checks whether or not the given lists represent the equal tokens in the same order. | ||||
|  * Tokens are compared by their properties, not by instance. | ||||
|  * @param {Token[]} left First list of tokens. | ||||
|  * @param {Token[]} right Second list of tokens. | ||||
|  * @returns {boolean} `true` if the lists have same tokens. | ||||
|  */ | ||||
| function areEqualTokenLists(left, right) { | ||||
|     if (left.length !== right.length) { | ||||
|         return false; | ||||
|     } | ||||
|  | ||||
|     for (let i = 0; i < left.length; i++) { | ||||
|         const leftToken = left[i], | ||||
|             rightToken = right[i]; | ||||
|  | ||||
|         if (leftToken.type !== rightToken.type || leftToken.value !== rightToken.value) { | ||||
|             return false; | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     return true; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether or not the given keys are equal. | ||||
|  * @param {Key} left First key. | ||||
|  * @param {Key} right Second key. | ||||
|  * @returns {boolean} `true` if the keys are equal. | ||||
|  */ | ||||
| function areEqualKeys(left, right) { | ||||
|     if (typeof left === "string" && typeof right === "string") { | ||||
|  | ||||
|         // Statically computed names. | ||||
|         return left === right; | ||||
|     } | ||||
|     if (Array.isArray(left) && Array.isArray(right)) { | ||||
|  | ||||
|         // Token lists. | ||||
|         return areEqualTokenLists(left, right); | ||||
|     } | ||||
|  | ||||
|     return false; | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether or not a given node is of an accessor kind ('get' or 'set'). | ||||
|  * @param {ASTNode} node A node to check. | ||||
|  * @returns {boolean} `true` if the node is of an accessor kind. | ||||
|  */ | ||||
| function isAccessorKind(node) { | ||||
|     return node.kind === "get" || node.kind === "set"; | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require grouped accessor pairs in object literals and classes", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/grouped-accessor-pairs" | ||||
|         }, | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 enum: ["anyOrder", "getBeforeSet", "setBeforeGet"] | ||||
|             } | ||||
|         ], | ||||
|  | ||||
|         messages: { | ||||
|             notGrouped: "Accessor pair {{ formerName }} and {{ latterName }} should be grouped.", | ||||
|             invalidOrder: "Expected {{ latterName }} to be before {{ formerName }}." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const order = context.options[0] || "anyOrder"; | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         /** | ||||
|          * Reports the given accessor pair. | ||||
|          * @param {string} messageId messageId to report. | ||||
|          * @param {ASTNode} formerNode getter/setter node that is defined before `latterNode`. | ||||
|          * @param {ASTNode} latterNode getter/setter node that is defined after `formerNode`. | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function report(messageId, formerNode, latterNode) { | ||||
|             context.report({ | ||||
|                 node: latterNode, | ||||
|                 messageId, | ||||
|                 loc: astUtils.getFunctionHeadLoc(latterNode.value, sourceCode), | ||||
|                 data: { | ||||
|                     formerName: astUtils.getFunctionNameWithKind(formerNode.value), | ||||
|                     latterName: astUtils.getFunctionNameWithKind(latterNode.value) | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks accessor pairs in the given list of nodes. | ||||
|          * @param {ASTNode[]} nodes The list to check. | ||||
|          * @param {Function} shouldCheck – Predicate that returns `true` if the node should be checked. | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function checkList(nodes, shouldCheck) { | ||||
|             const accessors = []; | ||||
|             let found = false; | ||||
|  | ||||
|             for (let i = 0; i < nodes.length; i++) { | ||||
|                 const node = nodes[i]; | ||||
|  | ||||
|                 if (shouldCheck(node) && isAccessorKind(node)) { | ||||
|  | ||||
|                     // Creates a new `AccessorData` object for the given getter or setter node. | ||||
|                     const name = astUtils.getStaticPropertyName(node); | ||||
|                     const key = (name !== null) ? name : sourceCode.getTokens(node.key); | ||||
|  | ||||
|                     // Merges the given `AccessorData` object into the given accessors list. | ||||
|                     for (let j = 0; j < accessors.length; j++) { | ||||
|                         const accessor = accessors[j]; | ||||
|  | ||||
|                         if (areEqualKeys(accessor.key, key)) { | ||||
|                             accessor.getters.push(...node.kind === "get" ? [node] : []); | ||||
|                             accessor.setters.push(...node.kind === "set" ? [node] : []); | ||||
|                             found = true; | ||||
|                             break; | ||||
|                         } | ||||
|                     } | ||||
|                     if (!found) { | ||||
|                         accessors.push({ | ||||
|                             key, | ||||
|                             getters: node.kind === "get" ? [node] : [], | ||||
|                             setters: node.kind === "set" ? [node] : [] | ||||
|                         }); | ||||
|                     } | ||||
|                     found = false; | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             for (const { getters, setters } of accessors) { | ||||
|  | ||||
|                 // Don't report accessor properties that have duplicate getters or setters. | ||||
|                 if (getters.length === 1 && setters.length === 1) { | ||||
|                     const [getter] = getters, | ||||
|                         [setter] = setters, | ||||
|                         getterIndex = nodes.indexOf(getter), | ||||
|                         setterIndex = nodes.indexOf(setter), | ||||
|                         formerNode = getterIndex < setterIndex ? getter : setter, | ||||
|                         latterNode = getterIndex < setterIndex ? setter : getter; | ||||
|  | ||||
|                     if (Math.abs(getterIndex - setterIndex) > 1) { | ||||
|                         report("notGrouped", formerNode, latterNode); | ||||
|                     } else if ( | ||||
|                         (order === "getBeforeSet" && getterIndex > setterIndex) || | ||||
|                         (order === "setBeforeGet" && getterIndex < setterIndex) | ||||
|                     ) { | ||||
|                         report("invalidOrder", formerNode, latterNode); | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             ObjectExpression(node) { | ||||
|                 checkList(node.properties, n => n.type === "Property"); | ||||
|             }, | ||||
|             ClassBody(node) { | ||||
|                 checkList(node.body, n => n.type === "MethodDefinition" && !n.static); | ||||
|                 checkList(node.body, n => n.type === "MethodDefinition" && n.static); | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										76
									
								
								node_modules/eslint/lib/rules/guard-for-in.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										76
									
								
								node_modules/eslint/lib/rules/guard-for-in.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,76 @@ | ||||
| /** | ||||
|  * @fileoverview Rule to flag for-in loops without if statements inside | ||||
|  * @author Nicholas C. Zakas | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require `for-in` loops to include an `if` statement", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/guard-for-in" | ||||
|         }, | ||||
|  | ||||
|         schema: [], | ||||
|         messages: { | ||||
|             wrap: "The body of a for-in should be wrapped in an if statement to filter unwanted properties from the prototype." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         return { | ||||
|  | ||||
|             ForInStatement(node) { | ||||
|                 const body = node.body; | ||||
|  | ||||
|                 // empty statement | ||||
|                 if (body.type === "EmptyStatement") { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // if statement | ||||
|                 if (body.type === "IfStatement") { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // empty block | ||||
|                 if (body.type === "BlockStatement" && body.body.length === 0) { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // block with just if statement | ||||
|                 if (body.type === "BlockStatement" && body.body.length === 1 && body.body[0].type === "IfStatement") { | ||||
|                     return; | ||||
|                 } | ||||
|  | ||||
|                 // block that starts with if statement | ||||
|                 if (body.type === "BlockStatement" && body.body.length >= 1 && body.body[0].type === "IfStatement") { | ||||
|                     const i = body.body[0]; | ||||
|  | ||||
|                     // ... whose consequent is a continue | ||||
|                     if (i.consequent.type === "ContinueStatement") { | ||||
|                         return; | ||||
|                     } | ||||
|  | ||||
|                     // ... whose consequent is a block that contains only a continue | ||||
|                     if (i.consequent.type === "BlockStatement" && i.consequent.body.length === 1 && i.consequent.body[0].type === "ContinueStatement") { | ||||
|                         return; | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 context.report({ node, messageId: "wrap" }); | ||||
|             } | ||||
|         }; | ||||
|  | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										101
									
								
								node_modules/eslint/lib/rules/handle-callback-err.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										101
									
								
								node_modules/eslint/lib/rules/handle-callback-err.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,101 @@ | ||||
| /** | ||||
|  * @fileoverview Ensure handling of errors when we know they exist. | ||||
|  * @author Jamund Ferguson | ||||
|  * @deprecated in ESLint v7.0.0 | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|  | ||||
|         replacedBy: [], | ||||
|  | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Require error handling in callbacks", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/handle-callback-err" | ||||
|         }, | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 type: "string" | ||||
|             } | ||||
|         ], | ||||
|         messages: { | ||||
|             expected: "Expected error to be handled." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         const errorArgument = context.options[0] || "err"; | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         /** | ||||
|          * Checks if the given argument should be interpreted as a regexp pattern. | ||||
|          * @param {string} stringToCheck The string which should be checked. | ||||
|          * @returns {boolean} Whether or not the string should be interpreted as a pattern. | ||||
|          */ | ||||
|         function isPattern(stringToCheck) { | ||||
|             const firstChar = stringToCheck[0]; | ||||
|  | ||||
|             return firstChar === "^"; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks if the given name matches the configured error argument. | ||||
|          * @param {string} name The name which should be compared. | ||||
|          * @returns {boolean} Whether or not the given name matches the configured error variable name. | ||||
|          */ | ||||
|         function matchesConfiguredErrorName(name) { | ||||
|             if (isPattern(errorArgument)) { | ||||
|                 const regexp = new RegExp(errorArgument, "u"); | ||||
|  | ||||
|                 return regexp.test(name); | ||||
|             } | ||||
|             return name === errorArgument; | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Get the parameters of a given function scope. | ||||
|          * @param {Object} scope The function scope. | ||||
|          * @returns {Array} All parameters of the given scope. | ||||
|          */ | ||||
|         function getParameters(scope) { | ||||
|             return scope.variables.filter(variable => variable.defs[0] && variable.defs[0].type === "Parameter"); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Check to see if we're handling the error object properly. | ||||
|          * @param {ASTNode} node The AST node to check. | ||||
|          * @returns {void} | ||||
|          */ | ||||
|         function checkForError(node) { | ||||
|             const scope = sourceCode.getScope(node), | ||||
|                 parameters = getParameters(scope), | ||||
|                 firstParameter = parameters[0]; | ||||
|  | ||||
|             if (firstParameter && matchesConfiguredErrorName(firstParameter.name)) { | ||||
|                 if (firstParameter.references.length === 0) { | ||||
|                     context.report({ node, messageId: "expected" }); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|             FunctionDeclaration: checkForError, | ||||
|             FunctionExpression: checkForError, | ||||
|             ArrowFunctionExpression: checkForError | ||||
|         }; | ||||
|  | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										246
									
								
								node_modules/eslint/lib/rules/id-blacklist.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										246
									
								
								node_modules/eslint/lib/rules/id-blacklist.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,246 @@ | ||||
| /** | ||||
|  * @fileoverview Rule that warns when identifier names that are | ||||
|  * specified in the configuration are used. | ||||
|  * @author Keith Cirkel (http://keithcirkel.co.uk) | ||||
|  * @deprecated in ESLint v7.5.0 | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Checks whether the given node represents assignment target in a normal assignment or destructuring. | ||||
|  * @param {ASTNode} node The node to check. | ||||
|  * @returns {boolean} `true` if the node is assignment target. | ||||
|  */ | ||||
| function isAssignmentTarget(node) { | ||||
|     const parent = node.parent; | ||||
|  | ||||
|     return ( | ||||
|  | ||||
|         // normal assignment | ||||
|         ( | ||||
|             parent.type === "AssignmentExpression" && | ||||
|             parent.left === node | ||||
|         ) || | ||||
|  | ||||
|         // destructuring | ||||
|         parent.type === "ArrayPattern" || | ||||
|         parent.type === "RestElement" || | ||||
|         ( | ||||
|             parent.type === "Property" && | ||||
|             parent.value === node && | ||||
|             parent.parent.type === "ObjectPattern" | ||||
|         ) || | ||||
|         ( | ||||
|             parent.type === "AssignmentPattern" && | ||||
|             parent.left === node | ||||
|         ) | ||||
|     ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether the given node represents an imported name that is renamed in the same import/export specifier. | ||||
|  * | ||||
|  * Examples: | ||||
|  * import { a as b } from 'mod'; // node `a` is renamed import | ||||
|  * export { a as b } from 'mod'; // node `a` is renamed import | ||||
|  * @param {ASTNode} node `Identifier` node to check. | ||||
|  * @returns {boolean} `true` if the node is a renamed import. | ||||
|  */ | ||||
| function isRenamedImport(node) { | ||||
|     const parent = node.parent; | ||||
|  | ||||
|     return ( | ||||
|         ( | ||||
|             parent.type === "ImportSpecifier" && | ||||
|             parent.imported !== parent.local && | ||||
|             parent.imported === node | ||||
|         ) || | ||||
|         ( | ||||
|             parent.type === "ExportSpecifier" && | ||||
|             parent.parent.source && // re-export | ||||
|             parent.local !== parent.exported && | ||||
|             parent.local === node | ||||
|         ) | ||||
|     ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether the given node is a renamed identifier node in an ObjectPattern destructuring. | ||||
|  * | ||||
|  * Examples: | ||||
|  * const { a : b } = foo; // node `a` is renamed node. | ||||
|  * @param {ASTNode} node `Identifier` node to check. | ||||
|  * @returns {boolean} `true` if the node is a renamed node in an ObjectPattern destructuring. | ||||
|  */ | ||||
| function isRenamedInDestructuring(node) { | ||||
|     const parent = node.parent; | ||||
|  | ||||
|     return ( | ||||
|         ( | ||||
|             !parent.computed && | ||||
|             parent.type === "Property" && | ||||
|             parent.parent.type === "ObjectPattern" && | ||||
|             parent.value !== node && | ||||
|             parent.key === node | ||||
|         ) | ||||
|     ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether the given node represents shorthand definition of a property in an object literal. | ||||
|  * @param {ASTNode} node `Identifier` node to check. | ||||
|  * @returns {boolean} `true` if the node is a shorthand property definition. | ||||
|  */ | ||||
| function isShorthandPropertyDefinition(node) { | ||||
|     const parent = node.parent; | ||||
|  | ||||
|     return ( | ||||
|         parent.type === "Property" && | ||||
|         parent.parent.type === "ObjectExpression" && | ||||
|         parent.shorthand | ||||
|     ); | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         deprecated: true, | ||||
|         replacedBy: ["id-denylist"], | ||||
|  | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Disallow specified identifiers", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/id-blacklist" | ||||
|         }, | ||||
|  | ||||
|         schema: { | ||||
|             type: "array", | ||||
|             items: { | ||||
|                 type: "string" | ||||
|             }, | ||||
|             uniqueItems: true | ||||
|         }, | ||||
|         messages: { | ||||
|             restricted: "Identifier '{{name}}' is restricted." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         const denyList = new Set(context.options); | ||||
|         const reportedNodes = new Set(); | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         let globalScope; | ||||
|  | ||||
|         /** | ||||
|          * Checks whether the given name is restricted. | ||||
|          * @param {string} name The name to check. | ||||
|          * @returns {boolean} `true` if the name is restricted. | ||||
|          * @private | ||||
|          */ | ||||
|         function isRestricted(name) { | ||||
|             return denyList.has(name); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks whether the given node represents a reference to a global variable that is not declared in the source code. | ||||
|          * These identifiers will be allowed, as it is assumed that user has no control over the names of external global variables. | ||||
|          * @param {ASTNode} node `Identifier` node to check. | ||||
|          * @returns {boolean} `true` if the node is a reference to a global variable. | ||||
|          */ | ||||
|         function isReferenceToGlobalVariable(node) { | ||||
|             const variable = globalScope.set.get(node.name); | ||||
|  | ||||
|             return variable && variable.defs.length === 0 && | ||||
|                 variable.references.some(ref => ref.identifier === node); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines whether the given node should be checked. | ||||
|          * @param {ASTNode} node `Identifier` node. | ||||
|          * @returns {boolean} `true` if the node should be checked. | ||||
|          */ | ||||
|         function shouldCheck(node) { | ||||
|             const parent = node.parent; | ||||
|  | ||||
|             /* | ||||
|              * Member access has special rules for checking property names. | ||||
|              * Read access to a property with a restricted name is allowed, because it can be on an object that user has no control over. | ||||
|              * Write access isn't allowed, because it potentially creates a new property with a restricted name. | ||||
|              */ | ||||
|             if ( | ||||
|                 parent.type === "MemberExpression" && | ||||
|                 parent.property === node && | ||||
|                 !parent.computed | ||||
|             ) { | ||||
|                 return isAssignmentTarget(parent); | ||||
|             } | ||||
|  | ||||
|             return ( | ||||
|                 parent.type !== "CallExpression" && | ||||
|                 parent.type !== "NewExpression" && | ||||
|                 !isRenamedImport(node) && | ||||
|                 !isRenamedInDestructuring(node) && | ||||
|                 !( | ||||
|                     isReferenceToGlobalVariable(node) && | ||||
|                     !isShorthandPropertyDefinition(node) | ||||
|                 ) | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports an AST node as a rule violation. | ||||
|          * @param {ASTNode} node The node to report. | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function report(node) { | ||||
|  | ||||
|             /* | ||||
|              * We used the range instead of the node because it's possible | ||||
|              * for the same identifier to be represented by two different | ||||
|              * nodes, with the most clear example being shorthand properties: | ||||
|              * { foo } | ||||
|              * In this case, "foo" is represented by one node for the name | ||||
|              * and one for the value. The only way to know they are the same | ||||
|              * is to look at the range. | ||||
|              */ | ||||
|             if (!reportedNodes.has(node.range.toString())) { | ||||
|                 context.report({ | ||||
|                     node, | ||||
|                     messageId: "restricted", | ||||
|                     data: { | ||||
|                         name: node.name | ||||
|                     } | ||||
|                 }); | ||||
|                 reportedNodes.add(node.range.toString()); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|  | ||||
|             Program(node) { | ||||
|                 globalScope = sourceCode.getScope(node); | ||||
|             }, | ||||
|  | ||||
|             Identifier(node) { | ||||
|                 if (isRestricted(node.name) && shouldCheck(node)) { | ||||
|                     report(node); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										228
									
								
								node_modules/eslint/lib/rules/id-denylist.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										228
									
								
								node_modules/eslint/lib/rules/id-denylist.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,228 @@ | ||||
| /** | ||||
|  * @fileoverview Rule that warns when identifier names that are | ||||
|  * specified in the configuration are used. | ||||
|  * @author Keith Cirkel (http://keithcirkel.co.uk) | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Helpers | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** | ||||
|  * Checks whether the given node represents assignment target in a normal assignment or destructuring. | ||||
|  * @param {ASTNode} node The node to check. | ||||
|  * @returns {boolean} `true` if the node is assignment target. | ||||
|  */ | ||||
| function isAssignmentTarget(node) { | ||||
|     const parent = node.parent; | ||||
|  | ||||
|     return ( | ||||
|  | ||||
|         // normal assignment | ||||
|         ( | ||||
|             parent.type === "AssignmentExpression" && | ||||
|             parent.left === node | ||||
|         ) || | ||||
|  | ||||
|         // destructuring | ||||
|         parent.type === "ArrayPattern" || | ||||
|         parent.type === "RestElement" || | ||||
|         ( | ||||
|             parent.type === "Property" && | ||||
|             parent.value === node && | ||||
|             parent.parent.type === "ObjectPattern" | ||||
|         ) || | ||||
|         ( | ||||
|             parent.type === "AssignmentPattern" && | ||||
|             parent.left === node | ||||
|         ) | ||||
|     ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether the given node represents an imported name that is renamed in the same import/export specifier. | ||||
|  * | ||||
|  * Examples: | ||||
|  * import { a as b } from 'mod'; // node `a` is renamed import | ||||
|  * export { a as b } from 'mod'; // node `a` is renamed import | ||||
|  * @param {ASTNode} node `Identifier` node to check. | ||||
|  * @returns {boolean} `true` if the node is a renamed import. | ||||
|  */ | ||||
| function isRenamedImport(node) { | ||||
|     const parent = node.parent; | ||||
|  | ||||
|     return ( | ||||
|         ( | ||||
|             parent.type === "ImportSpecifier" && | ||||
|             parent.imported !== parent.local && | ||||
|             parent.imported === node | ||||
|         ) || | ||||
|         ( | ||||
|             parent.type === "ExportSpecifier" && | ||||
|             parent.parent.source && // re-export | ||||
|             parent.local !== parent.exported && | ||||
|             parent.local === node | ||||
|         ) | ||||
|     ); | ||||
| } | ||||
|  | ||||
| /** | ||||
|  * Checks whether the given node is an ObjectPattern destructuring. | ||||
|  * | ||||
|  * Examples: | ||||
|  * const { a : b } = foo; | ||||
|  * @param {ASTNode} node `Identifier` node to check. | ||||
|  * @returns {boolean} `true` if the node is in an ObjectPattern destructuring. | ||||
|  */ | ||||
| function isPropertyNameInDestructuring(node) { | ||||
|     const parent = node.parent; | ||||
|  | ||||
|     return ( | ||||
|         ( | ||||
|             !parent.computed && | ||||
|             parent.type === "Property" && | ||||
|             parent.parent.type === "ObjectPattern" && | ||||
|             parent.key === node | ||||
|         ) | ||||
|     ); | ||||
| } | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Disallow specified identifiers", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/id-denylist" | ||||
|         }, | ||||
|  | ||||
|         schema: { | ||||
|             type: "array", | ||||
|             items: { | ||||
|                 type: "string" | ||||
|             }, | ||||
|             uniqueItems: true | ||||
|         }, | ||||
|         messages: { | ||||
|             restricted: "Identifier '{{name}}' is restricted.", | ||||
|             restrictedPrivate: "Identifier '#{{name}}' is restricted." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|  | ||||
|         const denyList = new Set(context.options); | ||||
|         const reportedNodes = new Set(); | ||||
|         const sourceCode = context.sourceCode; | ||||
|  | ||||
|         let globalScope; | ||||
|  | ||||
|         /** | ||||
|          * Checks whether the given name is restricted. | ||||
|          * @param {string} name The name to check. | ||||
|          * @returns {boolean} `true` if the name is restricted. | ||||
|          * @private | ||||
|          */ | ||||
|         function isRestricted(name) { | ||||
|             return denyList.has(name); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Checks whether the given node represents a reference to a global variable that is not declared in the source code. | ||||
|          * These identifiers will be allowed, as it is assumed that user has no control over the names of external global variables. | ||||
|          * @param {ASTNode} node `Identifier` node to check. | ||||
|          * @returns {boolean} `true` if the node is a reference to a global variable. | ||||
|          */ | ||||
|         function isReferenceToGlobalVariable(node) { | ||||
|             const variable = globalScope.set.get(node.name); | ||||
|  | ||||
|             return variable && variable.defs.length === 0 && | ||||
|                 variable.references.some(ref => ref.identifier === node); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Determines whether the given node should be checked. | ||||
|          * @param {ASTNode} node `Identifier` node. | ||||
|          * @returns {boolean} `true` if the node should be checked. | ||||
|          */ | ||||
|         function shouldCheck(node) { | ||||
|             const parent = node.parent; | ||||
|  | ||||
|             /* | ||||
|              * Member access has special rules for checking property names. | ||||
|              * Read access to a property with a restricted name is allowed, because it can be on an object that user has no control over. | ||||
|              * Write access isn't allowed, because it potentially creates a new property with a restricted name. | ||||
|              */ | ||||
|             if ( | ||||
|                 parent.type === "MemberExpression" && | ||||
|                 parent.property === node && | ||||
|                 !parent.computed | ||||
|             ) { | ||||
|                 return isAssignmentTarget(parent); | ||||
|             } | ||||
|  | ||||
|             return ( | ||||
|                 parent.type !== "CallExpression" && | ||||
|                 parent.type !== "NewExpression" && | ||||
|                 !isRenamedImport(node) && | ||||
|                 !isPropertyNameInDestructuring(node) && | ||||
|                 !isReferenceToGlobalVariable(node) | ||||
|             ); | ||||
|         } | ||||
|  | ||||
|         /** | ||||
|          * Reports an AST node as a rule violation. | ||||
|          * @param {ASTNode} node The node to report. | ||||
|          * @returns {void} | ||||
|          * @private | ||||
|          */ | ||||
|         function report(node) { | ||||
|  | ||||
|             /* | ||||
|              * We used the range instead of the node because it's possible | ||||
|              * for the same identifier to be represented by two different | ||||
|              * nodes, with the most clear example being shorthand properties: | ||||
|              * { foo } | ||||
|              * In this case, "foo" is represented by one node for the name | ||||
|              * and one for the value. The only way to know they are the same | ||||
|              * is to look at the range. | ||||
|              */ | ||||
|             if (!reportedNodes.has(node.range.toString())) { | ||||
|                 const isPrivate = node.type === "PrivateIdentifier"; | ||||
|  | ||||
|                 context.report({ | ||||
|                     node, | ||||
|                     messageId: isPrivate ? "restrictedPrivate" : "restricted", | ||||
|                     data: { | ||||
|                         name: node.name | ||||
|                     } | ||||
|                 }); | ||||
|                 reportedNodes.add(node.range.toString()); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
|  | ||||
|             Program(node) { | ||||
|                 globalScope = sourceCode.getScope(node); | ||||
|             }, | ||||
|  | ||||
|             [[ | ||||
|                 "Identifier", | ||||
|                 "PrivateIdentifier" | ||||
|             ]](node) { | ||||
|                 if (isRestricted(node.name) && shouldCheck(node)) { | ||||
|                     report(node); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
							
								
								
									
										177
									
								
								node_modules/eslint/lib/rules/id-length.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										177
									
								
								node_modules/eslint/lib/rules/id-length.js
									
									
									
										generated
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,177 @@ | ||||
| /** | ||||
|  * @fileoverview Rule that warns when identifier names are shorter or longer | ||||
|  * than the values provided in configuration. | ||||
|  * @author Burak Yigit Kaya aka BYK | ||||
|  */ | ||||
|  | ||||
| "use strict"; | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Requirements | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| const { getGraphemeCount } = require("../shared/string-utils"); | ||||
|  | ||||
| //------------------------------------------------------------------------------ | ||||
| // Rule Definition | ||||
| //------------------------------------------------------------------------------ | ||||
|  | ||||
| /** @type {import('../shared/types').Rule} */ | ||||
| module.exports = { | ||||
|     meta: { | ||||
|         type: "suggestion", | ||||
|  | ||||
|         docs: { | ||||
|             description: "Enforce minimum and maximum identifier lengths", | ||||
|             recommended: false, | ||||
|             url: "https://eslint.org/docs/latest/rules/id-length" | ||||
|         }, | ||||
|  | ||||
|         schema: [ | ||||
|             { | ||||
|                 type: "object", | ||||
|                 properties: { | ||||
|                     min: { | ||||
|                         type: "integer", | ||||
|                         default: 2 | ||||
|                     }, | ||||
|                     max: { | ||||
|                         type: "integer" | ||||
|                     }, | ||||
|                     exceptions: { | ||||
|                         type: "array", | ||||
|                         uniqueItems: true, | ||||
|                         items: { | ||||
|                             type: "string" | ||||
|                         } | ||||
|                     }, | ||||
|                     exceptionPatterns: { | ||||
|                         type: "array", | ||||
|                         uniqueItems: true, | ||||
|                         items: { | ||||
|                             type: "string" | ||||
|                         } | ||||
|                     }, | ||||
|                     properties: { | ||||
|                         enum: ["always", "never"] | ||||
|                     } | ||||
|                 }, | ||||
|                 additionalProperties: false | ||||
|             } | ||||
|         ], | ||||
|         messages: { | ||||
|             tooShort: "Identifier name '{{name}}' is too short (< {{min}}).", | ||||
|             tooShortPrivate: "Identifier name '#{{name}}' is too short (< {{min}}).", | ||||
|             tooLong: "Identifier name '{{name}}' is too long (> {{max}}).", | ||||
|             tooLongPrivate: "Identifier name #'{{name}}' is too long (> {{max}})." | ||||
|         } | ||||
|     }, | ||||
|  | ||||
|     create(context) { | ||||
|         const options = context.options[0] || {}; | ||||
|         const minLength = typeof options.min !== "undefined" ? options.min : 2; | ||||
|         const maxLength = typeof options.max !== "undefined" ? options.max : Infinity; | ||||
|         const properties = options.properties !== "never"; | ||||
|         const exceptions = new Set(options.exceptions); | ||||
|         const exceptionPatterns = (options.exceptionPatterns || []).map(pattern => new RegExp(pattern, "u")); | ||||
|         const reportedNodes = new Set(); | ||||
|  | ||||
|         /** | ||||
|          * Checks if a string matches the provided exception patterns | ||||
|          * @param {string} name The string to check. | ||||
|          * @returns {boolean} if the string is a match | ||||
|          * @private | ||||
|          */ | ||||
|         function matchesExceptionPattern(name) { | ||||
|             return exceptionPatterns.some(pattern => pattern.test(name)); | ||||
|         } | ||||
|  | ||||
|         const SUPPORTED_EXPRESSIONS = { | ||||
|             MemberExpression: properties && function(parent) { | ||||
|                 return !parent.computed && ( | ||||
|  | ||||
|                     // regular property assignment | ||||
|                     (parent.parent.left === parent && parent.parent.type === "AssignmentExpression" || | ||||
|  | ||||
|                     // or the last identifier in an ObjectPattern destructuring | ||||
|                     parent.parent.type === "Property" && parent.parent.value === parent && | ||||
|                     parent.parent.parent.type === "ObjectPattern" && parent.parent.parent.parent.left === parent.parent.parent) | ||||
|                 ); | ||||
|             }, | ||||
|             AssignmentPattern(parent, node) { | ||||
|                 return parent.left === node; | ||||
|             }, | ||||
|             VariableDeclarator(parent, node) { | ||||
|                 return parent.id === node; | ||||
|             }, | ||||
|             Property(parent, node) { | ||||
|  | ||||
|                 if (parent.parent.type === "ObjectPattern") { | ||||
|                     const isKeyAndValueSame = parent.value.name === parent.key.name; | ||||
|  | ||||
|                     return ( | ||||
|                         !isKeyAndValueSame && parent.value === node || | ||||
|                         isKeyAndValueSame && parent.key === node && properties | ||||
|                     ); | ||||
|                 } | ||||
|                 return properties && !parent.computed && parent.key.name === node.name; | ||||
|             }, | ||||
|             ImportDefaultSpecifier: true, | ||||
|             RestElement: true, | ||||
|             FunctionExpression: true, | ||||
|             ArrowFunctionExpression: true, | ||||
|             ClassDeclaration: true, | ||||
|             FunctionDeclaration: true, | ||||
|             MethodDefinition: true, | ||||
|             PropertyDefinition: true, | ||||
|             CatchClause: true, | ||||
|             ArrayPattern: true | ||||
|         }; | ||||
|  | ||||
|         return { | ||||
|             [[ | ||||
|                 "Identifier", | ||||
|                 "PrivateIdentifier" | ||||
|             ]](node) { | ||||
|                 const name = node.name; | ||||
|                 const parent = node.parent; | ||||
|  | ||||
|                 const nameLength = getGraphemeCount(name); | ||||
|  | ||||
|                 const isShort = nameLength < minLength; | ||||
|                 const isLong = nameLength > maxLength; | ||||
|  | ||||
|                 if (!(isShort || isLong) || exceptions.has(name) || matchesExceptionPattern(name)) { | ||||
|                     return; // Nothing to report | ||||
|                 } | ||||
|  | ||||
|                 const isValidExpression = SUPPORTED_EXPRESSIONS[parent.type]; | ||||
|  | ||||
|                 /* | ||||
|                  * We used the range instead of the node because it's possible | ||||
|                  * for the same identifier to be represented by two different | ||||
|                  * nodes, with the most clear example being shorthand properties: | ||||
|                  * { foo } | ||||
|                  * In this case, "foo" is represented by one node for the name | ||||
|                  * and one for the value. The only way to know they are the same | ||||
|                  * is to look at the range. | ||||
|                  */ | ||||
|                 if (isValidExpression && !reportedNodes.has(node.range.toString()) && (isValidExpression === true || isValidExpression(parent, node))) { | ||||
|                     reportedNodes.add(node.range.toString()); | ||||
|  | ||||
|                     let messageId = isShort ? "tooShort" : "tooLong"; | ||||
|  | ||||
|                     if (node.type === "PrivateIdentifier") { | ||||
|                         messageId += "Private"; | ||||
|                     } | ||||
|  | ||||
|                     context.report({ | ||||
|                         node, | ||||
|                         messageId, | ||||
|                         data: { name, min: minLength, max: maxLength } | ||||
|                     }); | ||||
|                 } | ||||
|             } | ||||
|         }; | ||||
|     } | ||||
| }; | ||||
Some files were not shown because too many files have changed in this diff Show More
		Reference in New Issue
	
	Block a user