diff --git a/src/compiler/program.ts b/src/compiler/program.ts index 76fa4b62aab9c..053fc2f77e3c0 100644 --- a/src/compiler/program.ts +++ b/src/compiler/program.ts @@ -936,6 +936,7 @@ namespace ts { getOptionsDiagnostics, getGlobalDiagnostics, getSemanticDiagnostics, + getCachedSemanticDiagnostics, getSuggestionDiagnostics, getDeclarationDiagnostics, getBindAndCheckDiagnostics, @@ -1656,6 +1657,12 @@ namespace ts { return getDiagnosticsHelper(sourceFile, getSemanticDiagnosticsForFile, cancellationToken); } + function getCachedSemanticDiagnostics(sourceFile?: SourceFile): readonly Diagnostic[] | undefined { + return sourceFile + ? cachedBindAndCheckDiagnosticsForFile.perFile?.get(sourceFile.path) + : cachedBindAndCheckDiagnosticsForFile.allDiagnostics; + } + function getBindAndCheckDiagnostics(sourceFile: SourceFile, cancellationToken?: CancellationToken): readonly Diagnostic[] { return getBindAndCheckDiagnosticsForFile(sourceFile, cancellationToken); } diff --git a/src/compiler/types.ts b/src/compiler/types.ts index dbc916cd56756..27e8493cf74e4 100644 --- a/src/compiler/types.ts +++ b/src/compiler/types.ts @@ -3762,6 +3762,8 @@ namespace ts { /* @internal */ getDiagnosticsProducingTypeChecker(): TypeChecker; /* @internal */ dropDiagnosticsProducingTypeChecker(): void; + /* @internal */ getCachedSemanticDiagnostics(sourceFile?: SourceFile): readonly Diagnostic[] | undefined; + /* @internal */ getClassifiableNames(): Set<__String>; getTypeCatalog(): readonly Type[]; diff --git a/src/testRunner/unittests/tscWatch/watchApi.ts b/src/testRunner/unittests/tscWatch/watchApi.ts index 6dcf1b30f7b35..01172b983ca30 100644 --- a/src/testRunner/unittests/tscWatch/watchApi.ts +++ b/src/testRunner/unittests/tscWatch/watchApi.ts @@ -123,4 +123,36 @@ namespace ts.tscWatch { checkProgramActualFiles(watch.getProgram().getProgram(), [mainFile.path, otherFile.path, libFile.path]); }); }); + + describe("unittests:: tsc-watch:: watchAPI:: when watchHost uses createSemanticDiagnosticsBuilderProgram", () => { + it("verifies that noEmit is handled on createSemanticDiagnosticsBuilderProgram and typechecking happens only on affected files", () => { + const config: File = { + path: `${projectRoot}/tsconfig.json`, + content: "{}" + }; + const mainFile: File = { + path: `${projectRoot}/main.ts`, + content: "export const x = 10;" + }; + const otherFile: File = { + path: `${projectRoot}/other.ts`, + content: "export const y = 10;" + }; + const sys = createWatchedSystem([config, mainFile, otherFile, libFile]); + const watchCompilerHost = createWatchCompilerHost( + config.path, + { noEmit: true }, + sys, + createSemanticDiagnosticsBuilderProgram + ); + const watch = createWatchProgram(watchCompilerHost); + checkProgramActualFiles(watch.getProgram().getProgram(), [mainFile.path, otherFile.path, libFile.path]); + sys.appendFile(mainFile.path, "\n// SomeComment"); + sys.runQueuedTimeoutCallbacks(); + const program = watch.getProgram().getProgram(); + assert.deepEqual(program.getCachedSemanticDiagnostics(program.getSourceFile(mainFile.path)), []); + // Should not retrieve diagnostics for other file thats not changed + assert.deepEqual(program.getCachedSemanticDiagnostics(program.getSourceFile(otherFile.path)), /*expected*/ undefined); + }); + }); }