diff --git a/src/compiler/tsbuild.ts b/src/compiler/tsbuild.ts index cc6899163fc..f1e32051310 100644 --- a/src/compiler/tsbuild.ts +++ b/src/compiler/tsbuild.ts @@ -194,20 +194,24 @@ namespace ts { } } - interface ConfigFileMap { - setValue(fileName: ResolvedConfigFileName, value: T): void; - getValue(fileName: ResolvedConfigFileName): T | undefined; - hasKey(fileName: ResolvedConfigFileName): boolean; - removeKey(fileName: ResolvedConfigFileName): void; - forEach(action: (value: T, key: ResolvedConfigFilePath) => void): void; - getSize(): number; + type ResolvedConfigFilePath = ResolvedConfigFileName & Path; + + interface FileMap extends Map { + get(key: U): T | undefined; + has(key: U): boolean; + forEach(action: (value: T, key: U) => void): void; + readonly size: number; + keys(): Iterator; + values(): Iterator; + entries(): Iterator<[U, T]>; + set(key: U, value: T): this; + delete(key: U): boolean; clear(): void; } - type ResolvedConfigFilePath = ResolvedConfigFileName & Path; + type ConfigFileMap = FileMap; - - function getOrCreateValueFromConfigFileMap(configFileMap: Map, resolved: ResolvedConfigFilePath, createT: () => T): T { + function getOrCreateValueFromConfigFileMap(configFileMap: ConfigFileMap, resolved: ResolvedConfigFilePath, createT: () => T): T { const existingValue = configFileMap.get(resolved); let newValue: T | undefined; if (!existingValue) { @@ -217,7 +221,7 @@ namespace ts { return existingValue || newValue!; } - function getOrCreateValueMapFromConfigFileMap(configFileMap: Map>, resolved: ResolvedConfigFilePath): Map { + function getOrCreateValueMapFromConfigFileMap(configFileMap: ConfigFileMap>, resolved: ResolvedConfigFilePath): Map { return getOrCreateValueFromConfigFileMap>(configFileMap, resolved, createMap); } @@ -354,16 +358,16 @@ namespace ts { // Watch state const builderPrograms = createFileMap(); const diagnostics = createFileMap>(); - const projectPendingBuild = createFileMap(); + const projectPendingBuild = createMap() as ConfigFileMap; const projectErrorsReported = createFileMap(); let timerToBuildInvalidatedProject: any; let reportFileChangeDetected = false; const { watchFile, watchFilePath, watchDirectory, writeLog } = createWatchFactory(host, options); // Watches for the solution - const allWatchedWildcardDirectories = createMap>(); - const allWatchedInputFiles = createMap>(); - const allWatchedConfigFiles = createMap(); + const allWatchedWildcardDirectories = createMap() as ConfigFileMap>; + const allWatchedInputFiles = createMap() as ConfigFileMap>; + const allWatchedConfigFiles = createMap() as ConfigFileMap; return { buildAllProjects, @@ -394,7 +398,15 @@ namespace ts { // TODO remove this and use normal map so we arent transforming paths constantly - function createFileMap(): ConfigFileMap { + function createFileMap(): { + setValue(fileName: ResolvedConfigFileName, value: T): void; + getValue(fileName: ResolvedConfigFileName): T | undefined; + hasKey(fileName: ResolvedConfigFileName): boolean; + removeKey(fileName: ResolvedConfigFileName): void; + forEach(action: (value: T, key: ResolvedConfigFilePath) => void): void; + getSize(): number; + clear(): void; + } { const lookup = createMap(); return { setValue, @@ -435,7 +447,6 @@ namespace ts { } } - function resetBuildContext(opts = defaultOptions) { options = opts; baseCompilerOptions = getCompilerOptionsOfBuildOptions(options); @@ -848,28 +859,29 @@ namespace ts { /** * return true if new addition */ - function addProjToQueue(proj: ResolvedConfigFileName, reloadLevel: ConfigFileProgramReloadLevel) { - const value = projectPendingBuild.getValue(proj); + function addProjToQueue(proj: ResolvedConfigFilePath, reloadLevel: ConfigFileProgramReloadLevel) { + const value = projectPendingBuild.get(proj); if (value === undefined) { - projectPendingBuild.setValue(proj, reloadLevel); + projectPendingBuild.set(proj, reloadLevel); } else if (value < reloadLevel) { - projectPendingBuild.setValue(proj, reloadLevel); + projectPendingBuild.set(proj, reloadLevel); } } function getNextInvalidatedProject() { for (const project of getBuildOrder()) { - const reloadLevel = projectPendingBuild.getValue(project); + const projectPath = toResolvedConfigFilePath(project); + const reloadLevel = projectPendingBuild.get(projectPath); if (reloadLevel !== undefined) { - projectPendingBuild.removeKey(project); + projectPendingBuild.delete(projectPath); return { project, reloadLevel }; } } } function hasPendingInvalidatedProjects() { - return !!projectPendingBuild.getSize(); + return !!projectPendingBuild.size; } function scheduleBuildInvalidatedProject() { @@ -969,7 +981,8 @@ namespace ts { // Always use build order to queue projects for (let index = buildOrder.indexOf(resolved) + 1; index < buildOrder.length; index++) { const project = buildOrder[index]; - if (projectPendingBuild.hasKey(project)) continue; + const projectPath = toResolvedConfigFilePath(project); + if (projectPendingBuild.has(projectPath)) continue; const config = parseConfigFile(project); if (!config || !config.projectReferences) continue; @@ -1001,15 +1014,15 @@ namespace ts { status.type = UpToDateStatusType.UpToDateWithUpstreamTypes; } } - addProjToQueue(project, ConfigFileProgramReloadLevel.None); + addProjToQueue(projectPath, ConfigFileProgramReloadLevel.None); break; } } } function createBuildOrder(roots: readonly ResolvedConfigFileName[]): readonly ResolvedConfigFileName[] { - const temporaryMarks = createMap(); - const permanentMarks = createMap(); + const temporaryMarks = createMap() as ConfigFileMap; + const permanentMarks = createMap() as ConfigFileMap; const circularityReportStack: string[] = []; let buildOrder: ResolvedConfigFileName[] | undefined; for (const root of roots) { @@ -1138,7 +1151,7 @@ namespace ts { // Actual Emit const emitterDiagnostics = createDiagnosticCollection(); - const emittedOutputs = createMap(); + const emittedOutputs = createMap() as FileMap; outputFiles.forEach(({ name, text, writeByteOrderMark }) => { let priorChangeTime: Date | undefined; if (!anyDtsChanged && isDeclarationFile(name)) { @@ -1241,7 +1254,7 @@ namespace ts { // Actual Emit Debug.assert(!!outputFiles.length); const emitterDiagnostics = createDiagnosticCollection(); - const emittedOutputs = createMap(); + const emittedOutputs = createMap() as FileMap; outputFiles.forEach(({ name, text, writeByteOrderMark }) => { emittedOutputs.set(toPath(name), name); writeFile(compilerHost, emitterDiagnostics, name, text, writeByteOrderMark); @@ -1286,7 +1299,7 @@ namespace ts { projectStatus.setValue(proj.options.configFilePath as ResolvedConfigFilePath, status); } - function updateOutputTimestampsWorker(proj: ParsedCommandLine, priorNewestUpdateTime: Date, verboseMessage: DiagnosticMessage, skipOutputs?: Map) { + function updateOutputTimestampsWorker(proj: ParsedCommandLine, priorNewestUpdateTime: Date, verboseMessage: DiagnosticMessage, skipOutputs?: FileMap) { const outputs = getAllProjectOutputs(proj, !host.useCaseSensitiveFileNames()); if (!skipOutputs || outputs.length !== skipOutputs.size) { if (options.verbose) {