@typespec/compiler 1.3.0-dev.10 → 1.3.0-dev.11
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/manifest.js +2 -2
- package/dist/src/core/checker.d.ts +0 -1
- package/dist/src/core/checker.d.ts.map +1 -1
- package/dist/src/core/checker.js +247 -199
- package/dist/src/core/checker.js.map +1 -1
- package/dist/src/core/types.d.ts +4 -0
- package/dist/src/core/types.d.ts.map +1 -1
- package/dist/src/core/types.js.map +1 -1
- package/package.json +1 -1
package/dist/src/core/checker.js
CHANGED
|
@@ -25,6 +25,7 @@ import { IdentifierKind, ResolutionResultFlags, SyntaxKind, } from "./types.js";
|
|
|
25
25
|
const TypeInstantiationMap = class extends MultiKeyMap {
|
|
26
26
|
};
|
|
27
27
|
export function createChecker(program, resolver) {
|
|
28
|
+
const waitingForResolution = new Map();
|
|
28
29
|
const stats = {
|
|
29
30
|
createdTypes: 0,
|
|
30
31
|
finishedTypes: 0,
|
|
@@ -41,11 +42,11 @@ export function createChecker(program, resolver) {
|
|
|
41
42
|
const globalNamespaceType = createGlobalNamespaceType();
|
|
42
43
|
// Caches the deprecation test of nodes in the program
|
|
43
44
|
const nodeDeprecationMap = new Map();
|
|
44
|
-
const errorType =
|
|
45
|
-
const voidType =
|
|
46
|
-
const neverType =
|
|
47
|
-
const unknownType =
|
|
48
|
-
const nullType =
|
|
45
|
+
const errorType = createAndFinishType({ kind: "Intrinsic", name: "ErrorType" });
|
|
46
|
+
const voidType = createAndFinishType({ kind: "Intrinsic", name: "void" });
|
|
47
|
+
const neverType = createAndFinishType({ kind: "Intrinsic", name: "never" });
|
|
48
|
+
const unknownType = createAndFinishType({ kind: "Intrinsic", name: "unknown" });
|
|
49
|
+
const nullType = createAndFinishType({ kind: "Intrinsic", name: "null" });
|
|
49
50
|
/**
|
|
50
51
|
* Set keeping track of node pending type resolution.
|
|
51
52
|
* Key is the SymId of a node. It can be retrieved with getNodeSymId(node)
|
|
@@ -553,6 +554,8 @@ export function createChecker(program, resolver) {
|
|
|
553
554
|
pendingResolutions.finish(getNodeSym(node), ResolutionKind.Constraint);
|
|
554
555
|
}
|
|
555
556
|
if (node.default) {
|
|
557
|
+
// Set this to unknownType in case the default points back to the template itself causing failures
|
|
558
|
+
type.default = unknownType;
|
|
556
559
|
type.default = checkTemplateParameterDefault(node.default, parentNode.templateParameters, index, type.constraint);
|
|
557
560
|
}
|
|
558
561
|
}
|
|
@@ -1160,10 +1163,42 @@ export function createChecker(program, resolver) {
|
|
|
1160
1163
|
// we're not instantiating this model and we've already checked it
|
|
1161
1164
|
return links.declaredType;
|
|
1162
1165
|
}
|
|
1166
|
+
const intersection = initModel(node);
|
|
1163
1167
|
const options = node.options.map((o) => [o, getTypeForNode(o, mapper)]);
|
|
1164
|
-
|
|
1165
|
-
|
|
1166
|
-
|
|
1168
|
+
ensureResolved(options.map(([, type]) => type), intersection, () => {
|
|
1169
|
+
const type = mergeModelTypes(node.symbol, node, options, mapper, intersection);
|
|
1170
|
+
linkType(links, type, mapper);
|
|
1171
|
+
finishType(intersection);
|
|
1172
|
+
});
|
|
1173
|
+
return intersection;
|
|
1174
|
+
}
|
|
1175
|
+
function ensureResolved(types, awaitingType, callback) {
|
|
1176
|
+
const waitingFor = new Set();
|
|
1177
|
+
for (const type of types) {
|
|
1178
|
+
if (type === undefined)
|
|
1179
|
+
continue;
|
|
1180
|
+
if (type.creating) {
|
|
1181
|
+
waitingFor.add(type);
|
|
1182
|
+
}
|
|
1183
|
+
}
|
|
1184
|
+
function check() {
|
|
1185
|
+
if (waitingFor.size === 0) {
|
|
1186
|
+
callback();
|
|
1187
|
+
}
|
|
1188
|
+
}
|
|
1189
|
+
for (const type of waitingFor) {
|
|
1190
|
+
waitingForResolution.set(type, [
|
|
1191
|
+
...(waitingForResolution.get(type) || []),
|
|
1192
|
+
[
|
|
1193
|
+
awaitingType,
|
|
1194
|
+
() => {
|
|
1195
|
+
waitingFor.delete(type);
|
|
1196
|
+
check();
|
|
1197
|
+
},
|
|
1198
|
+
],
|
|
1199
|
+
]);
|
|
1200
|
+
}
|
|
1201
|
+
check();
|
|
1167
1202
|
}
|
|
1168
1203
|
function checkDecoratorDeclaration(node, mapper) {
|
|
1169
1204
|
const symbol = getMergedSymbol(node.symbol);
|
|
@@ -1268,18 +1303,8 @@ export function createChecker(program, resolver) {
|
|
|
1268
1303
|
};
|
|
1269
1304
|
}
|
|
1270
1305
|
}
|
|
1271
|
-
function mergeModelTypes(parentModelSym, node, options, mapper) {
|
|
1272
|
-
const properties =
|
|
1273
|
-
const intersection = createType({
|
|
1274
|
-
kind: "Model",
|
|
1275
|
-
node,
|
|
1276
|
-
name: "",
|
|
1277
|
-
namespace: getParentNamespaceType(node),
|
|
1278
|
-
properties: properties,
|
|
1279
|
-
decorators: [],
|
|
1280
|
-
derivedModels: [],
|
|
1281
|
-
sourceModels: [],
|
|
1282
|
-
});
|
|
1306
|
+
function mergeModelTypes(parentModelSym, node, options, mapper, intersection) {
|
|
1307
|
+
const properties = intersection.properties;
|
|
1283
1308
|
const indexers = [];
|
|
1284
1309
|
const modelOptions = options.filter((entry) => {
|
|
1285
1310
|
const [optionNode, option] = entry;
|
|
@@ -1339,7 +1364,7 @@ export function createChecker(program, resolver) {
|
|
|
1339
1364
|
else if (indexers.length > 1) {
|
|
1340
1365
|
intersection.indexer = {
|
|
1341
1366
|
key: indexers[0].key,
|
|
1342
|
-
value: mergeModelTypes(undefined, node, indexers.map((x) => [x.value.node, x.value]), mapper),
|
|
1367
|
+
value: mergeModelTypes(undefined, node, indexers.map((x) => [x.value.node, x.value]), mapper, initModel(node)),
|
|
1343
1368
|
};
|
|
1344
1369
|
}
|
|
1345
1370
|
linkMapper(intersection, mapper);
|
|
@@ -1476,7 +1501,6 @@ export function createChecker(program, resolver) {
|
|
|
1476
1501
|
}
|
|
1477
1502
|
const namespace = getParentNamespaceType(node);
|
|
1478
1503
|
const name = node.id.sv;
|
|
1479
|
-
let decorators = [];
|
|
1480
1504
|
const { resolvedSymbol: parameterModelSym } = resolver.resolveMetaMemberByName(symbol, "parameters");
|
|
1481
1505
|
if (parameterModelSym?.members) {
|
|
1482
1506
|
const members = resolver.getAugmentedSymbolTable(parameterModelSym.members);
|
|
@@ -1488,78 +1512,71 @@ export function createChecker(program, resolver) {
|
|
|
1488
1512
|
}
|
|
1489
1513
|
}
|
|
1490
1514
|
}
|
|
1491
|
-
// Is this a definition or reference?
|
|
1492
|
-
let parameters, returnType, sourceOperation;
|
|
1493
|
-
if (node.signature.kind === SyntaxKind.OperationSignatureReference) {
|
|
1494
|
-
// Attempt to resolve the operation
|
|
1495
|
-
const baseOperation = checkOperationIs(node, node.signature.baseOperation, mapper);
|
|
1496
|
-
if (baseOperation) {
|
|
1497
|
-
sourceOperation = baseOperation;
|
|
1498
|
-
// Reference the same return type and create the parameters type
|
|
1499
|
-
const clone = initializeClone(baseOperation.parameters, {
|
|
1500
|
-
properties: createRekeyableMap(),
|
|
1501
|
-
});
|
|
1502
|
-
clone.properties = createRekeyableMap(Array.from(baseOperation.parameters.properties.entries()).map(([key, prop]) => [
|
|
1503
|
-
key,
|
|
1504
|
-
cloneTypeForSymbol(getMemberSymbol(parameterModelSym, prop.name), prop, {
|
|
1505
|
-
model: clone,
|
|
1506
|
-
sourceProperty: prop,
|
|
1507
|
-
}),
|
|
1508
|
-
]));
|
|
1509
|
-
parameters = finishType(clone);
|
|
1510
|
-
returnType = baseOperation.returnType;
|
|
1511
|
-
// Copy decorators from the base operation, inserting the base decorators first
|
|
1512
|
-
decorators = [...baseOperation.decorators];
|
|
1513
|
-
}
|
|
1514
|
-
else {
|
|
1515
|
-
// If we can't resolve the signature we return an empty model.
|
|
1516
|
-
parameters = createAndFinishType({
|
|
1517
|
-
kind: "Model",
|
|
1518
|
-
name: "",
|
|
1519
|
-
decorators: [],
|
|
1520
|
-
properties: createRekeyableMap(),
|
|
1521
|
-
derivedModels: [],
|
|
1522
|
-
sourceModels: [],
|
|
1523
|
-
});
|
|
1524
|
-
returnType = voidType;
|
|
1525
|
-
}
|
|
1526
|
-
}
|
|
1527
|
-
else {
|
|
1528
|
-
parameters = getTypeForNode(node.signature.parameters, mapper);
|
|
1529
|
-
returnType = getTypeForNode(node.signature.returnType, mapper);
|
|
1530
|
-
}
|
|
1531
1515
|
const operationType = createType({
|
|
1532
1516
|
kind: "Operation",
|
|
1533
1517
|
name,
|
|
1534
1518
|
namespace,
|
|
1519
|
+
parameters: null,
|
|
1520
|
+
returnType: voidType,
|
|
1535
1521
|
node,
|
|
1536
|
-
|
|
1537
|
-
returnType,
|
|
1538
|
-
decorators,
|
|
1539
|
-
sourceOperation,
|
|
1522
|
+
decorators: [],
|
|
1540
1523
|
interface: parentInterface,
|
|
1541
1524
|
});
|
|
1542
1525
|
if (links) {
|
|
1543
1526
|
linkType(links, operationType, mapper);
|
|
1544
1527
|
}
|
|
1545
|
-
decorators.push(...checkDecorators(operationType, node, mapper));
|
|
1546
|
-
operationType.parameters.namespace = namespace;
|
|
1547
1528
|
const parent = node.parent;
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
1551
|
-
|
|
1552
|
-
|
|
1553
|
-
|
|
1529
|
+
function finishOperation() {
|
|
1530
|
+
operationType.parameters.namespace = namespace;
|
|
1531
|
+
operationType.decorators.push(...checkDecorators(operationType, node, mapper));
|
|
1532
|
+
const runDecorators = parent.kind === SyntaxKind.InterfaceStatement
|
|
1533
|
+
? shouldRunDecorators(parent, mapper) && shouldRunDecorators(node, mapper)
|
|
1534
|
+
: shouldRunDecorators(node, mapper);
|
|
1535
|
+
return finishType(operationType, { skipDecorators: !runDecorators });
|
|
1554
1536
|
}
|
|
1555
|
-
|
|
1556
|
-
|
|
1557
|
-
|
|
1537
|
+
// Is this a definition or reference?
|
|
1538
|
+
if (node.signature.kind === SyntaxKind.OperationSignatureReference) {
|
|
1539
|
+
// Attempt to resolve the operation
|
|
1540
|
+
const baseOperation = checkOperationIs(node, node.signature.baseOperation, mapper);
|
|
1541
|
+
if (baseOperation) {
|
|
1542
|
+
ensureResolved([baseOperation], operationType, () => {
|
|
1543
|
+
operationType.sourceOperation = baseOperation;
|
|
1544
|
+
// Reference the same return type and create the parameters type
|
|
1545
|
+
const clone = initializeClone(baseOperation.parameters, {
|
|
1546
|
+
properties: createRekeyableMap(),
|
|
1547
|
+
});
|
|
1548
|
+
clone.properties = createRekeyableMap(Array.from(baseOperation.parameters.properties.entries()).map(([key, prop]) => [
|
|
1549
|
+
key,
|
|
1550
|
+
cloneTypeForSymbol(getMemberSymbol(parameterModelSym, prop.name), prop, {
|
|
1551
|
+
model: clone,
|
|
1552
|
+
sourceProperty: prop,
|
|
1553
|
+
}),
|
|
1554
|
+
]));
|
|
1555
|
+
operationType.parameters = finishType(clone);
|
|
1556
|
+
operationType.returnType = baseOperation.returnType;
|
|
1557
|
+
// Copy decorators from the base operation, inserting the base decorators first
|
|
1558
|
+
operationType.decorators.push(...baseOperation.decorators);
|
|
1559
|
+
finishOperation();
|
|
1560
|
+
});
|
|
1558
1561
|
}
|
|
1559
|
-
|
|
1560
|
-
|
|
1562
|
+
else {
|
|
1563
|
+
// If we can't resolve the signature we return an empty model.
|
|
1564
|
+
operationType.parameters = initModel();
|
|
1565
|
+
operationType.returnType = voidType;
|
|
1566
|
+
finishOperation();
|
|
1561
1567
|
}
|
|
1562
1568
|
}
|
|
1569
|
+
else {
|
|
1570
|
+
operationType.parameters = getTypeForNode(node.signature.parameters, mapper);
|
|
1571
|
+
operationType.returnType = getTypeForNode(node.signature.returnType, mapper);
|
|
1572
|
+
ensureResolved([operationType.parameters], operationType, () => {
|
|
1573
|
+
finishOperation();
|
|
1574
|
+
});
|
|
1575
|
+
}
|
|
1576
|
+
linkMapper(operationType, mapper);
|
|
1577
|
+
if (parent.kind !== SyntaxKind.InterfaceStatement && mapper === undefined) {
|
|
1578
|
+
namespace?.operations.set(name, operationType);
|
|
1579
|
+
}
|
|
1563
1580
|
return operationType;
|
|
1564
1581
|
}
|
|
1565
1582
|
function checkOperationIs(operation, opReference, mapper) {
|
|
@@ -2419,6 +2436,20 @@ export function createChecker(program, resolver) {
|
|
|
2419
2436
|
checkSourceFile(file);
|
|
2420
2437
|
}
|
|
2421
2438
|
internalDecoratorValidation();
|
|
2439
|
+
assertNoPendingResolutions();
|
|
2440
|
+
}
|
|
2441
|
+
function assertNoPendingResolutions() {
|
|
2442
|
+
if (waitingForResolution.size === 0) {
|
|
2443
|
+
return;
|
|
2444
|
+
}
|
|
2445
|
+
const message = [
|
|
2446
|
+
"Unexpected pending resolutions found",
|
|
2447
|
+
...[...waitingForResolution.entries()].flatMap(([type, items]) => {
|
|
2448
|
+
const base = ` (${type.kind}) ${getTypeName(type)} => `;
|
|
2449
|
+
return items.map(([item], index) => `${index === 0 ? base : " ".repeat(base.length)}${getTypeName(item)}`);
|
|
2450
|
+
}),
|
|
2451
|
+
].join("\n");
|
|
2452
|
+
compilerAssert(false, message);
|
|
2422
2453
|
}
|
|
2423
2454
|
function checkDuplicateSymbols() {
|
|
2424
2455
|
program.reportDuplicateSymbols(resolver.symbols.global.exports);
|
|
@@ -2523,65 +2554,67 @@ export function createChecker(program, resolver) {
|
|
|
2523
2554
|
}
|
|
2524
2555
|
}
|
|
2525
2556
|
const isBase = checkModelIs(node, node.is, mapper);
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
2541
|
-
|
|
2542
|
-
|
|
2543
|
-
|
|
2557
|
+
ensureResolved([
|
|
2558
|
+
isBase,
|
|
2559
|
+
...node.properties
|
|
2560
|
+
.filter((x) => x.kind === SyntaxKind.ModelSpreadProperty)
|
|
2561
|
+
.map((x) => checkSpreadTarget(node, x.target, mapper)),
|
|
2562
|
+
], type, () => {
|
|
2563
|
+
if (isBase) {
|
|
2564
|
+
type.sourceModel = isBase;
|
|
2565
|
+
type.sourceModels.push({ usage: "is", model: isBase });
|
|
2566
|
+
decorators.push(...isBase.decorators);
|
|
2567
|
+
if (isBase.indexer) {
|
|
2568
|
+
type.indexer = isBase.indexer;
|
|
2569
|
+
}
|
|
2570
|
+
for (const prop of isBase.properties.values()) {
|
|
2571
|
+
const memberSym = getMemberSymbol(node.symbol, prop.name);
|
|
2572
|
+
const newProp = cloneTypeForSymbol(memberSym, prop, {
|
|
2573
|
+
sourceProperty: prop,
|
|
2574
|
+
model: type,
|
|
2575
|
+
});
|
|
2576
|
+
linkIndirectMember(node, newProp, mapper);
|
|
2577
|
+
type.properties.set(prop.name, newProp);
|
|
2578
|
+
}
|
|
2579
|
+
}
|
|
2580
|
+
if (isBase) {
|
|
2581
|
+
type.baseModel = isBase.baseModel;
|
|
2582
|
+
}
|
|
2583
|
+
else if (node.extends) {
|
|
2584
|
+
type.baseModel = checkClassHeritage(node, node.extends, mapper);
|
|
2585
|
+
if (type.baseModel) {
|
|
2586
|
+
copyDeprecation(type.baseModel, type);
|
|
2587
|
+
}
|
|
2544
2588
|
}
|
|
2545
|
-
}
|
|
2546
|
-
if (isBase) {
|
|
2547
|
-
type.baseModel = isBase.baseModel;
|
|
2548
|
-
}
|
|
2549
|
-
else if (node.extends) {
|
|
2550
|
-
type.baseModel = checkClassHeritage(node, node.extends, mapper);
|
|
2551
2589
|
if (type.baseModel) {
|
|
2552
|
-
|
|
2590
|
+
type.baseModel.derivedModels.push(type);
|
|
2553
2591
|
}
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
|
|
2574
|
-
|
|
2575
|
-
|
|
2576
|
-
}
|
|
2577
|
-
if (indexer) {
|
|
2578
|
-
type.indexer = indexer;
|
|
2579
|
-
}
|
|
2580
|
-
lateBindMemberContainer(type);
|
|
2581
|
-
lateBindMembers(type);
|
|
2592
|
+
// Hold on to the model type that's being defined so that it
|
|
2593
|
+
// can be referenced
|
|
2594
|
+
if (mapper === undefined) {
|
|
2595
|
+
type.namespace?.models.set(type.name, type);
|
|
2596
|
+
}
|
|
2597
|
+
// Evaluate the properties after
|
|
2598
|
+
checkModelProperties(node, type.properties, type, mapper);
|
|
2599
|
+
decorators.push(...checkDecorators(type, node, mapper));
|
|
2600
|
+
linkMapper(type, mapper);
|
|
2601
|
+
finishType(type, { skipDecorators: !shouldRunDecorators(node, mapper) });
|
|
2602
|
+
lateBindMemberContainer(type);
|
|
2603
|
+
lateBindMembers(type);
|
|
2604
|
+
const indexer = getIndexer(program, type);
|
|
2605
|
+
if (type.name === "Array" && isInTypeSpecNamespace(type)) {
|
|
2606
|
+
stdTypes.Array = type;
|
|
2607
|
+
}
|
|
2608
|
+
else if (type.name === "Record" && isInTypeSpecNamespace(type)) {
|
|
2609
|
+
stdTypes.Record = type;
|
|
2610
|
+
}
|
|
2611
|
+
if (indexer) {
|
|
2612
|
+
type.indexer = indexer;
|
|
2613
|
+
}
|
|
2614
|
+
});
|
|
2582
2615
|
return type;
|
|
2583
2616
|
}
|
|
2584
|
-
function
|
|
2617
|
+
function shouldRunDecorators(node, mapper) {
|
|
2585
2618
|
// Node is not a template we should create the type.
|
|
2586
2619
|
if (node.templateParameters.length === 0) {
|
|
2587
2620
|
return true;
|
|
@@ -2600,22 +2633,17 @@ export function createChecker(program, resolver) {
|
|
|
2600
2633
|
// we're not instantiating this model and we've already checked it
|
|
2601
2634
|
return links.declaredType;
|
|
2602
2635
|
}
|
|
2603
|
-
const
|
|
2604
|
-
const
|
|
2605
|
-
kind: "Model",
|
|
2606
|
-
name: "",
|
|
2607
|
-
node: node,
|
|
2608
|
-
properties,
|
|
2609
|
-
indexer: undefined,
|
|
2610
|
-
namespace: getParentNamespaceType(node),
|
|
2611
|
-
decorators: [],
|
|
2612
|
-
derivedModels: [],
|
|
2613
|
-
sourceModels: [],
|
|
2614
|
-
});
|
|
2636
|
+
const type = initModel(node);
|
|
2637
|
+
const properties = type.properties;
|
|
2615
2638
|
linkType(links, type, mapper);
|
|
2616
2639
|
linkMapper(type, mapper);
|
|
2617
|
-
|
|
2618
|
-
|
|
2640
|
+
ensureResolved(node.properties
|
|
2641
|
+
.filter((x) => x.kind === SyntaxKind.ModelSpreadProperty)
|
|
2642
|
+
.map((x) => checkSpreadTarget(node, x.target, mapper)), type, () => {
|
|
2643
|
+
checkModelProperties(node, properties, type, mapper);
|
|
2644
|
+
finishType(type);
|
|
2645
|
+
});
|
|
2646
|
+
return type;
|
|
2619
2647
|
}
|
|
2620
2648
|
/** Find the indexer that applies to this model. Either defined on itself or from a base model */
|
|
2621
2649
|
function findIndexer(model) {
|
|
@@ -3334,6 +3362,23 @@ export function createChecker(program, resolver) {
|
|
|
3334
3362
|
}
|
|
3335
3363
|
return isType;
|
|
3336
3364
|
}
|
|
3365
|
+
/** Get the type for the spread target */
|
|
3366
|
+
function checkSpreadTarget(model, target, mapper) {
|
|
3367
|
+
const modelSymId = getNodeSym(model);
|
|
3368
|
+
const targetSym = resolver.getNodeLinks(target).resolvedSymbol;
|
|
3369
|
+
if (targetSym === modelSymId) {
|
|
3370
|
+
if (mapper === undefined) {
|
|
3371
|
+
reportCheckerDiagnostic(createDiagnostic({
|
|
3372
|
+
code: "spread-model",
|
|
3373
|
+
messageId: "selfSpread",
|
|
3374
|
+
target: target,
|
|
3375
|
+
}));
|
|
3376
|
+
}
|
|
3377
|
+
return undefined;
|
|
3378
|
+
}
|
|
3379
|
+
const type = getTypeForNode(target, mapper);
|
|
3380
|
+
return type;
|
|
3381
|
+
}
|
|
3337
3382
|
function checkSpreadProperty(parentModelSym, targetNode, parentModel, mapper) {
|
|
3338
3383
|
const targetType = getTypeForNode(targetNode, mapper);
|
|
3339
3384
|
if (targetType.kind === "TemplateParameter" || isErrorType(targetType)) {
|
|
@@ -3347,13 +3392,6 @@ export function createChecker(program, resolver) {
|
|
|
3347
3392
|
reportCheckerDiagnostic(createDiagnostic({ code: "spread-model", target: targetNode }), mapper);
|
|
3348
3393
|
return [[], undefined];
|
|
3349
3394
|
}
|
|
3350
|
-
if (parentModel === targetType) {
|
|
3351
|
-
reportCheckerDiagnostic(createDiagnostic({
|
|
3352
|
-
code: "spread-model",
|
|
3353
|
-
messageId: "selfSpread",
|
|
3354
|
-
target: targetNode,
|
|
3355
|
-
}));
|
|
3356
|
-
}
|
|
3357
3395
|
parentModel.sourceModels.push({ usage: "spread", model: targetType });
|
|
3358
3396
|
const props = [];
|
|
3359
3397
|
// copy each property
|
|
@@ -3425,15 +3463,16 @@ export function createChecker(program, resolver) {
|
|
|
3425
3463
|
type.decorators = checkDecorators(type, prop, mapper);
|
|
3426
3464
|
const parentTemplate = getParentTemplateNode(prop);
|
|
3427
3465
|
linkMapper(type, mapper);
|
|
3428
|
-
|
|
3466
|
+
let runDecorators = false;
|
|
3467
|
+
if (!parentTemplate || shouldRunDecorators(parentTemplate, mapper)) {
|
|
3429
3468
|
const docComment = docFromCommentForSym.get(sym);
|
|
3430
3469
|
if (docComment) {
|
|
3431
3470
|
type.decorators.unshift(createDocFromCommentDecorator("self", docComment));
|
|
3432
3471
|
}
|
|
3433
|
-
|
|
3472
|
+
runDecorators = true;
|
|
3434
3473
|
}
|
|
3435
3474
|
pendingResolutions.finish(sym, ResolutionKind.Type);
|
|
3436
|
-
return type;
|
|
3475
|
+
return finishType(type, { skipDecorators: !runDecorators });
|
|
3437
3476
|
}
|
|
3438
3477
|
function createDocFromCommentDecorator(key, doc) {
|
|
3439
3478
|
return {
|
|
@@ -3809,13 +3848,10 @@ export function createChecker(program, resolver) {
|
|
|
3809
3848
|
type.namespace?.scalars.set(type.name, type);
|
|
3810
3849
|
}
|
|
3811
3850
|
linkMapper(type, mapper);
|
|
3812
|
-
if (shouldCreateTypeForTemplate(node, mapper)) {
|
|
3813
|
-
finishType(type);
|
|
3814
|
-
}
|
|
3815
3851
|
if (isInTypeSpecNamespace(type)) {
|
|
3816
3852
|
stdTypes[type.name] = type;
|
|
3817
3853
|
}
|
|
3818
|
-
return type;
|
|
3854
|
+
return finishType(type, { skipDecorators: !shouldRunDecorators(node, mapper) });
|
|
3819
3855
|
}
|
|
3820
3856
|
function checkScalarExtends(scalar, extendsRef, mapper) {
|
|
3821
3857
|
const symId = getNodeSym(scalar);
|
|
@@ -3882,13 +3918,12 @@ export function createChecker(program, resolver) {
|
|
|
3882
3918
|
parameters: node.parameters.map((x) => checkFunctionParameter(x, mapper, false)),
|
|
3883
3919
|
});
|
|
3884
3920
|
linkMapper(member, mapper);
|
|
3885
|
-
if (shouldCreateTypeForTemplate(node.parent, mapper)) {
|
|
3886
|
-
finishType(member);
|
|
3887
|
-
}
|
|
3888
3921
|
if (links) {
|
|
3889
3922
|
linkType(links, member, mapper);
|
|
3890
3923
|
}
|
|
3891
|
-
return finishType(member
|
|
3924
|
+
return finishType(member, {
|
|
3925
|
+
skipDecorators: !shouldRunDecorators(node.parent, mapper),
|
|
3926
|
+
});
|
|
3892
3927
|
}
|
|
3893
3928
|
function checkAlias(node, mapper) {
|
|
3894
3929
|
const links = getSymbolLinks(node.symbol);
|
|
@@ -4057,15 +4092,14 @@ export function createChecker(program, resolver) {
|
|
|
4057
4092
|
interfaceType.operations.set(key, value);
|
|
4058
4093
|
}
|
|
4059
4094
|
linkMapper(interfaceType, mapper);
|
|
4060
|
-
if (shouldCreateTypeForTemplate(node, mapper)) {
|
|
4061
|
-
finishType(interfaceType);
|
|
4062
|
-
}
|
|
4063
4095
|
if (mapper === undefined) {
|
|
4064
4096
|
interfaceType.namespace?.interfaces.set(interfaceType.name, interfaceType);
|
|
4065
4097
|
}
|
|
4066
4098
|
lateBindMemberContainer(interfaceType);
|
|
4067
4099
|
lateBindMembers(interfaceType);
|
|
4068
|
-
return interfaceType
|
|
4100
|
+
return finishType(interfaceType, {
|
|
4101
|
+
skipDecorators: !shouldRunDecorators(node, mapper),
|
|
4102
|
+
});
|
|
4069
4103
|
}
|
|
4070
4104
|
function checkInterfaceMembers(node, mapper, interfaceType) {
|
|
4071
4105
|
const ownMembers = new Map();
|
|
@@ -4107,15 +4141,12 @@ export function createChecker(program, resolver) {
|
|
|
4107
4141
|
unionType.decorators = checkDecorators(unionType, node, mapper);
|
|
4108
4142
|
checkUnionVariants(unionType, node, variants, mapper);
|
|
4109
4143
|
linkMapper(unionType, mapper);
|
|
4110
|
-
if (shouldCreateTypeForTemplate(node, mapper)) {
|
|
4111
|
-
finishType(unionType);
|
|
4112
|
-
}
|
|
4113
4144
|
if (mapper === undefined) {
|
|
4114
4145
|
unionType.namespace?.unions.set(unionType.name, unionType);
|
|
4115
4146
|
}
|
|
4116
4147
|
lateBindMemberContainer(unionType);
|
|
4117
4148
|
lateBindMembers(unionType);
|
|
4118
|
-
return unionType;
|
|
4149
|
+
return finishType(unionType, { skipDecorators: !shouldRunDecorators(node, mapper) });
|
|
4119
4150
|
}
|
|
4120
4151
|
function checkUnionVariants(parentUnion, node, variants, mapper) {
|
|
4121
4152
|
for (const variantNode of node.options) {
|
|
@@ -4150,13 +4181,12 @@ export function createChecker(program, resolver) {
|
|
|
4150
4181
|
});
|
|
4151
4182
|
variantType.decorators = checkDecorators(variantType, variantNode, mapper);
|
|
4152
4183
|
linkMapper(variantType, mapper);
|
|
4153
|
-
if (shouldCreateTypeForTemplate(variantNode.parent, mapper)) {
|
|
4154
|
-
finishType(variantType);
|
|
4155
|
-
}
|
|
4156
4184
|
if (links) {
|
|
4157
4185
|
linkType(links, variantType, mapper);
|
|
4158
4186
|
}
|
|
4159
|
-
return variantType
|
|
4187
|
+
return finishType(variantType, {
|
|
4188
|
+
skipDecorators: !shouldRunDecorators(variantNode.parent, mapper),
|
|
4189
|
+
});
|
|
4160
4190
|
}
|
|
4161
4191
|
function isMemberNode(node) {
|
|
4162
4192
|
return node.symbol && !!(node.symbol.flags & 65536 /* SymbolFlags.Member */);
|
|
@@ -4271,6 +4301,19 @@ export function createChecker(program, resolver) {
|
|
|
4271
4301
|
createType(typeDef);
|
|
4272
4302
|
return finishType(typeDef);
|
|
4273
4303
|
}
|
|
4304
|
+
/** Initialize model type for the given node */
|
|
4305
|
+
function initModel(node) {
|
|
4306
|
+
return createType({
|
|
4307
|
+
kind: "Model",
|
|
4308
|
+
node,
|
|
4309
|
+
name: "",
|
|
4310
|
+
namespace: node && getParentNamespaceType(node),
|
|
4311
|
+
properties: createRekeyableMap(),
|
|
4312
|
+
decorators: [],
|
|
4313
|
+
derivedModels: [],
|
|
4314
|
+
sourceModels: [],
|
|
4315
|
+
});
|
|
4316
|
+
}
|
|
4274
4317
|
/**
|
|
4275
4318
|
* Given the own-properties of a type, returns a fully-initialized type.
|
|
4276
4319
|
*/
|
|
@@ -4278,6 +4321,7 @@ export function createChecker(program, resolver) {
|
|
|
4278
4321
|
stats.createdTypes++;
|
|
4279
4322
|
Object.setPrototypeOf(typeDef, typePrototype);
|
|
4280
4323
|
typeDef.isFinished = false;
|
|
4324
|
+
typeDef.creating = true;
|
|
4281
4325
|
// If the type has an associated syntax node, check any directives that
|
|
4282
4326
|
// might be attached.
|
|
4283
4327
|
const createdType = typeDef;
|
|
@@ -4287,9 +4331,29 @@ export function createChecker(program, resolver) {
|
|
|
4287
4331
|
}
|
|
4288
4332
|
return createdType;
|
|
4289
4333
|
}
|
|
4290
|
-
function finishType(typeDef) {
|
|
4334
|
+
function finishType(typeDef, options = {}) {
|
|
4291
4335
|
stats.finishedTypes++;
|
|
4292
|
-
|
|
4336
|
+
if (!options.skipDecorators) {
|
|
4337
|
+
if ("decorators" in typeDef) {
|
|
4338
|
+
for (const decApp of typeDef.decorators) {
|
|
4339
|
+
applyDecoratorToType(program, decApp, typeDef);
|
|
4340
|
+
}
|
|
4341
|
+
}
|
|
4342
|
+
typeDef.isFinished = true;
|
|
4343
|
+
Object.setPrototypeOf(typeDef, typePrototype);
|
|
4344
|
+
}
|
|
4345
|
+
markAsChecked(typeDef);
|
|
4346
|
+
return typeDef;
|
|
4347
|
+
}
|
|
4348
|
+
function markAsChecked(type) {
|
|
4349
|
+
if (!type.creating)
|
|
4350
|
+
return;
|
|
4351
|
+
delete type.creating;
|
|
4352
|
+
const pending = waitingForResolution.get(type);
|
|
4353
|
+
if (pending) {
|
|
4354
|
+
pending.forEach(([_, resolution]) => resolution());
|
|
4355
|
+
}
|
|
4356
|
+
waitingForResolution.delete(type);
|
|
4293
4357
|
}
|
|
4294
4358
|
function getLiteralType(node) {
|
|
4295
4359
|
return createLiteralType(node.value, node);
|
|
@@ -4412,12 +4476,9 @@ export function createChecker(program, resolver) {
|
|
|
4412
4476
|
* recursively by the caller.
|
|
4413
4477
|
*/
|
|
4414
4478
|
function cloneType(type, additionalProps = {}) {
|
|
4415
|
-
|
|
4416
|
-
if (type.isFinished) {
|
|
4417
|
-
clone = finishType(clone);
|
|
4418
|
-
}
|
|
4479
|
+
const clone = initializeClone(type, additionalProps);
|
|
4419
4480
|
compilerAssert(clone.kind === type.kind, "cloneType must not change type kind");
|
|
4420
|
-
return clone;
|
|
4481
|
+
return finishType(clone, { skipDecorators: !type.isFinished });
|
|
4421
4482
|
}
|
|
4422
4483
|
/**
|
|
4423
4484
|
* Clone a type linking to the given symbol.
|
|
@@ -4473,7 +4534,7 @@ export function createChecker(program, resolver) {
|
|
|
4473
4534
|
break;
|
|
4474
4535
|
}
|
|
4475
4536
|
program.literalTypes.set(value, type);
|
|
4476
|
-
return type;
|
|
4537
|
+
return finishType(type);
|
|
4477
4538
|
}
|
|
4478
4539
|
/**
|
|
4479
4540
|
* Check if the source type can be assigned to the target type and emit diagnostics
|
|
@@ -4708,7 +4769,7 @@ export function filterModelProperties(program, model, filter) {
|
|
|
4708
4769
|
typekit.type.finishType(newProperty);
|
|
4709
4770
|
}
|
|
4710
4771
|
}
|
|
4711
|
-
return
|
|
4772
|
+
return program.checker.finishType(newModel);
|
|
4712
4773
|
}
|
|
4713
4774
|
/**
|
|
4714
4775
|
* Gets the property from the nearest base type that is overridden by the
|
|
@@ -4754,9 +4815,6 @@ function countPropertiesInherited(model, filter) {
|
|
|
4754
4815
|
}
|
|
4755
4816
|
return count;
|
|
4756
4817
|
}
|
|
4757
|
-
export function finishTypeForProgram(program, typeDef) {
|
|
4758
|
-
return finishTypeForProgramAndChecker(program, program.checker.typePrototype, typeDef);
|
|
4759
|
-
}
|
|
4760
4818
|
function linkMapper(typeDef, mapper) {
|
|
4761
4819
|
if (mapper) {
|
|
4762
4820
|
compilerAssert(!typeDef.templateMapper, "Mapper provided but template arguments already set.");
|
|
@@ -4830,16 +4888,6 @@ function getDocContent(content) {
|
|
|
4830
4888
|
}
|
|
4831
4889
|
return docs.join("");
|
|
4832
4890
|
}
|
|
4833
|
-
function finishTypeForProgramAndChecker(program, typePrototype, typeDef) {
|
|
4834
|
-
if ("decorators" in typeDef) {
|
|
4835
|
-
for (const decApp of typeDef.decorators) {
|
|
4836
|
-
applyDecoratorToType(program, decApp, typeDef);
|
|
4837
|
-
}
|
|
4838
|
-
}
|
|
4839
|
-
Object.setPrototypeOf(typeDef, typePrototype);
|
|
4840
|
-
typeDef.isFinished = true;
|
|
4841
|
-
return typeDef;
|
|
4842
|
-
}
|
|
4843
4891
|
function reportDeprecation(program, target, message, reportFunc) {
|
|
4844
4892
|
if (program.compilerOptions.ignoreDeprecated !== true) {
|
|
4845
4893
|
reportFunc(createDiagnostic({
|