diff options
Diffstat (limited to 'tools/node_modules/eslint/lib/file-finder.js')
-rw-r--r-- | tools/node_modules/eslint/lib/file-finder.js | 145 |
1 files changed, 145 insertions, 0 deletions
diff --git a/tools/node_modules/eslint/lib/file-finder.js b/tools/node_modules/eslint/lib/file-finder.js new file mode 100644 index 0000000000..3458bbf52a --- /dev/null +++ b/tools/node_modules/eslint/lib/file-finder.js @@ -0,0 +1,145 @@ +/** + * @fileoverview Util class to find config files. + * @author Aliaksei Shytkin + */ + +"use strict"; + +//------------------------------------------------------------------------------ +// Requirements +//------------------------------------------------------------------------------ + +const fs = require("fs"), + path = require("path"); + +//------------------------------------------------------------------------------ +// Helpers +//------------------------------------------------------------------------------ + +/** + * Get the entries for a directory. Including a try-catch may be detrimental to + * function performance, so move it out here a separate function. + * @param {string} directory The directory to search in. + * @returns {string[]} The entries in the directory or an empty array on error. + * @private + */ +function getDirectoryEntries(directory) { + try { + + return fs.readdirSync(directory); + } catch (ex) { + return []; + } +} + +/** + * Create a hash of filenames from a directory listing + * @param {string[]} entries Array of directory entries. + * @param {string} directory Path to a current directory. + * @param {string[]} supportedConfigs List of support filenames. + * @returns {Object} Hashmap of filenames + */ +function normalizeDirectoryEntries(entries, directory, supportedConfigs) { + const fileHash = {}; + + entries.forEach(entry => { + if (supportedConfigs.indexOf(entry) >= 0) { + const resolvedEntry = path.resolve(directory, entry); + + if (fs.statSync(resolvedEntry).isFile()) { + fileHash[entry] = resolvedEntry; + } + } + }); + return fileHash; +} + +//------------------------------------------------------------------------------ +// API +//------------------------------------------------------------------------------ + +/** + * FileFinder class + */ +class FileFinder { + + /** + * @param {string[]} files The basename(s) of the file(s) to find. + * @param {stirng} cwd Current working directory + */ + constructor(files, cwd) { + this.fileNames = Array.isArray(files) ? files : [files]; + this.cwd = cwd || process.cwd(); + this.cache = {}; + } + + /** + * Find all instances of files with the specified file names, in directory and + * parent directories. Cache the results. + * Does not check if a matching directory entry is a file. + * Searches for all the file names in this.fileNames. + * Is currently used by lib/config.js to find .eslintrc and package.json files. + * @param {string} directory The directory to start the search from. + * @returns {GeneratorFunction} to iterate the file paths found + */ + *findAllInDirectoryAndParents(directory) { + const cache = this.cache; + + if (directory) { + directory = path.resolve(this.cwd, directory); + } else { + directory = this.cwd; + } + + if (cache.hasOwnProperty(directory)) { + yield* cache[directory]; + return; // to avoid doing the normal loop afterwards + } + + const dirs = []; + const fileNames = this.fileNames; + let searched = 0; + + do { + dirs[searched++] = directory; + cache[directory] = []; + + const filesMap = normalizeDirectoryEntries(getDirectoryEntries(directory), directory, fileNames); + + if (Object.keys(filesMap).length) { + for (let k = 0; k < fileNames.length; k++) { + + if (filesMap[fileNames[k]]) { + const filePath = filesMap[fileNames[k]]; + + // Add the file path to the cache of each directory searched. + for (let j = 0; j < searched; j++) { + cache[dirs[j]].push(filePath); + } + yield filePath; + break; + } + } + } + + const child = directory; + + // Assign parent directory to directory. + directory = path.dirname(directory); + + if (directory === child) { + return; + } + + } while (!cache.hasOwnProperty(directory)); + + // Add what has been cached previously to the cache of each directory searched. + for (let i = 0; i < searched; i++) { + dirs.push.apply(cache[dirs[i]], cache[directory]); + } + + yield* cache[dirs[0]]; + } +} + +module.exports = FileFinder; |