Skip to content

Commit fd81d04

Browse files
authored
Lazy calculation of expensive file explaining diagnsotics and some caching to be used to share the diagnostic data (#58398)
1 parent 2070713 commit fd81d04

File tree

49 files changed

+8088
-170
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

49 files changed

+8088
-170
lines changed

src/compiler/program.ts

Lines changed: 197 additions & 54 deletions
Large diffs are not rendered by default.

src/compiler/types.ts

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -4608,26 +4608,24 @@ export type FileIncludeReason =
46084608

46094609
/** @internal */
46104610
export const enum FilePreprocessingDiagnosticsKind {
4611-
FilePreprocessingReferencedDiagnostic,
4611+
FilePreprocessingLibReferenceDiagnostic,
46124612
FilePreprocessingFileExplainingDiagnostic,
46134613
ResolutionDiagnostics,
46144614
}
46154615

46164616
/** @internal */
4617-
export interface FilePreprocessingReferencedDiagnostic {
4618-
kind: FilePreprocessingDiagnosticsKind.FilePreprocessingReferencedDiagnostic;
4619-
reason: ReferencedFile;
4620-
diagnostic: DiagnosticMessage;
4621-
args?: DiagnosticArguments;
4617+
export interface FilePreprocessingLibReferenceDiagnostic {
4618+
kind: FilePreprocessingDiagnosticsKind.FilePreprocessingLibReferenceDiagnostic;
4619+
reason: ReferencedFile & { kind: FileIncludeKind.LibReferenceDirective; };
46224620
}
46234621

46244622
/** @internal */
46254623
export interface FilePreprocessingFileExplainingDiagnostic {
46264624
kind: FilePreprocessingDiagnosticsKind.FilePreprocessingFileExplainingDiagnostic;
4627-
file?: Path;
4625+
file: Path | undefined;
46284626
fileProcessingReason: FileIncludeReason;
46294627
diagnostic: DiagnosticMessage;
4630-
args?: DiagnosticArguments;
4628+
args: DiagnosticArguments;
46314629
}
46324630

46334631
/** @internal */
@@ -4637,7 +4635,7 @@ export interface ResolutionDiagnostics {
46374635
}
46384636

46394637
/** @internal */
4640-
export type FilePreprocessingDiagnostics = FilePreprocessingReferencedDiagnostic | FilePreprocessingFileExplainingDiagnostic | ResolutionDiagnostics;
4638+
export type FilePreprocessingDiagnostics = FilePreprocessingLibReferenceDiagnostic | FilePreprocessingFileExplainingDiagnostic | ResolutionDiagnostics;
46414639

46424640
/** @internal */
46434641
export const enum EmitOnly {

src/compiler/watchPublic.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -594,6 +594,7 @@ export function createWatchProgram<T extends BuilderProgram>(host: WatchCompiler
594594
});
595595
parsedConfigs = undefined;
596596
}
597+
builderProgram = undefined!;
597598
}
598599

599600
function getResolutionCache() {

src/testRunner/unittests/helpers.ts

Lines changed: 31 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -21,6 +21,7 @@ export interface NamedSourceText {
2121
export interface ProgramWithSourceTexts extends ts.Program {
2222
sourceTexts?: readonly NamedSourceText[];
2323
host: TestCompilerHost;
24+
version: number;
2425
}
2526

2627
export interface TestCompilerHost extends ts.CompilerHost {
@@ -102,7 +103,7 @@ function createSourceFileWithText(fileName: string, sourceText: SourceText, targ
102103
return file;
103104
}
104105

105-
export function createTestCompilerHost(texts: readonly NamedSourceText[], target: ts.ScriptTarget, oldProgram?: ProgramWithSourceTexts, useGetSourceFileByPath?: boolean) {
106+
export function createTestCompilerHost(texts: readonly NamedSourceText[], target: ts.ScriptTarget, oldProgram?: ProgramWithSourceTexts, useGetSourceFileByPath?: boolean, useCaseSensitiveFileNames?: boolean) {
106107
const files = ts.arrayToMap(texts, t => t.name, t => {
107108
if (oldProgram) {
108109
let oldFile = oldProgram.getSourceFile(t.name) as SourceFileWithText;
@@ -115,52 +116,64 @@ export function createTestCompilerHost(texts: readonly NamedSourceText[], target
115116
}
116117
return createSourceFileWithText(t.name, t.text, target);
117118
});
118-
const useCaseSensitiveFileNames = ts.sys && ts.sys.useCaseSensitiveFileNames;
119+
if (useCaseSensitiveFileNames === undefined) useCaseSensitiveFileNames = ts.sys && ts.sys.useCaseSensitiveFileNames;
119120
const getCanonicalFileName = ts.createGetCanonicalFileName(useCaseSensitiveFileNames);
121+
const filesByPath = ts.mapEntries(files, (fileName, file) => [ts.toPath(fileName, "", getCanonicalFileName), file]);
120122
const trace: string[] = [];
121123
const result: TestCompilerHost = {
122124
trace: s => trace.push(s),
123125
getTrace: () => trace,
124126
clearTrace: () => trace.length = 0,
125-
getSourceFile: fileName => files.get(fileName),
127+
getSourceFile: fileName => filesByPath.get(ts.toPath(fileName, "", getCanonicalFileName)),
126128
getDefaultLibFileName: () => "lib.d.ts",
127129
writeFile: ts.notImplemented,
128130
getCurrentDirectory: () => "",
129131
getDirectories: () => [],
130132
getCanonicalFileName,
131133
useCaseSensitiveFileNames: () => useCaseSensitiveFileNames,
132134
getNewLine: () => ts.sys ? ts.sys.newLine : newLine,
133-
fileExists: fileName => files.has(fileName),
135+
fileExists: fileName => filesByPath.has(ts.toPath(fileName, "", getCanonicalFileName)),
134136
readFile: fileName => {
135-
const file = files.get(fileName);
137+
const file = filesByPath.get(ts.toPath(fileName, "", getCanonicalFileName));
136138
return file && file.text;
137139
},
138140
};
139141
if (useGetSourceFileByPath) {
140-
const filesByPath = ts.mapEntries(files, (fileName, file) => [ts.toPath(fileName, "", getCanonicalFileName), file]);
141142
result.getSourceFileByPath = (_fileName, path) => filesByPath.get(path);
142143
}
143144
return result;
144145
}
145146

146-
export function newProgram(texts: NamedSourceText[], rootNames: string[], options: ts.CompilerOptions, useGetSourceFileByPath?: boolean): ProgramWithSourceTexts {
147-
const host = createTestCompilerHost(texts, options.target!, /*oldProgram*/ undefined, useGetSourceFileByPath);
148-
const program = ts.createProgram(rootNames, options, host) as ProgramWithSourceTexts;
149-
program.sourceTexts = texts;
150-
program.host = host;
151-
return program;
147+
export function newProgram(texts: NamedSourceText[], rootNames: string[], options: ts.CompilerOptions, useGetSourceFileByPath?: boolean, useCaseSensitiveFileNames?: boolean): ProgramWithSourceTexts {
148+
const host = createTestCompilerHost(texts, options.target!, /*oldProgram*/ undefined, useGetSourceFileByPath, useCaseSensitiveFileNames);
149+
return programToProgramWithSourceTexts(
150+
ts.createProgram(rootNames, options, host),
151+
texts,
152+
host,
153+
1,
154+
);
152155
}
153156

154-
export function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: readonly string[], options: ts.CompilerOptions, updater: (files: NamedSourceText[]) => void, newTexts?: NamedSourceText[], useGetSourceFileByPath?: boolean) {
157+
function programToProgramWithSourceTexts(program: ts.Program, texts: NamedSourceText[], host: TestCompilerHost, version: number): ProgramWithSourceTexts {
158+
const result = program as ProgramWithSourceTexts;
159+
result.sourceTexts = texts;
160+
result.host = host;
161+
result.version = version;
162+
return result;
163+
}
164+
165+
export function updateProgram(oldProgram: ProgramWithSourceTexts, rootNames: readonly string[], options: ts.CompilerOptions, updater: (files: NamedSourceText[]) => void, newTexts?: NamedSourceText[], useGetSourceFileByPath?: boolean, useCaseSensitiveFileNames?: boolean) {
155166
if (!newTexts) {
156167
newTexts = oldProgram.sourceTexts!.slice(0);
157168
}
158169
updater(newTexts);
159-
const host = createTestCompilerHost(newTexts, options.target!, oldProgram, useGetSourceFileByPath);
160-
const program = ts.createProgram(rootNames, options, host, oldProgram) as ProgramWithSourceTexts;
161-
program.sourceTexts = newTexts;
162-
program.host = host;
163-
return program;
170+
const host = createTestCompilerHost(newTexts, options.target!, oldProgram, useGetSourceFileByPath, useCaseSensitiveFileNames);
171+
return programToProgramWithSourceTexts(
172+
ts.createProgram(rootNames, options, host, oldProgram),
173+
newTexts,
174+
host,
175+
oldProgram.version + 1,
176+
);
164177
}
165178

166179
export function updateProgramText(files: readonly NamedSourceText[], fileName: string, newProgramText: string) {
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
import { dedent } from "../../_namespaces/Utils";
2+
import { jsonToReadableText } from "../helpers";
3+
import {
4+
FsContents,
5+
libContent,
6+
} from "./contents";
7+
import { libFile } from "./virtualFileSystemWithWatch";
8+
9+
export function getFsContentsForMultipleErrorsForceConsistentCasingInFileNames(): FsContents {
10+
return {
11+
"/home/src/projects/project/src/struct.d.ts": dedent`
12+
import * as xs1 from "fp-ts/lib/Struct";
13+
import * as xs2 from "fp-ts/lib/struct";
14+
import * as xs3 from "./Struct";
15+
import * as xs4 from "./struct";
16+
`,
17+
"/home/src/projects/project/src/anotherFile.ts": dedent`
18+
import * as xs1 from "fp-ts/lib/Struct";
19+
import * as xs2 from "fp-ts/lib/struct";
20+
import * as xs3 from "./Struct";
21+
import * as xs4 from "./struct";
22+
`,
23+
"/home/src/projects/project/src/oneMore.ts": dedent`
24+
import * as xs1 from "fp-ts/lib/Struct";
25+
import * as xs2 from "fp-ts/lib/struct";
26+
import * as xs3 from "./Struct";
27+
import * as xs4 from "./struct";
28+
`,
29+
"/home/src/projects/project/tsconfig.json": jsonToReadableText({}),
30+
"/home/src/projects/project/node_modules/fp-ts/lib/struct.d.ts": `export function foo(): void`,
31+
[libFile.path]: libContent,
32+
};
33+
}

src/testRunner/unittests/helpers/libraryResolution.ts

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -91,3 +91,46 @@ export function getCommandLineArgsForLibResolution(withoutConfig: true | undefin
9191
["project1/core.d.ts", "project1/utils.d.ts", "project1/file.ts", "project1/index.ts", "project1/file2.ts", "--lib", "es5,dom", "--traceResolution", "--explainFiles"] :
9292
["-p", "project1", "--explainFiles"];
9393
}
94+
95+
function getFsContentsForLibResolutionUnknown(): FsContents {
96+
return {
97+
"/home/src/projects/project1/utils.d.ts": `export const y = 10;`,
98+
"/home/src/projects/project1/file.ts": `export const file = 10;`,
99+
"/home/src/projects/project1/core.d.ts": `export const core = 10;`,
100+
"/home/src/projects/project1/index.ts": `export const x = "type1";`,
101+
"/home/src/projects/project1/file2.ts": dedent`
102+
/// <reference lib="webworker2"/>
103+
/// <reference lib="unknownlib"/>
104+
/// <reference lib="scripthost"/>
105+
`,
106+
"/home/src/projects/project1/tsconfig.json": jsonToReadableText({
107+
compilerOptions: {
108+
composite: true,
109+
traceResolution: true,
110+
},
111+
}),
112+
"/home/src/lib/lib.d.ts": libContent,
113+
"/home/src/lib/lib.webworker.d.ts": "interface WebWorkerInterface { }",
114+
"/home/src/lib/lib.scripthost.d.ts": "interface ScriptHostInterface { }",
115+
};
116+
}
117+
118+
export function getFsForLibResolutionUnknown() {
119+
return loadProjectFromFiles(
120+
getFsContentsForLibResolutionUnknown(),
121+
{
122+
cwd: "/home/src/projects",
123+
executingFilePath: "/home/src/lib/tsc.js",
124+
},
125+
);
126+
}
127+
128+
export function getSysForLibResolutionUnknown() {
129+
return createWatchedSystem(
130+
getFsContentsForLibResolutionUnknown(),
131+
{
132+
currentDirectory: "/home/src/projects",
133+
executingFilePath: "/home/src/lib/tsc.js",
134+
},
135+
);
136+
}

0 commit comments

Comments
 (0)