fix(compiler-cli): type checking of expressions within ICUs (#39072)
Expressions within ICU expressions in templates were not previously type-checked, as they were skipped while traversing the elements within a template. This commit enables type checking of these expressions by actually visiting the expressions. BREAKING CHANGE: Expressions within ICUs are now type-checked again, fixing a regression in Ivy. This may cause compilation failures if errors are found in expressions that appear within an ICU. Please correct these expressions to resolve the type-check errors. Fixes #39064 PR Close #39072
This commit is contained in:
parent
f84b3786dc
commit
0a16e60afa
|
@ -6,7 +6,7 @@
|
|||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {AST, BindingPipe, BindingType, BoundTarget, DYNAMIC_TYPE, ImplicitReceiver, MethodCall, ParsedEventType, ParseSourceSpan, PropertyRead, PropertyWrite, SchemaMetadata, TmplAstBoundAttribute, TmplAstBoundEvent, TmplAstBoundText, TmplAstElement, TmplAstNode, TmplAstReference, TmplAstTemplate, TmplAstTextAttribute, TmplAstVariable} from '@angular/compiler';
|
||||
import {AST, BindingPipe, BindingType, BoundTarget, DYNAMIC_TYPE, ImplicitReceiver, MethodCall, ParsedEventType, ParseSourceSpan, PropertyRead, PropertyWrite, SchemaMetadata, TmplAstBoundAttribute, TmplAstBoundEvent, TmplAstBoundText, TmplAstElement, TmplAstIcu, TmplAstNode, TmplAstReference, TmplAstTemplate, TmplAstTextAttribute, TmplAstVariable} from '@angular/compiler';
|
||||
import * as ts from 'typescript';
|
||||
|
||||
import {Reference} from '../../imports';
|
||||
|
@ -1333,6 +1333,8 @@ class Scope {
|
|||
this.checkAndAppendReferencesOfNode(node);
|
||||
} else if (node instanceof TmplAstBoundText) {
|
||||
this.opQueue.push(new TcbTextInterpolationOp(this.tcb, this, node));
|
||||
} else if (node instanceof TmplAstIcu) {
|
||||
this.appendIcuExpressions(node);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1459,6 +1461,17 @@ class Scope {
|
|||
this.appendDeepSchemaChecks(node.children);
|
||||
}
|
||||
}
|
||||
|
||||
private appendIcuExpressions(node: TmplAstIcu): void {
|
||||
for (const variable of Object.values(node.vars)) {
|
||||
this.opQueue.push(new TcbTextInterpolationOp(this.tcb, this, variable));
|
||||
}
|
||||
for (const placeholder of Object.values(node.placeholders)) {
|
||||
if (placeholder instanceof TmplAstBoundText) {
|
||||
this.opQueue.push(new TcbTextInterpolationOp(this.tcb, this, placeholder));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
interface TcbBoundInput {
|
||||
|
|
|
@ -176,6 +176,21 @@ runInEachFileSystem(() => {
|
|||
]);
|
||||
});
|
||||
|
||||
it('checks expressions in ICUs', () => {
|
||||
const messages = diagnose(
|
||||
`<span i18n>{switch, plural, other { {{interpolation}}
|
||||
{nestedSwitch, plural, other { {{nestedInterpolation}} }}
|
||||
}}</span>`,
|
||||
`class TestComponent {}`);
|
||||
|
||||
expect(messages.sort()).toEqual([
|
||||
`TestComponent.html(1, 13): Property 'switch' does not exist on type 'TestComponent'.`,
|
||||
`TestComponent.html(1, 39): Property 'interpolation' does not exist on type 'TestComponent'.`,
|
||||
`TestComponent.html(2, 14): Property 'nestedSwitch' does not exist on type 'TestComponent'.`,
|
||||
`TestComponent.html(2, 46): Property 'nestedInterpolation' does not exist on type 'TestComponent'.`,
|
||||
]);
|
||||
});
|
||||
|
||||
it('produces diagnostics for pipes', () => {
|
||||
const messages = diagnose(
|
||||
`<div>{{ person.name | pipe:person.age:1 }}</div>`, `
|
||||
|
|
|
@ -92,7 +92,7 @@ export {getParseErrors, isSyntaxError, syntaxError, Version} from './util';
|
|||
export {SourceMap} from './output/source_map';
|
||||
export * from './injectable_compiler_2';
|
||||
export * from './render3/view/api';
|
||||
export {BoundAttribute as TmplAstBoundAttribute, BoundEvent as TmplAstBoundEvent, BoundText as TmplAstBoundText, Content as TmplAstContent, Element as TmplAstElement, Node as TmplAstNode, RecursiveVisitor as TmplAstRecursiveVisitor, Reference as TmplAstReference, Template as TmplAstTemplate, Text as TmplAstText, TextAttribute as TmplAstTextAttribute, Variable as TmplAstVariable,} from './render3/r3_ast';
|
||||
export {BoundAttribute as TmplAstBoundAttribute, BoundEvent as TmplAstBoundEvent, BoundText as TmplAstBoundText, Content as TmplAstContent, Element as TmplAstElement, Icu as TmplAstIcu, Node as TmplAstNode, RecursiveVisitor as TmplAstRecursiveVisitor, Reference as TmplAstReference, Template as TmplAstTemplate, Text as TmplAstText, TextAttribute as TmplAstTextAttribute, Variable as TmplAstVariable} from './render3/r3_ast';
|
||||
export * from './render3/view/t2_api';
|
||||
export * from './render3/view/t2_binder';
|
||||
export {Identifiers as R3Identifiers} from './render3/r3_identifiers';
|
||||
|
|
Loading…
Reference in New Issue