refactor(compiler-cli): add `BananaInBoxCheck` to the template checks (#42984)
Add the implementation of a Template Check that ensures the correct use of two-way binding syntax. Generates a warning when '([foo])="bar"' is found instead of '[(foo)]="bar"'. Refs #42966 PR Close #42984
This commit is contained in:
parent
9a0a2b6e75
commit
d6411c2729
|
@ -34,6 +34,7 @@ export enum ErrorCode {
|
|||
INJECTABLE_DUPLICATE_PROV = 9001,
|
||||
INLINE_TCB_REQUIRED = 8900,
|
||||
INLINE_TYPE_CTOR_REQUIRED = 8901,
|
||||
INVALID_BANANA_IN_BOX = 8101,
|
||||
MISSING_PIPE = 8004,
|
||||
MISSING_REFERENCE_TARGET = 8003,
|
||||
NGMODULE_DECLARATION_NOT_UNIQUE = 6007,
|
||||
|
@ -67,7 +68,6 @@ export enum ErrorCode {
|
|||
WRITE_TO_READ_ONLY_VARIABLE = 8005
|
||||
}
|
||||
|
||||
|
||||
// (No @packageDocumentation comment for this package)
|
||||
|
||||
```
|
||||
|
|
|
@ -172,6 +172,16 @@ export enum ErrorCode {
|
|||
*/
|
||||
SPLIT_TWO_WAY_BINDING = 8007,
|
||||
|
||||
/**
|
||||
* A two way binding in a template has an incorrect syntax,
|
||||
* parentheses outside brackets. For example:
|
||||
*
|
||||
* ```
|
||||
* <div ([foo])="bar" />
|
||||
* ```
|
||||
*/
|
||||
INVALID_BANANA_IN_BOX = 8101,
|
||||
|
||||
/**
|
||||
* The template type-checking engine would need to generate an inline type check block for a
|
||||
* component, but the current type-checking environment doesn't support it.
|
||||
|
|
|
@ -0,0 +1,13 @@
|
|||
load("//tools:defaults.bzl", "ts_library")
|
||||
|
||||
ts_library(
|
||||
name = "invalid_banana_in_box",
|
||||
srcs = ["index.ts"],
|
||||
visibility = ["//packages/compiler-cli/src/ngtsc/typecheck/extended:__subpackages__"],
|
||||
deps = [
|
||||
"//packages/compiler",
|
||||
"//packages/compiler-cli/src/ngtsc/diagnostics",
|
||||
"//packages/compiler-cli/src/ngtsc/typecheck/extended/api",
|
||||
"@npm//typescript",
|
||||
],
|
||||
)
|
|
@ -0,0 +1,65 @@
|
|||
/**
|
||||
* @license
|
||||
* Copyright Google LLC All Rights Reserved.
|
||||
*
|
||||
* Use of this source code is governed by an MIT-style license that can be
|
||||
* found in the LICENSE file at https://angular.io/license
|
||||
*/
|
||||
|
||||
import {TmplAstBoundEvent, TmplAstNode, TmplAstRecursiveVisitor} from '@angular/compiler';
|
||||
import * as ts from 'typescript';
|
||||
import {ErrorCode} from '../../../../../diagnostics';
|
||||
import {TemplateCheck, TemplateContext, TemplateDiagnostic} from '../../../api/api';
|
||||
|
||||
/**
|
||||
* Ensures the two-way binding syntax is correct.
|
||||
* Parentheses should be inside the brackets "[()]".
|
||||
* Will return diagnostic information when "([])" is found.
|
||||
*/
|
||||
export class InvalidBananaInBoxCheck implements TemplateCheck<ErrorCode.INVALID_BANANA_IN_BOX> {
|
||||
code: ErrorCode.INVALID_BANANA_IN_BOX = 8101;
|
||||
|
||||
run(ctx: TemplateContext,
|
||||
template: TmplAstNode[]): TemplateDiagnostic<ErrorCode.INVALID_BANANA_IN_BOX>[] {
|
||||
const visitor = new BananaVisitor(ctx);
|
||||
|
||||
return visitor.getDiagnostics(template);
|
||||
}
|
||||
}
|
||||
|
||||
class BananaVisitor extends TmplAstRecursiveVisitor {
|
||||
private diagnostics: ts.Diagnostic[] = [];
|
||||
|
||||
constructor(public readonly ctx: TemplateContext) {
|
||||
super();
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for outputs with names surrounded in brackets "[]".
|
||||
* The syntax '([foo])="bar"' would be interpreted as an @Output()
|
||||
* with name '[foo]'. Just like '(foo)="bar"' would have the name 'foo'.
|
||||
* Generate diagnostic information for the cases found.
|
||||
*/
|
||||
override visitBoundEvent(boundEvent: TmplAstBoundEvent) {
|
||||
const name = boundEvent.name;
|
||||
if (name.startsWith('[') && name.endsWith(']')) {
|
||||
const boundSyntax = boundEvent.sourceSpan.toString();
|
||||
const expectedBoundSyntax = boundSyntax.replace(`(${name})`, `[(${name.slice(1, -1)})]`);
|
||||
this.diagnostics.push(
|
||||
this.ctx.templateTypeChecker.makeTemplateDiagnostic<ErrorCode.INVALID_BANANA_IN_BOX>(
|
||||
this.ctx.component, boundEvent.sourceSpan, ts.DiagnosticCategory.Warning,
|
||||
ErrorCode.INVALID_BANANA_IN_BOX,
|
||||
`In the two-way binding syntax the parentheses should be inside the brackets, ex. '${
|
||||
expectedBoundSyntax}'.
|
||||
Find more at https://angular.io/guide/two-way-binding`));
|
||||
}
|
||||
}
|
||||
|
||||
getDiagnostics(template: TmplAstNode[]): ts.Diagnostic[] {
|
||||
this.diagnostics = [];
|
||||
for (const node of template) {
|
||||
node.visit(this);
|
||||
}
|
||||
return this.diagnostics;
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue