mirror of
https://github.com/angular/angular.git
synced 2026-09-14 13:54:52 +08:00
fix(compiler-cli): ensure component import diagnostics are reported within the imports expression
PR #60455 improved error reporting for `@Component.imports` by scoping the diagnostic to an individual element within the `imports` array, but this may introduce hard to track diagnostics when it ends up being reported (far) away from the component itself. This can be even more problematic when the diagnostic would end up being reported in a declaration file, as happened in issue #65686; the declaration files of an imported library contained syntax that the static interpreter did not support, hence the `@Component.imports` was rejected with a diagnostic reported in the library's declaration file. This diagnostic isn't guaranteed to be reported (e.g. the CLI only gathers Angular-specific diagnostics for Angular-compiled files, which excludes declaration files). This commit changes the diagnostic location to ensure it is being reported within the `@Component.imports` expression, in most cases retaining the desirable effect of #60455 while avoiding out-of-band diagnostics.
This commit is contained in:
committed by
Kristiyan Kostadinov
parent
eb5f5b61c3
commit
106ba63650
@@ -2589,12 +2589,70 @@ runInEachFileSystem((os: string) => {
|
||||
export class HelloDir {}
|
||||
|
||||
const someVar = {} as any;
|
||||
const tuple = [() => {}] as const;
|
||||
|
||||
@Component({
|
||||
template: '<div hello></div>',
|
||||
imports: [
|
||||
someVar,
|
||||
HelloDir,
|
||||
'invalid',
|
||||
tuple,
|
||||
]
|
||||
})
|
||||
export class TestCmp {}
|
||||
`,
|
||||
);
|
||||
|
||||
const diags = env.driveDiagnostics();
|
||||
expect(diags.length).toBe(3);
|
||||
{
|
||||
const message = ts.flattenDiagnosticMessageText(diags[0].messageText, '\n');
|
||||
expect(getDiagnosticSourceCode(diags[0])).toBe('someVar');
|
||||
expect(message).toContain(
|
||||
`'imports' must be an array of components, directives, pipes, or NgModules.`,
|
||||
);
|
||||
expect(message).toContain(`Value is of type '{}'`);
|
||||
}
|
||||
{
|
||||
const message = ts.flattenDiagnosticMessageText(diags[1].messageText, '\n');
|
||||
expect(getDiagnosticSourceCode(diags[1])).toBe(`'invalid'`);
|
||||
expect(message).toContain(
|
||||
`'imports' must be an array of components, directives, pipes, or NgModules.`,
|
||||
);
|
||||
expect(message).toContain(`Value is of type 'string'`);
|
||||
}
|
||||
{
|
||||
const message = ts.flattenDiagnosticMessageText(diags[2].messageText, '\n');
|
||||
expect(getDiagnosticSourceCode(diags[2])).toBe('tuple');
|
||||
expect(message).toContain(
|
||||
`'imports' must be an array of components, directives, pipes, or NgModules.`,
|
||||
);
|
||||
expect(message).toContain(`Value is of type '[(not statically analyzable)]'.`);
|
||||
}
|
||||
});
|
||||
|
||||
it('should report imports diagnostic for declaration file in original expression', () => {
|
||||
env.write(
|
||||
'node_modules/external/index.d.ts',
|
||||
`
|
||||
export declare const UNRESOLVED_ITEM: readonly [unresolved];
|
||||
`,
|
||||
);
|
||||
env.write(
|
||||
'test.ts',
|
||||
`
|
||||
import {Component, Directive} from '@angular/core';
|
||||
import {UNRESOLVED_ITEM as Unresolved} from 'external';
|
||||
|
||||
@Directive({selector: '[hello]'})
|
||||
export class HelloDir {}
|
||||
|
||||
@Component({
|
||||
template: '<div hello></div>',
|
||||
imports: [
|
||||
[Unresolved],
|
||||
HelloDir,
|
||||
]
|
||||
})
|
||||
export class TestCmp {}
|
||||
@@ -2606,11 +2664,12 @@ runInEachFileSystem((os: string) => {
|
||||
? ts.flattenDiagnosticMessageText(diags[0].messageText, '\n')
|
||||
: '';
|
||||
expect(diags.length).toBe(1);
|
||||
expect(getDiagnosticSourceCode(diags[0])).toBe('someVar');
|
||||
expect(diags[0].file!.fileName).toContain('test.ts');
|
||||
expect(getDiagnosticSourceCode(diags[0])).toBe('Unresolved');
|
||||
expect(message).toContain(
|
||||
`'imports' must be an array of components, directives, pipes, or NgModules.`,
|
||||
);
|
||||
expect(message).toContain(`Value is of type '{}'`);
|
||||
expect(message).toContain(`Value is of type '[(not statically analyzable)]'.`);
|
||||
});
|
||||
|
||||
describe('empty and missing selectors', () => {
|
||||
|
||||
Reference in New Issue
Block a user