diff --git a/packages/typescript-estree/src/create-program/createDefaultProgram.ts b/packages/typescript-estree/src/create-program/createDefaultProgram.ts index b42ec76c678b..f169f2da4389 100644 --- a/packages/typescript-estree/src/create-program/createDefaultProgram.ts +++ b/packages/typescript-estree/src/create-program/createDefaultProgram.ts @@ -23,11 +23,11 @@ function createDefaultProgram( parseSettings.filePath || 'unnamed file', ); - if (parseSettings.projects.length !== 1) { + if (parseSettings.projects.size !== 1) { return undefined; } - const tsconfigPath = parseSettings.projects[0]; + const tsconfigPath = Array.from(parseSettings.projects.values())[0]; const commandLine = ts.getParsedCommandLineOfConfigFile( tsconfigPath, diff --git a/packages/typescript-estree/src/create-program/createProjectProgram.ts b/packages/typescript-estree/src/create-program/createProjectProgram.ts index a58097e3cd73..3e8432d0b46f 100644 --- a/packages/typescript-estree/src/create-program/createProjectProgram.ts +++ b/packages/typescript-estree/src/create-program/createProjectProgram.ts @@ -48,7 +48,9 @@ function createProjectProgram( parseSettings.filePath, parseSettings.tsconfigRootDir, ); - const relativeProjects = parseSettings.projects.map(describeProjectFilePath); + const relativeProjects = Array.from(parseSettings.projects.values()).map( + describeProjectFilePath, + ); const describedPrograms = relativeProjects.length === 1 ? relativeProjects[0] @@ -93,7 +95,7 @@ function createProjectProgram( if (!hasMatchedAnError) { const [describedInclusions, describedSpecifiers] = - parseSettings.projects.length === 1 + parseSettings.projects.size === 1 ? ['that TSConfig does not', 'that TSConfig'] : ['none of those TSConfigs', 'one of those TSConfigs']; errorLines.push( diff --git a/packages/typescript-estree/src/create-program/getWatchProgramsForProjects.ts b/packages/typescript-estree/src/create-program/getWatchProgramsForProjects.ts index 1ad82ec29b3d..01ef2a2532b9 100644 --- a/packages/typescript-estree/src/create-program/getWatchProgramsForProjects.ts +++ b/packages/typescript-estree/src/create-program/getWatchProgramsForProjects.ts @@ -151,7 +151,7 @@ function getWatchProgramsForProjects( ); } - const currentProjectsFromSettings = new Set(parseSettings.projects); + const currentProjectsFromSettings = new Map(parseSettings.projects); /* * before we go into the process of attempting to find and update every program @@ -198,13 +198,13 @@ function getWatchProgramsForProjects( * - the file is new/renamed, and the program hasn't been updated. */ for (const tsconfigPath of parseSettings.projects) { - const existingWatch = knownWatchProgramMap.get(tsconfigPath); + const existingWatch = knownWatchProgramMap.get(tsconfigPath[0]); if (existingWatch) { const updatedProgram = maybeInvalidateProgram( existingWatch, filePath, - tsconfigPath, + tsconfigPath[0], ); if (!updatedProgram) { continue; @@ -215,7 +215,7 @@ function getWatchProgramsForProjects( // cache and check the file list const fileList = updateCachedFileList( - tsconfigPath, + tsconfigPath[0], updatedProgram, parseSettings, ); @@ -229,15 +229,19 @@ function getWatchProgramsForProjects( continue; } - const programWatch = createWatchProgram(tsconfigPath, parseSettings); - knownWatchProgramMap.set(tsconfigPath, programWatch); + const programWatch = createWatchProgram(tsconfigPath[1], parseSettings); + knownWatchProgramMap.set(tsconfigPath[0], programWatch); const program = programWatch.getProgram().getProgram(); // sets parent pointers in source files program.getTypeChecker(); // cache and check the file list - const fileList = updateCachedFileList(tsconfigPath, program, parseSettings); + const fileList = updateCachedFileList( + tsconfigPath[0], + program, + parseSettings, + ); if (fileList.has(filePath)) { log('Found program for file. %s', filePath); // we can return early because we know this program contains the file diff --git a/packages/typescript-estree/src/parseSettings/createParseSettings.ts b/packages/typescript-estree/src/parseSettings/createParseSettings.ts index 49d048391d8f..b5d52ce569b8 100644 --- a/packages/typescript-estree/src/parseSettings/createParseSettings.ts +++ b/packages/typescript-estree/src/parseSettings/createParseSettings.ts @@ -113,7 +113,7 @@ export function createParseSettings( : console.log, // eslint-disable-line no-console preserveNodeMaps: options.preserveNodeMaps !== false, programs: Array.isArray(options.programs) ? options.programs : null, - projects: [], + projects: new Map(), range: options.range === true, singleRun, suppressDeprecatedPropertyWarnings: @@ -172,7 +172,7 @@ export function createParseSettings( // So in this specific case we default to 'none' if no value was provided if ( options.jsDocParsingMode == null && - parseSettings.projects.length === 0 && + parseSettings.projects.size === 0 && parseSettings.programs == null && parseSettings.EXPERIMENTAL_projectService == null ) { diff --git a/packages/typescript-estree/src/parseSettings/index.ts b/packages/typescript-estree/src/parseSettings/index.ts index 1df275901066..3511e3be718d 100644 --- a/packages/typescript-estree/src/parseSettings/index.ts +++ b/packages/typescript-estree/src/parseSettings/index.ts @@ -128,7 +128,7 @@ export interface MutableParseSettings { /** * Normalized paths to provided project paths. */ - projects: readonly CanonicalPath[]; + projects: ReadonlyMap; /** * Whether to add the `range` property to AST nodes. diff --git a/packages/typescript-estree/src/parseSettings/resolveProjectList.ts b/packages/typescript-estree/src/parseSettings/resolveProjectList.ts index 9c3b8480499a..4b24608b6ff8 100644 --- a/packages/typescript-estree/src/parseSettings/resolveProjectList.ts +++ b/packages/typescript-estree/src/parseSettings/resolveProjectList.ts @@ -18,8 +18,10 @@ const log = debug( 'typescript-eslint:typescript-estree:parser:parseSettings:resolveProjectList', ); -let RESOLUTION_CACHE: ExpiringCache | null = - null; +let RESOLUTION_CACHE: ExpiringCache< + string, + ReadonlyMap +> | null = null; export function clearGlobCache(): void { RESOLUTION_CACHE?.clear(); @@ -36,7 +38,7 @@ export function resolveProjectList( singleRun: boolean; tsconfigRootDir: string; }>, -): readonly CanonicalPath[] { +): ReadonlyMap { const sanitizedProjects: string[] = []; // Normalize and sanitize the project paths @@ -49,7 +51,7 @@ export function resolveProjectList( } if (sanitizedProjects.length === 0) { - return []; + return new Map(); } const projectFolderIgnoreList = ( @@ -91,7 +93,7 @@ export function resolveProjectList( const nonGlobProjects = sanitizedProjects.filter(project => !isGlob(project)); const globProjects = sanitizedProjects.filter(project => isGlob(project)); - const uniqueCanonicalProjectPaths = new Set( + const uniqueCanonicalProjectPaths = new Map( nonGlobProjects .concat( globProjects.length === 0 @@ -100,11 +102,12 @@ export function resolveProjectList( cwd: options.tsconfigRootDir, }), ) - .map(project => + .map(project => [ getCanonicalFileName( ensureAbsolutePath(project, options.tsconfigRootDir), ), - ), + ensureAbsolutePath(project, options.tsconfigRootDir), + ]), ); log( @@ -112,9 +115,8 @@ export function resolveProjectList( uniqueCanonicalProjectPaths, ); - const returnValue = Array.from(uniqueCanonicalProjectPaths); - RESOLUTION_CACHE.set(cacheKey, returnValue); - return returnValue; + RESOLUTION_CACHE.set(cacheKey, uniqueCanonicalProjectPaths); + return uniqueCanonicalProjectPaths; } function getHash({ diff --git a/packages/typescript-estree/src/parser.ts b/packages/typescript-estree/src/parser.ts index b4931a6da36e..d724d81e379d 100644 --- a/packages/typescript-estree/src/parser.ts +++ b/packages/typescript-estree/src/parser.ts @@ -188,12 +188,12 @@ function parseAndGenerateServices( if ( parseSettings.singleRun && !parseSettings.programs && - parseSettings.projects.length > 0 + parseSettings.projects.size > 0 ) { parseSettings.programs = { *[Symbol.iterator](): Iterator { for (const configFile of parseSettings.projects) { - const existingProgram = existingPrograms.get(configFile); + const existingProgram = existingPrograms.get(configFile[0]); if (existingProgram) { yield existingProgram; } else { @@ -201,8 +201,8 @@ function parseAndGenerateServices( 'Detected single-run/CLI usage, creating Program once ahead of time for project: %s', configFile, ); - const newProgram = createProgramFromConfigFile(configFile); - existingPrograms.set(configFile, newProgram); + const newProgram = createProgramFromConfigFile(configFile[1]); + existingPrograms.set(configFile[0], newProgram); yield newProgram; } } @@ -214,7 +214,7 @@ function parseAndGenerateServices( * Generate a full ts.Program or offer provided instances in order to be able to provide parser services, such as type-checking */ const hasFullTypeInformation = - parseSettings.programs != null || parseSettings.projects.length > 0; + parseSettings.programs != null || parseSettings.projects.size > 0; if ( typeof options.errorOnTypeScriptSyntacticAndSemanticIssues === 'boolean' && diff --git a/packages/typescript-estree/tests/lib/semanticInfo-singleRun.test.ts b/packages/typescript-estree/tests/lib/semanticInfo-singleRun.test.ts index 1051b8d2f171..f041d403f4fb 100644 --- a/packages/typescript-estree/tests/lib/semanticInfo-singleRun.test.ts +++ b/packages/typescript-estree/tests/lib/semanticInfo-singleRun.test.ts @@ -1,7 +1,6 @@ import glob = require('glob'); import * as path from 'path'; -import { getCanonicalFileName } from '../../src/create-program/shared'; import { createProgramFromConfigFile as createProgramFromConfigFileOriginal } from '../../src/create-program/useProvidedPrograms'; import { clearParseAndGenerateServicesCalls, @@ -94,7 +93,7 @@ const options = { } as const; const resolvedProject = (p: string): string => - getCanonicalFileName(path.resolve(path.join(process.cwd(), FIXTURES_DIR), p)); + path.resolve(path.join(process.cwd(), FIXTURES_DIR), p); describe('semanticInfo - singleRun', () => { beforeEach(() => { diff --git a/packages/website/src/components/linter/config.ts b/packages/website/src/components/linter/config.ts index 8262487369c1..c0e22f4e1637 100644 --- a/packages/website/src/components/linter/config.ts +++ b/packages/website/src/components/linter/config.ts @@ -25,7 +25,7 @@ export const defaultParseSettings: ParseSettings = { log: console.log, preserveNodeMaps: true, programs: null, - projects: [], + projects: new Map(), range: true, singleRun: false, suppressDeprecatedPropertyWarnings: false,