UNPKG

@typescript-eslint/typescript-estree

Version:

A parser that converts TypeScript source code into an ESTree compatible form

100 lines (99 loc) 4.41 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.clearGlobCache = clearGlobCache; exports.resolveProjectList = resolveProjectList; exports.clearGlobResolutionCache = clearGlobResolutionCache; const debug_1 = __importDefault(require("debug")); const fast_glob_1 = require("fast-glob"); const is_glob_1 = __importDefault(require("is-glob")); const shared_1 = require("../create-program/shared"); const ExpiringCache_1 = require("./ExpiringCache"); const log = (0, debug_1.default)('typescript-eslint:typescript-estree:parseSettings:resolveProjectList'); let RESOLUTION_CACHE = null; function clearGlobCache() { RESOLUTION_CACHE?.clear(); } /** * Normalizes, sanitizes, resolves and filters the provided project paths */ function resolveProjectList(options) { const sanitizedProjects = []; // Normalize and sanitize the project paths if (options.project != null) { for (const project of options.project) { if (typeof project === 'string') { sanitizedProjects.push(project); } } } if (sanitizedProjects.length === 0) { return new Map(); } const projectFolderIgnoreList = (options.projectFolderIgnoreList ?? ['**/node_modules/**']) .filter(folder => typeof folder === 'string') // prefix with a ! for not match glob .map(folder => (folder.startsWith('!') ? folder : `!${folder}`)); const cacheKey = getHash({ project: sanitizedProjects, projectFolderIgnoreList, tsconfigRootDir: options.tsconfigRootDir, }); if (RESOLUTION_CACHE == null) { // note - we initialize the global cache based on the first config we encounter. // this does mean that you can't have multiple lifetimes set per folder // I doubt that anyone will really bother reconfiguring this, let alone // try to do complicated setups, so we'll deal with this later if ever. RESOLUTION_CACHE = new ExpiringCache_1.ExpiringCache(options.singleRun ? 'Infinity' : (options.cacheLifetime?.glob ?? ExpiringCache_1.DEFAULT_TSCONFIG_CACHE_DURATION_SECONDS)); } else { const cached = RESOLUTION_CACHE.get(cacheKey); if (cached) { return cached; } } // Transform glob patterns into paths const nonGlobProjects = sanitizedProjects.filter(project => !(0, is_glob_1.default)(project)); const globProjects = sanitizedProjects.filter(project => (0, is_glob_1.default)(project)); let globProjectPaths = []; if (globProjects.length > 0) { // Although fast-glob supports multiple patterns, fast-glob returns arbitrary order of results // to improve performance. To ensure the order is correct, we need to call fast-glob for each pattern // separately and then concatenate the results in patterns' order. globProjectPaths = globProjects.flatMap(pattern => (0, fast_glob_1.sync)(pattern, { cwd: options.tsconfigRootDir, ignore: projectFolderIgnoreList, })); } const uniqueCanonicalProjectPaths = new Map([...nonGlobProjects, ...globProjectPaths].map(project => [ (0, shared_1.getCanonicalFileName)((0, shared_1.ensureAbsolutePath)(project, options.tsconfigRootDir)), (0, shared_1.ensureAbsolutePath)(project, options.tsconfigRootDir), ])); log('parserOptions.project (excluding ignored) matched projects: %s', uniqueCanonicalProjectPaths); RESOLUTION_CACHE.set(cacheKey, uniqueCanonicalProjectPaths); return uniqueCanonicalProjectPaths; } function getHash({ project, projectFolderIgnoreList, tsconfigRootDir, }) { // create a stable representation of the config const hashObject = { tsconfigRootDir, // the project order does matter and can impact the resolved globs project, // the ignore order won't doesn't ever matter projectFolderIgnoreList: [...projectFolderIgnoreList].sort(), }; return (0, shared_1.createHash)(JSON.stringify(hashObject)); } /** * Exported for testing purposes only * @internal */ function clearGlobResolutionCache() { RESOLUTION_CACHE?.clear(); RESOLUTION_CACHE = null; }