@typespec/compiler 0.62.0-dev.8 → 0.62.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/generated-defs/TypeSpec.Prototypes.d.ts +6 -0
- package/dist/generated-defs/TypeSpec.Prototypes.d.ts.map +1 -0
- package/dist/generated-defs/TypeSpec.Prototypes.js +2 -0
- package/dist/generated-defs/TypeSpec.Prototypes.js.map +1 -0
- package/dist/generated-defs/TypeSpec.Prototypes.ts-test.d.ts +2 -0
- package/dist/generated-defs/TypeSpec.Prototypes.ts-test.d.ts.map +1 -0
- package/dist/generated-defs/TypeSpec.Prototypes.ts-test.js +5 -0
- package/dist/generated-defs/TypeSpec.Prototypes.ts-test.js.map +1 -0
- package/dist/generated-defs/TypeSpec.d.ts +149 -9
- package/dist/generated-defs/TypeSpec.d.ts.map +1 -1
- package/dist/manifest.js +2 -2
- package/dist/src/core/binder.d.ts +8 -0
- package/dist/src/core/binder.d.ts.map +1 -1
- package/dist/src/core/binder.js +107 -43
- package/dist/src/core/binder.js.map +1 -1
- package/dist/src/core/checker.d.ts +3 -7
- package/dist/src/core/checker.d.ts.map +1 -1
- package/dist/src/core/checker.js +341 -824
- package/dist/src/core/checker.js.map +1 -1
- package/dist/src/core/cli/utils.js +1 -1
- package/dist/src/core/cli/utils.js.map +1 -1
- package/dist/src/core/diagnostics.d.ts +5 -1
- package/dist/src/core/diagnostics.d.ts.map +1 -1
- package/dist/src/core/diagnostics.js +33 -4
- package/dist/src/core/diagnostics.js.map +1 -1
- package/dist/src/core/helpers/operation-utils.d.ts.map +1 -1
- package/dist/src/core/helpers/operation-utils.js +4 -1
- package/dist/src/core/helpers/operation-utils.js.map +1 -1
- package/dist/src/core/helpers/syntax-utils.d.ts +2 -0
- package/dist/src/core/helpers/syntax-utils.d.ts.map +1 -1
- package/dist/src/core/helpers/syntax-utils.js +11 -0
- package/dist/src/core/helpers/syntax-utils.js.map +1 -1
- package/dist/src/core/index.d.ts +1 -1
- package/dist/src/core/index.d.ts.map +1 -1
- package/dist/src/core/index.js +1 -1
- package/dist/src/core/index.js.map +1 -1
- package/dist/src/core/inspector/node.d.ts +2 -0
- package/dist/src/core/inspector/node.d.ts.map +1 -0
- package/dist/src/core/inspector/node.js +35 -0
- package/dist/src/core/inspector/node.js.map +1 -0
- package/dist/src/core/inspector/symbol.d.ts +3 -0
- package/dist/src/core/inspector/symbol.d.ts.map +1 -0
- package/dist/src/core/inspector/symbol.js +84 -0
- package/dist/src/core/inspector/symbol.js.map +1 -0
- package/dist/src/core/logger/console-sink.d.ts +1 -0
- package/dist/src/core/logger/console-sink.d.ts.map +1 -1
- package/dist/src/core/logger/console-sink.js +22 -6
- package/dist/src/core/logger/console-sink.js.map +1 -1
- package/dist/src/core/logger/logger.js +1 -1
- package/dist/src/core/logger/logger.js.map +1 -1
- package/dist/src/core/messages.d.ts +99 -43
- package/dist/src/core/messages.d.ts.map +1 -1
- package/dist/src/core/messages.js +29 -13
- package/dist/src/core/messages.js.map +1 -1
- package/dist/src/core/name-resolver.d.ts +107 -0
- package/dist/src/core/name-resolver.d.ts.map +1 -0
- package/dist/src/core/name-resolver.js +989 -0
- package/dist/src/core/name-resolver.js.map +1 -0
- package/dist/src/core/program.d.ts.map +1 -1
- package/dist/src/core/program.js +14 -4
- package/dist/src/core/program.js.map +1 -1
- package/dist/src/core/semantic-walker.d.ts.map +1 -1
- package/dist/src/core/semantic-walker.js +3 -1
- package/dist/src/core/semantic-walker.js.map +1 -1
- package/dist/src/core/type-utils.js +2 -2
- package/dist/src/core/type-utils.js.map +1 -1
- package/dist/src/core/types.d.ts +149 -35
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/core/types.js +9 -0
- package/dist/src/core/types.js.map +1 -1
- package/dist/src/index.d.ts +5 -5
- package/dist/src/index.d.ts.map +1 -1
- package/dist/src/index.js +13 -4
- package/dist/src/index.js.map +1 -1
- package/dist/src/lib/decorators.d.ts +2 -13
- package/dist/src/lib/decorators.d.ts.map +1 -1
- package/dist/src/lib/decorators.js +1 -33
- package/dist/src/lib/decorators.js.map +1 -1
- package/dist/src/lib/intrinsic/decorators.d.ts +5 -0
- package/dist/src/lib/intrinsic/decorators.d.ts.map +1 -0
- package/dist/src/lib/intrinsic/decorators.js +25 -0
- package/dist/src/lib/intrinsic/decorators.js.map +1 -0
- package/dist/src/lib/intrinsic/tsp-index.d.ts +9 -0
- package/dist/src/lib/intrinsic/tsp-index.d.ts.map +1 -0
- package/dist/src/lib/intrinsic/tsp-index.js +11 -0
- package/dist/src/lib/intrinsic/tsp-index.js.map +1 -0
- package/dist/src/lib/paging.d.ts +112 -0
- package/dist/src/lib/paging.d.ts.map +1 -0
- package/dist/src/lib/paging.js +260 -0
- package/dist/src/lib/paging.js.map +1 -0
- package/dist/src/lib/tsp-index.d.ts.map +1 -1
- package/dist/src/lib/tsp-index.js +12 -2
- package/dist/src/lib/tsp-index.js.map +1 -1
- package/dist/src/server/completion.d.ts.map +1 -1
- package/dist/src/server/completion.js +7 -6
- package/dist/src/server/completion.js.map +1 -1
- package/dist/src/server/diagnostics.d.ts +8 -0
- package/dist/src/server/diagnostics.d.ts.map +1 -0
- package/dist/src/server/diagnostics.js +106 -0
- package/dist/src/server/diagnostics.js.map +1 -0
- package/dist/src/server/serverlib.d.ts.map +1 -1
- package/dist/src/server/serverlib.js +18 -43
- package/dist/src/server/serverlib.js.map +1 -1
- package/dist/src/server/type-details.js +3 -2
- package/dist/src/server/type-details.js.map +1 -1
- package/dist/src/server/type-signature.js +2 -1
- package/dist/src/server/type-signature.js.map +1 -1
- package/dist/src/testing/expect.js +1 -1
- package/dist/src/testing/expect.js.map +1 -1
- package/dist/src/testing/test-host.js +1 -1
- package/dist/src/testing/test-host.js.map +1 -1
- package/dist/src/testing/test-utils.d.ts +6 -0
- package/dist/src/testing/test-utils.d.ts.map +1 -1
- package/dist/src/testing/test-utils.js +19 -1
- package/dist/src/testing/test-utils.js.map +1 -1
- package/dist/src/utils/misc.d.ts +6 -5
- package/dist/src/utils/misc.d.ts.map +1 -1
- package/dist/src/utils/misc.js.map +1 -1
- package/lib/intrinsics.tsp +2 -1
- package/lib/prototypes.tsp +18 -0
- package/lib/std/decorators.tsp +152 -8
- package/package.json +6 -8
- package/templates/scaffolding.json +4 -4
- package/dist/src/lib/intrinsic-decorators.d.ts +0 -6
- package/dist/src/lib/intrinsic-decorators.d.ts.map +0 -1
- package/dist/src/lib/intrinsic-decorators.js +0 -17
- package/dist/src/lib/intrinsic-decorators.js.map +0 -1
|
@@ -0,0 +1,989 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* The name resolver is responsible for resolving identifiers to symbols and
|
|
3
|
+
* creating symbols for types that become known during this process. After name
|
|
4
|
+
* resolution, we can do some limited analysis of the reference graph in order
|
|
5
|
+
* to support e.g. augment decorators.
|
|
6
|
+
*
|
|
7
|
+
* Name resolution does not alter any AST nodes or attached symbols in order to
|
|
8
|
+
* ensure AST nodes and attached symbols can be trivially reused between
|
|
9
|
+
* compilations. Instead, symbols created here are either stored in augmented
|
|
10
|
+
* symbol tables or as merged symbols. Any metadata about symbols and nodes are
|
|
11
|
+
* stored in symbol links and node links respectively. The resolver provides
|
|
12
|
+
* APIs for managing this metadata which is useful during later phases.
|
|
13
|
+
*
|
|
14
|
+
* While we resolve some identifiers to symbols during this phase, we often
|
|
15
|
+
* cannot say for sure that an identifier does not exist. Some symbols must be
|
|
16
|
+
* late-bound because the symbol does not become known until after the program
|
|
17
|
+
* has been checked. A common example is members of a model template which often
|
|
18
|
+
* cannot be known until the template is instantiated. Instead, we mark that the
|
|
19
|
+
* reference is unknown and will resolve the symbol (or report an error if it
|
|
20
|
+
* doesn't exist) in later phases. These unknown references cannot be used as
|
|
21
|
+
* the target of an augment decorator.
|
|
22
|
+
*
|
|
23
|
+
* There are some errors we can detect because we have complete symbol
|
|
24
|
+
* information, but we do not report them from here. For example, because we
|
|
25
|
+
* know all namespace bindings and all the declarations inside of them, we could
|
|
26
|
+
* in principle report an error when we attempt to `using` something that isn't
|
|
27
|
+
* a namespace. However, giving a good error message sometimes requires knowing
|
|
28
|
+
* what type was mistakenly referenced, so we merely mark that resolution has
|
|
29
|
+
* failed and move on. Even in cases where we could give a good error we chose
|
|
30
|
+
* not to in order to uniformly handle error reporting in the checker.
|
|
31
|
+
*
|
|
32
|
+
* Name resolution has three sub-phases:
|
|
33
|
+
*
|
|
34
|
+
* 1. Merge namespace symbols and decorator implementation/declaration symbols
|
|
35
|
+
* 2. Resolve using references to namespaces and create namespace-local bindings
|
|
36
|
+
* for used symbols
|
|
37
|
+
* 3. Resolve type references and bind members
|
|
38
|
+
*
|
|
39
|
+
* The reference resolution and member binding phase implements a deferred
|
|
40
|
+
* resolution strategy. Often we cannot resolve a reference without binding
|
|
41
|
+
* members, but we often cannot bind members without resolving references. In
|
|
42
|
+
* such situations, we stop resolving or binding the current reference or type
|
|
43
|
+
* and attempt to resolve or bind the reference or type it depends on. Once we
|
|
44
|
+
* have done so, we return to the original reference or type and complete our
|
|
45
|
+
* work.
|
|
46
|
+
*
|
|
47
|
+
* This is accomplished by doing a depth-first traversal of the reference graph.
|
|
48
|
+
* On the way down, we discover any dependencies that need to be resolved or
|
|
49
|
+
* bound for the current node, and recurse into the AST nodes, so that on the
|
|
50
|
+
* way back up, all of our dependencies are bound and resolved and we can
|
|
51
|
+
* complete. So while we start with a depth-first traversal of the ASTs in order
|
|
52
|
+
* to discover work to do, most of the actual work is done while following the
|
|
53
|
+
* reference graph, binding and resolving along the way. Circular references are
|
|
54
|
+
* discovered during the reference graph walk and marked as such. Symbol and
|
|
55
|
+
* node links are used to ensure we never resolve the same reference twice. The
|
|
56
|
+
* checker implements a very similar algorithm to evaluate the types of the
|
|
57
|
+
* program.
|
|
58
|
+
**/
|
|
59
|
+
import { mutate } from "../utils/misc.js";
|
|
60
|
+
import { createSymbol, createSymbolTable, getSymNode } from "./binder.js";
|
|
61
|
+
import { compilerAssert } from "./diagnostics.js";
|
|
62
|
+
import { visitChildren } from "./parser.js";
|
|
63
|
+
import { ResolutionResultFlags, SyntaxKind, } from "./types.js";
|
|
64
|
+
// This needs to be global to be sure to not reallocate per program.
|
|
65
|
+
let currentNodeId = 0;
|
|
66
|
+
let currentSymbolId = 0;
|
|
67
|
+
export function createResolver(program) {
|
|
68
|
+
const mergedSymbols = new Map();
|
|
69
|
+
const augmentedSymbolTables = new Map();
|
|
70
|
+
const nodeLinks = new Map();
|
|
71
|
+
const symbolLinks = new Map();
|
|
72
|
+
const globalNamespaceNode = createGlobalNamespaceNode();
|
|
73
|
+
const globalNamespaceSym = createSymbol(globalNamespaceNode, "global", 256 /* SymbolFlags.Namespace */ | 1048576 /* SymbolFlags.Declaration */);
|
|
74
|
+
mutate(globalNamespaceNode).symbol = globalNamespaceSym;
|
|
75
|
+
mutate(globalNamespaceSym.exports).set(globalNamespaceNode.id.sv, globalNamespaceSym);
|
|
76
|
+
const metaTypePrototypes = createMetaTypePrototypes();
|
|
77
|
+
const nullSym = createSymbol(undefined, "null", 0 /* SymbolFlags.None */);
|
|
78
|
+
const augmentDecoratorsForSym = new Map();
|
|
79
|
+
return {
|
|
80
|
+
symbols: { global: globalNamespaceSym, null: nullSym },
|
|
81
|
+
resolveProgram() {
|
|
82
|
+
// Merge namespace symbols and decorator implementation/declaration symbols
|
|
83
|
+
for (const file of program.jsSourceFiles.values()) {
|
|
84
|
+
mergeSymbolTable(file.symbol.exports, mutate(globalNamespaceSym.exports));
|
|
85
|
+
}
|
|
86
|
+
for (const file of program.sourceFiles.values()) {
|
|
87
|
+
mergeSymbolTable(file.symbol.exports, mutate(globalNamespaceSym.exports));
|
|
88
|
+
}
|
|
89
|
+
const typespecNamespaceBinding = globalNamespaceSym.exports.get("TypeSpec");
|
|
90
|
+
if (typespecNamespaceBinding) {
|
|
91
|
+
mutate(typespecNamespaceBinding.exports).set("null", nullSym);
|
|
92
|
+
for (const file of program.sourceFiles.values()) {
|
|
93
|
+
addUsingSymbols(typespecNamespaceBinding.exports, file.locals);
|
|
94
|
+
}
|
|
95
|
+
}
|
|
96
|
+
// Bind usings to namespaces, create namespace-local bindings for used symbols
|
|
97
|
+
for (const file of program.sourceFiles.values()) {
|
|
98
|
+
setUsingsForFile(file);
|
|
99
|
+
}
|
|
100
|
+
// Begin reference graph walk starting at each node to ensure we visit all possible
|
|
101
|
+
// references and types that need binding.
|
|
102
|
+
for (const file of program.sourceFiles.values()) {
|
|
103
|
+
bindAndResolveNode(file);
|
|
104
|
+
}
|
|
105
|
+
},
|
|
106
|
+
getMergedSymbol,
|
|
107
|
+
getAugmentedSymbolTable,
|
|
108
|
+
getNodeLinks,
|
|
109
|
+
getSymbolLinks,
|
|
110
|
+
resolveMemberExpressionForSym,
|
|
111
|
+
resolveMetaMemberByName,
|
|
112
|
+
resolveTypeReference,
|
|
113
|
+
getAugmentDecoratorsForSym,
|
|
114
|
+
};
|
|
115
|
+
function getAugmentDecoratorsForSym(sym) {
|
|
116
|
+
return augmentDecoratorsForSym.get(sym) ?? [];
|
|
117
|
+
}
|
|
118
|
+
function getMergedSymbol(sym) {
|
|
119
|
+
if (!sym)
|
|
120
|
+
return sym;
|
|
121
|
+
return mergedSymbols.get(sym) || sym;
|
|
122
|
+
}
|
|
123
|
+
/**
|
|
124
|
+
* @internal
|
|
125
|
+
*/
|
|
126
|
+
function getNodeLinks(n) {
|
|
127
|
+
const id = getNodeId(n);
|
|
128
|
+
if (nodeLinks.has(id)) {
|
|
129
|
+
return nodeLinks.get(id);
|
|
130
|
+
}
|
|
131
|
+
const links = {};
|
|
132
|
+
nodeLinks.set(id, links);
|
|
133
|
+
return links;
|
|
134
|
+
}
|
|
135
|
+
function getNodeId(n) {
|
|
136
|
+
if (n._id === undefined) {
|
|
137
|
+
mutate(n)._id = currentNodeId++;
|
|
138
|
+
}
|
|
139
|
+
return n._id;
|
|
140
|
+
}
|
|
141
|
+
/**
|
|
142
|
+
* @internal
|
|
143
|
+
*/
|
|
144
|
+
function getSymbolLinks(s) {
|
|
145
|
+
const id = getSymbolId(s);
|
|
146
|
+
if (symbolLinks.has(id)) {
|
|
147
|
+
return symbolLinks.get(id);
|
|
148
|
+
}
|
|
149
|
+
const links = {};
|
|
150
|
+
symbolLinks.set(id, links);
|
|
151
|
+
return links;
|
|
152
|
+
}
|
|
153
|
+
function getSymbolId(s) {
|
|
154
|
+
if (s.id === undefined) {
|
|
155
|
+
mutate(s).id = currentSymbolId++;
|
|
156
|
+
}
|
|
157
|
+
return s.id;
|
|
158
|
+
}
|
|
159
|
+
function resolveTypeReference(node, options = {}) {
|
|
160
|
+
const links = getNodeLinks(node);
|
|
161
|
+
if (links.resolutionResult) {
|
|
162
|
+
return links;
|
|
163
|
+
}
|
|
164
|
+
let result = resolveTypeReferenceWorker(node, options);
|
|
165
|
+
const resolvedSym = result.resolvedSymbol;
|
|
166
|
+
Object.assign(links, result);
|
|
167
|
+
if (resolvedSym && resolvedSym.flags & 128 /* SymbolFlags.Alias */) {
|
|
168
|
+
// unwrap aliases
|
|
169
|
+
const aliasNode = resolvedSym.declarations[0];
|
|
170
|
+
const aliasResult = resolveAlias(aliasNode);
|
|
171
|
+
// For alias if the alias itself is a template declaration then its not actually instantiating the reference
|
|
172
|
+
const isTemplateInstantiation = aliasResult.isTemplateInstantiation && aliasNode.templateParameters.length === 0;
|
|
173
|
+
if (isTemplateInstantiation) {
|
|
174
|
+
links.isTemplateInstantiation = true;
|
|
175
|
+
}
|
|
176
|
+
if (aliasResult.finalSymbol) {
|
|
177
|
+
links.finalSymbol = aliasResult.finalSymbol;
|
|
178
|
+
}
|
|
179
|
+
result = {
|
|
180
|
+
...aliasResult,
|
|
181
|
+
finalSymbol: links.finalSymbol,
|
|
182
|
+
isTemplateInstantiation: result.isTemplateInstantiation || isTemplateInstantiation,
|
|
183
|
+
};
|
|
184
|
+
}
|
|
185
|
+
else if (resolvedSym && resolvedSym.flags & 2048 /* SymbolFlags.TemplateParameter */) {
|
|
186
|
+
// references to template parameters with constraints can reference the
|
|
187
|
+
// constraint type members
|
|
188
|
+
const templateNode = resolvedSym.declarations[0];
|
|
189
|
+
if (templateNode.constraint) {
|
|
190
|
+
result = resolveTemplateParameter(templateNode);
|
|
191
|
+
}
|
|
192
|
+
}
|
|
193
|
+
// make sure we've bound and fully resolved the referenced
|
|
194
|
+
// node before returning it.
|
|
195
|
+
if (resolvedSym) {
|
|
196
|
+
if (resolvedSym.flags & 1048576 /* SymbolFlags.Declaration */ &&
|
|
197
|
+
~resolvedSym.flags & 256 /* SymbolFlags.Namespace */) {
|
|
198
|
+
bindAndResolveNode(resolvedSym.declarations[0]);
|
|
199
|
+
}
|
|
200
|
+
}
|
|
201
|
+
return result;
|
|
202
|
+
}
|
|
203
|
+
function resolveTypeReferenceWorker(node, options) {
|
|
204
|
+
if (node.kind === SyntaxKind.TypeReference) {
|
|
205
|
+
const result = resolveTypeReference(node.target, options);
|
|
206
|
+
return node.arguments.length > 0 ? { ...result, isTemplateInstantiation: true } : result;
|
|
207
|
+
}
|
|
208
|
+
else if (node.kind === SyntaxKind.MemberExpression) {
|
|
209
|
+
return resolveMemberExpression(node, options);
|
|
210
|
+
}
|
|
211
|
+
else if (node.kind === SyntaxKind.Identifier) {
|
|
212
|
+
return resolveIdentifier(node, options);
|
|
213
|
+
}
|
|
214
|
+
compilerAssert(false, "Unexpected node kind");
|
|
215
|
+
}
|
|
216
|
+
function resolveMemberExpression(node, options) {
|
|
217
|
+
const baseResult = resolveTypeReference(node.base, {
|
|
218
|
+
...options,
|
|
219
|
+
resolveDecorators: false, // When resolving the base it can never be a decorator
|
|
220
|
+
});
|
|
221
|
+
if (baseResult.resolutionResult & ResolutionResultFlags.ResolutionFailed) {
|
|
222
|
+
return baseResult;
|
|
223
|
+
}
|
|
224
|
+
const baseSym = baseResult.finalSymbol;
|
|
225
|
+
compilerAssert(baseSym, "Base symbol must be defined if resolution did not fail");
|
|
226
|
+
const memberResult = resolveMemberExpressionForSym(baseSym, node, options);
|
|
227
|
+
const idNodeLinks = getNodeLinks(node.id);
|
|
228
|
+
idNodeLinks.resolvedSymbol = memberResult.resolvedSymbol;
|
|
229
|
+
idNodeLinks.resolutionResult = memberResult.resolutionResult;
|
|
230
|
+
const isTemplateInstantiation = baseResult.isTemplateInstantiation || memberResult.isTemplateInstantiation;
|
|
231
|
+
idNodeLinks.isTemplateInstantiation = isTemplateInstantiation;
|
|
232
|
+
return {
|
|
233
|
+
...memberResult,
|
|
234
|
+
isTemplateInstantiation,
|
|
235
|
+
};
|
|
236
|
+
}
|
|
237
|
+
function resolveMemberExpressionForSym(baseSym, node, options = {}) {
|
|
238
|
+
if (node.selector === ".") {
|
|
239
|
+
if (baseSym.flags & 118 /* SymbolFlags.MemberContainer */) {
|
|
240
|
+
return resolveMember(baseSym, node.id);
|
|
241
|
+
}
|
|
242
|
+
else if (baseSym.flags & 131328 /* SymbolFlags.ExportContainer */) {
|
|
243
|
+
const res = resolveExport(getMergedSymbol(baseSym), node.id, options);
|
|
244
|
+
return res;
|
|
245
|
+
}
|
|
246
|
+
}
|
|
247
|
+
else {
|
|
248
|
+
return resolveMetaMember(baseSym, node.id);
|
|
249
|
+
}
|
|
250
|
+
return failedResult(ResolutionResultFlags.NotFound);
|
|
251
|
+
}
|
|
252
|
+
function resolveMember(baseSym, id) {
|
|
253
|
+
const baseNode = baseSym.node ?? baseSym.declarations[0];
|
|
254
|
+
compilerAssert(baseNode, "Base symbol must have an associated node");
|
|
255
|
+
bindMemberContainer(baseNode);
|
|
256
|
+
switch (baseNode.kind) {
|
|
257
|
+
case SyntaxKind.ModelStatement:
|
|
258
|
+
case SyntaxKind.ModelExpression:
|
|
259
|
+
case SyntaxKind.IntersectionExpression:
|
|
260
|
+
return resolveModelMember(baseSym, baseNode, id);
|
|
261
|
+
case SyntaxKind.InterfaceStatement:
|
|
262
|
+
return resolveInterfaceMember(baseSym, id);
|
|
263
|
+
case SyntaxKind.EnumStatement:
|
|
264
|
+
return resolveEnumMember(baseSym, id);
|
|
265
|
+
case SyntaxKind.UnionStatement:
|
|
266
|
+
return resolveUnionVariant(baseSym, id);
|
|
267
|
+
case SyntaxKind.ScalarStatement:
|
|
268
|
+
return resolveScalarConstructor(baseSym, id);
|
|
269
|
+
}
|
|
270
|
+
compilerAssert(false, "Unknown member container kind: " + SyntaxKind[baseNode.kind]);
|
|
271
|
+
}
|
|
272
|
+
function resolvedResult(resolvedSymbol) {
|
|
273
|
+
return {
|
|
274
|
+
resolvedSymbol,
|
|
275
|
+
finalSymbol: resolvedSymbol,
|
|
276
|
+
resolutionResult: ResolutionResultFlags.Resolved,
|
|
277
|
+
};
|
|
278
|
+
}
|
|
279
|
+
function failedResult(resolutionResult) {
|
|
280
|
+
return {
|
|
281
|
+
resolvedSymbol: undefined,
|
|
282
|
+
finalSymbol: undefined,
|
|
283
|
+
resolutionResult,
|
|
284
|
+
};
|
|
285
|
+
}
|
|
286
|
+
function ambiguousResult(symbols) {
|
|
287
|
+
return {
|
|
288
|
+
resolutionResult: ResolutionResultFlags.Ambiguous,
|
|
289
|
+
resolvedSymbol: undefined,
|
|
290
|
+
finalSymbol: undefined,
|
|
291
|
+
ambiguousSymbols: symbols,
|
|
292
|
+
};
|
|
293
|
+
}
|
|
294
|
+
function resolveModelMember(modelSym, modelNode, id) {
|
|
295
|
+
// step 1: check direct members
|
|
296
|
+
// spreads have already been bound
|
|
297
|
+
const memberSym = tableLookup(modelSym.members, id);
|
|
298
|
+
if (memberSym) {
|
|
299
|
+
return resolvedResult(memberSym);
|
|
300
|
+
}
|
|
301
|
+
const modelSymLinks = getSymbolLinks(modelSym);
|
|
302
|
+
// step 2: check extends. Don't look up to extends references if we have
|
|
303
|
+
// unknown members, and resolve any property as unknown if we extend
|
|
304
|
+
// something unknown.
|
|
305
|
+
const extendsRef = modelNode.kind === SyntaxKind.ModelStatement ? modelNode.extends : undefined;
|
|
306
|
+
if (extendsRef &&
|
|
307
|
+
extendsRef.kind === SyntaxKind.TypeReference &&
|
|
308
|
+
!modelSymLinks.hasUnknownMembers) {
|
|
309
|
+
const { finalSymbol: extendsSym, resolutionResult: extendsResult } = resolveTypeReference(extendsRef);
|
|
310
|
+
if (extendsResult & ResolutionResultFlags.Resolved) {
|
|
311
|
+
return resolveMember(extendsSym, id);
|
|
312
|
+
}
|
|
313
|
+
if (extendsResult & ResolutionResultFlags.Unknown) {
|
|
314
|
+
modelSymLinks.hasUnknownMembers = true;
|
|
315
|
+
return failedResult(ResolutionResultFlags.Unknown);
|
|
316
|
+
}
|
|
317
|
+
}
|
|
318
|
+
// step 3: return either unknown or not found depending on whether we have
|
|
319
|
+
// unknown members
|
|
320
|
+
return failedResult(modelSymLinks.hasUnknownMembers
|
|
321
|
+
? ResolutionResultFlags.Unknown
|
|
322
|
+
: ResolutionResultFlags.NotFound);
|
|
323
|
+
}
|
|
324
|
+
function resolveInterfaceMember(ifaceSym, id) {
|
|
325
|
+
const slinks = getSymbolLinks(ifaceSym);
|
|
326
|
+
const memberSym = tableLookup(ifaceSym.members, id);
|
|
327
|
+
if (memberSym) {
|
|
328
|
+
return resolvedResult(memberSym);
|
|
329
|
+
}
|
|
330
|
+
return failedResult(slinks.hasUnknownMembers ? ResolutionResultFlags.Unknown : ResolutionResultFlags.NotFound);
|
|
331
|
+
}
|
|
332
|
+
function resolveEnumMember(enumSym, id) {
|
|
333
|
+
const memberSym = tableLookup(enumSym.members, id);
|
|
334
|
+
if (memberSym) {
|
|
335
|
+
return resolvedResult(memberSym);
|
|
336
|
+
}
|
|
337
|
+
return failedResult(ResolutionResultFlags.NotFound);
|
|
338
|
+
}
|
|
339
|
+
function resolveUnionVariant(unionSym, id) {
|
|
340
|
+
const memberSym = tableLookup(unionSym.members, id);
|
|
341
|
+
if (memberSym) {
|
|
342
|
+
return resolvedResult(memberSym);
|
|
343
|
+
}
|
|
344
|
+
return failedResult(ResolutionResultFlags.NotFound);
|
|
345
|
+
}
|
|
346
|
+
function resolveScalarConstructor(scalarSym, id) {
|
|
347
|
+
const memberSym = tableLookup(scalarSym.members, id);
|
|
348
|
+
if (memberSym) {
|
|
349
|
+
return resolvedResult(memberSym);
|
|
350
|
+
}
|
|
351
|
+
return failedResult(ResolutionResultFlags.NotFound);
|
|
352
|
+
}
|
|
353
|
+
function resolveExport(baseSym, id, options) {
|
|
354
|
+
const node = baseSym.declarations[0];
|
|
355
|
+
compilerAssert(node.kind === SyntaxKind.NamespaceStatement ||
|
|
356
|
+
node.kind === SyntaxKind.TypeSpecScript ||
|
|
357
|
+
node.kind === SyntaxKind.JsNamespaceDeclaration, `Unexpected node kind ${SyntaxKind[node.kind]}`);
|
|
358
|
+
const exportSym = tableLookup(baseSym.exports, id, options.resolveDecorators);
|
|
359
|
+
if (!exportSym) {
|
|
360
|
+
return failedResult(ResolutionResultFlags.NotFound);
|
|
361
|
+
}
|
|
362
|
+
return resolvedResult(exportSym);
|
|
363
|
+
}
|
|
364
|
+
function resolveAlias(node) {
|
|
365
|
+
const symbol = node.symbol;
|
|
366
|
+
const slinks = getSymbolLinks(symbol);
|
|
367
|
+
if (slinks.aliasResolutionResult) {
|
|
368
|
+
return {
|
|
369
|
+
resolutionResult: slinks.aliasResolutionResult,
|
|
370
|
+
resolvedSymbol: slinks.aliasedSymbol,
|
|
371
|
+
finalSymbol: slinks.aliasedSymbol,
|
|
372
|
+
isTemplateInstantiation: slinks.aliasResolutionIsTemplate,
|
|
373
|
+
};
|
|
374
|
+
}
|
|
375
|
+
if (node.value.kind === SyntaxKind.TypeReference) {
|
|
376
|
+
const result = resolveTypeReference(node.value);
|
|
377
|
+
if (result.finalSymbol && result.finalSymbol.flags & 128 /* SymbolFlags.Alias */) {
|
|
378
|
+
const aliasLinks = getSymbolLinks(result.finalSymbol);
|
|
379
|
+
slinks.aliasedSymbol = aliasLinks.aliasedSymbol
|
|
380
|
+
? aliasLinks.aliasedSymbol
|
|
381
|
+
: result.finalSymbol;
|
|
382
|
+
}
|
|
383
|
+
else {
|
|
384
|
+
slinks.aliasedSymbol = result.finalSymbol;
|
|
385
|
+
}
|
|
386
|
+
slinks.aliasResolutionResult = result.resolutionResult;
|
|
387
|
+
slinks.aliasResolutionIsTemplate = result.isTemplateInstantiation;
|
|
388
|
+
return {
|
|
389
|
+
resolvedSymbol: result.resolvedSymbol,
|
|
390
|
+
finalSymbol: slinks.aliasedSymbol,
|
|
391
|
+
resolutionResult: slinks.aliasResolutionResult,
|
|
392
|
+
isTemplateInstantiation: result.isTemplateInstantiation,
|
|
393
|
+
};
|
|
394
|
+
}
|
|
395
|
+
else if (node.value.symbol) {
|
|
396
|
+
// a type literal
|
|
397
|
+
slinks.aliasedSymbol = node.value.symbol;
|
|
398
|
+
slinks.aliasResolutionResult = ResolutionResultFlags.Resolved;
|
|
399
|
+
return resolvedResult(node.value.symbol);
|
|
400
|
+
}
|
|
401
|
+
else {
|
|
402
|
+
// a computed type
|
|
403
|
+
slinks.aliasResolutionResult = ResolutionResultFlags.Unknown;
|
|
404
|
+
return failedResult(ResolutionResultFlags.Unknown);
|
|
405
|
+
}
|
|
406
|
+
}
|
|
407
|
+
function resolveTemplateParameter(node) {
|
|
408
|
+
const symbol = node.symbol;
|
|
409
|
+
const slinks = getSymbolLinks(symbol);
|
|
410
|
+
if (!node.constraint) {
|
|
411
|
+
return resolvedResult(node.symbol);
|
|
412
|
+
}
|
|
413
|
+
if (slinks.constraintResolutionResult) {
|
|
414
|
+
return {
|
|
415
|
+
finalSymbol: slinks.constraintSymbol,
|
|
416
|
+
resolvedSymbol: slinks.constraintSymbol,
|
|
417
|
+
resolutionResult: slinks.constraintResolutionResult,
|
|
418
|
+
};
|
|
419
|
+
}
|
|
420
|
+
if (node.constraint && node.constraint.kind === SyntaxKind.TypeReference) {
|
|
421
|
+
const result = resolveTypeReference(node.constraint);
|
|
422
|
+
slinks.constraintSymbol = result.finalSymbol;
|
|
423
|
+
slinks.constraintResolutionResult = result.resolutionResult;
|
|
424
|
+
return result;
|
|
425
|
+
}
|
|
426
|
+
else if (node.constraint.symbol) {
|
|
427
|
+
// a type literal
|
|
428
|
+
slinks.constraintSymbol = node.constraint.symbol;
|
|
429
|
+
slinks.constraintResolutionResult = ResolutionResultFlags.Resolved;
|
|
430
|
+
return resolvedResult(node.constraint.symbol);
|
|
431
|
+
}
|
|
432
|
+
else {
|
|
433
|
+
// a computed type, just resolve to the template parameter symbol itself.
|
|
434
|
+
slinks.constraintSymbol = node.symbol;
|
|
435
|
+
slinks.constraintResolutionResult = ResolutionResultFlags.Resolved;
|
|
436
|
+
return resolvedResult(node.symbol);
|
|
437
|
+
}
|
|
438
|
+
}
|
|
439
|
+
function resolveExpression(node) {
|
|
440
|
+
if (node.kind === SyntaxKind.TypeReference) {
|
|
441
|
+
return resolveTypeReference(node);
|
|
442
|
+
}
|
|
443
|
+
if (node.symbol) {
|
|
444
|
+
return resolvedResult(node.symbol);
|
|
445
|
+
}
|
|
446
|
+
return failedResult(ResolutionResultFlags.Unknown);
|
|
447
|
+
}
|
|
448
|
+
function resolveMetaMember(baseSym, id) {
|
|
449
|
+
return resolveMetaMemberByName(baseSym, id.sv);
|
|
450
|
+
}
|
|
451
|
+
function resolveMetaMemberByName(baseSym, sv) {
|
|
452
|
+
const baseNode = getSymNode(baseSym);
|
|
453
|
+
const prototype = metaTypePrototypes.get(baseNode.kind);
|
|
454
|
+
if (!prototype) {
|
|
455
|
+
return failedResult(ResolutionResultFlags.NotFound);
|
|
456
|
+
}
|
|
457
|
+
const getter = prototype.get(sv);
|
|
458
|
+
if (!getter) {
|
|
459
|
+
return failedResult(ResolutionResultFlags.NotFound);
|
|
460
|
+
}
|
|
461
|
+
return getter(baseSym);
|
|
462
|
+
}
|
|
463
|
+
function tableLookup(table, node, resolveDecorator = false) {
|
|
464
|
+
table = augmentedSymbolTables.get(table) ?? table;
|
|
465
|
+
let sym;
|
|
466
|
+
if (resolveDecorator) {
|
|
467
|
+
sym = table.get("@" + node.sv);
|
|
468
|
+
}
|
|
469
|
+
else {
|
|
470
|
+
sym = table.get(node.sv);
|
|
471
|
+
}
|
|
472
|
+
if (!sym)
|
|
473
|
+
return sym;
|
|
474
|
+
return getMergedSymbol(sym);
|
|
475
|
+
}
|
|
476
|
+
/**
|
|
477
|
+
* This method will take a member container and compute all the known member
|
|
478
|
+
* symbols. It will determine whether it has unknown members and set the
|
|
479
|
+
* symbol link value appropriately. This is used during resolution to know if
|
|
480
|
+
* member resolution should return `unknown` when a member isn't found.
|
|
481
|
+
*/
|
|
482
|
+
function bindMemberContainer(node) {
|
|
483
|
+
const sym = node.symbol;
|
|
484
|
+
const symLinks = getSymbolLinks(sym);
|
|
485
|
+
if (symLinks.membersBound) {
|
|
486
|
+
return;
|
|
487
|
+
}
|
|
488
|
+
symLinks.membersBound = true;
|
|
489
|
+
switch (node.kind) {
|
|
490
|
+
case SyntaxKind.ModelStatement:
|
|
491
|
+
case SyntaxKind.ModelExpression:
|
|
492
|
+
bindModelMembers(node);
|
|
493
|
+
return;
|
|
494
|
+
case SyntaxKind.IntersectionExpression:
|
|
495
|
+
bindIntersectionMembers(node);
|
|
496
|
+
return;
|
|
497
|
+
case SyntaxKind.InterfaceStatement:
|
|
498
|
+
bindInterfaceMembers(node);
|
|
499
|
+
return;
|
|
500
|
+
case SyntaxKind.EnumStatement:
|
|
501
|
+
bindEnumMembers(node);
|
|
502
|
+
return;
|
|
503
|
+
case SyntaxKind.UnionStatement:
|
|
504
|
+
bindUnionMembers(node);
|
|
505
|
+
return;
|
|
506
|
+
case SyntaxKind.ScalarStatement:
|
|
507
|
+
bindScalarMembers(node);
|
|
508
|
+
return;
|
|
509
|
+
}
|
|
510
|
+
}
|
|
511
|
+
// TODO: had to keep the metaTypeMembers which this pr originally tried to get rid as we need for ops parameters to be cloned and have a new reference
|
|
512
|
+
function bindOperationStatementParameters(node) {
|
|
513
|
+
const targetTable = getAugmentedSymbolTable(node.symbol.metatypeMembers);
|
|
514
|
+
if (node.signature.kind === SyntaxKind.OperationSignatureDeclaration) {
|
|
515
|
+
const { finalSymbol: sym } = resolveExpression(node.signature.parameters);
|
|
516
|
+
if (sym) {
|
|
517
|
+
targetTable.set("parameters", sym);
|
|
518
|
+
}
|
|
519
|
+
}
|
|
520
|
+
else {
|
|
521
|
+
const { finalSymbol: sig } = resolveTypeReference(node.signature.baseOperation);
|
|
522
|
+
if (sig) {
|
|
523
|
+
const sigTable = getAugmentedSymbolTable(sig.metatypeMembers);
|
|
524
|
+
const sigParameterSym = sigTable.get("parameters");
|
|
525
|
+
if (sigParameterSym !== undefined) {
|
|
526
|
+
const parametersSym = createSymbol(sigParameterSym.node, "parameters", 2 /* SymbolFlags.Model */ & 118 /* SymbolFlags.MemberContainer */);
|
|
527
|
+
getAugmentedSymbolTable(parametersSym.members).include(getAugmentedSymbolTable(sigParameterSym.members), parametersSym);
|
|
528
|
+
targetTable.set("parameters", parametersSym);
|
|
529
|
+
targetTable.set("returnType", sigTable.get("returnType"));
|
|
530
|
+
}
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
}
|
|
534
|
+
function bindDeclarationIdentifier(node) {
|
|
535
|
+
if (node.kind === SyntaxKind.TypeSpecScript || node.kind === SyntaxKind.JsSourceFile)
|
|
536
|
+
return;
|
|
537
|
+
const links = getNodeLinks(node.id);
|
|
538
|
+
let sym;
|
|
539
|
+
if (node.symbol === undefined) {
|
|
540
|
+
return;
|
|
541
|
+
}
|
|
542
|
+
if (node.symbol.flags & 262144 /* SymbolFlags.Member */) {
|
|
543
|
+
compilerAssert(node.parent, "Node should have a parent");
|
|
544
|
+
const parentSym = getMergedSymbol(node.parent.symbol);
|
|
545
|
+
const table = parentSym.exports ?? getAugmentedSymbolTable(parentSym.members);
|
|
546
|
+
sym = table.get(node.id.sv);
|
|
547
|
+
}
|
|
548
|
+
else {
|
|
549
|
+
sym = node.symbol;
|
|
550
|
+
}
|
|
551
|
+
compilerAssert(sym, "Should have a symbol");
|
|
552
|
+
links.resolvedSymbol = sym;
|
|
553
|
+
links.resolutionResult = ResolutionResultFlags.Resolved;
|
|
554
|
+
}
|
|
555
|
+
function bindModelMembers(node) {
|
|
556
|
+
const modelSym = node.symbol;
|
|
557
|
+
const modelSymLinks = getSymbolLinks(modelSym);
|
|
558
|
+
const targetTable = getAugmentedSymbolTable(modelSym.members);
|
|
559
|
+
const isRef = node.kind === SyntaxKind.ModelStatement ? node.is : undefined;
|
|
560
|
+
if (isRef && isRef.kind === SyntaxKind.TypeReference) {
|
|
561
|
+
const { finalSymbol: isSym, resolutionResult: isResult } = resolveTypeReference(isRef);
|
|
562
|
+
setUnknownMembers(modelSymLinks, isSym, isResult);
|
|
563
|
+
if (isResult & ResolutionResultFlags.Resolved && isSym.flags & 2 /* SymbolFlags.Model */) {
|
|
564
|
+
const sourceTable = getAugmentedSymbolTable(isSym.members);
|
|
565
|
+
targetTable.include(sourceTable, modelSym);
|
|
566
|
+
}
|
|
567
|
+
}
|
|
568
|
+
// here we just need to check if we're extending something with unknown symbols
|
|
569
|
+
const extendsRef = node.kind === SyntaxKind.ModelStatement ? node.extends : undefined;
|
|
570
|
+
if (extendsRef && extendsRef.kind === SyntaxKind.TypeReference) {
|
|
571
|
+
const { finalSymbol: sym, resolutionResult: result } = resolveTypeReference(extendsRef);
|
|
572
|
+
setUnknownMembers(modelSymLinks, sym, result);
|
|
573
|
+
}
|
|
574
|
+
// here we just need to include spread properties, since regular properties
|
|
575
|
+
// were bound by the binder.
|
|
576
|
+
for (const propertyNode of node.properties) {
|
|
577
|
+
if (propertyNode.kind !== SyntaxKind.ModelSpreadProperty) {
|
|
578
|
+
continue;
|
|
579
|
+
}
|
|
580
|
+
const { finalSymbol: sourceSym, resolutionResult: sourceResult } = resolveTypeReference(propertyNode.target);
|
|
581
|
+
setUnknownMembers(modelSymLinks, sourceSym, sourceResult);
|
|
582
|
+
if (~sourceResult & ResolutionResultFlags.Resolved) {
|
|
583
|
+
continue;
|
|
584
|
+
}
|
|
585
|
+
compilerAssert(sourceSym, "Spread symbol must be defined if resolution succeeded");
|
|
586
|
+
if (~sourceSym.flags & 2 /* SymbolFlags.Model */) {
|
|
587
|
+
// will be a checker error
|
|
588
|
+
continue;
|
|
589
|
+
}
|
|
590
|
+
const sourceTable = getAugmentedSymbolTable(sourceSym.members);
|
|
591
|
+
targetTable.include(sourceTable, modelSym);
|
|
592
|
+
}
|
|
593
|
+
}
|
|
594
|
+
function bindIntersectionMembers(node) {
|
|
595
|
+
const intersectionSym = node.symbol;
|
|
596
|
+
const intersectionSymLinks = getSymbolLinks(intersectionSym);
|
|
597
|
+
const targetTable = getAugmentedSymbolTable(intersectionSym.members);
|
|
598
|
+
// here we just need to include spread properties, since regular properties
|
|
599
|
+
// were bound by the binder.
|
|
600
|
+
for (const expr of node.options) {
|
|
601
|
+
const { finalSymbol: sourceSym, resolutionResult: sourceResult } = resolveExpression(expr);
|
|
602
|
+
setUnknownMembers(intersectionSymLinks, sourceSym, sourceResult);
|
|
603
|
+
if (~sourceResult & ResolutionResultFlags.Resolved) {
|
|
604
|
+
continue;
|
|
605
|
+
}
|
|
606
|
+
compilerAssert(sourceSym, "Spread symbol must be defined if resolution succeeded");
|
|
607
|
+
if (~sourceSym.flags & 2 /* SymbolFlags.Model */) {
|
|
608
|
+
// will be a checker error
|
|
609
|
+
continue;
|
|
610
|
+
}
|
|
611
|
+
const sourceTable = getAugmentedSymbolTable(sourceSym.members);
|
|
612
|
+
targetTable.include(sourceTable, intersectionSym);
|
|
613
|
+
}
|
|
614
|
+
}
|
|
615
|
+
function setUnknownMembers(targetSymLinks, sym, result) {
|
|
616
|
+
if (result & ResolutionResultFlags.Unknown) {
|
|
617
|
+
targetSymLinks.hasUnknownMembers = true;
|
|
618
|
+
}
|
|
619
|
+
else if (result & ResolutionResultFlags.Resolved) {
|
|
620
|
+
const isSymLinks = getSymbolLinks(sym);
|
|
621
|
+
if (isSymLinks.hasUnknownMembers) {
|
|
622
|
+
targetSymLinks.hasUnknownMembers = true;
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
function bindInterfaceMembers(node) {
|
|
627
|
+
const ifaceSym = node.symbol;
|
|
628
|
+
const ifaceSymLinks = getSymbolLinks(ifaceSym);
|
|
629
|
+
for (const extendsRef of node.extends) {
|
|
630
|
+
const { finalSymbol: extendsSym, resolutionResult: extendsResult } = resolveTypeReference(extendsRef);
|
|
631
|
+
setUnknownMembers(ifaceSymLinks, extendsSym, extendsResult);
|
|
632
|
+
if (~extendsResult & ResolutionResultFlags.Resolved) {
|
|
633
|
+
continue;
|
|
634
|
+
}
|
|
635
|
+
compilerAssert(extendsSym, "Extends symbol must be defined if resolution succeeded");
|
|
636
|
+
if (~extendsSym.flags & 32 /* SymbolFlags.Interface */) {
|
|
637
|
+
// will be a checker error
|
|
638
|
+
continue;
|
|
639
|
+
}
|
|
640
|
+
const sourceTable = getAugmentedSymbolTable(extendsSym.members);
|
|
641
|
+
const targetTable = getAugmentedSymbolTable(ifaceSym.members);
|
|
642
|
+
targetTable.include(sourceTable, ifaceSym);
|
|
643
|
+
}
|
|
644
|
+
}
|
|
645
|
+
function bindEnumMembers(node) {
|
|
646
|
+
const enumSym = node.symbol;
|
|
647
|
+
const enumSymLinks = getSymbolLinks(enumSym);
|
|
648
|
+
const targetTable = getAugmentedSymbolTable(enumSym.members);
|
|
649
|
+
for (const memberNode of node.members) {
|
|
650
|
+
if (memberNode.kind !== SyntaxKind.EnumSpreadMember) {
|
|
651
|
+
continue;
|
|
652
|
+
}
|
|
653
|
+
const { finalSymbol: sourceSym, resolutionResult: sourceResult } = resolveTypeReference(memberNode.target);
|
|
654
|
+
setUnknownMembers(enumSymLinks, sourceSym, sourceResult);
|
|
655
|
+
if (~sourceResult & ResolutionResultFlags.Resolved) {
|
|
656
|
+
continue;
|
|
657
|
+
}
|
|
658
|
+
compilerAssert(sourceSym, "Spread symbol must be defined if resolution succeeded");
|
|
659
|
+
if (~sourceSym.flags & 16 /* SymbolFlags.Enum */) {
|
|
660
|
+
// will be a checker error
|
|
661
|
+
continue;
|
|
662
|
+
}
|
|
663
|
+
const sourceTable = getAugmentedSymbolTable(sourceSym.members);
|
|
664
|
+
targetTable.include(sourceTable, enumSym);
|
|
665
|
+
}
|
|
666
|
+
}
|
|
667
|
+
function bindUnionMembers(node) {
|
|
668
|
+
// Everything is already bound in binder.ts
|
|
669
|
+
}
|
|
670
|
+
function bindScalarMembers(node) {
|
|
671
|
+
const scalarSym = node.symbol;
|
|
672
|
+
const targetTable = getAugmentedSymbolTable(scalarSym.members);
|
|
673
|
+
const scalarSymLinks = getSymbolLinks(scalarSym);
|
|
674
|
+
if (node.extends) {
|
|
675
|
+
const { finalSymbol: extendsSym, resolutionResult: extendsResult } = resolveTypeReference(node.extends);
|
|
676
|
+
setUnknownMembers(scalarSymLinks, extendsSym, extendsResult);
|
|
677
|
+
if (~extendsResult & ResolutionResultFlags.Resolved) {
|
|
678
|
+
return;
|
|
679
|
+
}
|
|
680
|
+
compilerAssert(extendsSym, "Scalar extends symbol must be defined if resolution succeeded");
|
|
681
|
+
const sourceTable = getAugmentedSymbolTable(extendsSym.members);
|
|
682
|
+
targetTable.include(sourceTable, scalarSym);
|
|
683
|
+
}
|
|
684
|
+
}
|
|
685
|
+
function bindTemplateParameter(node) {
|
|
686
|
+
const sym = node.symbol;
|
|
687
|
+
const links = getSymbolLinks(sym);
|
|
688
|
+
links.hasUnknownMembers = true;
|
|
689
|
+
}
|
|
690
|
+
function resolveIdentifier(node, options) {
|
|
691
|
+
let scope = node.parent;
|
|
692
|
+
let binding;
|
|
693
|
+
while (scope && scope.kind !== SyntaxKind.TypeSpecScript) {
|
|
694
|
+
if (scope.symbol && scope.symbol.flags & 131328 /* SymbolFlags.ExportContainer */) {
|
|
695
|
+
const mergedSymbol = getMergedSymbol(scope.symbol);
|
|
696
|
+
binding = tableLookup(mergedSymbol.exports, node, options.resolveDecorators);
|
|
697
|
+
if (binding)
|
|
698
|
+
return resolvedResult(binding);
|
|
699
|
+
}
|
|
700
|
+
if ("locals" in scope && scope.locals !== undefined) {
|
|
701
|
+
binding = tableLookup(scope.locals, node, options.resolveDecorators);
|
|
702
|
+
if (binding) {
|
|
703
|
+
return resolvedResult(binding);
|
|
704
|
+
}
|
|
705
|
+
}
|
|
706
|
+
scope = scope.parent;
|
|
707
|
+
}
|
|
708
|
+
if (!binding && scope && scope.kind === SyntaxKind.TypeSpecScript) {
|
|
709
|
+
// check any blockless namespace decls
|
|
710
|
+
for (const ns of scope.inScopeNamespaces) {
|
|
711
|
+
const mergedSymbol = getMergedSymbol(ns.symbol);
|
|
712
|
+
binding = tableLookup(mergedSymbol.exports, node, options.resolveDecorators);
|
|
713
|
+
if (binding)
|
|
714
|
+
return resolvedResult(binding);
|
|
715
|
+
}
|
|
716
|
+
// check "global scope" declarations
|
|
717
|
+
const globalBinding = tableLookup(globalNamespaceNode.symbol.exports, node, options.resolveDecorators);
|
|
718
|
+
// check using types
|
|
719
|
+
const usingBinding = tableLookup(scope.locals, node, options.resolveDecorators);
|
|
720
|
+
if (globalBinding && usingBinding) {
|
|
721
|
+
return ambiguousResult([globalBinding, usingBinding]);
|
|
722
|
+
}
|
|
723
|
+
else if (globalBinding) {
|
|
724
|
+
return resolvedResult(globalBinding);
|
|
725
|
+
}
|
|
726
|
+
else if (usingBinding) {
|
|
727
|
+
if (usingBinding.flags & 65536 /* SymbolFlags.DuplicateUsing */) {
|
|
728
|
+
return ambiguousResult([
|
|
729
|
+
...(augmentedSymbolTables.get(scope.locals)?.duplicates.get(usingBinding) ??
|
|
730
|
+
[]),
|
|
731
|
+
]);
|
|
732
|
+
}
|
|
733
|
+
return resolvedResult(usingBinding.symbolSource);
|
|
734
|
+
}
|
|
735
|
+
}
|
|
736
|
+
return failedResult(ResolutionResultFlags.Unknown);
|
|
737
|
+
}
|
|
738
|
+
/**
|
|
739
|
+
* We cannot inject symbols into the symbol tables hanging off syntax tree nodes as
|
|
740
|
+
* syntax tree nodes can be shared by other programs. This is called as a copy-on-write
|
|
741
|
+
* to inject using and late-bound symbols, and then we use the copy when resolving
|
|
742
|
+
* in the table.
|
|
743
|
+
*/
|
|
744
|
+
function getAugmentedSymbolTable(table) {
|
|
745
|
+
let augmented = augmentedSymbolTables.get(table);
|
|
746
|
+
if (!augmented) {
|
|
747
|
+
augmented = createSymbolTable(table);
|
|
748
|
+
augmentedSymbolTables.set(table, augmented);
|
|
749
|
+
}
|
|
750
|
+
return mutate(augmented);
|
|
751
|
+
}
|
|
752
|
+
function mergeSymbolTable(source, target) {
|
|
753
|
+
for (const [sym, duplicates] of source.duplicates) {
|
|
754
|
+
const targetSet = target.duplicates.get(sym);
|
|
755
|
+
if (targetSet === undefined) {
|
|
756
|
+
mutate(target.duplicates).set(sym, new Set([...duplicates]));
|
|
757
|
+
}
|
|
758
|
+
else {
|
|
759
|
+
for (const duplicate of duplicates) {
|
|
760
|
+
mutate(targetSet).add(duplicate);
|
|
761
|
+
}
|
|
762
|
+
}
|
|
763
|
+
}
|
|
764
|
+
for (const [key, sourceBinding] of source) {
|
|
765
|
+
if (sourceBinding.flags & 256 /* SymbolFlags.Namespace */) {
|
|
766
|
+
let targetBinding = target.get(key);
|
|
767
|
+
if (!targetBinding) {
|
|
768
|
+
targetBinding = {
|
|
769
|
+
...sourceBinding,
|
|
770
|
+
declarations: [],
|
|
771
|
+
exports: createSymbolTable(),
|
|
772
|
+
};
|
|
773
|
+
target.set(key, targetBinding);
|
|
774
|
+
}
|
|
775
|
+
if (targetBinding.flags & 256 /* SymbolFlags.Namespace */) {
|
|
776
|
+
mergedSymbols.set(sourceBinding, targetBinding);
|
|
777
|
+
mutate(targetBinding.declarations).push(...sourceBinding.declarations);
|
|
778
|
+
mergeSymbolTable(sourceBinding.exports, mutate(targetBinding.exports));
|
|
779
|
+
}
|
|
780
|
+
else {
|
|
781
|
+
// this will set a duplicate error
|
|
782
|
+
target.set(key, sourceBinding);
|
|
783
|
+
}
|
|
784
|
+
}
|
|
785
|
+
else if (sourceBinding.flags & 1024 /* SymbolFlags.Decorator */) {
|
|
786
|
+
mergeDeclarationOrImplementation(key, sourceBinding, target, 1024 /* SymbolFlags.Decorator */);
|
|
787
|
+
}
|
|
788
|
+
else if (sourceBinding.flags & 8192 /* SymbolFlags.Function */) {
|
|
789
|
+
mergeDeclarationOrImplementation(key, sourceBinding, target, 8192 /* SymbolFlags.Function */);
|
|
790
|
+
}
|
|
791
|
+
else {
|
|
792
|
+
target.set(key, sourceBinding);
|
|
793
|
+
}
|
|
794
|
+
}
|
|
795
|
+
}
|
|
796
|
+
function mergeDeclarationOrImplementation(key, sourceBinding, target, expectTargetFlags) {
|
|
797
|
+
const targetBinding = target.get(key);
|
|
798
|
+
if (!targetBinding || !(targetBinding.flags & expectTargetFlags)) {
|
|
799
|
+
target.set(key, sourceBinding);
|
|
800
|
+
return;
|
|
801
|
+
}
|
|
802
|
+
const isSourceImplementation = sourceBinding.flags & 2097152 /* SymbolFlags.Implementation */;
|
|
803
|
+
const isTargetImplementation = targetBinding.flags & 2097152 /* SymbolFlags.Implementation */;
|
|
804
|
+
if (!isTargetImplementation && isSourceImplementation) {
|
|
805
|
+
mergedSymbols.set(sourceBinding, targetBinding);
|
|
806
|
+
mutate(targetBinding).value = sourceBinding.value;
|
|
807
|
+
mutate(targetBinding).flags |= sourceBinding.flags;
|
|
808
|
+
mutate(targetBinding.declarations).push(...sourceBinding.declarations);
|
|
809
|
+
}
|
|
810
|
+
else if (isTargetImplementation && !isSourceImplementation) {
|
|
811
|
+
mergedSymbols.set(sourceBinding, targetBinding);
|
|
812
|
+
mutate(targetBinding).flags |= sourceBinding.flags;
|
|
813
|
+
mutate(targetBinding.declarations).unshift(...sourceBinding.declarations);
|
|
814
|
+
}
|
|
815
|
+
else {
|
|
816
|
+
// this will set a duplicate error
|
|
817
|
+
target.set(key, sourceBinding);
|
|
818
|
+
}
|
|
819
|
+
}
|
|
820
|
+
function setUsingsForFile(file) {
|
|
821
|
+
const usedUsing = new Map();
|
|
822
|
+
function isAlreadyAddedIn(sym, target) {
|
|
823
|
+
let current = sym;
|
|
824
|
+
while (current) {
|
|
825
|
+
if (usedUsing.get(sym)?.has(target)) {
|
|
826
|
+
return true;
|
|
827
|
+
}
|
|
828
|
+
current = current.parent;
|
|
829
|
+
}
|
|
830
|
+
let usingForScope = usedUsing.get(sym);
|
|
831
|
+
if (usingForScope === undefined) {
|
|
832
|
+
usingForScope = new Set();
|
|
833
|
+
usedUsing.set(sym, usingForScope);
|
|
834
|
+
}
|
|
835
|
+
usingForScope.add(target);
|
|
836
|
+
return false;
|
|
837
|
+
}
|
|
838
|
+
for (const using of file.usings) {
|
|
839
|
+
const parentNs = using.parent;
|
|
840
|
+
const { finalSymbol: usedSym, resolutionResult: usedSymResult } = resolveTypeReference(using.name);
|
|
841
|
+
if (~usedSymResult & ResolutionResultFlags.Resolved) {
|
|
842
|
+
continue; // Keep going and count on checker to report those errors.
|
|
843
|
+
}
|
|
844
|
+
compilerAssert(usedSym, "Used symbol must be defined if resolution succeeded");
|
|
845
|
+
if (~usedSym.flags & 256 /* SymbolFlags.Namespace */) {
|
|
846
|
+
continue; // Keep going and count on checker to report those errors.
|
|
847
|
+
}
|
|
848
|
+
const namespaceSym = getMergedSymbol(usedSym);
|
|
849
|
+
if (isAlreadyAddedIn(getMergedSymbol(parentNs.symbol), namespaceSym)) {
|
|
850
|
+
continue;
|
|
851
|
+
}
|
|
852
|
+
addUsingSymbols(namespaceSym.exports, parentNs.locals);
|
|
853
|
+
}
|
|
854
|
+
}
|
|
855
|
+
function addUsingSymbols(source, destination) {
|
|
856
|
+
const augmented = getAugmentedSymbolTable(destination);
|
|
857
|
+
for (const symbolSource of source.values()) {
|
|
858
|
+
const sym = {
|
|
859
|
+
flags: 32768 /* SymbolFlags.Using */,
|
|
860
|
+
declarations: [],
|
|
861
|
+
name: symbolSource.name,
|
|
862
|
+
symbolSource: symbolSource,
|
|
863
|
+
node: undefined,
|
|
864
|
+
};
|
|
865
|
+
augmented.set(sym.name, sym);
|
|
866
|
+
}
|
|
867
|
+
}
|
|
868
|
+
function createGlobalNamespaceNode() {
|
|
869
|
+
const nsId = {
|
|
870
|
+
kind: SyntaxKind.Identifier,
|
|
871
|
+
pos: 0,
|
|
872
|
+
end: 0,
|
|
873
|
+
sv: "global",
|
|
874
|
+
symbol: undefined,
|
|
875
|
+
flags: 8 /* NodeFlags.Synthetic */,
|
|
876
|
+
};
|
|
877
|
+
const nsNode = {
|
|
878
|
+
kind: SyntaxKind.NamespaceStatement,
|
|
879
|
+
decorators: [],
|
|
880
|
+
pos: 0,
|
|
881
|
+
end: 0,
|
|
882
|
+
id: nsId,
|
|
883
|
+
symbol: undefined,
|
|
884
|
+
locals: createSymbolTable(),
|
|
885
|
+
flags: 8 /* NodeFlags.Synthetic */,
|
|
886
|
+
};
|
|
887
|
+
return nsNode;
|
|
888
|
+
}
|
|
889
|
+
function bindAndResolveNode(node) {
|
|
890
|
+
switch (node.kind) {
|
|
891
|
+
case SyntaxKind.TypeReference:
|
|
892
|
+
resolveTypeReference(node);
|
|
893
|
+
break;
|
|
894
|
+
case SyntaxKind.ModelStatement:
|
|
895
|
+
case SyntaxKind.ModelExpression:
|
|
896
|
+
case SyntaxKind.InterfaceStatement:
|
|
897
|
+
case SyntaxKind.EnumStatement:
|
|
898
|
+
case SyntaxKind.ScalarStatement:
|
|
899
|
+
case SyntaxKind.UnionStatement:
|
|
900
|
+
case SyntaxKind.IntersectionExpression:
|
|
901
|
+
bindMemberContainer(node);
|
|
902
|
+
break;
|
|
903
|
+
case SyntaxKind.OperationStatement:
|
|
904
|
+
bindOperationStatementParameters(node);
|
|
905
|
+
break;
|
|
906
|
+
case SyntaxKind.AliasStatement:
|
|
907
|
+
resolveAlias(node);
|
|
908
|
+
break;
|
|
909
|
+
case SyntaxKind.TemplateParameterDeclaration:
|
|
910
|
+
bindTemplateParameter(node);
|
|
911
|
+
break;
|
|
912
|
+
case SyntaxKind.DecoratorExpression:
|
|
913
|
+
case SyntaxKind.ProjectionDecoratorReferenceExpression:
|
|
914
|
+
resolveDecoratorTarget(node);
|
|
915
|
+
break;
|
|
916
|
+
case SyntaxKind.AugmentDecoratorStatement:
|
|
917
|
+
resolveAugmentDecorator(node);
|
|
918
|
+
break;
|
|
919
|
+
case SyntaxKind.CallExpression:
|
|
920
|
+
resolveTypeReference(node.target);
|
|
921
|
+
break;
|
|
922
|
+
case SyntaxKind.ProjectionStatement:
|
|
923
|
+
resolveProjection(node);
|
|
924
|
+
break;
|
|
925
|
+
}
|
|
926
|
+
if ("id" in node && node.kind !== SyntaxKind.MemberExpression && node.id) {
|
|
927
|
+
bindDeclarationIdentifier(node);
|
|
928
|
+
}
|
|
929
|
+
visitChildren(node, bindAndResolveNode);
|
|
930
|
+
}
|
|
931
|
+
function resolveProjection(projection) {
|
|
932
|
+
switch (projection.selector.kind) {
|
|
933
|
+
case SyntaxKind.Identifier:
|
|
934
|
+
case SyntaxKind.MemberExpression:
|
|
935
|
+
resolveTypeReference(projection.selector);
|
|
936
|
+
}
|
|
937
|
+
}
|
|
938
|
+
function resolveDecoratorTarget(decorator) {
|
|
939
|
+
resolveTypeReference(decorator.target, { resolveDecorators: true });
|
|
940
|
+
}
|
|
941
|
+
function createMetaTypePrototypes() {
|
|
942
|
+
const nodeInterfaces = new Map();
|
|
943
|
+
// model properties
|
|
944
|
+
const modelPropertyPrototype = new Map();
|
|
945
|
+
modelPropertyPrototype.set("type", (baseSym) => {
|
|
946
|
+
const node = baseSym.node;
|
|
947
|
+
return resolveExpression(node.value);
|
|
948
|
+
});
|
|
949
|
+
nodeInterfaces.set(SyntaxKind.ModelProperty, modelPropertyPrototype);
|
|
950
|
+
// operations
|
|
951
|
+
const operationPrototype = new Map();
|
|
952
|
+
// For parameters it is a cloned symbol as all the params are spread
|
|
953
|
+
operationPrototype.set("parameters", (baseSym) => {
|
|
954
|
+
const sym = getAugmentedSymbolTable(baseSym.metatypeMembers)?.get("parameters");
|
|
955
|
+
return sym === undefined
|
|
956
|
+
? failedResult(ResolutionResultFlags.ResolutionFailed)
|
|
957
|
+
: resolvedResult(sym);
|
|
958
|
+
});
|
|
959
|
+
// For returnType we just return the reference so we can just do it dynamically
|
|
960
|
+
operationPrototype.set("returnType", (baseSym) => {
|
|
961
|
+
let node = baseSym.declarations[0];
|
|
962
|
+
while (node.signature.kind === SyntaxKind.OperationSignatureReference) {
|
|
963
|
+
const baseResult = resolveTypeReference(node.signature.baseOperation);
|
|
964
|
+
if (baseResult.resolutionResult & ResolutionResultFlags.Resolved) {
|
|
965
|
+
node = baseSym.declarations[0];
|
|
966
|
+
}
|
|
967
|
+
else {
|
|
968
|
+
return baseResult;
|
|
969
|
+
}
|
|
970
|
+
}
|
|
971
|
+
return resolveExpression(node.signature.returnType);
|
|
972
|
+
});
|
|
973
|
+
nodeInterfaces.set(SyntaxKind.OperationStatement, operationPrototype);
|
|
974
|
+
return nodeInterfaces;
|
|
975
|
+
}
|
|
976
|
+
function resolveAugmentDecorator(decNode) {
|
|
977
|
+
resolveTypeReference(decNode.target, { resolveDecorators: true });
|
|
978
|
+
const targetResult = resolveTypeReference(decNode.targetType);
|
|
979
|
+
if (targetResult.resolvedSymbol && !targetResult.isTemplateInstantiation) {
|
|
980
|
+
let list = augmentDecoratorsForSym.get(targetResult.resolvedSymbol);
|
|
981
|
+
if (list === undefined) {
|
|
982
|
+
list = [];
|
|
983
|
+
augmentDecoratorsForSym.set(targetResult.resolvedSymbol, list);
|
|
984
|
+
}
|
|
985
|
+
list.unshift(decNode);
|
|
986
|
+
}
|
|
987
|
+
}
|
|
988
|
+
}
|
|
989
|
+
//# sourceMappingURL=name-resolver.js.map
|