fix(compiler-cli): report non-template diagnostics (#40331)

Report non-template diagnotics when calling `getDiagnotics` function of
the language service we only returned template diagnotics. This change
causes it to return all diagnotics, not just diagnostics from the
template type checker.

PR Close #40331
This commit is contained in:
Zach Arend
2021-01-06 14:17:45 -08:00
committed by atscott
parent 625d2c252b
commit 4db89f4576
10 changed files with 100 additions and 44 deletions
+1
View File
@@ -33,6 +33,7 @@ ts_library(
"//packages/compiler-cli/src/ngtsc/shims",
"//packages/compiler-cli/src/ngtsc/translator",
"//packages/compiler-cli/src/ngtsc/typecheck",
"//packages/compiler-cli/src/ngtsc/typecheck/api",
"@npm//@bazel/typescript",
"@npm//@types/node",
"@npm//chokidar",
@@ -30,7 +30,6 @@ import {ivySwitchTransform} from '../../switch';
import {aliasTransformFactory, CompilationMode, declarationTransformFactory, DecoratorHandler, DtsTransformRegistry, ivyTransformFactory, TraitCompiler} from '../../transform';
import {TemplateTypeCheckerImpl} from '../../typecheck';
import {OptimizeFor, TemplateTypeChecker, TypeCheckingConfig, TypeCheckingProgramStrategy} from '../../typecheck/api';
import {isTemplateDiagnostic} from '../../typecheck/diagnostics';
import {getSourceFileOrNull, isDtsPath, resolveModuleName} from '../../util/src/typescript';
import {LazyRoute, NgCompilerAdapter, NgCompilerOptions} from '../api';
@@ -84,11 +83,12 @@ export class NgCompiler {
private constructionDiagnostics: ts.Diagnostic[] = [];
/**
* Semantic diagnostics related to the program itself.
* Non-template diagnostics related to the program itself. Does not include template
* diagnostics because the template type checker memoizes them itself.
*
* This is set by (and memoizes) `getDiagnostics`.
* This is set by (and memoizes) `getNonTemplateDiagnostics`.
*/
private diagnostics: ts.Diagnostic[]|null = null;
private nonTemplateDiagnostics: ts.Diagnostic[]|null = null;
private closureCompilerEnabled: boolean;
private nextProgram: ts.Program;
@@ -175,38 +175,23 @@ export class NgCompiler {
return this.incrementalDriver.depGraph.getResourceDependencies(file);
}
/**
* Get all Angular-related diagnostics for this compilation.
*/
getDiagnostics(): ts.Diagnostic[] {
return [...this.getNonTemplateDiagnostics(), ...this.getTemplateDiagnostics()];
}
/**
* Get all Angular-related diagnostics for this compilation.
*
* If a `ts.SourceFile` is passed, only diagnostics related to that file are returned.
*/
getDiagnostics(file?: ts.SourceFile): ts.Diagnostic[] {
if (this.diagnostics === null) {
const compilation = this.ensureAnalyzed();
this.diagnostics =
[...compilation.traitCompiler.diagnostics, ...this.getTemplateDiagnostics()];
if (this.entryPoint !== null && compilation.exportReferenceGraph !== null) {
this.diagnostics.push(...checkForPrivateExports(
this.entryPoint, this.tsProgram.getTypeChecker(), compilation.exportReferenceGraph));
}
}
if (file === undefined) {
return this.diagnostics;
} else {
return this.diagnostics.filter(diag => {
if (diag.file === file) {
return true;
} else if (isTemplateDiagnostic(diag) && diag.componentFile === file) {
// Template diagnostics are reported when diagnostics for the component file are
// requested (since no consumer of `getDiagnostics` would ever ask for diagnostics from
// the fake ts.SourceFile for templates).
return true;
} else {
return false;
}
});
}
getDiagnosticsForFile(file: ts.SourceFile, optimizeFor: OptimizeFor): ts.Diagnostic[] {
return [
...this.getNonTemplateDiagnostics().filter(diag => diag.file === file),
...this.getTemplateDiagnosticsForFile(file, optimizeFor)
];
}
/**
@@ -582,6 +567,37 @@ export class NgCompiler {
return diagnostics;
}
private getTemplateDiagnosticsForFile(sf: ts.SourceFile, optimizeFor: OptimizeFor):
ReadonlyArray<ts.Diagnostic> {
const compilation = this.ensureAnalyzed();
// Get the diagnostics.
const typeCheckSpan = this.perfRecorder.start('typeCheckDiagnostics');
const diagnostics: ts.Diagnostic[] = [];
if (!sf.isDeclarationFile && !this.adapter.isShim(sf)) {
diagnostics.push(...compilation.templateTypeChecker.getDiagnosticsForFile(sf, optimizeFor));
}
const program = this.typeCheckingProgramStrategy.getProgram();
this.perfRecorder.stop(typeCheckSpan);
this.incrementalStrategy.setIncrementalDriver(this.incrementalDriver, program);
this.nextProgram = program;
return diagnostics;
}
private getNonTemplateDiagnostics(): ts.Diagnostic[] {
if (this.nonTemplateDiagnostics === null) {
const compilation = this.ensureAnalyzed();
this.nonTemplateDiagnostics = [...compilation.traitCompiler.diagnostics];
if (this.entryPoint !== null && compilation.exportReferenceGraph !== null) {
this.nonTemplateDiagnostics.push(...checkForPrivateExports(
this.entryPoint, this.tsProgram.getTypeChecker(), compilation.exportReferenceGraph));
}
}
return this.nonTemplateDiagnostics;
}
/**
* Reifies the inter-dependencies of NgModules and the components within their compilation scopes
* into the `IncrementalDriver`'s dependency graph.
@@ -17,6 +17,7 @@ ts_library(
"//packages/compiler-cli/src/ngtsc/incremental",
"//packages/compiler-cli/src/ngtsc/reflection",
"//packages/compiler-cli/src/ngtsc/typecheck",
"//packages/compiler-cli/src/ngtsc/typecheck/api",
"@npm//typescript",
],
)
@@ -13,6 +13,7 @@ import {runInEachFileSystem} from '../../file_system/testing';
import {NoopIncrementalBuildStrategy} from '../../incremental';
import {ClassDeclaration, isNamedClassDeclaration} from '../../reflection';
import {ReusedProgramStrategy} from '../../typecheck';
import {OptimizeFor} from '../../typecheck/api';
import {NgCompilerOptions} from '../api';
@@ -54,7 +55,8 @@ runInEachFileSystem(() => {
new NoopIncrementalBuildStrategy(), /** enableTemplateTypeChecker */ false,
/* usePoisonedData */ false);
const diags = compiler.getDiagnostics(getSourceFileOrError(program, COMPONENT));
const diags = compiler.getDiagnosticsForFile(
getSourceFileOrError(program, COMPONENT), OptimizeFor.SingleFile);
expect(diags.length).toBe(1);
expect(diags[0].messageText).toContain('does_not_exist');
});
+4 -1
View File
@@ -20,6 +20,7 @@ import {NOOP_PERF_RECORDER, PerfRecorder, PerfTracker} from './perf';
import {DeclarationNode} from './reflection';
import {retagAllTsFiles, untagAllTsFiles} from './shims';
import {ReusedProgramStrategy} from './typecheck';
import {OptimizeFor} from './typecheck/api';
@@ -182,7 +183,9 @@ export class NgtscProgram implements api.Program {
}
}
const diagnostics = this.compiler.getDiagnostics(sf);
const diagnostics = sf === undefined ?
this.compiler.getDiagnostics() :
this.compiler.getDiagnosticsForFile(sf, OptimizeFor.WholeProgram);
this.reuseTsProgram = this.compiler.getNextProgram();
return diagnostics;
}
@@ -14,6 +14,7 @@ import {NodeJSFileSystem, setFileSystem} from './file_system';
import {PatchedProgramIncrementalBuildStrategy} from './incremental';
import {NOOP_PERF_RECORDER} from './perf';
import {untagAllTsFiles} from './shims';
import {OptimizeFor} from './typecheck/api';
import {ReusedProgramStrategy} from './typecheck/src/augmented_program';
// The following is needed to fix a the chicken-and-egg issue where the sync (into g3) script will
@@ -111,7 +112,10 @@ export class NgTscPlugin implements TscPlugin {
}
getDiagnostics(file?: ts.SourceFile): ts.Diagnostic[] {
return this.compiler.getDiagnostics(file);
if (file === undefined) {
return this.compiler.getDiagnostics();
}
return this.compiler.getDiagnosticsForFile(file, OptimizeFor.WholeProgram);
}
getOptionDiagnostics(): ts.Diagnostic[] {