feat(compiler-cli): define interfaces to be used for TemplateTypeChecker (#38618)

This commit defines the interfaces which outline the information the
`TemplateTypeChecker` can return when requesting a Symbol for an item in the
`TemplateAst`.
Rather than providing the `ts.Symbol`, `ts.Type`, etc.
information in several separate functions, the `TemplateTypeChecker` can
instead provide all the useful information it knows about a particular
node in the `TemplateAst` and allow the callers to determine what to do
with it.

PR Close #38618
This commit is contained in:
Andrew Scott 2020-08-17 15:42:30 -07:00 committed by Andrew Kushnir
parent 26f28200bf
commit 9e77bd3087
2 changed files with 231 additions and 0 deletions

View File

@ -9,3 +9,4 @@
export * from './api'; export * from './api';
export * from './checker'; export * from './checker';
export * from './context'; export * from './context';
export * from './symbols';

View File

@ -0,0 +1,230 @@
/**
* @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 {TmplAstElement, TmplAstReference, TmplAstTemplate, TmplAstVariable} from '@angular/compiler';
import * as ts from 'typescript';
import {AbsoluteFsPath} from '../../file_system';
export enum SymbolKind {
Input,
Output,
Binding,
Reference,
Variable,
Directive,
Element,
Template,
Expression,
}
/**
* A representation of an entity in the `TemplateAst`.
*/
export type Symbol = InputBindingSymbol|OutputBindingSymbol|ElementSymbol|ReferenceSymbol|
VariableSymbol|ExpressionSymbol|DirectiveSymbol|TemplateSymbol;
/** Information about where a `ts.Node` can be found in the type check block shim file. */
export interface ShimLocation {
/**
* The fully qualified path of the file which contains the generated TypeScript type check
* code for the component's template.
*/
shimPath: AbsoluteFsPath;
/** The location in the shim file where node appears. */
positionInShimFile: number;
}
/**
* A generic representation of some node in a template.
*/
export interface TsNodeSymbolInfo {
/** The `ts.Type` of the template node. */
tsType: ts.Type;
/** The `ts.Symbol` for the template node */
tsSymbol: ts.Symbol|null;
/** The position of the most relevant part of the template node. */
shimLocation: ShimLocation;
}
/**
* A representation of an expression in a component template.
*/
export interface ExpressionSymbol {
kind: SymbolKind.Expression;
/** The `ts.Type` of the expression AST. */
tsType: ts.Type;
/**
* The `ts.Symbol` of the entity. This could be `null`, for example `AST` expression
* `{{foo.bar + foo.baz}}` does not have a `ts.Symbol` but `foo.bar` and `foo.baz` both do.
*/
tsSymbol: ts.Symbol|null;
/** The position of the most relevant part of the expression. */
shimLocation: ShimLocation;
}
/** Represents either an input or output binding in a template. */
export interface BindingSymbol {
kind: SymbolKind.Binding;
/** The `ts.Type` of the class member on the directive that is the target of the binding. */
tsType: ts.Type;
/** The `ts.Symbol` of the class member on the directive that is the target of the binding. */
tsSymbol: ts.Symbol;
/**
* The `DirectiveSymbol` or `ElementSymbol` for the Directive, Component, or `HTMLElement` with
* the binding.
*/
target: DirectiveSymbol|ElementSymbol|TemplateSymbol;
/** The location in the shim file where the field access for the binding appears. */
shimLocation: ShimLocation;
}
/**
* A representation of an input binding in a component template.
*/
export interface InputBindingSymbol {
kind: SymbolKind.Input;
/** A single input may be bound to multiple components or directives. */
bindings: BindingSymbol[];
}
/**
* A representation of an output binding in a component template.
*/
export interface OutputBindingSymbol {
kind: SymbolKind.Output;
/** A single output may be bound to multiple components or directives. */
bindings: BindingSymbol[];
}
/**
* A representation of a local reference in a component template.
*/
export interface ReferenceSymbol {
kind: SymbolKind.Reference;
/**
* The `ts.Type` of the Reference value.
*
* `TmplAstTemplate` - The type of the `TemplateRef`
* `TmplAstElement` - The `ts.Type` for the `HTMLElement`.
* Directive - The `ts.Type` for the class declaration.
*/
tsType: ts.Type;
/**
* The `ts.Symbol` for the Reference value.
*
* `TmplAstTemplate` - A `TemplateRef` symbol.
* `TmplAstElement` - The symbol for the `HTMLElement`.
* Directive - The symbol for the class declaration of the directive.
*/
tsSymbol: ts.Symbol;
/**
* Depending on the type of the reference, this is one of the following:
* - `TmplAstElement` when the local ref refers to the HTML element
* - `TmplAstTemplate` when the ref refers to an `ng-template`
* - `ts.ClassDeclaration` when the local ref refers to a Directive instance (#ref="myExportAs")
*/
target: TmplAstElement|TmplAstTemplate|ts.ClassDeclaration;
/**
* The node in the `TemplateAst` where the symbol is declared. That is, node for the `#ref` or
* `#ref="exportAs"`.
*/
declaration: TmplAstReference;
/** The location in the shim file of a variable that holds the type of the local ref. */
shimLocation: ShimLocation;
}
/**
* A representation of a context variable in a component template.
*/
export interface VariableSymbol {
kind: SymbolKind.Variable;
/**
* The `ts.Type` of the entity.
*
* This will be `any` if there is no `ngTemplateContextGuard`.
*/
tsType: ts.Type;
/**
* The `ts.Symbol` for the context variable.
*
* This will be `null` if there is no `ngTemplateContextGuard`.
*/
tsSymbol: ts.Symbol|null;
/**
* The node in the `TemplateAst` where the variable is declared. That is, the node for the `let-`
* node in the template.
*/
declaration: TmplAstVariable;
/** The location in the shim file of a variable that holds the type of the template variable. */
shimLocation: ShimLocation;
}
/**
* A representation of an element in a component template.
*/
export interface ElementSymbol {
kind: SymbolKind.Element;
/** The `ts.Type` for the `HTMLElement`. */
tsType: ts.Type;
/** The `ts.Symbol` for the `HTMLElement`. */
tsSymbol: ts.Symbol|null;
/** A list of directives applied to the element. */
directives: DirectiveSymbol[];
/** The location in the shim file for the variable that holds the type of the element. */
shimLocation: ShimLocation;
}
export interface TemplateSymbol {
kind: SymbolKind.Template;
/** A list of directives applied to the element. */
directives: DirectiveSymbol[];
}
/**
* A representation of a directive/component whose selector matches a node in a component
* template.
*/
export interface DirectiveSymbol {
kind: SymbolKind.Directive;
/** The `ts.Type` for the class declaration. */
tsType: ts.Type;
/** The `ts.Symbol` for the class declaration. */
tsSymbol: ts.Symbol;
/** The location in the shim file for the variable that holds the type of the directive. */
shimLocation: ShimLocation;
}