Skip to content

Commit 9c4248c

Browse files
authored
cache parsed tsconfig files (#607)
1 parent e9426b5 commit 9c4248c

File tree

3 files changed

+40
-28
lines changed

3 files changed

+40
-28
lines changed

packages/wotan/src/project-host.ts

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -25,6 +25,16 @@ export class ProjectHost implements ts.CompilerHost {
2525
private processedFiles = new Map<string, ProcessedFileInfo>();
2626
private sourceFileCache = new Map<string, ts.SourceFile | undefined>();
2727
private fileContent = new Map<string, string>();
28+
private tsconfigCache = new Map<string, ts.ExtendedConfigCacheEntry>();
29+
private commandLineCache = new Map<string, ts.ParsedCommandLine>();
30+
31+
private parseConfigHost: ts.ParseConfigHost = {
32+
useCaseSensitiveFileNames: this.useCaseSensitiveFileNames(),
33+
readDirectory:
34+
(rootDir, extensions, excludes, includes, depth) => this.readDirectory(rootDir, extensions, excludes, includes, depth),
35+
fileExists: (f) => this.fileExists(f),
36+
readFile: (f) => this.readFile(f),
37+
};
2838

2939
public getCanonicalFileName = ts.sys.useCaseSensitiveFileNames ? (f: string) => f : (f: string) => f.toLowerCase();
3040
private moduleResolutionCache = ts.createModuleResolutionCache(this.cwd, this.getCanonicalFileName);
@@ -208,6 +218,8 @@ export class ProjectHost implements ts.CompilerHost {
208218
(entry) => entry.kind === FileKind.Directory ? path.join(dir, entry.name) : undefined,
209219
);
210220
}
221+
public getSourceFile(fileName: string, languageVersion: ts.ScriptTarget.JSON): ts.JsonSourceFile | undefined;
222+
public getSourceFile(fileName: string, languageVersion: ts.ScriptTarget): ts.SourceFile | undefined;
211223
public getSourceFile(fileName: string, languageVersion: ts.ScriptTarget) {
212224
return resolveCachedResult(
213225
this.sourceFileCache,
@@ -225,6 +237,7 @@ export class ProjectHost implements ts.CompilerHost {
225237
oldProgram: ts.Program | undefined,
226238
projectReferences: ReadonlyArray<ts.ProjectReference> | undefined,
227239
) {
240+
options = {...options, suppressOutputPathCheck: true};
228241
this.compilerOptions = options;
229242
this.moduleResolutionCache = ts.createModuleResolutionCache(this.cwd, this.getCanonicalFileName, options);
230243
return ts.createProgram({rootNames, options, oldProgram, projectReferences, host: this});
@@ -255,6 +268,29 @@ export class ProjectHost implements ts.CompilerHost {
255268
this.processedFiles.delete(fileName);
256269
}
257270

271+
public getParsedCommandLine(fileName: string) {
272+
return resolveCachedResult(this.commandLineCache, fileName, this.parseConfigFile);
273+
}
274+
275+
@bind
276+
private parseConfigFile(fileName: string) {
277+
// Note to future self: it's highly unlikely that a tsconfig of a project reference is used as base config for another tsconfig.
278+
// Therefore it doesn't make such sense to read or write the tsconfigCache here.
279+
const sourceFile = this.getSourceFile(fileName, ts.ScriptTarget.JSON);
280+
if (sourceFile === undefined)
281+
return;
282+
return ts.parseJsonSourceFileConfigFileContent(
283+
sourceFile,
284+
this.parseConfigHost,
285+
path.dirname(fileName),
286+
undefined,
287+
fileName,
288+
undefined,
289+
undefined,
290+
<ts.Map<ts.ExtendedConfigCacheEntry>>this.tsconfigCache,
291+
);
292+
}
293+
258294
public resolveModuleNames(names: string[], file: string, _?: unknown, reference?: ts.ResolvedProjectReference) {
259295
const seen = new Map<string, ts.ResolvedModuleFull | undefined>();
260296
const resolve = (name: string) =>

packages/wotan/src/runner.ts

Lines changed: 4 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import {
1313
import * as path from 'path';
1414
import * as ts from 'typescript';
1515
import * as glob from 'glob';
16-
import { unixifyPath, hasSupportedExtension, addUnique, flatMap, createParseConfigHost, hasParseErrors, invertChangeRange } from './utils';
16+
import { unixifyPath, hasSupportedExtension, addUnique, flatMap, hasParseErrors, invertChangeRange } from './utils';
1717
import { Minimatch, IMinimatch } from 'minimatch';
1818
import { ProcessorLoader } from './services/processor-loader';
1919
import { injectable } from 'inversify';
@@ -327,20 +327,13 @@ export class Runner {
327327
if (!addUnique(seen, configFilePath))
328328
continue;
329329

330-
let commandLine: ts.ParsedCommandLine;
330+
let commandLine;
331331
if (typeof configFile !== 'string') {
332332
({commandLine} = configFile);
333333
} else {
334-
const sourceFile = host.getSourceFile(configFile, ts.ScriptTarget.JSON);
335-
if (sourceFile === undefined)
334+
commandLine = host.getParsedCommandLine(configFile);
335+
if (commandLine === undefined)
336336
continue;
337-
commandLine = ts.parseJsonSourceFileConfigFileContent(
338-
<ts.TsConfigSourceFile>sourceFile,
339-
createParseConfigHost(host),
340-
path.dirname(configFile),
341-
{noEmit: true},
342-
configFile,
343-
);
344337
}
345338
if (commandLine.errors.length !== 0)
346339
this.logger.warn(ts.formatDiagnostics(commandLine.errors, host));

packages/wotan/src/utils.ts

Lines changed: 0 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -141,23 +141,6 @@ export function addUnique<T>(arr: T[], item: T & {[K in keyof T]: T[K]}) {
141141
return true;
142142
}
143143

144-
export function createParseConfigHost(
145-
host: Required<Pick<ts.CompilerHost, 'readDirectory' | 'readFile' | 'useCaseSensitiveFileNames' | 'fileExists'>>,
146-
): ts.ParseConfigHost {
147-
return {
148-
useCaseSensitiveFileNames: host.useCaseSensitiveFileNames(),
149-
readDirectory(rootDir, extensions, excludes, includes, depth) {
150-
return host.readDirectory(rootDir, extensions, excludes, includes, depth);
151-
},
152-
fileExists(f) {
153-
return host.fileExists(f);
154-
},
155-
readFile(f) {
156-
return host.readFile(f);
157-
},
158-
};
159-
}
160-
161144
export function hasParseErrors(sourceFile: ts.SourceFile) {
162145
return (<{parseDiagnostics: ts.Diagnostic[]}><{}>sourceFile).parseDiagnostics.length !== 0;
163146
}

0 commit comments

Comments
 (0)