1 | /**
|
---|
2 | * @license
|
---|
3 | * Copyright Google LLC All Rights Reserved.
|
---|
4 | *
|
---|
5 | * Use of this source code is governed by an MIT-style license that can be
|
---|
6 | * found in the LICENSE file at https://angular.io/license
|
---|
7 | */
|
---|
8 | /// <amd-module name="@angular/compiler-cli/src/ngtsc/typecheck/src/type_check_block" />
|
---|
9 | import { BoundTarget, SchemaMetadata, TmplAstElement, TmplAstNode, TmplAstReference, TmplAstTemplate, TmplAstVariable } from '@angular/compiler';
|
---|
10 | import * as ts from 'typescript';
|
---|
11 | import { Reference } from '../../imports';
|
---|
12 | import { ClassDeclaration } from '../../reflection';
|
---|
13 | import { TemplateId, TypeCheckableDirectiveMeta, TypeCheckBlockMetadata } from '../api';
|
---|
14 | import { DomSchemaChecker } from './dom';
|
---|
15 | import { Environment } from './environment';
|
---|
16 | import { OutOfBandDiagnosticRecorder } from './oob';
|
---|
17 | /**
|
---|
18 | * Controls how generics for the component context class will be handled during TCB generation.
|
---|
19 | */
|
---|
20 | export declare enum TcbGenericContextBehavior {
|
---|
21 | /**
|
---|
22 | * References to generic parameter bounds will be emitted via the `TypeParameterEmitter`.
|
---|
23 | *
|
---|
24 | * The caller must verify that all parameter bounds are emittable in order to use this mode.
|
---|
25 | */
|
---|
26 | UseEmitter = 0,
|
---|
27 | /**
|
---|
28 | * Generic parameter declarations will be copied directly from the `ts.ClassDeclaration` of the
|
---|
29 | * component class.
|
---|
30 | *
|
---|
31 | * The caller must only use the generated TCB code in a context where such copies will still be
|
---|
32 | * valid, such as an inline type check block.
|
---|
33 | */
|
---|
34 | CopyClassNodes = 1,
|
---|
35 | /**
|
---|
36 | * Any generic parameters for the component context class will be set to `any`.
|
---|
37 | *
|
---|
38 | * Produces a less useful type, but is always safe to use.
|
---|
39 | */
|
---|
40 | FallbackToAny = 2
|
---|
41 | }
|
---|
42 | /**
|
---|
43 | * Given a `ts.ClassDeclaration` for a component, and metadata regarding that component, compose a
|
---|
44 | * "type check block" function.
|
---|
45 | *
|
---|
46 | * When passed through TypeScript's TypeChecker, type errors that arise within the type check block
|
---|
47 | * function indicate issues in the template itself.
|
---|
48 | *
|
---|
49 | * As a side effect of generating a TCB for the component, `ts.Diagnostic`s may also be produced
|
---|
50 | * directly for issues within the template which are identified during generation. These issues are
|
---|
51 | * recorded in either the `domSchemaChecker` (which checks usage of DOM elements and bindings) as
|
---|
52 | * well as the `oobRecorder` (which records errors when the type-checking code generator is unable
|
---|
53 | * to sufficiently understand a template).
|
---|
54 | *
|
---|
55 | * @param env an `Environment` into which type-checking code will be generated.
|
---|
56 | * @param ref a `Reference` to the component class which should be type-checked.
|
---|
57 | * @param name a `ts.Identifier` to use for the generated `ts.FunctionDeclaration`.
|
---|
58 | * @param meta metadata about the component's template and the function being generated.
|
---|
59 | * @param domSchemaChecker used to check and record errors regarding improper usage of DOM elements
|
---|
60 | * and bindings.
|
---|
61 | * @param oobRecorder used to record errors regarding template elements which could not be correctly
|
---|
62 | * translated into types during TCB generation.
|
---|
63 | * @param genericContextBehavior controls how generic parameters (especially parameters with generic
|
---|
64 | * bounds) will be referenced from the generated TCB code.
|
---|
65 | */
|
---|
66 | export declare function generateTypeCheckBlock(env: Environment, ref: Reference<ClassDeclaration<ts.ClassDeclaration>>, name: ts.Identifier, meta: TypeCheckBlockMetadata, domSchemaChecker: DomSchemaChecker, oobRecorder: OutOfBandDiagnosticRecorder, genericContextBehavior: TcbGenericContextBehavior): ts.FunctionDeclaration;
|
---|
67 | /**
|
---|
68 | * A code generation operation that's involved in the construction of a Type Check Block.
|
---|
69 | *
|
---|
70 | * The generation of a TCB is non-linear. Bindings within a template may result in the need to
|
---|
71 | * construct certain types earlier than they otherwise would be constructed. That is, if the
|
---|
72 | * generation of a TCB for a template is broken down into specific operations (constructing a
|
---|
73 | * directive, extracting a variable from a let- operation, etc), then it's possible for operations
|
---|
74 | * earlier in the sequence to depend on operations which occur later in the sequence.
|
---|
75 | *
|
---|
76 | * `TcbOp` abstracts the different types of operations which are required to convert a template into
|
---|
77 | * a TCB. This allows for two phases of processing for the template, where 1) a linear sequence of
|
---|
78 | * `TcbOp`s is generated, and then 2) these operations are executed, not necessarily in linear
|
---|
79 | * order.
|
---|
80 | *
|
---|
81 | * Each `TcbOp` may insert statements into the body of the TCB, and also optionally return a
|
---|
82 | * `ts.Expression` which can be used to reference the operation's result.
|
---|
83 | */
|
---|
84 | declare abstract class TcbOp {
|
---|
85 | /**
|
---|
86 | * Set to true if this operation can be considered optional. Optional operations are only executed
|
---|
87 | * when depended upon by other operations, otherwise they are disregarded. This allows for less
|
---|
88 | * code to generate, parse and type-check, overall positively contributing to performance.
|
---|
89 | */
|
---|
90 | abstract readonly optional: boolean;
|
---|
91 | abstract execute(): ts.Expression | null;
|
---|
92 | /**
|
---|
93 | * Replacement value or operation used while this `TcbOp` is executing (i.e. to resolve circular
|
---|
94 | * references during its execution).
|
---|
95 | *
|
---|
96 | * This is usually a `null!` expression (which asks TS to infer an appropriate type), but another
|
---|
97 | * `TcbOp` can be returned in cases where additional code generation is necessary to deal with
|
---|
98 | * circular references.
|
---|
99 | */
|
---|
100 | circularFallback(): TcbOp | ts.Expression;
|
---|
101 | }
|
---|
102 | /**
|
---|
103 | * A `TcbOp` which generates code to check event bindings on an element that correspond with the
|
---|
104 | * outputs of a directive.
|
---|
105 | *
|
---|
106 | * Executing this operation returns nothing.
|
---|
107 | */
|
---|
108 | export declare class TcbDirectiveOutputsOp extends TcbOp {
|
---|
109 | private tcb;
|
---|
110 | private scope;
|
---|
111 | private node;
|
---|
112 | private dir;
|
---|
113 | constructor(tcb: Context, scope: Scope, node: TmplAstTemplate | TmplAstElement, dir: TypeCheckableDirectiveMeta);
|
---|
114 | get optional(): boolean;
|
---|
115 | execute(): null;
|
---|
116 | }
|
---|
117 | /**
|
---|
118 | * Overall generation context for the type check block.
|
---|
119 | *
|
---|
120 | * `Context` handles operations during code generation which are global with respect to the whole
|
---|
121 | * block. It's responsible for variable name allocation and management of any imports needed. It
|
---|
122 | * also contains the template metadata itself.
|
---|
123 | */
|
---|
124 | export declare class Context {
|
---|
125 | readonly env: Environment;
|
---|
126 | readonly domSchemaChecker: DomSchemaChecker;
|
---|
127 | readonly oobRecorder: OutOfBandDiagnosticRecorder;
|
---|
128 | readonly id: TemplateId;
|
---|
129 | readonly boundTarget: BoundTarget<TypeCheckableDirectiveMeta>;
|
---|
130 | private pipes;
|
---|
131 | readonly schemas: SchemaMetadata[];
|
---|
132 | private nextId;
|
---|
133 | constructor(env: Environment, domSchemaChecker: DomSchemaChecker, oobRecorder: OutOfBandDiagnosticRecorder, id: TemplateId, boundTarget: BoundTarget<TypeCheckableDirectiveMeta>, pipes: Map<string, Reference<ClassDeclaration<ts.ClassDeclaration>>>, schemas: SchemaMetadata[]);
|
---|
134 | /**
|
---|
135 | * Allocate a new variable name for use within the `Context`.
|
---|
136 | *
|
---|
137 | * Currently this uses a monotonically increasing counter, but in the future the variable name
|
---|
138 | * might change depending on the type of data being stored.
|
---|
139 | */
|
---|
140 | allocateId(): ts.Identifier;
|
---|
141 | getPipeByName(name: string): Reference<ClassDeclaration<ts.ClassDeclaration>> | null;
|
---|
142 | }
|
---|
143 | /**
|
---|
144 | * Local scope within the type check block for a particular template.
|
---|
145 | *
|
---|
146 | * The top-level template and each nested `<ng-template>` have their own `Scope`, which exist in a
|
---|
147 | * hierarchy. The structure of this hierarchy mirrors the syntactic scopes in the generated type
|
---|
148 | * check block, where each nested template is encased in an `if` structure.
|
---|
149 | *
|
---|
150 | * As a template's `TcbOp`s are executed in a given `Scope`, statements are added via
|
---|
151 | * `addStatement()`. When this processing is complete, the `Scope` can be turned into a `ts.Block`
|
---|
152 | * via `renderToBlock()`.
|
---|
153 | *
|
---|
154 | * If a `TcbOp` requires the output of another, it can call `resolve()`.
|
---|
155 | */
|
---|
156 | declare class Scope {
|
---|
157 | private tcb;
|
---|
158 | private parent;
|
---|
159 | private guard;
|
---|
160 | /**
|
---|
161 | * A queue of operations which need to be performed to generate the TCB code for this scope.
|
---|
162 | *
|
---|
163 | * This array can contain either a `TcbOp` which has yet to be executed, or a `ts.Expression|null`
|
---|
164 | * representing the memoized result of executing the operation. As operations are executed, their
|
---|
165 | * results are written into the `opQueue`, overwriting the original operation.
|
---|
166 | *
|
---|
167 | * If an operation is in the process of being executed, it is temporarily overwritten here with
|
---|
168 | * `INFER_TYPE_FOR_CIRCULAR_OP_EXPR`. This way, if a cycle is encountered where an operation
|
---|
169 | * depends transitively on its own result, the inner operation will infer the least narrow type
|
---|
170 | * that fits instead. This has the same semantics as TypeScript itself when types are referenced
|
---|
171 | * circularly.
|
---|
172 | */
|
---|
173 | private opQueue;
|
---|
174 | /**
|
---|
175 | * A map of `TmplAstElement`s to the index of their `TcbElementOp` in the `opQueue`
|
---|
176 | */
|
---|
177 | private elementOpMap;
|
---|
178 | /**
|
---|
179 | * A map of maps which tracks the index of `TcbDirectiveCtorOp`s in the `opQueue` for each
|
---|
180 | * directive on a `TmplAstElement` or `TmplAstTemplate` node.
|
---|
181 | */
|
---|
182 | private directiveOpMap;
|
---|
183 | /**
|
---|
184 | * A map of `TmplAstReference`s to the index of their `TcbReferenceOp` in the `opQueue`
|
---|
185 | */
|
---|
186 | private referenceOpMap;
|
---|
187 | /**
|
---|
188 | * Map of immediately nested <ng-template>s (within this `Scope`) represented by `TmplAstTemplate`
|
---|
189 | * nodes to the index of their `TcbTemplateContextOp`s in the `opQueue`.
|
---|
190 | */
|
---|
191 | private templateCtxOpMap;
|
---|
192 | /**
|
---|
193 | * Map of variables declared on the template that created this `Scope` (represented by
|
---|
194 | * `TmplAstVariable` nodes) to the index of their `TcbVariableOp`s in the `opQueue`.
|
---|
195 | */
|
---|
196 | private varMap;
|
---|
197 | /**
|
---|
198 | * Statements for this template.
|
---|
199 | *
|
---|
200 | * Executing the `TcbOp`s in the `opQueue` populates this array.
|
---|
201 | */
|
---|
202 | private statements;
|
---|
203 | private constructor();
|
---|
204 | /**
|
---|
205 | * Constructs a `Scope` given either a `TmplAstTemplate` or a list of `TmplAstNode`s.
|
---|
206 | *
|
---|
207 | * @param tcb the overall context of TCB generation.
|
---|
208 | * @param parent the `Scope` of the parent template (if any) or `null` if this is the root
|
---|
209 | * `Scope`.
|
---|
210 | * @param templateOrNodes either a `TmplAstTemplate` representing the template for which to
|
---|
211 | * calculate the `Scope`, or a list of nodes if no outer template object is available.
|
---|
212 | * @param guard an expression that is applied to this scope for type narrowing purposes.
|
---|
213 | */
|
---|
214 | static forNodes(tcb: Context, parent: Scope | null, templateOrNodes: TmplAstTemplate | (TmplAstNode[]), guard: ts.Expression | null): Scope;
|
---|
215 | /**
|
---|
216 | * Look up a `ts.Expression` representing the value of some operation in the current `Scope`,
|
---|
217 | * including any parent scope(s). This method always returns a mutable clone of the
|
---|
218 | * `ts.Expression` with the comments cleared.
|
---|
219 | *
|
---|
220 | * @param node a `TmplAstNode` of the operation in question. The lookup performed will depend on
|
---|
221 | * the type of this node:
|
---|
222 | *
|
---|
223 | * Assuming `directive` is not present, then `resolve` will return:
|
---|
224 | *
|
---|
225 | * * `TmplAstElement` - retrieve the expression for the element DOM node
|
---|
226 | * * `TmplAstTemplate` - retrieve the template context variable
|
---|
227 | * * `TmplAstVariable` - retrieve a template let- variable
|
---|
228 | * * `TmplAstReference` - retrieve variable created for the local ref
|
---|
229 | *
|
---|
230 | * @param directive if present, a directive type on a `TmplAstElement` or `TmplAstTemplate` to
|
---|
231 | * look up instead of the default for an element or template node.
|
---|
232 | */
|
---|
233 | resolve(node: TmplAstElement | TmplAstTemplate | TmplAstVariable | TmplAstReference, directive?: TypeCheckableDirectiveMeta): ts.Expression;
|
---|
234 | /**
|
---|
235 | * Add a statement to this scope.
|
---|
236 | */
|
---|
237 | addStatement(stmt: ts.Statement): void;
|
---|
238 | /**
|
---|
239 | * Get the statements.
|
---|
240 | */
|
---|
241 | render(): ts.Statement[];
|
---|
242 | /**
|
---|
243 | * Returns an expression of all template guards that apply to this scope, including those of
|
---|
244 | * parent scopes. If no guards have been applied, null is returned.
|
---|
245 | */
|
---|
246 | guards(): ts.Expression | null;
|
---|
247 | private resolveLocal;
|
---|
248 | /**
|
---|
249 | * Like `executeOp`, but assert that the operation actually returned `ts.Expression`.
|
---|
250 | */
|
---|
251 | private resolveOp;
|
---|
252 | /**
|
---|
253 | * Execute a particular `TcbOp` in the `opQueue`.
|
---|
254 | *
|
---|
255 | * This method replaces the operation in the `opQueue` with the result of execution (once done)
|
---|
256 | * and also protects against a circular dependency from the operation to itself by temporarily
|
---|
257 | * setting the operation's result to a special expression.
|
---|
258 | */
|
---|
259 | private executeOp;
|
---|
260 | private appendNode;
|
---|
261 | private checkAndAppendReferencesOfNode;
|
---|
262 | private appendDirectivesAndInputsOfNode;
|
---|
263 | private appendOutputsOfNode;
|
---|
264 | private appendDeepSchemaChecks;
|
---|
265 | private appendIcuExpressions;
|
---|
266 | }
|
---|
267 | export {};
|
---|