-
Notifications
You must be signed in to change notification settings - Fork 24.8k
/
checker.ts
227 lines (199 loc) Β· 9.27 KB
/
checker.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
/**
* @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 {AST, LiteralPrimitive, ParseSourceSpan, PropertyRead, SafePropertyRead, TmplAstElement, TmplAstNode, TmplAstTemplate, TmplAstTextAttribute} from '@angular/compiler';
import ts from 'typescript';
import {AbsoluteFsPath} from '../../../../src/ngtsc/file_system';
import {ErrorCode} from '../../diagnostics';
import {FullTemplateMapping, NgTemplateDiagnostic, TypeCheckableDirectiveMeta} from './api';
import {GlobalCompletion} from './completion';
import {PotentialDirective, PotentialImport, PotentialPipe} from './scope';
import {ElementSymbol, Symbol, TcbLocation, TemplateSymbol} from './symbols';
/**
* Interface to the Angular Template Type Checker to extract diagnostics and intelligence from the
* compiler's understanding of component templates.
*
* This interface is analogous to TypeScript's own `ts.TypeChecker` API.
*
* In general, this interface supports two kinds of operations:
* - updating Type Check Blocks (TCB)s that capture the template in the form of TypeScript code
* - querying information about available TCBs, including diagnostics
*
* Once a TCB is available, information about it can be queried. If no TCB is available to answer a
* query, depending on the method either `null` will be returned or an error will be thrown.
*/
export interface TemplateTypeChecker {
/**
* Retrieve the template in use for the given component.
*/
getTemplate(component: ts.ClassDeclaration): TmplAstNode[]|null;
/**
* Get all `ts.Diagnostic`s currently available for the given `ts.SourceFile`.
*
* This method will fail (throw) if there are components within the `ts.SourceFile` that do not
* have TCBs available.
*
* Generating a template type-checking program is expensive, and in some workflows (e.g. checking
* an entire program before emit), it should ideally only be done once. The `optimizeFor` flag
* allows the caller to hint to `getDiagnosticsForFile` (which internally will create a template
* type-checking program if needed) whether the caller is interested in just the results of the
* single file, or whether they plan to query about other files in the program. Based on this
* flag, `getDiagnosticsForFile` will determine how much of the user's program to prepare for
* checking as part of the template type-checking program it creates.
*/
getDiagnosticsForFile(sf: ts.SourceFile, optimizeFor: OptimizeFor): ts.Diagnostic[];
/**
* Given a `shim` and position within the file, returns information for mapping back to a template
* location.
*/
getTemplateMappingAtTcbLocation(tcbLocation: TcbLocation): FullTemplateMapping|null;
/**
* Get all `ts.Diagnostic`s currently available that pertain to the given component.
*
* This method always runs in `OptimizeFor.SingleFile` mode.
*/
getDiagnosticsForComponent(component: ts.ClassDeclaration): ts.Diagnostic[];
/**
* Ensures shims for the whole program are generated. This type of operation would be required by
* operations like "find references" and "refactor/rename" because references may appear in type
* check blocks generated from templates anywhere in the program.
*/
generateAllTypeCheckBlocks(): void;
/**
* Returns `true` if the given file is in the record of known shims generated by the compiler,
* `false` if we cannot find the file in the shim records.
*/
isTrackedTypeCheckFile(filePath: AbsoluteFsPath): boolean;
/**
* Retrieve the top-level node representing the TCB for the given component.
*
* This can return `null` if there is no TCB available for the component.
*
* This method always runs in `OptimizeFor.SingleFile` mode.
*/
getTypeCheckBlock(component: ts.ClassDeclaration): ts.Node|null;
/**
* Retrieves a `Symbol` for the node in a component's template.
*
* This method can return `null` if a valid `Symbol` cannot be determined for the node.
*
* @see Symbol
*/
getSymbolOfNode(node: TmplAstElement, component: ts.ClassDeclaration): ElementSymbol|null;
getSymbolOfNode(node: TmplAstTemplate, component: ts.ClassDeclaration): TemplateSymbol|null;
getSymbolOfNode(node: AST|TmplAstNode, component: ts.ClassDeclaration): Symbol|null;
/**
* Get "global" `Completion`s in the given context.
*
* Global completions are completions in the global context, as opposed to completions within an
* existing expression. For example, completing inside a new interpolation expression (`{{|}}`) or
* inside a new property binding `[input]="|" should retrieve global completions, which will
* include completions from the template's context component, as well as any local references or
* template variables which are in scope for that expression.
*/
getGlobalCompletions(
context: TmplAstTemplate|null, component: ts.ClassDeclaration,
node: AST|TmplAstNode): GlobalCompletion|null;
/**
* For the given expression node, retrieve a `TcbLocation` that can be used to perform
* autocompletion at that point in the expression, if such a location exists.
*/
getExpressionCompletionLocation(
expr: PropertyRead|SafePropertyRead, component: ts.ClassDeclaration): TcbLocation|null;
/**
* For the given node represents a `LiteralPrimitive`(the `TextAttribute` represents a string
* literal), retrieve a `TcbLocation` that can be used to perform autocompletion at that point in
* the node, if such a location exists.
*/
getLiteralCompletionLocation(
strNode: LiteralPrimitive|TmplAstTextAttribute, component: ts.ClassDeclaration): TcbLocation
|null;
/**
* Get basic metadata on the directives which are in scope or can be imported for the given
* component.
*/
getPotentialTemplateDirectives(component: ts.ClassDeclaration): PotentialDirective[];
/**
* Get basic metadata on the pipes which are in scope for the given component.
*/
getPipesInScope(component: ts.ClassDeclaration): PotentialPipe[]|null;
/**
* Retrieve a `Map` of potential template element tags, to either the `PotentialDirective` that
* declares them (if the tag is from a directive/component), or `null` if the tag originates from
* the DOM schema.
*/
getPotentialElementTags(component: ts.ClassDeclaration): Map<string, PotentialDirective|null>;
/**
* In the context of an Angular trait, generate potential imports for a directive.
*/
getPotentialImportsFor(directive: PotentialDirective, inComponent: ts.ClassDeclaration):
ReadonlyArray<PotentialImport>;
/**
* Get the primary decorator for an Angular class (such as @Component). This does not work for
* `@Injectable`.
*/
getPrimaryAngularDecorator(target: ts.ClassDeclaration): ts.Decorator|null;
/**
* Get the class of the NgModule that owns this Angular trait. If the result is `null`, that
* probably means the provided component is standalone.
*/
getOwningNgModule(component: ts.ClassDeclaration): ts.ClassDeclaration|null;
/**
* Retrieve any potential DOM bindings for the given element.
*
* This returns an array of objects which list both the attribute and property names of each
* binding, which are usually identical but can vary if the HTML attribute name is for example a
* reserved keyword in JS, like the `for` attribute which corresponds to the `htmlFor` property.
*/
getPotentialDomBindings(tagName: string): {attribute: string, property: string}[];
/**
* Retrieve any potential DOM events.
*/
getPotentialDomEvents(tagName: string): string[];
/**
* Retrieve the type checking engine's metadata for the given directive class, if available.
*/
getDirectiveMetadata(dir: ts.ClassDeclaration): TypeCheckableDirectiveMeta|null;
/**
* Reset the `TemplateTypeChecker`'s state for the given class, so that it will be recomputed on
* the next request.
*/
invalidateClass(clazz: ts.ClassDeclaration): void;
/**
* Constructs a `ts.Diagnostic` for a given `ParseSourceSpan` within a template.
*/
makeTemplateDiagnostic<T extends ErrorCode>(
clazz: ts.ClassDeclaration, sourceSpan: ParseSourceSpan, category: ts.DiagnosticCategory,
errorCode: T, message: string, relatedInformation?: {
text: string,
start: number,
end: number,
sourceFile: ts.SourceFile,
}[]): NgTemplateDiagnostic<T>;
}
/**
* Describes the scope of the caller's interest in template type-checking results.
*/
export enum OptimizeFor {
/**
* Indicates that a consumer of a `TemplateTypeChecker` is only interested in results for a
* given file, and wants them as fast as possible.
*
* Calling `TemplateTypeChecker` methods successively for multiple files while specifying
* `OptimizeFor.SingleFile` can result in significant unnecessary overhead overall.
*/
SingleFile,
/**
* Indicates that a consumer of a `TemplateTypeChecker` intends to query for results pertaining
* to the entire user program, and so the type-checker should internally optimize for this case.
*
* Initial calls to retrieve type-checking information may take longer, but repeated calls to
* gather information for the whole user program will be significantly faster with this mode of
* optimization.
*/
WholeProgram,
}