Skip to content

Commit f952953

Browse files
committed
Use the old source file when re-resolving modules
1 parent 334bf4e commit f952953

File tree

2 files changed

+20
-7
lines changed

2 files changed

+20
-7
lines changed

src/compiler/program.ts

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -704,7 +704,7 @@ namespace ts {
704704

705705
interface OldProgramState {
706706
program: Program | undefined;
707-
file: SourceFile;
707+
oldSourceFile: SourceFile | undefined;
708708
/** The collection of paths modified *since* the old program. */
709709
modifiedFilePaths: Path[];
710710
}
@@ -754,7 +754,6 @@ namespace ts {
754754
/** A transient placeholder used to mark predicted resolution in the result list. */
755755
const predictedToResolveToAmbientModuleMarker: ResolvedModuleFull = <any>{};
756756

757-
758757
for (let i = 0; i < moduleNames.length; i++) {
759758
const moduleName = moduleNames[i];
760759
// If the source file is unchanged and doesnt have invalidated resolution, reuse the module resolutions
@@ -825,9 +824,10 @@ namespace ts {
825824
// If we change our policy of rechecking failed lookups on each program create,
826825
// we should adjust the value returned here.
827826
function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName: string, oldProgramState: OldProgramState): boolean {
828-
const resolutionToFile = getResolvedModule(oldProgramState.file, moduleName);
829-
if (resolutionToFile) {
830-
// module used to be resolved to file - ignore it
827+
const resolutionToFile = getResolvedModule(oldProgramState.oldSourceFile, moduleName);
828+
const resolvedFile = resolutionToFile && oldProgramState.program && oldProgramState.program.getSourceFile(resolutionToFile.resolvedFileName);
829+
if (resolutionToFile && !resolvedFile.externalModuleIndicator) {
830+
// module used to be resolved to module - ignore it
831831
return false;
832832
}
833833
const ambientModule = oldProgramState.program && oldProgramState.program.getTypeChecker().tryFindAmbientModuleWithoutAugmentations(moduleName);
@@ -1001,7 +1001,7 @@ namespace ts {
10011001
const newSourceFilePath = getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory);
10021002
if (resolveModuleNamesWorker) {
10031003
const moduleNames = getModuleNames(newSourceFile);
1004-
const oldProgramState = { program: oldProgram, file: oldSourceFile, modifiedFilePaths };
1004+
const oldProgramState: OldProgramState = { program: oldProgram, oldSourceFile, modifiedFilePaths };
10051005
const resolutions = resolveModuleNamesReusingOldState(moduleNames, newSourceFilePath, newSourceFile, oldProgramState);
10061006
// ensure that module resolution results are still correct
10071007
const resolutionsChanged = hasChangesInResolutions(moduleNames, resolutions, oldSourceFile.resolvedModules, moduleResolutionIsEqualTo);
@@ -1945,7 +1945,7 @@ namespace ts {
19451945
if (file.imports.length || file.moduleAugmentations.length) {
19461946
// Because global augmentation doesn't have string literal name, we can check for global augmentation as such.
19471947
const moduleNames = getModuleNames(file);
1948-
const oldProgramState = { program: oldProgram, file, modifiedFilePaths };
1948+
const oldProgramState: OldProgramState = { program: oldProgram, oldSourceFile: oldProgram && oldProgram.getSourceFile(file.fileName), modifiedFilePaths };
19491949
const resolutions = resolveModuleNamesReusingOldState(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory), file, oldProgramState);
19501950
Debug.assert(resolutions.length === moduleNames.length);
19511951
for (let i = 0; i < moduleNames.length; i++) {

src/harness/unittests/reuseProgramStructure.ts

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -389,6 +389,19 @@ namespace ts {
389389
checkResolvedModulesCache(program4, "a.ts", createMapFromTemplate({ b: createResolvedModule("b.ts"), c: undefined }));
390390
});
391391

392+
it("set the resolvedImports after re-using an ambient external module declaration", () => {
393+
const files = [
394+
{ name: "/a.ts", text: SourceText.New("", "", 'import * as a from "a";') },
395+
{ name: "/types/zzz/index.d.ts", text: SourceText.New("", "", 'declare module "a" { }') },
396+
];
397+
const options: CompilerOptions = { target, typeRoots: ["/types"] };
398+
const program1 = newProgram(files, ["/a.ts"], options);
399+
const program2 = updateProgram(program1, ["/a.ts"], options, files => {
400+
files[0].text = files[0].text.updateProgram('import * as aa from "a";');
401+
});
402+
assert.isDefined(program2.getSourceFile("/a.ts").resolvedModules.get("a"), "'a' is not an unresolved module after re-use");
403+
});
404+
392405
it("resolved type directives cache follows type directives", () => {
393406
const files = [
394407
{ name: "/a.ts", text: SourceText.New("/// <reference types='typedefs'/>", "", "var x = $") },

0 commit comments

Comments
 (0)