/
api.ts
276 lines (243 loc) Β· 9.76 KB
/
api.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
/**
* @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 {ConstantPool, Expression, Statement, Type} from '@angular/compiler';
import * as ts from 'typescript';
import {Reexport} from '../../imports';
import {SemanticSymbol} from '../../incremental/semantic_graph';
import {IndexingContext} from '../../indexer';
import {ClassDeclaration, Decorator} from '../../reflection';
import {ImportManager} from '../../translator';
import {TypeCheckContext} from '../../typecheck/api';
import {ExtendedTemplateChecker} from '../../typecheck/extended/api';
import {Xi18nContext} from '../../xi18n';
/**
* Specifies the compilation mode that is used for the compilation.
*/
export enum CompilationMode {
/**
* Generates fully AOT compiled code using Ivy instructions.
*/
FULL,
/**
* Generates code using a stable, but intermediate format suitable to be published to NPM.
*/
PARTIAL,
}
export enum HandlerPrecedence {
/**
* Handler with PRIMARY precedence cannot overlap - there can only be one on a given class.
*
* If more than one PRIMARY handler matches a class, an error is produced.
*/
PRIMARY,
/**
* Handlers with SHARED precedence can match any class, possibly in addition to a single PRIMARY
* handler.
*
* It is not an error for a class to have any number of SHARED handlers.
*/
SHARED,
/**
* Handlers with WEAK precedence that match a class are ignored if any handlers with stronger
* precedence match a class.
*/
WEAK,
}
/**
* A set of options which can be passed to a `DecoratorHandler` by a consumer, to tailor the output
* of compilation beyond the decorators themselves.
*/
export enum HandlerFlags {
/**
* No flags set.
*/
NONE = 0x0,
/**
* Indicates that this decorator is fully inherited from its parent at runtime. In addition to
* normally inherited aspects such as inputs and queries, full inheritance applies to every aspect
* of the component or directive, such as the template function itself.
*
* Its primary effect is to cause the `CopyDefinitionFeature` to be applied to the definition
* being compiled. See that class for more information.
*/
FULL_INHERITANCE = 0x00000001,
}
/**
* Provides the interface between a decorator compiler from @angular/compiler and the Typescript
* compiler/transform.
*
* The decorator compilers in @angular/compiler do not depend on Typescript. The handler is
* responsible for extracting the information required to perform compilation from the decorators
* and Typescript source, invoking the decorator compiler, and returning the result.
*
* @param `D` The type of decorator metadata produced by `detect`.
* @param `A` The type of analysis metadata produced by `analyze`.
* @param `R` The type of resolution metadata produced by `resolve`.
*/
export interface DecoratorHandler<D, A, S extends SemanticSymbol|null, R> {
readonly name: string;
/**
* The precedence of a handler controls how it interacts with other handlers that match the same
* class.
*
* See the descriptions on `HandlerPrecedence` for an explanation of the behaviors involved.
*/
readonly precedence: HandlerPrecedence;
/**
* Scan a set of reflected decorators and determine if this handler is responsible for compilation
* of one of them.
*/
detect(node: ClassDeclaration, decorators: Decorator[]|null): DetectResult<D>|undefined;
/**
* Asynchronously perform pre-analysis on the decorator/class combination.
*
* `preanalyze` is optional and is not guaranteed to be called through all compilation flows. It
* will only be called if asynchronicity is supported in the CompilerHost.
*/
preanalyze?(node: ClassDeclaration, metadata: Readonly<D>): Promise<void>|undefined;
/**
* Perform analysis on the decorator/class combination, extracting information from the class
* required for compilation.
*
* Returns analyzed metadata if successful, or an array of diagnostic messages if the analysis
* fails or the decorator isn't valid.
*
* Analysis should always be a "pure" operation, with no side effects. This is because the
* detect/analysis steps might be skipped for files which have not changed during incremental
* builds. Any side effects required for compilation (e.g. registration of metadata) should happen
* in the `register` phase, which is guaranteed to run even for incremental builds.
*/
analyze(node: ClassDeclaration, metadata: Readonly<D>, handlerFlags?: HandlerFlags):
AnalysisOutput<A>;
/**
* React to a change in a resource file by updating the `analysis` or `resolution`, under the
* assumption that nothing in the TypeScript code has changed.
*/
updateResources?(node: ClassDeclaration, analysis: A, resolution: R): void;
/**
* Produces a `SemanticSymbol` that represents the class, which is registered into the semantic
* dependency graph. The symbol is used in incremental compilations to let the compiler determine
* how a change to the class affects prior emit results. See the `incremental` target's README for
* details on how this works.
*
* The symbol is passed in to `resolve`, where it can be extended with references into other parts
* of the compilation as needed.
*
* Only primary handlers are allowed to have symbols; handlers with `precedence` other than
* `HandlerPrecedence.PRIMARY` must return a `null` symbol.
*/
symbol(node: ClassDeclaration, analysis: Readonly<A>): S;
/**
* Post-process the analysis of a decorator/class combination and record any necessary information
* in the larger compilation.
*
* Registration always occurs for a given decorator/class, regardless of whether analysis was
* performed directly or whether the analysis results were reused from the previous program.
*/
register?(node: ClassDeclaration, analysis: A): void;
/**
* Registers information about the decorator for the indexing phase in a
* `IndexingContext`, which stores information about components discovered in the
* program.
*/
index?
(context: IndexingContext, node: ClassDeclaration, analysis: Readonly<A>,
resolution: Readonly<R>): void;
/**
* Perform resolution on the given decorator along with the result of analysis.
*
* The resolution phase happens after the entire `ts.Program` has been analyzed, and gives the
* `DecoratorHandler` a chance to leverage information from the whole compilation unit to enhance
* the `analysis` before the emit phase.
*/
resolve?(node: ClassDeclaration, analysis: Readonly<A>, symbol: S): ResolveResult<R>;
/**
* Extract i18n messages into the `Xi18nContext`, which is useful for generating various formats
* of message file outputs.
*/
xi18n?(bundle: Xi18nContext, node: ClassDeclaration, analysis: Readonly<A>): void;
typeCheck?
(ctx: TypeCheckContext, node: ClassDeclaration, analysis: Readonly<A>,
resolution: Readonly<R>): void;
extendedTemplateCheck?
(component: ts.ClassDeclaration, extendedTemplateChecker: ExtendedTemplateChecker):
ts.Diagnostic[];
/**
* Generate a description of the field which should be added to the class, including any
* initialization code to be generated.
*
* If the compilation mode is configured as partial, and an implementation of `compilePartial` is
* provided, then this method is not called.
*/
compileFull(
node: ClassDeclaration, analysis: Readonly<A>, resolution: Readonly<R>,
constantPool: ConstantPool): CompileResult|CompileResult[];
/**
* Generates code for the decorator using a stable, but intermediate format suitable to be
* published to NPM. This code is meant to be processed by the linker to achieve the final AOT
* compiled code.
*
* If present, this method is used if the compilation mode is configured as partial, otherwise
* `compileFull` is.
*/
compilePartial?
(node: ClassDeclaration, analysis: Readonly<A>, resolution: Readonly<R>): CompileResult
|CompileResult[];
}
/**
* The output of detecting a trait for a declaration as the result of the first phase of the
* compilation pipeline.
*/
export interface DetectResult<M> {
/**
* The node that triggered the match, which is typically a decorator.
*/
trigger: ts.Node|null;
/**
* Refers to the decorator that was recognized for this detection, if any. This can be a concrete
* decorator that is actually present in a file, or a synthetic decorator as inserted
* programmatically.
*/
decorator: Decorator|null;
/**
* An arbitrary object to carry over from the detection phase into the analysis phase.
*/
metadata: Readonly<M>;
}
/**
* The output of an analysis operation, consisting of possibly an arbitrary analysis object (used as
* the input to code generation) and potentially diagnostics if there were errors uncovered during
* analysis.
*/
export interface AnalysisOutput<A> {
analysis?: Readonly<A>;
diagnostics?: ts.Diagnostic[];
}
/**
* A description of the static field to add to a class, including an initialization expression
* and a type for the .d.ts file.
*/
export interface CompileResult {
name: string;
initializer: Expression;
statements: Statement[];
type: Type;
}
export interface ResolveResult<R> {
reexports?: Reexport[];
diagnostics?: ts.Diagnostic[];
data?: Readonly<R>;
}
export interface DtsTransform {
transformClassElement?(element: ts.ClassElement, imports: ImportManager): ts.ClassElement;
transformFunctionDeclaration?
(element: ts.FunctionDeclaration, imports: ImportManager): ts.FunctionDeclaration;
transformClass?
(clazz: ts.ClassDeclaration, elements: ReadonlyArray<ts.ClassElement>,
imports: ImportManager): ts.ClassDeclaration;
}