@typespec/compiler 0.62.0-dev.11 → 0.62.0-dev.12
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/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 +319 -814
- package/dist/src/core/checker.js.map +1 -1
- package/dist/src/core/diagnostics.js +2 -2
- 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/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/messages.d.ts +17 -43
- package/dist/src/core/messages.d.ts.map +1 -1
- package/dist/src/core/messages.js +3 -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 +9 -5
- 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 +140 -34
- 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/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/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/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/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 +2 -4
- 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/package.json +3 -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
package/dist/src/core/checker.js
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
|
-
import {
|
|
1
|
+
import { docFromCommentDecorator, getIndexer } from "../lib/intrinsic/decorators.js";
|
|
2
|
+
import { DuplicateTracker } from "../utils/duplicate-tracker.js";
|
|
2
3
|
import { MultiKeyMap, createRekeyableMap, isArray, mutate } from "../utils/misc.js";
|
|
3
|
-
import { createSymbol,
|
|
4
|
+
import { createSymbol, getSymNode } from "./binder.js";
|
|
4
5
|
import { createChangeIdentifierCodeFix } from "./compiler-code-fixes/change-identifier.codefix.js";
|
|
5
6
|
import { createModelToObjectValueCodeFix } from "./compiler-code-fixes/model-to-object-literal.codefix.js";
|
|
6
7
|
import { createTupleToArrayValueCodeFix } from "./compiler-code-fixes/tuple-to-array-value.codefix.js";
|
|
@@ -9,6 +10,7 @@ import { ProjectionError, compilerAssert, ignoreDiagnostics } from "./diagnostic
|
|
|
9
10
|
import { validateInheritanceDiscriminatedUnions } from "./helpers/discriminator-utils.js";
|
|
10
11
|
import { getLocationContext } from "./helpers/location-context.js";
|
|
11
12
|
import { explainStringTemplateNotSerializable } from "./helpers/string-template-utils.js";
|
|
13
|
+
import { typeReferenceToString } from "./helpers/syntax-utils.js";
|
|
12
14
|
import { getEntityName, getNamespaceFullName, getTypeName, } from "./helpers/type-name-utils.js";
|
|
13
15
|
import { legacyMarshallTypeForJS, marshallTypeForJS } from "./js-marshaller.js";
|
|
14
16
|
import { createDiagnostic } from "./messages.js";
|
|
@@ -17,20 +19,15 @@ import { exprIsBareIdentifier, getFirstAncestor, getIdentifierContext, hasParseE
|
|
|
17
19
|
import { createProjectionMembers } from "./projection-members.js";
|
|
18
20
|
import { createTypeRelationChecker } from "./type-relation-checker.js";
|
|
19
21
|
import { getFullyQualifiedSymbolName, getParentTemplateNode, isArrayModelType, isErrorType, isNullType, isTemplateInstance, isType, isValue, } from "./type-utils.js";
|
|
20
|
-
import { IdentifierKind, SyntaxKind, } from "./types.js";
|
|
22
|
+
import { IdentifierKind, ResolutionResultFlags, SyntaxKind, } from "./types.js";
|
|
21
23
|
/**
|
|
22
24
|
* Maps type arguments to type instantiation.
|
|
23
25
|
*/
|
|
24
26
|
const TypeInstantiationMap = class extends MultiKeyMap {
|
|
25
27
|
};
|
|
26
|
-
|
|
27
|
-
export function createChecker(program) {
|
|
28
|
+
export function createChecker(program, resolver) {
|
|
28
29
|
const stdTypes = {};
|
|
29
|
-
const symbolLinks = new Map();
|
|
30
|
-
const mergedSymbols = new Map();
|
|
31
30
|
const docFromCommentForSym = new Map();
|
|
32
|
-
const augmentDecoratorsForSym = new Map();
|
|
33
|
-
const augmentedSymbolTables = new Map();
|
|
34
31
|
const referenceSymCache = new WeakMap();
|
|
35
32
|
const valueExactTypes = new WeakMap();
|
|
36
33
|
let onCheckerDiagnostic = (x) => {
|
|
@@ -44,7 +41,6 @@ export function createChecker(program) {
|
|
|
44
41
|
return this.projections.filter((p) => p.id.sv === name);
|
|
45
42
|
},
|
|
46
43
|
};
|
|
47
|
-
const globalNamespaceNode = createGlobalNamespaceNode();
|
|
48
44
|
const globalNamespaceType = createGlobalNamespaceType();
|
|
49
45
|
// Caches the deprecation test of nodes in the program
|
|
50
46
|
const nodeDeprecationMap = new Map();
|
|
@@ -53,7 +49,6 @@ export function createChecker(program) {
|
|
|
53
49
|
const neverType = createType({ kind: "Intrinsic", name: "never" });
|
|
54
50
|
const unknownType = createType({ kind: "Intrinsic", name: "unknown" });
|
|
55
51
|
const nullType = createType({ kind: "Intrinsic", name: "null" });
|
|
56
|
-
const nullSym = createSymbol(undefined, "null", 0 /* SymbolFlags.None */);
|
|
57
52
|
const projectionsByTypeKind = new Map([
|
|
58
53
|
["Model", []],
|
|
59
54
|
["ModelProperty", []],
|
|
@@ -76,21 +71,9 @@ export function createChecker(program) {
|
|
|
76
71
|
* Key is the SymId of a node. It can be retrieved with getNodeSymId(node)
|
|
77
72
|
*/
|
|
78
73
|
const pendingResolutions = new PendingResolutions();
|
|
79
|
-
|
|
80
|
-
mergeSourceFile(file);
|
|
81
|
-
}
|
|
82
|
-
for (const file of program.sourceFiles.values()) {
|
|
83
|
-
mergeSourceFile(file);
|
|
84
|
-
}
|
|
85
|
-
const typespecNamespaceBinding = globalNamespaceNode.symbol.exports.get("TypeSpec");
|
|
74
|
+
const typespecNamespaceBinding = resolver.symbols.global.exports.get("TypeSpec");
|
|
86
75
|
if (typespecNamespaceBinding) {
|
|
87
76
|
initializeTypeSpecIntrinsics();
|
|
88
|
-
for (const file of program.sourceFiles.values()) {
|
|
89
|
-
addUsingSymbols(typespecNamespaceBinding.exports, file.locals);
|
|
90
|
-
}
|
|
91
|
-
}
|
|
92
|
-
for (const file of program.sourceFiles.values()) {
|
|
93
|
-
setUsingsForFile(file);
|
|
94
77
|
}
|
|
95
78
|
let evalContext = undefined;
|
|
96
79
|
const checker = {
|
|
@@ -102,9 +85,7 @@ export function createChecker(program) {
|
|
|
102
85
|
getNamespaceString: getNamespaceFullName,
|
|
103
86
|
getGlobalNamespaceType,
|
|
104
87
|
getGlobalNamespaceNode,
|
|
105
|
-
setUsingsForFile,
|
|
106
88
|
getMergedSymbol,
|
|
107
|
-
mergeSourceFile,
|
|
108
89
|
cloneType,
|
|
109
90
|
resolveIdentifier,
|
|
110
91
|
resolveCompletions,
|
|
@@ -153,18 +134,18 @@ export function createChecker(program) {
|
|
|
153
134
|
function initializeTypeSpecIntrinsics() {
|
|
154
135
|
// a utility function to log strings or numbers
|
|
155
136
|
mutate(typespecNamespaceBinding.exports).set("log", {
|
|
156
|
-
flags:
|
|
137
|
+
flags: 8192 /* SymbolFlags.Function */,
|
|
157
138
|
name: "log",
|
|
158
139
|
value(p, ...strs) {
|
|
159
140
|
program.trace("projection.log", strs.join(" "));
|
|
160
141
|
return voidType;
|
|
161
142
|
},
|
|
162
143
|
declarations: [],
|
|
144
|
+
node: undefined, // TODO: is this correct?
|
|
163
145
|
});
|
|
164
146
|
// Until we have an `unit` type for `null`
|
|
165
|
-
mutate(
|
|
166
|
-
|
|
167
|
-
getSymbolLinks(nullSym).type = nullType;
|
|
147
|
+
mutate(resolver.symbols.null).type = nullType;
|
|
148
|
+
getSymbolLinks(resolver.symbols.null).type = nullType;
|
|
168
149
|
}
|
|
169
150
|
function getStdType(name) {
|
|
170
151
|
const type = stdTypes[name];
|
|
@@ -172,7 +153,8 @@ export function createChecker(program) {
|
|
|
172
153
|
return type;
|
|
173
154
|
}
|
|
174
155
|
const sym = typespecNamespaceBinding?.exports?.get(name);
|
|
175
|
-
|
|
156
|
+
compilerAssert(sym, `Unexpected missing symbol to std type "${name}"`);
|
|
157
|
+
if (sym.flags & 2 /* SymbolFlags.Model */) {
|
|
176
158
|
checkModelStatement(sym.declarations[0], undefined);
|
|
177
159
|
}
|
|
178
160
|
else {
|
|
@@ -182,105 +164,6 @@ export function createChecker(program) {
|
|
|
182
164
|
compilerAssert(loadedType, `TypeSpec std type "${name}" should have been initalized before using array syntax.`);
|
|
183
165
|
return loadedType;
|
|
184
166
|
}
|
|
185
|
-
function mergeSourceFile(file) {
|
|
186
|
-
mergeSymbolTable(file.symbol.exports, mutate(globalNamespaceNode.symbol.exports));
|
|
187
|
-
}
|
|
188
|
-
function setUsingsForFile(file) {
|
|
189
|
-
const usedUsing = new Set();
|
|
190
|
-
for (const using of file.usings) {
|
|
191
|
-
const parentNs = using.parent;
|
|
192
|
-
const sym = resolveTypeReferenceSym(using.name, undefined);
|
|
193
|
-
if (!sym) {
|
|
194
|
-
continue;
|
|
195
|
-
}
|
|
196
|
-
if (!(sym.flags & 4096 /* SymbolFlags.Namespace */)) {
|
|
197
|
-
reportCheckerDiagnostic(createDiagnostic({ code: "using-invalid-ref", target: using }));
|
|
198
|
-
continue;
|
|
199
|
-
}
|
|
200
|
-
const namespaceSym = getMergedSymbol(sym);
|
|
201
|
-
if (usedUsing.has(namespaceSym)) {
|
|
202
|
-
reportCheckerDiagnostic(createDiagnostic({
|
|
203
|
-
code: "duplicate-using",
|
|
204
|
-
format: { usingName: memberExpressionToString(using.name) },
|
|
205
|
-
target: using,
|
|
206
|
-
}));
|
|
207
|
-
continue;
|
|
208
|
-
}
|
|
209
|
-
usedUsing.add(namespaceSym);
|
|
210
|
-
addUsingSymbols(sym.exports, parentNs.locals);
|
|
211
|
-
}
|
|
212
|
-
}
|
|
213
|
-
function applyAugmentDecorators(node) {
|
|
214
|
-
if (!node.statements || !isArray(node.statements)) {
|
|
215
|
-
return;
|
|
216
|
-
}
|
|
217
|
-
const augmentDecorators = node.statements.filter((x) => x.kind === SyntaxKind.AugmentDecoratorStatement);
|
|
218
|
-
for (const decNode of augmentDecorators) {
|
|
219
|
-
const ref = resolveTypeReferenceSym(decNode.targetType, undefined);
|
|
220
|
-
if (ref) {
|
|
221
|
-
let args = [];
|
|
222
|
-
if (ref.declarations[0].kind === SyntaxKind.AliasStatement) {
|
|
223
|
-
const aliasNode = ref.declarations[0];
|
|
224
|
-
if (aliasNode.value.kind === SyntaxKind.TypeReference) {
|
|
225
|
-
args = aliasNode.value.arguments;
|
|
226
|
-
}
|
|
227
|
-
}
|
|
228
|
-
else {
|
|
229
|
-
args = decNode.targetType.arguments;
|
|
230
|
-
}
|
|
231
|
-
if (ref.flags & 4096 /* SymbolFlags.Namespace */) {
|
|
232
|
-
const links = getSymbolLinks(getMergedSymbol(ref));
|
|
233
|
-
const type = links.type;
|
|
234
|
-
const decApp = checkDecoratorApplication(type, decNode, undefined);
|
|
235
|
-
if (decApp) {
|
|
236
|
-
type.decorators.push(decApp);
|
|
237
|
-
applyDecoratorToType(program, decApp, type);
|
|
238
|
-
}
|
|
239
|
-
}
|
|
240
|
-
else if (args.length > 0 || ref.flags & 67108864 /* SymbolFlags.LateBound */) {
|
|
241
|
-
reportCheckerDiagnostic(createDiagnostic({
|
|
242
|
-
code: "augment-decorator-target",
|
|
243
|
-
messageId: "noInstance",
|
|
244
|
-
target: decNode.target,
|
|
245
|
-
}));
|
|
246
|
-
}
|
|
247
|
-
else {
|
|
248
|
-
let list = augmentDecoratorsForSym.get(ref);
|
|
249
|
-
if (list === undefined) {
|
|
250
|
-
list = [];
|
|
251
|
-
augmentDecoratorsForSym.set(ref, list);
|
|
252
|
-
}
|
|
253
|
-
list.unshift(decNode);
|
|
254
|
-
}
|
|
255
|
-
}
|
|
256
|
-
}
|
|
257
|
-
}
|
|
258
|
-
function addUsingSymbols(source, destination) {
|
|
259
|
-
const augmented = getOrCreateAugmentedSymbolTable(destination);
|
|
260
|
-
for (const symbolSource of source.values()) {
|
|
261
|
-
const sym = {
|
|
262
|
-
flags: 524288 /* SymbolFlags.Using */,
|
|
263
|
-
declarations: [],
|
|
264
|
-
name: symbolSource.name,
|
|
265
|
-
symbolSource: symbolSource,
|
|
266
|
-
};
|
|
267
|
-
augmented.set(sym.name, sym);
|
|
268
|
-
}
|
|
269
|
-
}
|
|
270
|
-
/**
|
|
271
|
-
* We cannot inject symbols into the symbol tables hanging off syntax tree nodes as
|
|
272
|
-
* syntax tree nodes can be shared by other programs. This is called as a copy-on-write
|
|
273
|
-
* to inject using and late-bound symbols, and then we use the copy when resolving
|
|
274
|
-
* in the table.
|
|
275
|
-
*/
|
|
276
|
-
function getOrCreateAugmentedSymbolTable(table) {
|
|
277
|
-
let augmented = augmentedSymbolTables.get(table);
|
|
278
|
-
if (!augmented) {
|
|
279
|
-
augmented = createSymbolTable(table);
|
|
280
|
-
augmentedSymbolTables.set(table, augmented);
|
|
281
|
-
}
|
|
282
|
-
return mutate(augmented);
|
|
283
|
-
}
|
|
284
167
|
/**
|
|
285
168
|
* Create the link for the given type to the symbol links.
|
|
286
169
|
* If currently instantiating a template it will link to the instantiations.
|
|
@@ -311,13 +194,13 @@ export function createChecker(program) {
|
|
|
311
194
|
*/
|
|
312
195
|
function checkMemberSym(sym, mapper) {
|
|
313
196
|
const symbolLinks = getSymbolLinks(sym);
|
|
314
|
-
const memberContainer = getTypeForNode(sym.parent
|
|
197
|
+
const memberContainer = getTypeForNode(getSymNode(sym.parent), mapper);
|
|
315
198
|
const type = symbolLinks.declaredType ?? symbolLinks.type;
|
|
316
199
|
if (type) {
|
|
317
200
|
return type;
|
|
318
201
|
}
|
|
319
202
|
else {
|
|
320
|
-
return checkMember(sym
|
|
203
|
+
return checkMember(getSymNode(sym), mapper, memberContainer);
|
|
321
204
|
}
|
|
322
205
|
}
|
|
323
206
|
/**
|
|
@@ -671,6 +554,10 @@ export function createChecker(program) {
|
|
|
671
554
|
return checkCallExpression(node, mapper);
|
|
672
555
|
case SyntaxKind.TypeOfExpression:
|
|
673
556
|
return checkTypeOfExpression(node, mapper);
|
|
557
|
+
case SyntaxKind.AugmentDecoratorStatement:
|
|
558
|
+
return checkAugmentDecorator(node);
|
|
559
|
+
case SyntaxKind.UsingStatement:
|
|
560
|
+
return checkUsings(node);
|
|
674
561
|
default:
|
|
675
562
|
return errorType;
|
|
676
563
|
}
|
|
@@ -678,13 +565,12 @@ export function createChecker(program) {
|
|
|
678
565
|
/**
|
|
679
566
|
* Return a fully qualified id of node
|
|
680
567
|
*/
|
|
681
|
-
function
|
|
568
|
+
function getNodeSym(node) {
|
|
682
569
|
const symbol = node.kind === SyntaxKind.OperationStatement &&
|
|
683
570
|
node.parent?.kind === SyntaxKind.InterfaceStatement
|
|
684
571
|
? getSymbolForMember(node)
|
|
685
572
|
: node.symbol;
|
|
686
|
-
|
|
687
|
-
return symbol?.id;
|
|
573
|
+
return symbol;
|
|
688
574
|
}
|
|
689
575
|
/**
|
|
690
576
|
* Check if the given namespace is the standard library `TypeSpec` namespace.
|
|
@@ -704,7 +590,7 @@ export function createChecker(program) {
|
|
|
704
590
|
const parentNode = node.parent;
|
|
705
591
|
const grandParentNode = parentNode.parent;
|
|
706
592
|
const links = getSymbolLinks(node.symbol);
|
|
707
|
-
if (pendingResolutions.has(
|
|
593
|
+
if (pendingResolutions.has(getNodeSym(node), ResolutionKind.Constraint)) {
|
|
708
594
|
if (mapper === undefined) {
|
|
709
595
|
reportCheckerDiagnostic(createDiagnostic({
|
|
710
596
|
code: "circular-constraint",
|
|
@@ -731,9 +617,9 @@ export function createChecker(program) {
|
|
|
731
617
|
node: node,
|
|
732
618
|
});
|
|
733
619
|
if (node.constraint) {
|
|
734
|
-
pendingResolutions.start(
|
|
620
|
+
pendingResolutions.start(getNodeSym(node), ResolutionKind.Constraint);
|
|
735
621
|
type.constraint = getParamConstraintEntityForNode(node.constraint);
|
|
736
|
-
pendingResolutions.finish(
|
|
622
|
+
pendingResolutions.finish(getNodeSym(node), ResolutionKind.Constraint);
|
|
737
623
|
}
|
|
738
624
|
if (node.default) {
|
|
739
625
|
type.default = checkTemplateParameterDefault(node.default, parentNode.templateParameters, index, type.constraint);
|
|
@@ -1031,27 +917,28 @@ export function createChecker(program) {
|
|
|
1031
917
|
return result;
|
|
1032
918
|
}
|
|
1033
919
|
function checkTypeOrValueReferenceSymbol(sym, node, mapper, instantiateTemplates = true) {
|
|
1034
|
-
if (sym.flags &
|
|
920
|
+
if (sym.flags & 524288 /* SymbolFlags.Const */) {
|
|
1035
921
|
return getValueForNode(sym.declarations[0], mapper);
|
|
1036
922
|
}
|
|
1037
|
-
if (sym.flags &
|
|
923
|
+
if (sym.flags & 1024 /* SymbolFlags.Decorator */) {
|
|
1038
924
|
reportCheckerDiagnostic(createDiagnostic({ code: "invalid-type-ref", messageId: "decorator", target: sym }));
|
|
1039
925
|
return errorType;
|
|
1040
926
|
}
|
|
1041
|
-
if (sym.flags &
|
|
927
|
+
if (sym.flags & 8192 /* SymbolFlags.Function */) {
|
|
1042
928
|
reportCheckerDiagnostic(createDiagnostic({ code: "invalid-type-ref", messageId: "function", target: sym }));
|
|
1043
929
|
return errorType;
|
|
1044
930
|
}
|
|
1045
931
|
const argumentNodes = node.kind === SyntaxKind.TypeReference ? node.arguments : [];
|
|
1046
932
|
const symbolLinks = getSymbolLinks(sym);
|
|
1047
933
|
let baseType;
|
|
1048
|
-
if (sym.flags &
|
|
1049
|
-
|
|
1050
|
-
|
|
1051
|
-
|
|
1052
|
-
|
|
1053
|
-
|
|
1054
|
-
|
|
934
|
+
if (sym.flags & 1048576 /* SymbolFlags.Declaration */ &&
|
|
935
|
+
sym.flags &
|
|
936
|
+
(2 /* SymbolFlags.Model */ |
|
|
937
|
+
4 /* SymbolFlags.Scalar */ |
|
|
938
|
+
128 /* SymbolFlags.Alias */ |
|
|
939
|
+
32 /* SymbolFlags.Interface */ |
|
|
940
|
+
8 /* SymbolFlags.Operation */ |
|
|
941
|
+
64 /* SymbolFlags.Union */)) {
|
|
1055
942
|
const decl = sym.declarations[0];
|
|
1056
943
|
if (!isTemplatedNode(decl)) {
|
|
1057
944
|
if (argumentNodes.length > 0) {
|
|
@@ -1061,14 +948,14 @@ export function createChecker(program) {
|
|
|
1061
948
|
target: node,
|
|
1062
949
|
}));
|
|
1063
950
|
}
|
|
1064
|
-
if (sym.flags &
|
|
951
|
+
if (sym.flags & 4194304 /* SymbolFlags.LateBound */) {
|
|
1065
952
|
compilerAssert(sym.type, "Expected late bound symbol to have type");
|
|
1066
953
|
return sym.type;
|
|
1067
954
|
}
|
|
1068
955
|
else if (symbolLinks.declaredType) {
|
|
1069
956
|
baseType = symbolLinks.declaredType;
|
|
1070
957
|
}
|
|
1071
|
-
else if (sym.flags &
|
|
958
|
+
else if (sym.flags & 262144 /* SymbolFlags.Member */) {
|
|
1072
959
|
baseType = checkMemberSym(sym, mapper);
|
|
1073
960
|
}
|
|
1074
961
|
else {
|
|
@@ -1083,6 +970,7 @@ export function createChecker(program) {
|
|
|
1083
970
|
}
|
|
1084
971
|
}
|
|
1085
972
|
else {
|
|
973
|
+
const symNode = getSymNode(sym);
|
|
1086
974
|
// some other kind of reference
|
|
1087
975
|
if (argumentNodes.length > 0) {
|
|
1088
976
|
reportCheckerDiagnostic(createDiagnostic({
|
|
@@ -1091,12 +979,12 @@ export function createChecker(program) {
|
|
|
1091
979
|
target: node,
|
|
1092
980
|
}));
|
|
1093
981
|
}
|
|
1094
|
-
if (sym.flags &
|
|
982
|
+
if (sym.flags & 4194304 /* SymbolFlags.LateBound */) {
|
|
1095
983
|
compilerAssert(sym.type, `Expected late bound symbol to have type`);
|
|
1096
984
|
return sym.type;
|
|
1097
985
|
}
|
|
1098
|
-
else if (sym.flags &
|
|
1099
|
-
const mapped = checkTemplateParameterDeclaration(
|
|
986
|
+
else if (sym.flags & 2048 /* SymbolFlags.TemplateParameter */) {
|
|
987
|
+
const mapped = checkTemplateParameterDeclaration(symNode, mapper);
|
|
1100
988
|
baseType = mapped;
|
|
1101
989
|
}
|
|
1102
990
|
else if (symbolLinks.type) {
|
|
@@ -1107,12 +995,12 @@ export function createChecker(program) {
|
|
|
1107
995
|
baseType = symbolLinks.declaredType;
|
|
1108
996
|
}
|
|
1109
997
|
else {
|
|
1110
|
-
if (sym.flags &
|
|
998
|
+
if (sym.flags & 262144 /* SymbolFlags.Member */) {
|
|
1111
999
|
baseType = checkMemberSym(sym, mapper);
|
|
1112
1000
|
}
|
|
1113
1001
|
else {
|
|
1114
1002
|
// don't have a cached type for this symbol, so go grab it and cache it
|
|
1115
|
-
baseType = getTypeForNode(
|
|
1003
|
+
baseType = getTypeForNode(symNode, mapper);
|
|
1116
1004
|
symbolLinks.type = baseType;
|
|
1117
1005
|
}
|
|
1118
1006
|
}
|
|
@@ -1120,7 +1008,7 @@ export function createChecker(program) {
|
|
|
1120
1008
|
// Check for deprecations here, first on symbol, then on type. However,
|
|
1121
1009
|
// don't raise deprecation when the usage site is also a deprecated
|
|
1122
1010
|
// declaration.
|
|
1123
|
-
const declarationNode = sym
|
|
1011
|
+
const declarationNode = getSymNode(sym);
|
|
1124
1012
|
if (declarationNode && mapper === undefined && isType(baseType)) {
|
|
1125
1013
|
if (!isTypeReferenceContextDeprecated(node.parent)) {
|
|
1126
1014
|
checkDeprecated(baseType, declarationNode, node);
|
|
@@ -1145,11 +1033,11 @@ export function createChecker(program) {
|
|
|
1145
1033
|
if (symbolLinks.declaredType) {
|
|
1146
1034
|
return symbolLinks.declaredType;
|
|
1147
1035
|
}
|
|
1148
|
-
if (sym.flags &
|
|
1036
|
+
if (sym.flags & 4194304 /* SymbolFlags.LateBound */) {
|
|
1149
1037
|
compilerAssert(sym.type, "Expected late bound symbol to have type");
|
|
1150
1038
|
return sym.type;
|
|
1151
1039
|
}
|
|
1152
|
-
if (sym.flags &
|
|
1040
|
+
if (sym.flags & 262144 /* SymbolFlags.Member */) {
|
|
1153
1041
|
return checkMemberSym(sym, mapper);
|
|
1154
1042
|
}
|
|
1155
1043
|
else {
|
|
@@ -1166,13 +1054,13 @@ export function createChecker(program) {
|
|
|
1166
1054
|
function checkDeclaredTypeOrIndeterminate(sym, node, mapper) {
|
|
1167
1055
|
const type = sym.flags & 2 /* SymbolFlags.Model */
|
|
1168
1056
|
? checkModelStatement(node, mapper)
|
|
1169
|
-
: sym.flags &
|
|
1057
|
+
: sym.flags & 4 /* SymbolFlags.Scalar */
|
|
1170
1058
|
? checkScalar(node, mapper)
|
|
1171
|
-
: sym.flags &
|
|
1059
|
+
: sym.flags & 128 /* SymbolFlags.Alias */
|
|
1172
1060
|
? checkAlias(node, mapper)
|
|
1173
|
-
: sym.flags &
|
|
1061
|
+
: sym.flags & 32 /* SymbolFlags.Interface */
|
|
1174
1062
|
? checkInterface(node, mapper)
|
|
1175
|
-
: sym.flags &
|
|
1063
|
+
: sym.flags & 8 /* SymbolFlags.Operation */
|
|
1176
1064
|
? checkOperation(node, mapper)
|
|
1177
1065
|
: checkUnion(node, mapper);
|
|
1178
1066
|
return type;
|
|
@@ -1320,8 +1208,15 @@ export function createChecker(program) {
|
|
|
1320
1208
|
* with unions). The resulting model is anonymous.
|
|
1321
1209
|
*/
|
|
1322
1210
|
function checkIntersectionExpression(node, mapper) {
|
|
1211
|
+
const links = getSymbolLinks(node.symbol);
|
|
1212
|
+
if (links.declaredType && mapper === undefined) {
|
|
1213
|
+
// we're not instantiating this model and we've already checked it
|
|
1214
|
+
return links.declaredType;
|
|
1215
|
+
}
|
|
1323
1216
|
const options = node.options.map((o) => [o, getTypeForNode(o, mapper)]);
|
|
1324
|
-
|
|
1217
|
+
const type = mergeModelTypes(node.symbol, node, options, mapper);
|
|
1218
|
+
linkType(links, type, mapper);
|
|
1219
|
+
return type;
|
|
1325
1220
|
}
|
|
1326
1221
|
function checkDecoratorDeclaration(node, mapper) {
|
|
1327
1222
|
const symbol = getMergedSymbol(node.symbol);
|
|
@@ -1452,7 +1347,7 @@ export function createChecker(program) {
|
|
|
1452
1347
|
};
|
|
1453
1348
|
}
|
|
1454
1349
|
}
|
|
1455
|
-
function mergeModelTypes(node, options, mapper) {
|
|
1350
|
+
function mergeModelTypes(parentModelSym, node, options, mapper) {
|
|
1456
1351
|
const properties = createRekeyableMap();
|
|
1457
1352
|
const intersection = createType({
|
|
1458
1353
|
kind: "Model",
|
|
@@ -1502,11 +1397,16 @@ export function createChecker(program) {
|
|
|
1502
1397
|
}));
|
|
1503
1398
|
continue;
|
|
1504
1399
|
}
|
|
1505
|
-
const
|
|
1400
|
+
const memberSym = parentModelSym && getMemberSymbol(parentModelSym, prop.name);
|
|
1401
|
+
const overrides = {
|
|
1506
1402
|
sourceProperty: prop,
|
|
1507
1403
|
model: intersection,
|
|
1508
|
-
}
|
|
1404
|
+
};
|
|
1405
|
+
const newPropType = memberSym
|
|
1406
|
+
? cloneTypeForSymbol(memberSym, prop, overrides)
|
|
1407
|
+
: cloneType(prop, overrides);
|
|
1509
1408
|
properties.set(prop.name, newPropType);
|
|
1409
|
+
linkIndirectMember(node, newPropType, mapper);
|
|
1510
1410
|
for (const indexer of indexers.filter((x) => x !== option.indexer)) {
|
|
1511
1411
|
checkPropertyCompatibleWithIndexer(indexer, prop, node);
|
|
1512
1412
|
}
|
|
@@ -1518,7 +1418,7 @@ export function createChecker(program) {
|
|
|
1518
1418
|
else if (indexers.length > 1) {
|
|
1519
1419
|
intersection.indexer = {
|
|
1520
1420
|
key: indexers[0].key,
|
|
1521
|
-
value: mergeModelTypes(node, indexers.map((x) => [x.value.node, x.value]), mapper),
|
|
1421
|
+
value: mergeModelTypes(undefined, node, indexers.map((x) => [x.value.node, x.value]), mapper),
|
|
1522
1422
|
};
|
|
1523
1423
|
}
|
|
1524
1424
|
linkMapper(intersection, mapper);
|
|
@@ -1654,9 +1554,9 @@ export function createChecker(program) {
|
|
|
1654
1554
|
const namespace = getParentNamespaceType(node);
|
|
1655
1555
|
const name = node.id.sv;
|
|
1656
1556
|
let decorators = [];
|
|
1657
|
-
const parameterModelSym =
|
|
1557
|
+
const { resolvedSymbol: parameterModelSym } = resolver.resolveMetaMemberByName(symbol, "parameters");
|
|
1658
1558
|
if (parameterModelSym?.members) {
|
|
1659
|
-
const members =
|
|
1559
|
+
const members = resolver.getAugmentedSymbolTable(parameterModelSym.members);
|
|
1660
1560
|
const paramDocs = extractParamDocs(node);
|
|
1661
1561
|
for (const [name, memberSym] of members) {
|
|
1662
1562
|
const doc = paramDocs.get(name);
|
|
@@ -1743,27 +1643,24 @@ export function createChecker(program) {
|
|
|
1743
1643
|
if (!opReference)
|
|
1744
1644
|
return undefined;
|
|
1745
1645
|
// Ensure that we don't end up with a circular reference to the same operation
|
|
1746
|
-
const opSymId =
|
|
1646
|
+
const opSymId = getNodeSym(operation);
|
|
1747
1647
|
if (opSymId) {
|
|
1748
1648
|
pendingResolutions.start(opSymId, ResolutionKind.BaseType);
|
|
1749
1649
|
}
|
|
1750
|
-
const target =
|
|
1751
|
-
if (target === undefined) {
|
|
1752
|
-
return undefined;
|
|
1753
|
-
}
|
|
1650
|
+
const target = resolver.getNodeLinks(opReference).resolvedSymbol;
|
|
1754
1651
|
// Did we encounter a circular operation reference?
|
|
1755
|
-
if (pendingResolutions.has(
|
|
1652
|
+
if (target && pendingResolutions.has(target, ResolutionKind.BaseType)) {
|
|
1756
1653
|
if (mapper === undefined) {
|
|
1757
1654
|
reportCheckerDiagnostic(createDiagnostic({
|
|
1758
1655
|
code: "circular-op-signature",
|
|
1759
|
-
format: { typeName: target.
|
|
1656
|
+
format: { typeName: target.name },
|
|
1760
1657
|
target: opReference,
|
|
1761
1658
|
}));
|
|
1762
1659
|
}
|
|
1763
1660
|
return undefined;
|
|
1764
1661
|
}
|
|
1765
1662
|
// Resolve the base operation type
|
|
1766
|
-
const baseOperation =
|
|
1663
|
+
const baseOperation = getTypeForNode(opReference, mapper);
|
|
1767
1664
|
if (opSymId) {
|
|
1768
1665
|
pendingResolutions.finish(opSymId, ResolutionKind.BaseType);
|
|
1769
1666
|
}
|
|
@@ -1781,7 +1678,7 @@ export function createChecker(program) {
|
|
|
1781
1678
|
return globalNamespaceType;
|
|
1782
1679
|
}
|
|
1783
1680
|
function getGlobalNamespaceNode() {
|
|
1784
|
-
return
|
|
1681
|
+
return resolver.symbols.global.declarations[0];
|
|
1785
1682
|
}
|
|
1786
1683
|
function checkTupleExpression(node, mapper) {
|
|
1787
1684
|
return createAndFinishType({
|
|
@@ -1791,47 +1688,7 @@ export function createChecker(program) {
|
|
|
1791
1688
|
});
|
|
1792
1689
|
}
|
|
1793
1690
|
function getSymbolLinks(s) {
|
|
1794
|
-
|
|
1795
|
-
if (symbolLinks.has(id)) {
|
|
1796
|
-
return symbolLinks.get(id);
|
|
1797
|
-
}
|
|
1798
|
-
const links = {};
|
|
1799
|
-
symbolLinks.set(id, links);
|
|
1800
|
-
return links;
|
|
1801
|
-
}
|
|
1802
|
-
function getSymbolId(s) {
|
|
1803
|
-
if (s.id === undefined) {
|
|
1804
|
-
mutate(s).id = currentSymbolId++;
|
|
1805
|
-
}
|
|
1806
|
-
return s.id;
|
|
1807
|
-
}
|
|
1808
|
-
function resolveIdentifierInTable(node, table, options) {
|
|
1809
|
-
if (!table) {
|
|
1810
|
-
return undefined;
|
|
1811
|
-
}
|
|
1812
|
-
table = augmentedSymbolTables.get(table) ?? table;
|
|
1813
|
-
let sym;
|
|
1814
|
-
if (options.resolveDecorators) {
|
|
1815
|
-
sym = table.get("@" + node.sv);
|
|
1816
|
-
}
|
|
1817
|
-
else {
|
|
1818
|
-
sym = table.get(node.sv);
|
|
1819
|
-
}
|
|
1820
|
-
if (!sym)
|
|
1821
|
-
return sym;
|
|
1822
|
-
if (sym.flags & 1048576 /* SymbolFlags.DuplicateUsing */) {
|
|
1823
|
-
reportAmbiguousIdentifier(node, [...(table.duplicates.get(sym) ?? [])]);
|
|
1824
|
-
return sym;
|
|
1825
|
-
}
|
|
1826
|
-
return getMergedSymbol(sym);
|
|
1827
|
-
}
|
|
1828
|
-
function reportAmbiguousIdentifier(node, symbols) {
|
|
1829
|
-
const duplicateNames = symbols.map((s) => getFullyQualifiedSymbolName(s, { useGlobalPrefixAtTopLevel: true }));
|
|
1830
|
-
reportCheckerDiagnostic(createDiagnostic({
|
|
1831
|
-
code: "ambiguous-symbol",
|
|
1832
|
-
format: { name: node.sv, duplicateNames: duplicateNames.join(", ") },
|
|
1833
|
-
target: node,
|
|
1834
|
-
}));
|
|
1691
|
+
return resolver.getSymbolLinks(s);
|
|
1835
1692
|
}
|
|
1836
1693
|
function resolveIdentifier(id, mapper) {
|
|
1837
1694
|
let sym;
|
|
@@ -1849,29 +1706,8 @@ export function createChecker(program) {
|
|
|
1849
1706
|
break;
|
|
1850
1707
|
case IdentifierKind.ModelStatementProperty:
|
|
1851
1708
|
case IdentifierKind.Declaration:
|
|
1852
|
-
|
|
1853
|
-
|
|
1854
|
-
break;
|
|
1855
|
-
}
|
|
1856
|
-
compilerAssert(node.parent, "Parent expected.");
|
|
1857
|
-
const containerType = getTypeOrValueForNode(node.parent, mapper);
|
|
1858
|
-
if (containerType === null || isValue(containerType)) {
|
|
1859
|
-
return undefined;
|
|
1860
|
-
}
|
|
1861
|
-
if (isAnonymous(containerType)) {
|
|
1862
|
-
return undefined; // member of anonymous type cannot be referenced.
|
|
1863
|
-
}
|
|
1864
|
-
lateBindMemberContainer(containerType);
|
|
1865
|
-
let container = node.parent.symbol;
|
|
1866
|
-
if (!container && "symbol" in containerType && containerType.symbol) {
|
|
1867
|
-
container = containerType.symbol;
|
|
1868
|
-
}
|
|
1869
|
-
if (!container) {
|
|
1870
|
-
return undefined;
|
|
1871
|
-
}
|
|
1872
|
-
lateBindMembers(containerType, container);
|
|
1873
|
-
sym = resolveIdentifierInTable(id, container.exports ?? container.members, defaultSymbolResolutionOptions);
|
|
1874
|
-
break;
|
|
1709
|
+
const links = resolver.getNodeLinks(id);
|
|
1710
|
+
return links.resolvedSymbol;
|
|
1875
1711
|
case IdentifierKind.Other:
|
|
1876
1712
|
return undefined;
|
|
1877
1713
|
case IdentifierKind.Decorator:
|
|
@@ -2158,19 +1994,12 @@ export function createChecker(program) {
|
|
|
2158
1994
|
}
|
|
2159
1995
|
}
|
|
2160
1996
|
else if (identifier.parent && identifier.parent.kind === SyntaxKind.MemberExpression) {
|
|
2161
|
-
let base =
|
|
1997
|
+
let base = resolver.getNodeLinks(identifier.parent.base).resolvedSymbol;
|
|
2162
1998
|
if (base) {
|
|
2163
|
-
if (base.flags &
|
|
2164
|
-
base = getAliasedSymbol(base, undefined
|
|
1999
|
+
if (base.flags & 128 /* SymbolFlags.Alias */) {
|
|
2000
|
+
base = getAliasedSymbol(base, undefined);
|
|
2165
2001
|
}
|
|
2166
2002
|
if (base) {
|
|
2167
|
-
if (isTemplatedNode(base.declarations[0])) {
|
|
2168
|
-
const type = base.type ?? getTypeForNode(base.declarations[0], undefined);
|
|
2169
|
-
if (isTemplateInstance(type)) {
|
|
2170
|
-
lateBindMemberContainer(type);
|
|
2171
|
-
lateBindMembers(type, base);
|
|
2172
|
-
}
|
|
2173
|
-
}
|
|
2174
2003
|
addCompletions(base.exports ?? base.members);
|
|
2175
2004
|
}
|
|
2176
2005
|
}
|
|
@@ -2207,7 +2036,7 @@ export function createChecker(program) {
|
|
|
2207
2036
|
addCompletions(mergedSymbol.exports);
|
|
2208
2037
|
}
|
|
2209
2038
|
// check "global scope" declarations
|
|
2210
|
-
addCompletions(
|
|
2039
|
+
addCompletions(resolver.symbols.global.exports);
|
|
2211
2040
|
// check "global scope" usings
|
|
2212
2041
|
addCompletions(scope.locals);
|
|
2213
2042
|
}
|
|
@@ -2217,12 +2046,12 @@ export function createChecker(program) {
|
|
|
2217
2046
|
if (!table) {
|
|
2218
2047
|
return;
|
|
2219
2048
|
}
|
|
2220
|
-
table =
|
|
2049
|
+
table = resolver.getAugmentedSymbolTable(table);
|
|
2221
2050
|
for (const [key, sym] of table) {
|
|
2222
|
-
if (sym.flags &
|
|
2051
|
+
if (sym.flags & 65536 /* SymbolFlags.DuplicateUsing */) {
|
|
2223
2052
|
const duplicates = table.duplicates.get(sym);
|
|
2224
2053
|
for (const duplicate of duplicates) {
|
|
2225
|
-
if (duplicate.flags &
|
|
2054
|
+
if (duplicate.flags & 32768 /* SymbolFlags.Using */) {
|
|
2226
2055
|
const fqn = getFullyQualifiedSymbolName(duplicate.symbolSource);
|
|
2227
2056
|
addCompletion(fqn, duplicate);
|
|
2228
2057
|
}
|
|
@@ -2252,79 +2081,23 @@ export function createChecker(program) {
|
|
|
2252
2081
|
case IdentifierKind.ModelExpressionProperty:
|
|
2253
2082
|
case IdentifierKind.ModelStatementProperty:
|
|
2254
2083
|
case IdentifierKind.ObjectLiteralProperty:
|
|
2255
|
-
return !!(sym.flags &
|
|
2084
|
+
return !!(sym.flags & 262144 /* SymbolFlags.Member */);
|
|
2256
2085
|
case IdentifierKind.Decorator:
|
|
2257
2086
|
// Only return decorators and namespaces when completing decorator
|
|
2258
|
-
return !!(sym.flags & (
|
|
2087
|
+
return !!(sym.flags & (1024 /* SymbolFlags.Decorator */ | 256 /* SymbolFlags.Namespace */));
|
|
2259
2088
|
case IdentifierKind.Using:
|
|
2260
2089
|
// Only return namespaces when completing using
|
|
2261
|
-
return !!(sym.flags &
|
|
2090
|
+
return !!(sym.flags & 256 /* SymbolFlags.Namespace */);
|
|
2262
2091
|
case IdentifierKind.TypeReference:
|
|
2263
2092
|
// Do not return functions or decorators when completing types
|
|
2264
|
-
return !(sym.flags & (
|
|
2093
|
+
return !(sym.flags & (8192 /* SymbolFlags.Function */ | 1024 /* SymbolFlags.Decorator */));
|
|
2265
2094
|
case IdentifierKind.TemplateArgument:
|
|
2266
|
-
return !!(sym.flags &
|
|
2095
|
+
return !!(sym.flags & 2048 /* SymbolFlags.TemplateParameter */);
|
|
2267
2096
|
default:
|
|
2268
2097
|
compilerAssert(false, "We should have bailed up-front on other kinds.");
|
|
2269
2098
|
}
|
|
2270
2099
|
}
|
|
2271
2100
|
}
|
|
2272
|
-
function resolveIdentifierInScope(node, mapper, options) {
|
|
2273
|
-
compilerAssert(node.parent?.kind !== SyntaxKind.MemberExpression || node.parent.id !== node, "This function should not be used to resolve Y in member expression X.Y. Use resolveIdentifier() to resolve an arbitrary identifier.");
|
|
2274
|
-
if (hasParseError(node)) {
|
|
2275
|
-
// Don't report synthetic identifiers used for parser error recovery.
|
|
2276
|
-
// The parse error is the root cause and will already have been logged.
|
|
2277
|
-
return undefined;
|
|
2278
|
-
}
|
|
2279
|
-
let scope = node.parent;
|
|
2280
|
-
let binding;
|
|
2281
|
-
while (scope && scope.kind !== SyntaxKind.TypeSpecScript) {
|
|
2282
|
-
if (scope.symbol && "exports" in scope.symbol) {
|
|
2283
|
-
const mergedSymbol = getMergedSymbol(scope.symbol);
|
|
2284
|
-
binding = resolveIdentifierInTable(node, mergedSymbol.exports, options);
|
|
2285
|
-
if (binding)
|
|
2286
|
-
return binding;
|
|
2287
|
-
}
|
|
2288
|
-
if ("locals" in scope) {
|
|
2289
|
-
binding = resolveIdentifierInTable(node, scope.locals, options);
|
|
2290
|
-
if (binding)
|
|
2291
|
-
return binding;
|
|
2292
|
-
}
|
|
2293
|
-
scope = scope.parent;
|
|
2294
|
-
}
|
|
2295
|
-
if (!binding && scope && scope.kind === SyntaxKind.TypeSpecScript) {
|
|
2296
|
-
// check any blockless namespace decls
|
|
2297
|
-
for (const ns of scope.inScopeNamespaces) {
|
|
2298
|
-
const mergedSymbol = getMergedSymbol(ns.symbol);
|
|
2299
|
-
binding = resolveIdentifierInTable(node, mergedSymbol.exports, options);
|
|
2300
|
-
if (binding)
|
|
2301
|
-
return binding;
|
|
2302
|
-
}
|
|
2303
|
-
// check "global scope" declarations
|
|
2304
|
-
const globalBinding = resolveIdentifierInTable(node, globalNamespaceNode.symbol.exports, options);
|
|
2305
|
-
// check using types
|
|
2306
|
-
const usingBinding = resolveIdentifierInTable(node, scope.locals, options);
|
|
2307
|
-
if (globalBinding && usingBinding) {
|
|
2308
|
-
reportAmbiguousIdentifier(node, [globalBinding, usingBinding]);
|
|
2309
|
-
return globalBinding;
|
|
2310
|
-
}
|
|
2311
|
-
else if (globalBinding) {
|
|
2312
|
-
return globalBinding;
|
|
2313
|
-
}
|
|
2314
|
-
else if (usingBinding) {
|
|
2315
|
-
return usingBinding.flags & 1048576 /* SymbolFlags.DuplicateUsing */ ? undefined : usingBinding;
|
|
2316
|
-
}
|
|
2317
|
-
}
|
|
2318
|
-
if (mapper === undefined) {
|
|
2319
|
-
reportCheckerDiagnostic(createDiagnostic({
|
|
2320
|
-
code: "unknown-identifier",
|
|
2321
|
-
format: { id: node.sv },
|
|
2322
|
-
target: node,
|
|
2323
|
-
codefixes: getCodefixesForUnknownIdentifier(node),
|
|
2324
|
-
}));
|
|
2325
|
-
}
|
|
2326
|
-
return undefined;
|
|
2327
|
-
}
|
|
2328
2101
|
function getCodefixesForUnknownIdentifier(node) {
|
|
2329
2102
|
switch (node.sv) {
|
|
2330
2103
|
case "number":
|
|
@@ -2355,14 +2128,37 @@ export function createChecker(program) {
|
|
|
2355
2128
|
if (node.kind === SyntaxKind.TypeReference) {
|
|
2356
2129
|
return resolveTypeReferenceSym(node.target, mapper, options);
|
|
2357
2130
|
}
|
|
2358
|
-
if (node.kind === SyntaxKind.
|
|
2359
|
-
|
|
2131
|
+
else if (node.kind === SyntaxKind.Identifier) {
|
|
2132
|
+
const links = resolver.getNodeLinks(node);
|
|
2133
|
+
if (mapper === undefined && links.resolutionResult) {
|
|
2134
|
+
if (mapper === undefined && // do not report error when instantiating
|
|
2135
|
+
links.resolutionResult & (ResolutionResultFlags.NotFound | ResolutionResultFlags.Unknown)) {
|
|
2136
|
+
reportCheckerDiagnostic(createDiagnostic({
|
|
2137
|
+
code: "invalid-ref",
|
|
2138
|
+
messageId: options.resolveDecorators ? "decorator" : "identifier",
|
|
2139
|
+
format: { id: printTypeReferenceNode(node) },
|
|
2140
|
+
target: node,
|
|
2141
|
+
codefixes: getCodefixesForUnknownIdentifier(node),
|
|
2142
|
+
}));
|
|
2143
|
+
}
|
|
2144
|
+
else if (links.resolutionResult & ResolutionResultFlags.Ambiguous) {
|
|
2145
|
+
reportAmbiguousIdentifier(node, links.ambiguousSymbols);
|
|
2146
|
+
}
|
|
2147
|
+
}
|
|
2148
|
+
const sym = links.resolvedSymbol;
|
|
2149
|
+
return sym?.symbolSource ?? sym;
|
|
2150
|
+
}
|
|
2151
|
+
else if (node.kind === SyntaxKind.MemberExpression) {
|
|
2152
|
+
let base = resolveTypeReferenceSym(node.base, mapper, {
|
|
2153
|
+
...options,
|
|
2154
|
+
resolveDecorators: false, // when resolving decorator the base cannot also be one
|
|
2155
|
+
});
|
|
2360
2156
|
if (!base) {
|
|
2361
2157
|
return undefined;
|
|
2362
2158
|
}
|
|
2363
2159
|
// when resolving a type reference based on an alias, unwrap the alias.
|
|
2364
|
-
if (base.flags &
|
|
2365
|
-
const aliasedSym = getAliasedSymbol(base, mapper
|
|
2160
|
+
if (base.flags & 128 /* SymbolFlags.Alias */) {
|
|
2161
|
+
const aliasedSym = getAliasedSymbol(base, mapper);
|
|
2366
2162
|
if (!aliasedSym) {
|
|
2367
2163
|
reportCheckerDiagnostic(createDiagnostic({
|
|
2368
2164
|
code: "invalid-ref",
|
|
@@ -2379,104 +2175,72 @@ export function createChecker(program) {
|
|
|
2379
2175
|
}
|
|
2380
2176
|
base = aliasedSym;
|
|
2381
2177
|
}
|
|
2382
|
-
|
|
2383
|
-
return resolveMemberInContainer(node, base, mapper, options);
|
|
2384
|
-
}
|
|
2385
|
-
else {
|
|
2386
|
-
return resolveMetaProperty(node, base);
|
|
2387
|
-
}
|
|
2388
|
-
}
|
|
2389
|
-
if (node.kind === SyntaxKind.Identifier) {
|
|
2390
|
-
const sym = resolveIdentifierInScope(node, mapper, options);
|
|
2391
|
-
if (!sym)
|
|
2392
|
-
return undefined;
|
|
2393
|
-
return sym.flags & 524288 /* SymbolFlags.Using */ ? sym.symbolSource : sym;
|
|
2178
|
+
return resolveMemberInContainer(base, node, options);
|
|
2394
2179
|
}
|
|
2395
2180
|
compilerAssert(false, `Unknown type reference kind "${SyntaxKind[node.kind]}"`, node);
|
|
2396
2181
|
}
|
|
2397
|
-
function
|
|
2398
|
-
|
|
2399
|
-
|
|
2400
|
-
|
|
2401
|
-
|
|
2402
|
-
|
|
2403
|
-
|
|
2404
|
-
|
|
2405
|
-
|
|
2406
|
-
|
|
2407
|
-
|
|
2408
|
-
|
|
2409
|
-
}));
|
|
2410
|
-
return undefined;
|
|
2411
|
-
}
|
|
2182
|
+
function reportAmbiguousIdentifier(node, symbols) {
|
|
2183
|
+
const duplicateNames = symbols.map((s) => getFullyQualifiedSymbolName(s, { useGlobalPrefixAtTopLevel: true }));
|
|
2184
|
+
program.reportDiagnostic(createDiagnostic({
|
|
2185
|
+
code: "ambiguous-symbol",
|
|
2186
|
+
format: { name: node.sv, duplicateNames: duplicateNames.join(", ") },
|
|
2187
|
+
target: node,
|
|
2188
|
+
}));
|
|
2189
|
+
}
|
|
2190
|
+
function resolveMemberInContainer(base, node, options) {
|
|
2191
|
+
const { finalSymbol: sym, resolvedSymbol: nextSym } = resolver.resolveMemberExpressionForSym(base, node, options);
|
|
2192
|
+
const symbol = nextSym ?? sym;
|
|
2193
|
+
if (symbol) {
|
|
2412
2194
|
return symbol;
|
|
2413
2195
|
}
|
|
2414
|
-
|
|
2196
|
+
if (base.flags & 256 /* SymbolFlags.Namespace */) {
|
|
2197
|
+
reportCheckerDiagnostic(createDiagnostic({
|
|
2198
|
+
code: "invalid-ref",
|
|
2199
|
+
messageId: "underNamespace",
|
|
2200
|
+
format: {
|
|
2201
|
+
namespace: getFullyQualifiedSymbolName(base),
|
|
2202
|
+
id: node.id.sv,
|
|
2203
|
+
},
|
|
2204
|
+
target: node,
|
|
2205
|
+
}));
|
|
2206
|
+
}
|
|
2207
|
+
else if (base.flags & 1024 /* SymbolFlags.Decorator */) {
|
|
2415
2208
|
reportCheckerDiagnostic(createDiagnostic({
|
|
2416
2209
|
code: "invalid-ref",
|
|
2417
2210
|
messageId: "inDecorator",
|
|
2418
2211
|
format: { id: node.id.sv },
|
|
2419
2212
|
target: node,
|
|
2420
2213
|
}));
|
|
2421
|
-
return undefined;
|
|
2422
2214
|
}
|
|
2423
|
-
else if (base.flags &
|
|
2215
|
+
else if (base.flags & 8192 /* SymbolFlags.Function */) {
|
|
2424
2216
|
reportCheckerDiagnostic(createDiagnostic({
|
|
2425
2217
|
code: "invalid-ref",
|
|
2426
2218
|
messageId: "node",
|
|
2427
2219
|
format: { id: node.id.sv, nodeName: "function" },
|
|
2428
2220
|
target: node,
|
|
2429
2221
|
}));
|
|
2430
|
-
return undefined;
|
|
2431
2222
|
}
|
|
2432
|
-
else if (base.flags &
|
|
2433
|
-
|
|
2434
|
-
|
|
2435
|
-
|
|
2436
|
-
|
|
2437
|
-
|
|
2438
|
-
|
|
2439
|
-
}
|
|
2440
|
-
}
|
|
2441
|
-
const sym = resolveIdentifierInTable(node.id, base.members, options);
|
|
2442
|
-
if (!sym) {
|
|
2443
|
-
reportCheckerDiagnostic(createDiagnostic({
|
|
2444
|
-
code: "invalid-ref",
|
|
2445
|
-
messageId: "underContainer",
|
|
2446
|
-
format: { kind: getMemberKindName(base.declarations[0]), id: node.id.sv },
|
|
2447
|
-
target: node,
|
|
2448
|
-
}));
|
|
2449
|
-
return undefined;
|
|
2450
|
-
}
|
|
2451
|
-
return sym;
|
|
2223
|
+
else if (base.flags & 118 /* SymbolFlags.MemberContainer */) {
|
|
2224
|
+
reportCheckerDiagnostic(createDiagnostic({
|
|
2225
|
+
code: "invalid-ref",
|
|
2226
|
+
messageId: node.selector === "." ? "member" : "metaProperty",
|
|
2227
|
+
format: { kind: getMemberKindName(getSymNode(base)), id: node.id.sv },
|
|
2228
|
+
target: node,
|
|
2229
|
+
}));
|
|
2452
2230
|
}
|
|
2453
2231
|
else {
|
|
2232
|
+
const symNode = getSymNode(base);
|
|
2454
2233
|
reportCheckerDiagnostic(createDiagnostic({
|
|
2455
2234
|
code: "invalid-ref",
|
|
2456
2235
|
messageId: "node",
|
|
2457
2236
|
format: {
|
|
2458
2237
|
id: node.id.sv,
|
|
2459
|
-
nodeName:
|
|
2238
|
+
nodeName: symNode ? SyntaxKind[symNode.kind] : "Unknown node",
|
|
2460
2239
|
},
|
|
2461
2240
|
target: node,
|
|
2462
2241
|
}));
|
|
2463
|
-
return undefined;
|
|
2464
|
-
}
|
|
2465
|
-
}
|
|
2466
|
-
function resolveMetaProperty(node, base) {
|
|
2467
|
-
const resolved = resolveIdentifierInTable(node.id, base.metatypeMembers, {
|
|
2468
|
-
resolveDecorators: false,
|
|
2469
|
-
checkTemplateTypes: false,
|
|
2470
|
-
});
|
|
2471
|
-
if (!resolved) {
|
|
2472
|
-
reportCheckerDiagnostic(createDiagnostic({
|
|
2473
|
-
code: "invalid-ref",
|
|
2474
|
-
messageId: "metaProperty",
|
|
2475
|
-
format: { kind: getMemberKindName(base.declarations[0]), id: node.id.sv },
|
|
2476
|
-
target: node,
|
|
2477
|
-
}));
|
|
2478
2242
|
}
|
|
2479
|
-
return
|
|
2243
|
+
return undefined;
|
|
2480
2244
|
}
|
|
2481
2245
|
function getMemberKindName(node) {
|
|
2482
2246
|
switch (node.kind) {
|
|
@@ -2501,30 +2265,13 @@ export function createChecker(program) {
|
|
|
2501
2265
|
* (i.e. they contain symbols we don't know until we've instantiated the type and the type is an
|
|
2502
2266
|
* instantiation) we late bind the container which creates the symbol that will hold its members.
|
|
2503
2267
|
*/
|
|
2504
|
-
function getAliasedSymbol(aliasSymbol, mapper
|
|
2505
|
-
|
|
2506
|
-
|
|
2507
|
-
|
|
2508
|
-
|
|
2509
|
-
if (targetNode.kind === SyntaxKind.TypeReference ||
|
|
2510
|
-
targetNode.kind === SyntaxKind.MemberExpression ||
|
|
2511
|
-
targetNode.kind === SyntaxKind.Identifier) {
|
|
2512
|
-
const sym = resolveTypeReferenceSymInternal(targetNode, mapper, options);
|
|
2513
|
-
if (sym === undefined) {
|
|
2514
|
-
return undefined;
|
|
2515
|
-
}
|
|
2516
|
-
current = sym;
|
|
2517
|
-
}
|
|
2518
|
-
else {
|
|
2519
|
-
return undefined;
|
|
2520
|
-
}
|
|
2521
|
-
}
|
|
2522
|
-
const sym = current;
|
|
2523
|
-
const node = aliasSymbol.declarations[0];
|
|
2524
|
-
const resolvedTargetNode = sym.declarations[0];
|
|
2525
|
-
if (!options.checkTemplateTypes || !isTemplatedNode(resolvedTargetNode)) {
|
|
2526
|
-
return sym;
|
|
2268
|
+
function getAliasedSymbol(aliasSymbol, mapper) {
|
|
2269
|
+
const node = getSymNode(aliasSymbol);
|
|
2270
|
+
const links = resolver.getSymbolLinks(aliasSymbol);
|
|
2271
|
+
if (!links.aliasResolutionIsTemplate) {
|
|
2272
|
+
return links.aliasedSymbol ?? resolver.getNodeLinks(node).resolvedSymbol;
|
|
2527
2273
|
}
|
|
2274
|
+
// Otherwise for templates we need to get the type and retrieve the late bound symbol.
|
|
2528
2275
|
const aliasType = getTypeForNode(node, mapper);
|
|
2529
2276
|
if (isErrorType(aliasType)) {
|
|
2530
2277
|
return undefined;
|
|
@@ -2688,27 +2435,58 @@ export function createChecker(program) {
|
|
|
2688
2435
|
};
|
|
2689
2436
|
}
|
|
2690
2437
|
function checkProgram() {
|
|
2691
|
-
|
|
2438
|
+
checkDuplicateSymbols();
|
|
2692
2439
|
for (const file of program.sourceFiles.values()) {
|
|
2693
|
-
|
|
2440
|
+
checkDuplicateUsings(file);
|
|
2441
|
+
for (const ns of file.namespaces) {
|
|
2442
|
+
initializeTypeForNamespace(ns);
|
|
2443
|
+
}
|
|
2694
2444
|
}
|
|
2695
2445
|
for (const file of program.sourceFiles.values()) {
|
|
2696
|
-
|
|
2446
|
+
checkSourceFile(file);
|
|
2697
2447
|
}
|
|
2448
|
+
internalDecoratorValidation();
|
|
2449
|
+
}
|
|
2450
|
+
function checkDuplicateSymbols() {
|
|
2451
|
+
program.reportDuplicateSymbols(resolver.symbols.global.exports);
|
|
2698
2452
|
for (const file of program.sourceFiles.values()) {
|
|
2699
2453
|
for (const ns of file.namespaces) {
|
|
2700
|
-
const exports =
|
|
2454
|
+
const exports = getMergedSymbol(ns.symbol).exports ?? ns.symbol.exports;
|
|
2701
2455
|
program.reportDuplicateSymbols(exports);
|
|
2702
|
-
initializeTypeForNamespace(ns);
|
|
2703
2456
|
}
|
|
2704
2457
|
}
|
|
2705
|
-
|
|
2706
|
-
|
|
2458
|
+
}
|
|
2459
|
+
/** Report error with duplicate using in the same scope. */
|
|
2460
|
+
function checkDuplicateUsings(file) {
|
|
2461
|
+
const duplicateTrackers = new Map();
|
|
2462
|
+
function getTracker(sym) {
|
|
2463
|
+
const existing = duplicateTrackers.get(sym);
|
|
2464
|
+
if (existing)
|
|
2465
|
+
return existing;
|
|
2466
|
+
const newTacker = new DuplicateTracker();
|
|
2467
|
+
duplicateTrackers.set(sym, newTacker);
|
|
2468
|
+
return newTacker;
|
|
2707
2469
|
}
|
|
2708
|
-
for (const
|
|
2709
|
-
|
|
2470
|
+
for (const using of file.usings) {
|
|
2471
|
+
const ns = using.parent;
|
|
2472
|
+
const sym = getMergedSymbol(ns.symbol);
|
|
2473
|
+
const tracker = getTracker(sym);
|
|
2474
|
+
const targetSym = resolver.getNodeLinks(using.name).resolvedSymbol;
|
|
2475
|
+
if (!targetSym)
|
|
2476
|
+
continue;
|
|
2477
|
+
tracker.track(targetSym, using);
|
|
2478
|
+
}
|
|
2479
|
+
for (const tracker of duplicateTrackers.values()) {
|
|
2480
|
+
for (const [_, nodes] of tracker.entries()) {
|
|
2481
|
+
for (const node of nodes) {
|
|
2482
|
+
program.reportDiagnostic(createDiagnostic({
|
|
2483
|
+
code: "duplicate-using",
|
|
2484
|
+
format: { usingName: typeReferenceToString(node.name) },
|
|
2485
|
+
target: node,
|
|
2486
|
+
}));
|
|
2487
|
+
}
|
|
2488
|
+
}
|
|
2710
2489
|
}
|
|
2711
|
-
internalDecoratorValidation();
|
|
2712
2490
|
}
|
|
2713
2491
|
/**
|
|
2714
2492
|
* Post checking validation for internal decorators.
|
|
@@ -2716,22 +2494,6 @@ export function createChecker(program) {
|
|
|
2716
2494
|
function internalDecoratorValidation() {
|
|
2717
2495
|
validateInheritanceDiscriminatedUnions(program);
|
|
2718
2496
|
}
|
|
2719
|
-
function applyAugmentDecoratorsInScope(scope) {
|
|
2720
|
-
applyAugmentDecorators(scope);
|
|
2721
|
-
if (scope.statements === undefined) {
|
|
2722
|
-
return;
|
|
2723
|
-
}
|
|
2724
|
-
if (isArray(scope.statements)) {
|
|
2725
|
-
for (const statement of scope.statements) {
|
|
2726
|
-
if (statement.kind === SyntaxKind.NamespaceStatement) {
|
|
2727
|
-
applyAugmentDecoratorsInScope(statement);
|
|
2728
|
-
}
|
|
2729
|
-
}
|
|
2730
|
-
}
|
|
2731
|
-
else {
|
|
2732
|
-
applyAugmentDecoratorsInScope(scope.statements);
|
|
2733
|
-
}
|
|
2734
|
-
}
|
|
2735
2497
|
function checkSourceFile(file) {
|
|
2736
2498
|
for (const statement of file.statements) {
|
|
2737
2499
|
checkNode(statement, undefined);
|
|
@@ -2778,7 +2540,7 @@ export function createChecker(program) {
|
|
|
2778
2540
|
});
|
|
2779
2541
|
linkType(links, type, mapper);
|
|
2780
2542
|
if (node.symbol.members) {
|
|
2781
|
-
const members =
|
|
2543
|
+
const members = resolver.getAugmentedSymbolTable(node.symbol.members);
|
|
2782
2544
|
const propDocs = extractPropDocs(node);
|
|
2783
2545
|
for (const [name, memberSym] of members) {
|
|
2784
2546
|
const doc = propDocs.get(name);
|
|
@@ -2842,6 +2604,8 @@ export function createChecker(program) {
|
|
|
2842
2604
|
if (indexer) {
|
|
2843
2605
|
type.indexer = indexer;
|
|
2844
2606
|
}
|
|
2607
|
+
lateBindMemberContainer(type);
|
|
2608
|
+
lateBindMembers(type);
|
|
2845
2609
|
return type;
|
|
2846
2610
|
}
|
|
2847
2611
|
function shouldCreateTypeForTemplate(node, mapper) {
|
|
@@ -2858,6 +2622,11 @@ export function createChecker(program) {
|
|
|
2858
2622
|
mapper.args.every((t) => isValue(t) || t.entityKind === "Indeterminate" || t.kind !== "TemplateParameter"));
|
|
2859
2623
|
}
|
|
2860
2624
|
function checkModelExpression(node, mapper) {
|
|
2625
|
+
const links = getSymbolLinks(node.symbol);
|
|
2626
|
+
if (links.declaredType && mapper === undefined) {
|
|
2627
|
+
// we're not instantiating this model and we've already checked it
|
|
2628
|
+
return links.declaredType;
|
|
2629
|
+
}
|
|
2861
2630
|
const properties = createRekeyableMap();
|
|
2862
2631
|
const type = createType({
|
|
2863
2632
|
kind: "Model",
|
|
@@ -2870,6 +2639,7 @@ export function createChecker(program) {
|
|
|
2870
2639
|
derivedModels: [],
|
|
2871
2640
|
sourceModels: [],
|
|
2872
2641
|
});
|
|
2642
|
+
linkType(links, type, mapper);
|
|
2873
2643
|
linkMapper(type, mapper);
|
|
2874
2644
|
checkModelProperties(node, properties, type, mapper);
|
|
2875
2645
|
return finishType(type);
|
|
@@ -3429,190 +3199,6 @@ export function createChecker(program) {
|
|
|
3429
3199
|
}
|
|
3430
3200
|
properties.set(newProp.name, newProp);
|
|
3431
3201
|
}
|
|
3432
|
-
function bindAllMembers(node) {
|
|
3433
|
-
const bound = new Set();
|
|
3434
|
-
if (node.symbol) {
|
|
3435
|
-
bindMembers(node, node.symbol);
|
|
3436
|
-
}
|
|
3437
|
-
visitChildren(node, (child) => {
|
|
3438
|
-
bindAllMembers(child);
|
|
3439
|
-
});
|
|
3440
|
-
function bindMembers(node, containerSym) {
|
|
3441
|
-
if (bound.has(containerSym)) {
|
|
3442
|
-
return;
|
|
3443
|
-
}
|
|
3444
|
-
bound.add(containerSym);
|
|
3445
|
-
let containerMembers;
|
|
3446
|
-
switch (node.kind) {
|
|
3447
|
-
case SyntaxKind.ModelStatement:
|
|
3448
|
-
if (node.extends && node.extends.kind === SyntaxKind.TypeReference) {
|
|
3449
|
-
resolveAndCopyMembers(node.extends);
|
|
3450
|
-
}
|
|
3451
|
-
if (node.is && node.is.kind === SyntaxKind.TypeReference) {
|
|
3452
|
-
resolveAndCopyMembers(node.is);
|
|
3453
|
-
}
|
|
3454
|
-
for (const prop of node.properties) {
|
|
3455
|
-
if (prop.kind === SyntaxKind.ModelSpreadProperty) {
|
|
3456
|
-
resolveAndCopyMembers(prop.target);
|
|
3457
|
-
}
|
|
3458
|
-
else {
|
|
3459
|
-
const name = prop.id.sv;
|
|
3460
|
-
bindMember(name, prop, 4 /* SymbolFlags.ModelProperty */);
|
|
3461
|
-
}
|
|
3462
|
-
}
|
|
3463
|
-
break;
|
|
3464
|
-
case SyntaxKind.ScalarStatement:
|
|
3465
|
-
if (node.extends && node.extends.kind === SyntaxKind.TypeReference) {
|
|
3466
|
-
resolveAndCopyMembers(node.extends);
|
|
3467
|
-
}
|
|
3468
|
-
for (const member of node.members) {
|
|
3469
|
-
const name = member.id.sv;
|
|
3470
|
-
bindMember(name, member, 33554432 /* SymbolFlags.ScalarMember */);
|
|
3471
|
-
}
|
|
3472
|
-
break;
|
|
3473
|
-
case SyntaxKind.ModelExpression:
|
|
3474
|
-
for (const prop of node.properties) {
|
|
3475
|
-
if (prop.kind === SyntaxKind.ModelSpreadProperty) {
|
|
3476
|
-
resolveAndCopyMembers(prop.target);
|
|
3477
|
-
}
|
|
3478
|
-
else {
|
|
3479
|
-
const name = prop.id.sv;
|
|
3480
|
-
bindMember(name, prop, 4 /* SymbolFlags.ModelProperty */);
|
|
3481
|
-
}
|
|
3482
|
-
}
|
|
3483
|
-
break;
|
|
3484
|
-
case SyntaxKind.EnumStatement:
|
|
3485
|
-
for (const member of node.members.values()) {
|
|
3486
|
-
if (member.kind === SyntaxKind.EnumSpreadMember) {
|
|
3487
|
-
resolveAndCopyMembers(member.target);
|
|
3488
|
-
}
|
|
3489
|
-
else {
|
|
3490
|
-
const name = member.id.sv;
|
|
3491
|
-
bindMember(name, member, 64 /* SymbolFlags.EnumMember */);
|
|
3492
|
-
}
|
|
3493
|
-
}
|
|
3494
|
-
break;
|
|
3495
|
-
case SyntaxKind.InterfaceStatement:
|
|
3496
|
-
for (const member of node.operations.values()) {
|
|
3497
|
-
bindMember(member.id.sv, member, 256 /* SymbolFlags.InterfaceMember */ | 16 /* SymbolFlags.Operation */);
|
|
3498
|
-
}
|
|
3499
|
-
if (node.extends) {
|
|
3500
|
-
for (const ext of node.extends) {
|
|
3501
|
-
resolveAndCopyMembers(ext);
|
|
3502
|
-
}
|
|
3503
|
-
}
|
|
3504
|
-
break;
|
|
3505
|
-
case SyntaxKind.UnionStatement:
|
|
3506
|
-
for (const variant of node.options.values()) {
|
|
3507
|
-
if (!variant.id) {
|
|
3508
|
-
continue;
|
|
3509
|
-
}
|
|
3510
|
-
const name = variant.id.sv;
|
|
3511
|
-
bindMember(name, variant, 1024 /* SymbolFlags.UnionVariant */);
|
|
3512
|
-
}
|
|
3513
|
-
break;
|
|
3514
|
-
}
|
|
3515
|
-
function resolveAndCopyMembers(node) {
|
|
3516
|
-
let ref = resolveTypeReferenceSym(node, undefined);
|
|
3517
|
-
if (ref && ref.flags & 2048 /* SymbolFlags.Alias */) {
|
|
3518
|
-
ref = resolveAliasedSymbol(ref);
|
|
3519
|
-
}
|
|
3520
|
-
if (ref && ref.members) {
|
|
3521
|
-
bindMembers(ref.declarations[0], ref);
|
|
3522
|
-
copyMembers(ref.members);
|
|
3523
|
-
}
|
|
3524
|
-
}
|
|
3525
|
-
function resolveAliasedSymbol(ref) {
|
|
3526
|
-
const node = ref.declarations[0];
|
|
3527
|
-
switch (node.value.kind) {
|
|
3528
|
-
case SyntaxKind.MemberExpression:
|
|
3529
|
-
case SyntaxKind.TypeReference:
|
|
3530
|
-
const resolvedSym = resolveTypeReferenceSym(node.value, undefined);
|
|
3531
|
-
if (resolvedSym && resolvedSym.flags & 2048 /* SymbolFlags.Alias */) {
|
|
3532
|
-
return resolveAliasedSymbol(resolvedSym);
|
|
3533
|
-
}
|
|
3534
|
-
return resolvedSym;
|
|
3535
|
-
default:
|
|
3536
|
-
return undefined;
|
|
3537
|
-
}
|
|
3538
|
-
}
|
|
3539
|
-
function copyMembers(table) {
|
|
3540
|
-
const members = augmentedSymbolTables.get(table) ?? table;
|
|
3541
|
-
for (const member of members.values()) {
|
|
3542
|
-
bindMember(member.name, member.declarations[0], member.flags);
|
|
3543
|
-
}
|
|
3544
|
-
}
|
|
3545
|
-
function bindMember(name, node, kind) {
|
|
3546
|
-
const sym = createSymbol(node, name, kind, containerSym);
|
|
3547
|
-
compilerAssert(containerSym.members, "containerSym.members is undefined");
|
|
3548
|
-
containerMembers ??= getOrCreateAugmentedSymbolTable(containerSym.members);
|
|
3549
|
-
containerMembers.set(name, sym);
|
|
3550
|
-
}
|
|
3551
|
-
}
|
|
3552
|
-
}
|
|
3553
|
-
function copyMembersToContainer(targetContainerSym, table) {
|
|
3554
|
-
const members = augmentedSymbolTables.get(table) ?? table;
|
|
3555
|
-
compilerAssert(targetContainerSym.members, "containerSym.members is undefined");
|
|
3556
|
-
const containerMembers = getOrCreateAugmentedSymbolTable(targetContainerSym.members);
|
|
3557
|
-
for (const member of members.values()) {
|
|
3558
|
-
bindMemberToContainer(targetContainerSym, containerMembers, member.name, member.declarations[0], member.flags);
|
|
3559
|
-
}
|
|
3560
|
-
}
|
|
3561
|
-
function bindMemberToContainer(containerSym, containerMembers, name, node, kind) {
|
|
3562
|
-
const sym = createSymbol(node, name, kind, containerSym);
|
|
3563
|
-
compilerAssert(containerSym.members, "containerSym.members is undefined");
|
|
3564
|
-
containerMembers.set(name, sym);
|
|
3565
|
-
}
|
|
3566
|
-
function bindMetaTypes(node) {
|
|
3567
|
-
const visited = new Set();
|
|
3568
|
-
function visit(node, symbol) {
|
|
3569
|
-
if (visited.has(node)) {
|
|
3570
|
-
return;
|
|
3571
|
-
}
|
|
3572
|
-
visited.add(node);
|
|
3573
|
-
switch (node.kind) {
|
|
3574
|
-
case SyntaxKind.ModelProperty: {
|
|
3575
|
-
const sym = getSymbolForMember(node);
|
|
3576
|
-
if (sym) {
|
|
3577
|
-
const table = getOrCreateAugmentedSymbolTable(sym.metatypeMembers);
|
|
3578
|
-
table.set("type", node.value.kind === SyntaxKind.TypeReference
|
|
3579
|
-
? createSymbol(node.value, "", 2048 /* SymbolFlags.Alias */)
|
|
3580
|
-
: node.value.symbol);
|
|
3581
|
-
}
|
|
3582
|
-
break;
|
|
3583
|
-
}
|
|
3584
|
-
case SyntaxKind.OperationStatement: {
|
|
3585
|
-
const sym = symbol ?? node.symbol ?? getSymbolForMember(node);
|
|
3586
|
-
const table = getOrCreateAugmentedSymbolTable(sym.metatypeMembers);
|
|
3587
|
-
if (node.signature.kind === SyntaxKind.OperationSignatureDeclaration) {
|
|
3588
|
-
table.set("parameters", node.signature.parameters.symbol);
|
|
3589
|
-
table.set("returnType", node.signature.returnType.symbol);
|
|
3590
|
-
}
|
|
3591
|
-
else {
|
|
3592
|
-
const sig = resolveTypeReferenceSym(node.signature.baseOperation, undefined, {
|
|
3593
|
-
checkTemplateTypes: false,
|
|
3594
|
-
});
|
|
3595
|
-
if (sig) {
|
|
3596
|
-
visit(sig.declarations[0], sig);
|
|
3597
|
-
const sigTable = getOrCreateAugmentedSymbolTable(sig.metatypeMembers);
|
|
3598
|
-
const sigParameterSym = sigTable.get("parameters");
|
|
3599
|
-
if (sigParameterSym !== undefined) {
|
|
3600
|
-
const parametersSym = createSymbol(sigParameterSym.declarations[0], "parameters", 2 /* SymbolFlags.Model */ & 682 /* SymbolFlags.MemberContainer */);
|
|
3601
|
-
copyMembersToContainer(parametersSym, sigParameterSym.members);
|
|
3602
|
-
table.set("parameters", parametersSym);
|
|
3603
|
-
table.set("returnType", sigTable.get("returnType"));
|
|
3604
|
-
}
|
|
3605
|
-
}
|
|
3606
|
-
}
|
|
3607
|
-
break;
|
|
3608
|
-
}
|
|
3609
|
-
}
|
|
3610
|
-
visitChildren(node, (child) => {
|
|
3611
|
-
bindMetaTypes(child);
|
|
3612
|
-
});
|
|
3613
|
-
}
|
|
3614
|
-
visit(node);
|
|
3615
|
-
}
|
|
3616
3202
|
/**
|
|
3617
3203
|
* Initializes a late bound symbol for the type. This is generally necessary when attempting to
|
|
3618
3204
|
* access a symbol for a type that is created during the check phase.
|
|
@@ -3622,47 +3208,53 @@ export function createChecker(program) {
|
|
|
3622
3208
|
return;
|
|
3623
3209
|
switch (type.kind) {
|
|
3624
3210
|
case "Model":
|
|
3625
|
-
type.symbol = createSymbol(type.node, type.name, 2 /* SymbolFlags.Model */ |
|
|
3211
|
+
type.symbol = createSymbol(type.node, type.name, 2 /* SymbolFlags.Model */ | 4194304 /* SymbolFlags.LateBound */);
|
|
3626
3212
|
mutate(type.symbol).type = type;
|
|
3627
3213
|
break;
|
|
3628
3214
|
case "Interface":
|
|
3629
|
-
type.symbol = createSymbol(type.node, type.name,
|
|
3215
|
+
type.symbol = createSymbol(type.node, type.name, 32 /* SymbolFlags.Interface */ | 4194304 /* SymbolFlags.LateBound */);
|
|
3216
|
+
if (isTemplateInstance(type) && type.name === "Foo") {
|
|
3217
|
+
getSymbolLinks(type.symbol);
|
|
3218
|
+
}
|
|
3630
3219
|
mutate(type.symbol).type = type;
|
|
3631
3220
|
break;
|
|
3632
3221
|
case "Union":
|
|
3633
3222
|
if (!type.name)
|
|
3634
3223
|
return; // don't make a symbol for anonymous unions
|
|
3635
|
-
type.symbol = createSymbol(type.node, type.name,
|
|
3224
|
+
type.symbol = createSymbol(type.node, type.name, 64 /* SymbolFlags.Union */ | 4194304 /* SymbolFlags.LateBound */);
|
|
3636
3225
|
mutate(type.symbol).type = type;
|
|
3637
3226
|
break;
|
|
3638
3227
|
}
|
|
3639
3228
|
}
|
|
3640
|
-
function lateBindMembers(type
|
|
3641
|
-
|
|
3229
|
+
function lateBindMembers(type) {
|
|
3230
|
+
compilerAssert(type.symbol, "Type must have a symbol to late bind members");
|
|
3231
|
+
const containerSym = type.symbol;
|
|
3232
|
+
compilerAssert(containerSym.members, "Container symbol didn't have members at late-bind");
|
|
3233
|
+
const containerMembers = resolver.getAugmentedSymbolTable(containerSym.members);
|
|
3642
3234
|
switch (type.kind) {
|
|
3643
3235
|
case "Model":
|
|
3644
3236
|
for (const prop of walkPropertiesInherited(type)) {
|
|
3645
|
-
lateBindMember(prop,
|
|
3237
|
+
lateBindMember(prop, 262144 /* SymbolFlags.Member */ | 1048576 /* SymbolFlags.Declaration */);
|
|
3646
3238
|
}
|
|
3647
3239
|
break;
|
|
3648
3240
|
case "Scalar":
|
|
3649
3241
|
for (const member of type.constructors.values()) {
|
|
3650
|
-
lateBindMember(member,
|
|
3242
|
+
lateBindMember(member, 262144 /* SymbolFlags.Member */ | 1048576 /* SymbolFlags.Declaration */);
|
|
3651
3243
|
}
|
|
3652
3244
|
break;
|
|
3653
3245
|
case "Enum":
|
|
3654
3246
|
for (const member of type.members.values()) {
|
|
3655
|
-
lateBindMember(member,
|
|
3247
|
+
lateBindMember(member, 262144 /* SymbolFlags.Member */ | 1048576 /* SymbolFlags.Declaration */);
|
|
3656
3248
|
}
|
|
3657
3249
|
break;
|
|
3658
3250
|
case "Interface":
|
|
3659
3251
|
for (const member of type.operations.values()) {
|
|
3660
|
-
lateBindMember(member,
|
|
3252
|
+
lateBindMember(member, 262144 /* SymbolFlags.Member */ | 8 /* SymbolFlags.Operation */ | 1048576 /* SymbolFlags.Declaration */);
|
|
3661
3253
|
}
|
|
3662
3254
|
break;
|
|
3663
3255
|
case "Union":
|
|
3664
3256
|
for (const variant of type.variants.values()) {
|
|
3665
|
-
lateBindMember(variant,
|
|
3257
|
+
lateBindMember(variant, 262144 /* SymbolFlags.Member */ | 1048576 /* SymbolFlags.Declaration */);
|
|
3666
3258
|
}
|
|
3667
3259
|
break;
|
|
3668
3260
|
}
|
|
@@ -3671,10 +3263,9 @@ export function createChecker(program) {
|
|
|
3671
3263
|
// don't bind anything for union expressions
|
|
3672
3264
|
return;
|
|
3673
3265
|
}
|
|
3674
|
-
const sym = createSymbol(member.node, member.name, kind |
|
|
3266
|
+
const sym = createSymbol(member.node, member.name, kind | 4194304 /* SymbolFlags.LateBound */, containerSym);
|
|
3675
3267
|
mutate(sym).type = member;
|
|
3676
3268
|
compilerAssert(containerSym.members, "containerSym.members is undefined");
|
|
3677
|
-
containerMembers ??= getOrCreateAugmentedSymbolTable(containerSym.members);
|
|
3678
3269
|
containerMembers.set(member.name, sym);
|
|
3679
3270
|
}
|
|
3680
3271
|
}
|
|
@@ -3694,23 +3285,20 @@ export function createChecker(program) {
|
|
|
3694
3285
|
}));
|
|
3695
3286
|
return undefined;
|
|
3696
3287
|
}
|
|
3697
|
-
const modelSymId =
|
|
3288
|
+
const modelSymId = getNodeSym(model);
|
|
3698
3289
|
pendingResolutions.start(modelSymId, ResolutionKind.BaseType);
|
|
3699
|
-
const target =
|
|
3700
|
-
if (target
|
|
3701
|
-
return undefined;
|
|
3702
|
-
}
|
|
3703
|
-
if (pendingResolutions.has(getNodeSymId(target.declarations[0]), ResolutionKind.BaseType)) {
|
|
3290
|
+
const target = resolver.getNodeLinks(heritageRef).resolvedSymbol;
|
|
3291
|
+
if (target && pendingResolutions.has(target, ResolutionKind.BaseType)) {
|
|
3704
3292
|
if (mapper === undefined) {
|
|
3705
3293
|
reportCheckerDiagnostic(createDiagnostic({
|
|
3706
3294
|
code: "circular-base-type",
|
|
3707
|
-
format: { typeName: target.
|
|
3295
|
+
format: { typeName: target.name },
|
|
3708
3296
|
target: target,
|
|
3709
3297
|
}));
|
|
3710
3298
|
}
|
|
3711
3299
|
return undefined;
|
|
3712
3300
|
}
|
|
3713
|
-
const heritageType =
|
|
3301
|
+
const heritageType = getTypeForNode(heritageRef, mapper);
|
|
3714
3302
|
pendingResolutions.finish(modelSymId, ResolutionKind.BaseType);
|
|
3715
3303
|
if (isErrorType(heritageType)) {
|
|
3716
3304
|
compilerAssert(program.hasError(), "Should already have reported an error.", heritageRef);
|
|
@@ -3732,7 +3320,7 @@ export function createChecker(program) {
|
|
|
3732
3320
|
function checkModelIs(model, isExpr, mapper) {
|
|
3733
3321
|
if (!isExpr)
|
|
3734
3322
|
return undefined;
|
|
3735
|
-
const modelSymId =
|
|
3323
|
+
const modelSymId = getNodeSym(model);
|
|
3736
3324
|
pendingResolutions.start(modelSymId, ResolutionKind.BaseType);
|
|
3737
3325
|
let isType;
|
|
3738
3326
|
if (isExpr.kind === SyntaxKind.ModelExpression) {
|
|
@@ -3747,21 +3335,18 @@ export function createChecker(program) {
|
|
|
3747
3335
|
isType = checkArrayExpression(isExpr, mapper);
|
|
3748
3336
|
}
|
|
3749
3337
|
else if (isExpr.kind === SyntaxKind.TypeReference) {
|
|
3750
|
-
const target =
|
|
3751
|
-
if (target
|
|
3752
|
-
return undefined;
|
|
3753
|
-
}
|
|
3754
|
-
if (pendingResolutions.has(getNodeSymId(target.declarations[0]), ResolutionKind.BaseType)) {
|
|
3338
|
+
const target = resolver.getNodeLinks(isExpr).resolvedSymbol;
|
|
3339
|
+
if (target && pendingResolutions.has(target, ResolutionKind.BaseType)) {
|
|
3755
3340
|
if (mapper === undefined) {
|
|
3756
3341
|
reportCheckerDiagnostic(createDiagnostic({
|
|
3757
3342
|
code: "circular-base-type",
|
|
3758
|
-
format: { typeName: target.
|
|
3343
|
+
format: { typeName: target.name },
|
|
3759
3344
|
target: target,
|
|
3760
3345
|
}));
|
|
3761
3346
|
}
|
|
3762
3347
|
return undefined;
|
|
3763
3348
|
}
|
|
3764
|
-
isType =
|
|
3349
|
+
isType = getTypeForNode(isExpr, mapper);
|
|
3765
3350
|
}
|
|
3766
3351
|
else {
|
|
3767
3352
|
reportCheckerDiagnostic(createDiagnostic({ code: "is-model", target: isExpr }));
|
|
@@ -3824,16 +3409,14 @@ export function createChecker(program) {
|
|
|
3824
3409
|
if (containerNode.symbol === undefined) {
|
|
3825
3410
|
return;
|
|
3826
3411
|
}
|
|
3827
|
-
|
|
3828
|
-
const memberSym = getOrCreateAugmentedSymbolTable(containerNode.symbol.members).get(member.name);
|
|
3412
|
+
const memberSym = getMemberSymbol(containerNode.symbol, member.name);
|
|
3829
3413
|
if (memberSym) {
|
|
3830
|
-
const links = getSymbolLinks(memberSym);
|
|
3414
|
+
const links = resolver.getSymbolLinks(memberSym);
|
|
3831
3415
|
linkMemberType(links, member, mapper);
|
|
3832
3416
|
}
|
|
3833
3417
|
}
|
|
3834
3418
|
function checkModelProperty(prop, mapper) {
|
|
3835
3419
|
const sym = getSymbolForMember(prop);
|
|
3836
|
-
const symId = getSymbolId(sym);
|
|
3837
3420
|
const links = getSymbolLinksForMember(prop);
|
|
3838
3421
|
if (links && links.declaredType && mapper === undefined) {
|
|
3839
3422
|
return links.declaredType;
|
|
@@ -3847,7 +3430,7 @@ export function createChecker(program) {
|
|
|
3847
3430
|
type: undefined,
|
|
3848
3431
|
decorators: [],
|
|
3849
3432
|
});
|
|
3850
|
-
if (pendingResolutions.has(
|
|
3433
|
+
if (pendingResolutions.has(sym, ResolutionKind.Type) && mapper === undefined) {
|
|
3851
3434
|
reportCheckerDiagnostic(createDiagnostic({
|
|
3852
3435
|
code: "circular-prop",
|
|
3853
3436
|
format: { propName: name },
|
|
@@ -3856,7 +3439,7 @@ export function createChecker(program) {
|
|
|
3856
3439
|
type.type = errorType;
|
|
3857
3440
|
}
|
|
3858
3441
|
else {
|
|
3859
|
-
pendingResolutions.start(
|
|
3442
|
+
pendingResolutions.start(sym, ResolutionKind.Type);
|
|
3860
3443
|
type.type = getTypeForNode(prop.value, mapper);
|
|
3861
3444
|
if (prop.default) {
|
|
3862
3445
|
const defaultValue = checkDefaultValue(prop.default, type.type);
|
|
@@ -3880,12 +3463,12 @@ export function createChecker(program) {
|
|
|
3880
3463
|
}
|
|
3881
3464
|
finishType(type);
|
|
3882
3465
|
}
|
|
3883
|
-
pendingResolutions.finish(
|
|
3466
|
+
pendingResolutions.finish(sym, ResolutionKind.Type);
|
|
3884
3467
|
return type;
|
|
3885
3468
|
}
|
|
3886
3469
|
function createDocFromCommentDecorator(key, doc) {
|
|
3887
3470
|
return {
|
|
3888
|
-
decorator:
|
|
3471
|
+
decorator: docFromCommentDecorator,
|
|
3889
3472
|
args: [
|
|
3890
3473
|
{ value: createLiteralType(key), jsValue: key },
|
|
3891
3474
|
{ value: createLiteralType(doc), jsValue: doc },
|
|
@@ -3930,13 +3513,10 @@ export function createChecker(program) {
|
|
|
3930
3513
|
function checkDecoratorApplication(targetType, decNode, mapper) {
|
|
3931
3514
|
const sym = resolveTypeReferenceSym(decNode.target, undefined, true);
|
|
3932
3515
|
if (!sym) {
|
|
3933
|
-
|
|
3934
|
-
code: "unknown-decorator",
|
|
3935
|
-
target: decNode,
|
|
3936
|
-
}));
|
|
3516
|
+
// Error should already have been reported above
|
|
3937
3517
|
return undefined;
|
|
3938
3518
|
}
|
|
3939
|
-
if (!(sym.flags &
|
|
3519
|
+
if (!(sym.flags & 1024 /* SymbolFlags.Decorator */)) {
|
|
3940
3520
|
reportCheckerDiagnostic(createDiagnostic({
|
|
3941
3521
|
code: "invalid-decorator",
|
|
3942
3522
|
format: { id: sym.name },
|
|
@@ -3953,7 +3533,7 @@ export function createChecker(program) {
|
|
|
3953
3533
|
}
|
|
3954
3534
|
}
|
|
3955
3535
|
if (symbolLinks.declaredType) {
|
|
3956
|
-
compilerAssert(symbolLinks.declaredType.kind === "Decorator",
|
|
3536
|
+
compilerAssert(symbolLinks.declaredType.kind === "Decorator", `Expected to find a decorator type but got ${symbolLinks.declaredType.kind}`);
|
|
3957
3537
|
if (!checkDecoratorTarget(targetType, symbolLinks.declaredType, decNode)) {
|
|
3958
3538
|
hasError = true;
|
|
3959
3539
|
}
|
|
@@ -4162,7 +3742,7 @@ export function createChecker(program) {
|
|
|
4162
3742
|
return valid;
|
|
4163
3743
|
}
|
|
4164
3744
|
function checkAugmentDecorators(sym, targetType, mapper) {
|
|
4165
|
-
const augmentDecoratorNodes =
|
|
3745
|
+
const augmentDecoratorNodes = resolver.getAugmentDecoratorsForSym(sym);
|
|
4166
3746
|
const decorators = [];
|
|
4167
3747
|
for (const decNode of augmentDecoratorNodes) {
|
|
4168
3748
|
const decorator = checkDecoratorApplication(targetType, decNode, mapper);
|
|
@@ -4172,10 +3752,42 @@ export function createChecker(program) {
|
|
|
4172
3752
|
}
|
|
4173
3753
|
return decorators;
|
|
4174
3754
|
}
|
|
3755
|
+
/**
|
|
3756
|
+
* Check that augment decorator are targeting valid symbols.
|
|
3757
|
+
*/
|
|
3758
|
+
function checkAugmentDecorator(node) {
|
|
3759
|
+
// This will validate the target type is pointing to a valid ref.
|
|
3760
|
+
resolveTypeReferenceSym(node.targetType, undefined);
|
|
3761
|
+
const links = resolver.getNodeLinks(node.targetType);
|
|
3762
|
+
if (links.isTemplateInstantiation) {
|
|
3763
|
+
program.reportDiagnostic(createDiagnostic({
|
|
3764
|
+
code: "augment-decorator-target",
|
|
3765
|
+
messageId: "noInstance",
|
|
3766
|
+
target: node.targetType,
|
|
3767
|
+
}));
|
|
3768
|
+
}
|
|
3769
|
+
// If this was used to get a type this is invalid, only used for validation.
|
|
3770
|
+
return errorType;
|
|
3771
|
+
}
|
|
3772
|
+
/**
|
|
3773
|
+
* Check that using statements are targeting valid symbols.
|
|
3774
|
+
*/
|
|
3775
|
+
function checkUsings(node) {
|
|
3776
|
+
const usedSym = resolveTypeReferenceSym(node.name, undefined);
|
|
3777
|
+
if (usedSym) {
|
|
3778
|
+
if (~usedSym.flags & 256 /* SymbolFlags.Namespace */) {
|
|
3779
|
+
reportCheckerDiagnostic(createDiagnostic({ code: "using-invalid-ref", target: node.name }));
|
|
3780
|
+
}
|
|
3781
|
+
}
|
|
3782
|
+
// If this was used to get a type this is invalid, only used for validation.
|
|
3783
|
+
return errorType;
|
|
3784
|
+
}
|
|
4175
3785
|
function checkDecorators(targetType, node, mapper) {
|
|
4176
|
-
const sym = isMemberNode(node)
|
|
3786
|
+
const sym = isMemberNode(node)
|
|
3787
|
+
? (getSymbolForMember(node) ?? node.symbol)
|
|
3788
|
+
: getMergedSymbol(node.symbol);
|
|
4177
3789
|
const decorators = [];
|
|
4178
|
-
const augmentDecoratorNodes =
|
|
3790
|
+
const augmentDecoratorNodes = resolver.getAugmentDecoratorsForSym(sym);
|
|
4179
3791
|
const decoratorNodes = [
|
|
4180
3792
|
...augmentDecoratorNodes, // the first decorator will be executed at last, so augmented decorator should be placed at first.
|
|
4181
3793
|
...node.decorators,
|
|
@@ -4244,13 +3856,10 @@ export function createChecker(program) {
|
|
|
4244
3856
|
return type;
|
|
4245
3857
|
}
|
|
4246
3858
|
function checkScalarExtends(scalar, extendsRef, mapper) {
|
|
4247
|
-
const symId =
|
|
3859
|
+
const symId = getNodeSym(scalar);
|
|
4248
3860
|
pendingResolutions.start(symId, ResolutionKind.BaseType);
|
|
4249
|
-
const target =
|
|
4250
|
-
if (target
|
|
4251
|
-
return undefined;
|
|
4252
|
-
}
|
|
4253
|
-
if (pendingResolutions.has(getNodeSymId(target.declarations[0]), ResolutionKind.BaseType)) {
|
|
3861
|
+
const target = resolver.getNodeLinks(extendsRef).resolvedSymbol;
|
|
3862
|
+
if (target && pendingResolutions.has(target, ResolutionKind.BaseType)) {
|
|
4254
3863
|
if (mapper === undefined) {
|
|
4255
3864
|
reportCheckerDiagnostic(createDiagnostic({
|
|
4256
3865
|
code: "circular-base-type",
|
|
@@ -4260,7 +3869,7 @@ export function createChecker(program) {
|
|
|
4260
3869
|
}
|
|
4261
3870
|
return undefined;
|
|
4262
3871
|
}
|
|
4263
|
-
const extendsType =
|
|
3872
|
+
const extendsType = getTypeForNode(extendsRef, mapper);
|
|
4264
3873
|
pendingResolutions.finish(symId, ResolutionKind.BaseType);
|
|
4265
3874
|
if (isErrorType(extendsType)) {
|
|
4266
3875
|
compilerAssert(program.hasError(), "Should already have reported an error.", extendsRef);
|
|
@@ -4325,7 +3934,7 @@ export function createChecker(program) {
|
|
|
4325
3934
|
return links.declaredType;
|
|
4326
3935
|
}
|
|
4327
3936
|
checkTemplateDeclaration(node, mapper);
|
|
4328
|
-
const aliasSymId =
|
|
3937
|
+
const aliasSymId = getNodeSym(node);
|
|
4329
3938
|
if (pendingResolutions.has(aliasSymId, ResolutionKind.Type)) {
|
|
4330
3939
|
if (mapper === undefined) {
|
|
4331
3940
|
reportCheckerDiagnostic(createDiagnostic({
|
|
@@ -4358,8 +3967,7 @@ export function createChecker(program) {
|
|
|
4358
3967
|
return links.value;
|
|
4359
3968
|
}
|
|
4360
3969
|
const type = node.type ? getTypeForNode(node.type, undefined) : undefined;
|
|
4361
|
-
|
|
4362
|
-
if (pendingResolutions.has(symId, ResolutionKind.Value)) {
|
|
3970
|
+
if (pendingResolutions.has(node.symbol, ResolutionKind.Value)) {
|
|
4363
3971
|
reportCheckerDiagnostic(createDiagnostic({
|
|
4364
3972
|
code: "circular-const",
|
|
4365
3973
|
format: { name: node.id.sv },
|
|
@@ -4367,9 +3975,9 @@ export function createChecker(program) {
|
|
|
4367
3975
|
}));
|
|
4368
3976
|
return null;
|
|
4369
3977
|
}
|
|
4370
|
-
pendingResolutions.start(
|
|
3978
|
+
pendingResolutions.start(node.symbol, ResolutionKind.Value);
|
|
4371
3979
|
const value = getValueForNode(node.value, undefined, type && { kind: "assignment", type });
|
|
4372
|
-
pendingResolutions.finish(
|
|
3980
|
+
pendingResolutions.finish(node.symbol, ResolutionKind.Value);
|
|
4373
3981
|
if (value === null || (type && !checkValueOfType(value, type, node.id))) {
|
|
4374
3982
|
links.value = null;
|
|
4375
3983
|
return links.value;
|
|
@@ -4493,6 +4101,8 @@ export function createChecker(program) {
|
|
|
4493
4101
|
if (mapper === undefined) {
|
|
4494
4102
|
interfaceType.namespace?.interfaces.set(interfaceType.name, interfaceType);
|
|
4495
4103
|
}
|
|
4104
|
+
lateBindMemberContainer(interfaceType);
|
|
4105
|
+
lateBindMembers(interfaceType);
|
|
4496
4106
|
return interfaceType;
|
|
4497
4107
|
}
|
|
4498
4108
|
function checkInterfaceMembers(node, mapper, interfaceType) {
|
|
@@ -4541,6 +4151,8 @@ export function createChecker(program) {
|
|
|
4541
4151
|
if (mapper === undefined) {
|
|
4542
4152
|
unionType.namespace?.unions.set(unionType.name, unionType);
|
|
4543
4153
|
}
|
|
4154
|
+
lateBindMemberContainer(unionType);
|
|
4155
|
+
lateBindMembers(unionType);
|
|
4544
4156
|
return unionType;
|
|
4545
4157
|
}
|
|
4546
4158
|
function checkUnionVariants(parentUnion, node, variants, mapper) {
|
|
@@ -4585,13 +4197,10 @@ export function createChecker(program) {
|
|
|
4585
4197
|
return variantType;
|
|
4586
4198
|
}
|
|
4587
4199
|
function isMemberNode(node) {
|
|
4588
|
-
return (node.
|
|
4589
|
-
node.kind === SyntaxKind.EnumMember ||
|
|
4590
|
-
node.kind === SyntaxKind.OperationStatement ||
|
|
4591
|
-
node.kind === SyntaxKind.UnionVariant);
|
|
4200
|
+
return node.symbol && !!(node.symbol.flags & 262144 /* SymbolFlags.Member */);
|
|
4592
4201
|
}
|
|
4593
4202
|
function getMemberSymbol(parentSym, name) {
|
|
4594
|
-
return parentSym ?
|
|
4203
|
+
return parentSym ? resolver.getAugmentedSymbolTable(parentSym.members).get(name) : undefined;
|
|
4595
4204
|
}
|
|
4596
4205
|
function getSymbolForMember(node) {
|
|
4597
4206
|
if (!node.id) {
|
|
@@ -4599,11 +4208,11 @@ export function createChecker(program) {
|
|
|
4599
4208
|
}
|
|
4600
4209
|
const name = node.id.sv;
|
|
4601
4210
|
const parentSym = node.parent?.symbol;
|
|
4602
|
-
return parentSym ?
|
|
4211
|
+
return parentSym ? getMemberSymbol(parentSym, name) : undefined;
|
|
4603
4212
|
}
|
|
4604
4213
|
function getSymbolLinksForMember(node) {
|
|
4605
4214
|
const sym = getSymbolForMember(node);
|
|
4606
|
-
return sym ? (sym
|
|
4215
|
+
return sym ? (getSymNode(sym) === node ? getSymbolLinks(sym) : undefined) : undefined;
|
|
4607
4216
|
}
|
|
4608
4217
|
function checkEnumMember(node, mapper, parentEnum) {
|
|
4609
4218
|
const name = node.id.sv;
|
|
@@ -4723,119 +4332,17 @@ export function createChecker(program) {
|
|
|
4723
4332
|
function getLiteralType(node) {
|
|
4724
4333
|
return createLiteralType(node.value, node);
|
|
4725
4334
|
}
|
|
4726
|
-
function mergeSymbolTable(source, target) {
|
|
4727
|
-
for (const [sym, duplicates] of source.duplicates) {
|
|
4728
|
-
const targetSet = target.duplicates.get(sym);
|
|
4729
|
-
if (targetSet === undefined) {
|
|
4730
|
-
mutate(target.duplicates).set(sym, new Set([...duplicates]));
|
|
4731
|
-
}
|
|
4732
|
-
else {
|
|
4733
|
-
for (const duplicate of duplicates) {
|
|
4734
|
-
mutate(targetSet).add(duplicate);
|
|
4735
|
-
}
|
|
4736
|
-
}
|
|
4737
|
-
}
|
|
4738
|
-
for (const [key, sourceBinding] of source) {
|
|
4739
|
-
if (sourceBinding.flags & 4096 /* SymbolFlags.Namespace */) {
|
|
4740
|
-
let targetBinding = target.get(key);
|
|
4741
|
-
if (!targetBinding) {
|
|
4742
|
-
targetBinding = {
|
|
4743
|
-
...sourceBinding,
|
|
4744
|
-
declarations: [],
|
|
4745
|
-
exports: createSymbolTable(),
|
|
4746
|
-
};
|
|
4747
|
-
target.set(key, targetBinding);
|
|
4748
|
-
}
|
|
4749
|
-
if (targetBinding.flags & 4096 /* SymbolFlags.Namespace */) {
|
|
4750
|
-
mergedSymbols.set(sourceBinding, targetBinding);
|
|
4751
|
-
mutate(targetBinding.declarations).push(...sourceBinding.declarations);
|
|
4752
|
-
mergeSymbolTable(sourceBinding.exports, mutate(targetBinding.exports));
|
|
4753
|
-
}
|
|
4754
|
-
else {
|
|
4755
|
-
// this will set a duplicate error
|
|
4756
|
-
target.set(key, sourceBinding);
|
|
4757
|
-
}
|
|
4758
|
-
}
|
|
4759
|
-
else if (sourceBinding.flags & 4194304 /* SymbolFlags.Declaration */ ||
|
|
4760
|
-
sourceBinding.flags & 8388608 /* SymbolFlags.Implementation */) {
|
|
4761
|
-
if (sourceBinding.flags & 16384 /* SymbolFlags.Decorator */) {
|
|
4762
|
-
mergeDeclarationOrImplementation(key, sourceBinding, target, 16384 /* SymbolFlags.Decorator */);
|
|
4763
|
-
}
|
|
4764
|
-
else if (sourceBinding.flags & 131072 /* SymbolFlags.Function */) {
|
|
4765
|
-
mergeDeclarationOrImplementation(key, sourceBinding, target, 131072 /* SymbolFlags.Function */);
|
|
4766
|
-
}
|
|
4767
|
-
else {
|
|
4768
|
-
target.set(key, sourceBinding);
|
|
4769
|
-
}
|
|
4770
|
-
}
|
|
4771
|
-
else {
|
|
4772
|
-
target.set(key, sourceBinding);
|
|
4773
|
-
}
|
|
4774
|
-
}
|
|
4775
|
-
}
|
|
4776
|
-
function mergeDeclarationOrImplementation(key, sourceBinding, target, expectTargetFlags) {
|
|
4777
|
-
const targetBinding = target.get(key);
|
|
4778
|
-
if (!targetBinding || !(targetBinding.flags & expectTargetFlags)) {
|
|
4779
|
-
target.set(key, sourceBinding);
|
|
4780
|
-
return;
|
|
4781
|
-
}
|
|
4782
|
-
const isSourceDeclaration = sourceBinding.flags & 4194304 /* SymbolFlags.Declaration */;
|
|
4783
|
-
const isSourceImplementation = sourceBinding.flags & 8388608 /* SymbolFlags.Implementation */;
|
|
4784
|
-
const isTargetDeclaration = targetBinding.flags & 4194304 /* SymbolFlags.Declaration */;
|
|
4785
|
-
const isTargetImplementation = targetBinding.flags & 8388608 /* SymbolFlags.Implementation */;
|
|
4786
|
-
if (isTargetDeclaration && isTargetImplementation) {
|
|
4787
|
-
// If the target already has both a declration and implementation set the symbol which will mark it as duplicate
|
|
4788
|
-
target.set(key, sourceBinding);
|
|
4789
|
-
}
|
|
4790
|
-
else if (isTargetDeclaration && isSourceImplementation) {
|
|
4791
|
-
mergedSymbols.set(sourceBinding, targetBinding);
|
|
4792
|
-
mutate(targetBinding).value = sourceBinding.value;
|
|
4793
|
-
mutate(targetBinding).flags |= sourceBinding.flags;
|
|
4794
|
-
mutate(targetBinding.declarations).push(...sourceBinding.declarations);
|
|
4795
|
-
}
|
|
4796
|
-
else if (isTargetImplementation && isSourceDeclaration) {
|
|
4797
|
-
mergedSymbols.set(sourceBinding, targetBinding);
|
|
4798
|
-
mutate(targetBinding).flags |= sourceBinding.flags;
|
|
4799
|
-
mutate(targetBinding.declarations).unshift(...sourceBinding.declarations);
|
|
4800
|
-
}
|
|
4801
|
-
else {
|
|
4802
|
-
// this will set a duplicate error
|
|
4803
|
-
target.set(key, sourceBinding);
|
|
4804
|
-
}
|
|
4805
|
-
}
|
|
4806
4335
|
function getMergedSymbol(sym) {
|
|
4807
|
-
if (!sym)
|
|
4808
|
-
|
|
4809
|
-
return
|
|
4810
|
-
}
|
|
4811
|
-
function createGlobalNamespaceNode() {
|
|
4812
|
-
const nsId = {
|
|
4813
|
-
kind: SyntaxKind.Identifier,
|
|
4814
|
-
pos: 0,
|
|
4815
|
-
end: 0,
|
|
4816
|
-
sv: "global",
|
|
4817
|
-
symbol: undefined,
|
|
4818
|
-
flags: 8 /* NodeFlags.Synthetic */,
|
|
4819
|
-
};
|
|
4820
|
-
const nsNode = {
|
|
4821
|
-
kind: SyntaxKind.NamespaceStatement,
|
|
4822
|
-
decorators: [],
|
|
4823
|
-
pos: 0,
|
|
4824
|
-
end: 0,
|
|
4825
|
-
id: nsId,
|
|
4826
|
-
symbol: undefined,
|
|
4827
|
-
locals: createSymbolTable(),
|
|
4828
|
-
flags: 8 /* NodeFlags.Synthetic */,
|
|
4829
|
-
};
|
|
4830
|
-
mutate(nsNode).symbol = createSymbol(nsNode, nsId.sv, 4096 /* SymbolFlags.Namespace */);
|
|
4831
|
-
mutate(nsNode.symbol.exports).set(nsId.sv, nsNode.symbol);
|
|
4832
|
-
return nsNode;
|
|
4336
|
+
// if (!sym) return sym;
|
|
4337
|
+
// return mergedSymbols.get(sym) || sym;
|
|
4338
|
+
return resolver.getMergedSymbol(sym);
|
|
4833
4339
|
}
|
|
4834
4340
|
function createGlobalNamespaceType() {
|
|
4835
|
-
const
|
|
4341
|
+
const sym = resolver.symbols.global;
|
|
4342
|
+
const type = createType({
|
|
4836
4343
|
kind: "Namespace",
|
|
4837
4344
|
name: "",
|
|
4838
|
-
node:
|
|
4345
|
+
node: getGlobalNamespaceNode(),
|
|
4839
4346
|
models: new Map(),
|
|
4840
4347
|
scalars: new Map(),
|
|
4841
4348
|
operations: new Map(),
|
|
@@ -4847,8 +4354,9 @@ export function createChecker(program) {
|
|
|
4847
4354
|
functionDeclarations: new Map(),
|
|
4848
4355
|
decorators: [],
|
|
4849
4356
|
});
|
|
4850
|
-
getSymbolLinks(
|
|
4851
|
-
|
|
4357
|
+
getSymbolLinks(sym).type = type;
|
|
4358
|
+
type.decorators = checkAugmentDecorators(sym, type, undefined);
|
|
4359
|
+
return finishType(type);
|
|
4852
4360
|
}
|
|
4853
4361
|
function initializeClone(type, additionalProps) {
|
|
4854
4362
|
let clone;
|
|
@@ -5475,7 +4983,7 @@ export function createChecker(program) {
|
|
|
5475
4983
|
const ref = resolveTypeReferenceSym(node.target, undefined, true);
|
|
5476
4984
|
if (!ref)
|
|
5477
4985
|
throw new ProjectionError("Can't find decorator.");
|
|
5478
|
-
compilerAssert(ref.flags &
|
|
4986
|
+
compilerAssert(ref.flags & 1024 /* SymbolFlags.Decorator */, "should only resolve decorator symbols");
|
|
5479
4987
|
return createFunctionType((...args) => {
|
|
5480
4988
|
ref.value({ program }, ...args.map(unsafe_projectionArgumentMarshalForJS));
|
|
5481
4989
|
return voidType;
|
|
@@ -5491,15 +4999,15 @@ export function createChecker(program) {
|
|
|
5491
4999
|
currentContext = currentContext.parent;
|
|
5492
5000
|
}
|
|
5493
5001
|
// next, resolve outside
|
|
5494
|
-
const ref =
|
|
5002
|
+
const { finalSymbol: ref } = resolver.resolveTypeReference(node);
|
|
5495
5003
|
if (!ref)
|
|
5496
5004
|
throw new ProjectionError("Unknown identifier " + node.sv);
|
|
5497
|
-
if (ref.flags &
|
|
5005
|
+
if (ref.flags & 1024 /* SymbolFlags.Decorator */) {
|
|
5498
5006
|
// shouldn't ever resolve a decorator symbol here (without passing
|
|
5499
5007
|
// true to resolveTypeReference)
|
|
5500
5008
|
return errorType;
|
|
5501
5009
|
}
|
|
5502
|
-
else if (ref.flags &
|
|
5010
|
+
else if (ref.flags & 8192 /* SymbolFlags.Function */) {
|
|
5503
5011
|
// TODO: store this in a symbol link probably?
|
|
5504
5012
|
const t = createFunctionType((...args) => {
|
|
5505
5013
|
const retval = ref.value(program, ...args.map(unsafe_projectionArgumentMarshalForJS));
|
|
@@ -5566,16 +5074,6 @@ export function createChecker(program) {
|
|
|
5566
5074
|
function project(target, projection, args = []) {
|
|
5567
5075
|
return evalProjection(projection, target, args.map((x) => marshalProjectionReturn(x)));
|
|
5568
5076
|
}
|
|
5569
|
-
function memberExpressionToString(expr) {
|
|
5570
|
-
let current = expr;
|
|
5571
|
-
const parts = [];
|
|
5572
|
-
while (current.kind === SyntaxKind.MemberExpression) {
|
|
5573
|
-
parts.push(current.id.sv);
|
|
5574
|
-
current = current.base;
|
|
5575
|
-
}
|
|
5576
|
-
parts.push(current.sv);
|
|
5577
|
-
return parts.reverse().join(".");
|
|
5578
|
-
}
|
|
5579
5077
|
/**
|
|
5580
5078
|
* Check if the source type can be assigned to the target type and emit diagnostics
|
|
5581
5079
|
* @param source Type of a value
|
|
@@ -5641,9 +5139,6 @@ export function createChecker(program) {
|
|
|
5641
5139
|
return valueExactTypes.get(value);
|
|
5642
5140
|
}
|
|
5643
5141
|
}
|
|
5644
|
-
function isAnonymous(type) {
|
|
5645
|
-
return !("name" in type) || typeof type.name !== "string" || !type.name;
|
|
5646
|
-
}
|
|
5647
5142
|
/**
|
|
5648
5143
|
* Find all named models that could have been the source of the given
|
|
5649
5144
|
* property. This includes the named parents of all property sources in a
|
|
@@ -6067,4 +5562,14 @@ function unsafe_projectionArgumentMarshalForJS(arg) {
|
|
|
6067
5562
|
}
|
|
6068
5563
|
return arg;
|
|
6069
5564
|
}
|
|
5565
|
+
function printTypeReferenceNode(node) {
|
|
5566
|
+
switch (node.kind) {
|
|
5567
|
+
case SyntaxKind.MemberExpression:
|
|
5568
|
+
return `${printTypeReferenceNode(node.base)}.${printTypeReferenceNode(node.id)}`;
|
|
5569
|
+
case SyntaxKind.TypeReference:
|
|
5570
|
+
return printTypeReferenceNode(node.target);
|
|
5571
|
+
case SyntaxKind.Identifier:
|
|
5572
|
+
return node.sv;
|
|
5573
|
+
}
|
|
5574
|
+
}
|
|
6070
5575
|
//# sourceMappingURL=checker.js.map
|