From abf107851ab3d0b4b2ff539337af380cb4756f45 Mon Sep 17 00:00:00 2001 From: JoostK Date: Sun, 16 Jan 2022 15:50:04 +0100 Subject: [PATCH 1/2] Allow structure reuse if a declaration file within a package is updated Closes #47471 --- src/compiler/program.ts | 4 ++-- src/compiler/utilities.ts | 9 ++++++--- .../unittests/reuseProgramStructure.ts | 19 +++++++++++++++++++ 3 files changed, 27 insertions(+), 5 deletions(-) diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 80115dbd35dab..7017f138224e9 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -2829,14 +2829,14 @@ namespace ts { redirectTargetsMap.add(fileFromPackageId.path, fileName); addFileToFilesByName(dupFile, path, redirectedPath); addFileIncludeReason(dupFile, reason); - sourceFileToPackageName.set(path, packageId.name); + sourceFileToPackageName.set(path, packageIdToPackageName(packageId)); processingOtherFiles!.push(dupFile); return dupFile; } else if (file) { // This is the first source file to have this packageId. packageIdToSourceFile.set(packageIdKey, file); - sourceFileToPackageName.set(path, packageId.name); + sourceFileToPackageName.set(path, packageIdToPackageName(packageId)); } } addFileToFilesByName(file, path, redirectedPath); diff --git a/src/compiler/utilities.ts b/src/compiler/utilities.ts index 691a965ee661d..ed8ddf17227a0 100644 --- a/src/compiler/utilities.ts +++ b/src/compiler/utilities.ts @@ -192,9 +192,12 @@ namespace ts { return a === b || !!a && !!b && a.name === b.name && a.subModuleName === b.subModuleName && a.version === b.version; } - export function packageIdToString({ name, subModuleName, version }: PackageId): string { - const fullName = subModuleName ? `${name}/${subModuleName}` : name; - return `${fullName}@${version}`; + export function packageIdToPackageName({ name, subModuleName }: PackageId): string { + return subModuleName ? `${name}/${subModuleName}` : name; + } + + export function packageIdToString(packageId: PackageId): string { + return `${packageIdToPackageName(packageId)}@${packageId.version}`; } export function typeDirectiveIsEqualTo(oldResolution: ResolvedTypeReferenceDirective, newResolution: ResolvedTypeReferenceDirective): boolean { diff --git a/src/testRunner/unittests/reuseProgramStructure.ts b/src/testRunner/unittests/reuseProgramStructure.ts index 6dc13de241d47..ac9cfe11b914f 100644 --- a/src/testRunner/unittests/reuseProgramStructure.ts +++ b/src/testRunner/unittests/reuseProgramStructure.ts @@ -249,6 +249,25 @@ namespace ts { assert.equal(program1Diagnostics.length, program2Diagnostics.length); }); + it("successful if change affects a single module of a package", () => { + const files = [ + { name: "/a.ts", text: SourceText.New("", "import {b} from 'b'", "var a = b;") }, + { name: "/node_modules/b/index.d.ts", text: SourceText.New("", "export * from './internal';", "") }, + { name: "/node_modules/b/internal.d.ts", text: SourceText.New("", "", "export const b = 1;") }, + { name: "/node_modules/b/package.json", text: SourceText.New("", "", JSON.stringify({ name: "b", version: "1.2.3" })) }, + ]; + + const options: CompilerOptions = { target, moduleResolution: ModuleResolutionKind.NodeJs }; + const program1 = newProgram(files, ["/a.ts"], options); + const program2 = updateProgram(program1, ["/a.ts"], options, files => { + files[2].text = files[2].text.updateProgram("export const b = 2;"); + }); + assert.equal(program2.structureIsReused, StructureIsReused.Completely); + const program1Diagnostics = program1.getSemanticDiagnostics(program1.getSourceFile("a.ts")); + const program2Diagnostics = program2.getSemanticDiagnostics(program1.getSourceFile("a.ts")); + assert.equal(program1Diagnostics.length, program2Diagnostics.length); + }); + it("fails if change affects tripleslash references", () => { const program1 = newProgram(files, ["a.ts"], { target }); const program2 = updateProgram(program1, ["a.ts"], { target }, files => { From 040fc26267638b10a872a10cd85412404ef3e685 Mon Sep 17 00:00:00 2001 From: JoostK Date: Fri, 21 Jan 2022 18:50:46 +0100 Subject: [PATCH 2/2] Use correct program to obtain source file in structure reuse test --- src/testRunner/unittests/reuseProgramStructure.ts | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/testRunner/unittests/reuseProgramStructure.ts b/src/testRunner/unittests/reuseProgramStructure.ts index ac9cfe11b914f..3e9e5f2313441 100644 --- a/src/testRunner/unittests/reuseProgramStructure.ts +++ b/src/testRunner/unittests/reuseProgramStructure.ts @@ -234,7 +234,7 @@ namespace ts { }); assert.equal(program2.structureIsReused, StructureIsReused.Completely); const program1Diagnostics = program1.getSemanticDiagnostics(program1.getSourceFile("a.ts")); - const program2Diagnostics = program2.getSemanticDiagnostics(program1.getSourceFile("a.ts")); + const program2Diagnostics = program2.getSemanticDiagnostics(program2.getSourceFile("a.ts")); assert.equal(program1Diagnostics.length, program2Diagnostics.length); }); @@ -245,7 +245,7 @@ namespace ts { }); assert.equal(program2.structureIsReused, StructureIsReused.Completely); const program1Diagnostics = program1.getSemanticDiagnostics(program1.getSourceFile("a.ts")); - const program2Diagnostics = program2.getSemanticDiagnostics(program1.getSourceFile("a.ts")); + const program2Diagnostics = program2.getSemanticDiagnostics(program2.getSourceFile("a.ts")); assert.equal(program1Diagnostics.length, program2Diagnostics.length); }); @@ -264,7 +264,7 @@ namespace ts { }); assert.equal(program2.structureIsReused, StructureIsReused.Completely); const program1Diagnostics = program1.getSemanticDiagnostics(program1.getSourceFile("a.ts")); - const program2Diagnostics = program2.getSemanticDiagnostics(program1.getSourceFile("a.ts")); + const program2Diagnostics = program2.getSemanticDiagnostics(program2.getSourceFile("a.ts")); assert.equal(program1Diagnostics.length, program2Diagnostics.length); });