Skip to content

Use the correct old file when re-using file resolutions #20403

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 1 commit into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
14 changes: 7 additions & 7 deletions src/compiler/program.ts
Original file line number Diff line number Diff line change
Expand Up @@ -704,7 +704,7 @@ namespace ts {

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


for (let i = 0; i < moduleNames.length; i++) {
const moduleName = moduleNames[i];
// If the source file is unchanged and doesnt have invalidated resolution, reuse the module resolutions
Expand Down Expand Up @@ -825,9 +824,10 @@ namespace ts {
// If we change our policy of rechecking failed lookups on each program create,
// we should adjust the value returned here.
function moduleNameResolvesToAmbientModuleInNonModifiedFile(moduleName: string, oldProgramState: OldProgramState): boolean {
const resolutionToFile = getResolvedModule(oldProgramState.file, moduleName);
if (resolutionToFile) {
// module used to be resolved to file - ignore it
const resolutionToFile = getResolvedModule(oldProgramState.oldSourceFile, moduleName);
const resolvedFile = resolutionToFile && oldProgramState.program && oldProgramState.program.getSourceFile(resolutionToFile.resolvedFileName);
if (resolutionToFile && !resolvedFile.externalModuleIndicator) {
// module used to be resolved to module - ignore it
return false;
}
const ambientModule = oldProgramState.program && oldProgramState.program.getTypeChecker().tryFindAmbientModuleWithoutAugmentations(moduleName);
Expand Down Expand Up @@ -1001,7 +1001,7 @@ namespace ts {
const newSourceFilePath = getNormalizedAbsolutePath(newSourceFile.fileName, currentDirectory);
if (resolveModuleNamesWorker) {
const moduleNames = getModuleNames(newSourceFile);
const oldProgramState = { program: oldProgram, file: oldSourceFile, modifiedFilePaths };
const oldProgramState: OldProgramState = { program: oldProgram, oldSourceFile, modifiedFilePaths };
const resolutions = resolveModuleNamesReusingOldState(moduleNames, newSourceFilePath, newSourceFile, oldProgramState);
// ensure that module resolution results are still correct
const resolutionsChanged = hasChangesInResolutions(moduleNames, resolutions, oldSourceFile.resolvedModules, moduleResolutionIsEqualTo);
Expand Down Expand Up @@ -1945,7 +1945,7 @@ namespace ts {
if (file.imports.length || file.moduleAugmentations.length) {
// Because global augmentation doesn't have string literal name, we can check for global augmentation as such.
const moduleNames = getModuleNames(file);
const oldProgramState = { program: oldProgram, file, modifiedFilePaths };
const oldProgramState: OldProgramState = { program: oldProgram, oldSourceFile: oldProgram && oldProgram.getSourceFile(file.fileName), modifiedFilePaths };
const resolutions = resolveModuleNamesReusingOldState(moduleNames, getNormalizedAbsolutePath(file.fileName, currentDirectory), file, oldProgramState);
Debug.assert(resolutions.length === moduleNames.length);
for (let i = 0; i < moduleNames.length; i++) {
Expand Down
13 changes: 13 additions & 0 deletions src/harness/unittests/reuseProgramStructure.ts
Original file line number Diff line number Diff line change
Expand Up @@ -389,6 +389,19 @@ namespace ts {
checkResolvedModulesCache(program4, "a.ts", createMapFromTemplate({ b: createResolvedModule("b.ts"), c: undefined }));
});

it("set the resolvedImports after re-using an ambient external module declaration", () => {
const files = [
{ name: "/a.ts", text: SourceText.New("", "", 'import * as a from "a";') },
{ name: "/types/zzz/index.d.ts", text: SourceText.New("", "", 'declare module "a" { }') },
];
const options: CompilerOptions = { target, typeRoots: ["/types"] };
const program1 = newProgram(files, ["/a.ts"], options);
const program2 = updateProgram(program1, ["/a.ts"], options, files => {
files[0].text = files[0].text.updateProgram('import * as aa from "a";');
});
assert.isDefined(program2.getSourceFile("/a.ts").resolvedModules.get("a"), "'a' is not an unresolved module after re-use");
});

it("resolved type directives cache follows type directives", () => {
const files = [
{ name: "/a.ts", text: SourceText.New("/// <reference types='typedefs'/>", "", "var x = $") },
Expand Down