From 03a3978d65b1dea3d2ea2356edf775f6ec2e5e31 Mon Sep 17 00:00:00 2001 From: Sheetal Nandi Date: Mon, 8 Oct 2018 15:56:39 -0700 Subject: [PATCH] Use ambient modules as references to keep track of reporting and usage of modules correctly Fixes #27585 --- src/compiler/builderState.ts | 31 +++++++++++++++++++++ src/testRunner/unittests/tscWatchMode.ts | 35 ++++++++++++++++++++++++ 2 files changed, 66 insertions(+) diff --git a/src/compiler/builderState.ts b/src/compiler/builderState.ts index f5f2538a60b..1689733fac6 100644 --- a/src/compiler/builderState.ts +++ b/src/compiler/builderState.ts @@ -148,8 +148,39 @@ namespace ts.BuilderState { }); } + // Add module augmentation as references + if (sourceFile.moduleAugmentations.length) { + const checker = program.getTypeChecker(); + for (const moduleName of sourceFile.moduleAugmentations) { + if (!isStringLiteral(moduleName)) { continue; } + const symbol = checker.getSymbolAtLocation(moduleName); + if (!symbol) { continue; } + + // Add any file other than our own as reference + addReferenceFromAmbientModule(symbol); + } + } + + // From ambient modules + for (const ambientModule of program.getTypeChecker().getAmbientModules()) { + if (ambientModule.declarations.length > 1) { + addReferenceFromAmbientModule(ambientModule); + } + } + return referencedFiles; + function addReferenceFromAmbientModule(symbol: Symbol) { + // Add any file other than our own as reference + for (const declaration of symbol.declarations) { + const declarationSourceFile = getSourceFileOfNode(declaration); + if (declarationSourceFile && + declarationSourceFile !== sourceFile) { + addReferencedFile(declarationSourceFile.resolvedPath); + } + } + } + function addReferencedFile(referencedPath: Path) { if (!referencedFiles) { referencedFiles = createMap(); diff --git a/src/testRunner/unittests/tscWatchMode.ts b/src/testRunner/unittests/tscWatchMode.ts index c4b7d6adf44..7678bfe0625 100644 --- a/src/testRunner/unittests/tscWatchMode.ts +++ b/src/testRunner/unittests/tscWatchMode.ts @@ -1386,6 +1386,41 @@ foo().hello` // File a need not be rewritten assert.equal(host.getModifiedTime(`${currentDirectory}/a.js`), modifiedTimeOfAJs); }); + + it("updates errors when ambient modules of program changes", () => { + const currentDirectory = "/user/username/projects/myproject"; + const aFile: File = { + path: `${currentDirectory}/a.ts`, + content: `declare module 'a' { + type foo = number; +}` + }; + const config: File = { + path: `${currentDirectory}/tsconfig.json`, + content: "{}" + }; + const files = [aFile, config, libFile]; + const host = createWatchedSystem(files, { currentDirectory }); + const watch = createWatchOfConfigFile("tsconfig.json", host); + checkProgramActualFiles(watch(), [aFile.path, libFile.path]); + checkOutputErrorsInitial(host, emptyArray); + + // Create bts with same file contents + const bTsPath = `${currentDirectory}/b.ts`; + host.writeFile(bTsPath, aFile.content); + host.runQueuedTimeoutCallbacks(); + checkProgramActualFiles(watch(), [aFile.path, "b.ts", libFile.path]); + checkOutputErrorsIncremental(host, [ + "a.ts(2,8): error TS2300: Duplicate identifier 'foo'.\n", + "b.ts(2,8): error TS2300: Duplicate identifier 'foo'.\n" + ]); + + // Delete bTs + host.deleteFile(bTsPath); + host.runQueuedTimeoutCallbacks(); + checkProgramActualFiles(watch(), [aFile.path, libFile.path]); + checkOutputErrorsIncremental(host, emptyArray); + }); }); describe("tsc-watch emit with outFile or out setting", () => {