Skip to content

Commit 2150a77

Browse files
authored
Merge pull request #15261 from aozgaa/moduleReuse
Reuse Module Resolutions from Unchanged Files
2 parents 41b9f74 + 6082514 commit 2150a77

File tree

9 files changed

+449
-122
lines changed

9 files changed

+449
-122
lines changed

src/compiler/core.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -251,6 +251,15 @@ namespace ts {
251251
}
252252
}
253253

254+
export function zipToMap<T>(keys: string[], values: T[]): Map<T> {
255+
Debug.assert(keys.length === values.length);
256+
const map = createMap<T>();
257+
for (let i = 0; i < keys.length; ++i) {
258+
map.set(keys[i], values[i]);
259+
}
260+
return map;
261+
}
262+
254263
/**
255264
* Iterates through `array` by index and performs the callback on each element of array until the callback
256265
* returns a falsey value, then returns false.

src/compiler/diagnosticMessages.json

Lines changed: 9 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3203,9 +3203,16 @@
32033203
},
32043204
"Scoped package detected, looking in '{0}'": {
32053205
"category": "Message",
3206-
"code": "6182"
3206+
"code": 6182
3207+
},
3208+
"Reusing resolution of module '{0}' to file '{1}' from old program.": {
3209+
"category": "Message",
3210+
"code": 6183
3211+
},
3212+
"Reusing module resolutions originating in '{0}' since resolutions are unchanged from old program.": {
3213+
"category": "Message",
3214+
"code": 6184
32073215
},
3208-
32093216
"Variable '{0}' implicitly has an '{1}' type.": {
32103217
"category": "Error",
32113218
"code": 7005

src/compiler/program.ts

Lines changed: 125 additions & 86 deletions
Large diffs are not rendered by default.

src/compiler/types.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2408,7 +2408,14 @@ namespace ts {
24082408
/* @internal */ getResolvedTypeReferenceDirectives(): Map<ResolvedTypeReferenceDirective>;
24092409
/* @internal */ isSourceFileFromExternalLibrary(file: SourceFile): boolean;
24102410
// For testing purposes only.
2411-
/* @internal */ structureIsReused?: boolean;
2411+
/* @internal */ structureIsReused?: StructureIsReused;
2412+
}
2413+
2414+
/* @internal */
2415+
export const enum StructureIsReused {
2416+
Not = 0,
2417+
SafeModules = 1 << 0,
2418+
Completely = 1 << 1,
24122419
}
24132420

24142421
export interface CustomTransformers {

src/compiler/utilities.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -122,9 +122,8 @@ namespace ts {
122122

123123
/* @internal */
124124
export function hasChangesInResolutions<T>(names: string[], newResolutions: T[], oldResolutions: Map<T>, comparer: (oldResolution: T, newResolution: T) => boolean): boolean {
125-
if (names.length !== newResolutions.length) {
126-
return false;
127-
}
125+
Debug.assert(names.length === newResolutions.length);
126+
128127
for (let i = 0; i < names.length; i++) {
129128
const newResolution = newResolutions[i];
130129
const oldResolution = oldResolutions && oldResolutions.get(names[i]);

src/harness/unittests/cachingInServerLSHost.ts

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -201,14 +201,13 @@ namespace ts {
201201
assert.isTrue(diags.length === 1, "one diagnostic expected");
202202
assert.isTrue(typeof diags[0].messageText === "string" && ((<string>diags[0].messageText).indexOf("Cannot find module") === 0), "should be 'cannot find module' message");
203203

204-
// assert that import will success once file appear on disk
205204
fileMap.set(imported.name, imported);
206205
fileExistsCalledForBar = false;
207206
rootScriptInfo.editContent(0, root.content.length, `import {y} from "bar"`);
208207

209208
diags = project.getLanguageService().getSemanticDiagnostics(root.name);
210-
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called");
211-
assert.isTrue(diags.length === 0);
209+
assert.isTrue(fileExistsCalledForBar, "'fileExists' should be called.");
210+
assert.isTrue(diags.length === 0, "The import should succeed once the imported file appears on disk.");
212211
});
213212
});
214213
}

src/harness/unittests/moduleResolution.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1042,7 +1042,7 @@ import b = require("./moduleB");
10421042
assert.equal(diagnostics1.length, 1, "expected one diagnostic");
10431043

10441044
createProgram(names, {}, compilerHost, program1);
1045-
assert.isTrue(program1.structureIsReused);
1045+
assert.isTrue(program1.structureIsReused === StructureIsReused.Completely);
10461046
const diagnostics2 = program1.getFileProcessingDiagnostics().getDiagnostics();
10471047
assert.equal(diagnostics2.length, 1, "expected one diagnostic");
10481048
assert.equal(diagnostics1[0].messageText, diagnostics2[0].messageText, "expected one diagnostic");

src/harness/unittests/reuseProgramStructure.ts

Lines changed: 292 additions & 25 deletions
Large diffs are not rendered by default.

src/server/project.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -552,7 +552,7 @@ namespace ts.server {
552552
// bump up the version if
553553
// - oldProgram is not set - this is a first time updateGraph is called
554554
// - newProgram is different from the old program and structure of the old program was not reused.
555-
if (!oldProgram || (this.program !== oldProgram && !oldProgram.structureIsReused)) {
555+
if (!oldProgram || (this.program !== oldProgram && !(oldProgram.structureIsReused & StructureIsReused.Completely))) {
556556
hasChanges = true;
557557
if (oldProgram) {
558558
for (const f of oldProgram.getSourceFiles()) {

0 commit comments

Comments
 (0)