@typespec/compiler 1.3.0-dev.1 → 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/config/config-loader.d.ts +4 -4
- package/dist/src/config/config-loader.d.ts.map +1 -1
- package/dist/src/config/config-loader.js.map +1 -1
- package/dist/src/config/config-to-options.d.ts +2 -2
- package/dist/src/config/config-to-options.d.ts.map +1 -1
- package/dist/src/config/config-to-options.js.map +1 -1
- 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 +252 -201
- package/dist/src/core/checker.js.map +1 -1
- package/dist/src/core/cli/actions/compile/args.d.ts.map +1 -1
- package/dist/src/core/cli/actions/compile/args.js +2 -12
- package/dist/src/core/cli/actions/compile/args.js.map +1 -1
- package/dist/src/core/cli/actions/init.d.ts +5 -0
- package/dist/src/core/cli/actions/init.d.ts.map +1 -1
- package/dist/src/core/cli/actions/init.js +4 -1
- package/dist/src/core/cli/actions/init.js.map +1 -1
- package/dist/src/core/cli/cli.js +30 -1
- package/dist/src/core/cli/cli.js.map +1 -1
- package/dist/src/core/cli/utils.d.ts +5 -0
- package/dist/src/core/cli/utils.d.ts.map +1 -1
- package/dist/src/core/cli/utils.js +15 -0
- package/dist/src/core/cli/utils.js.map +1 -1
- package/dist/src/core/formatter-fs.js +1 -1
- package/dist/src/core/formatter-fs.js.map +1 -1
- package/dist/src/core/helpers/type-name-utils.js +1 -1
- package/dist/src/core/helpers/type-name-utils.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/dist/src/init/init.d.ts +4 -0
- package/dist/src/init/init.d.ts.map +1 -1
- package/dist/src/init/init.js +80 -46
- package/dist/src/init/init.js.map +1 -1
- package/dist/src/internals/index.d.ts +1 -0
- package/dist/src/internals/index.d.ts.map +1 -1
- package/dist/src/internals/index.js +1 -0
- package/dist/src/internals/index.js.map +1 -1
- package/dist/src/module-resolver/module-resolver.js +1 -1
- package/dist/src/module-resolver/module-resolver.js.map +1 -1
- package/dist/src/server/server.js +11 -6
- package/dist/src/server/server.js.map +1 -1
- package/dist/src/server/serverlib.js +1 -1
- package/dist/src/server/serverlib.js.map +1 -1
- package/dist/src/testing/test-host.d.ts.map +1 -1
- package/dist/src/testing/test-host.js +1 -0
- package/dist/src/testing/test-host.js.map +1 -1
- package/package.json +3 -3
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
|
}
|
|
@@ -1119,6 +1122,7 @@ export function createChecker(program, resolver) {
|
|
|
1119
1122
|
return Array.from(this.variants.values()).map((v) => v.type);
|
|
1120
1123
|
},
|
|
1121
1124
|
expression: true,
|
|
1125
|
+
namespace: getParentNamespaceType(node),
|
|
1122
1126
|
variants: createRekeyableMap(),
|
|
1123
1127
|
decorators: [],
|
|
1124
1128
|
});
|
|
@@ -1159,10 +1163,42 @@ export function createChecker(program, resolver) {
|
|
|
1159
1163
|
// we're not instantiating this model and we've already checked it
|
|
1160
1164
|
return links.declaredType;
|
|
1161
1165
|
}
|
|
1166
|
+
const intersection = initModel(node);
|
|
1162
1167
|
const options = node.options.map((o) => [o, getTypeForNode(o, mapper)]);
|
|
1163
|
-
|
|
1164
|
-
|
|
1165
|
-
|
|
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();
|
|
1166
1202
|
}
|
|
1167
1203
|
function checkDecoratorDeclaration(node, mapper) {
|
|
1168
1204
|
const symbol = getMergedSymbol(node.symbol);
|
|
@@ -1267,18 +1303,8 @@ export function createChecker(program, resolver) {
|
|
|
1267
1303
|
};
|
|
1268
1304
|
}
|
|
1269
1305
|
}
|
|
1270
|
-
function mergeModelTypes(parentModelSym, node, options, mapper) {
|
|
1271
|
-
const properties =
|
|
1272
|
-
const intersection = createType({
|
|
1273
|
-
kind: "Model",
|
|
1274
|
-
node,
|
|
1275
|
-
name: "",
|
|
1276
|
-
namespace: getParentNamespaceType(node),
|
|
1277
|
-
properties: properties,
|
|
1278
|
-
decorators: [],
|
|
1279
|
-
derivedModels: [],
|
|
1280
|
-
sourceModels: [],
|
|
1281
|
-
});
|
|
1306
|
+
function mergeModelTypes(parentModelSym, node, options, mapper, intersection) {
|
|
1307
|
+
const properties = intersection.properties;
|
|
1282
1308
|
const indexers = [];
|
|
1283
1309
|
const modelOptions = options.filter((entry) => {
|
|
1284
1310
|
const [optionNode, option] = entry;
|
|
@@ -1338,7 +1364,7 @@ export function createChecker(program, resolver) {
|
|
|
1338
1364
|
else if (indexers.length > 1) {
|
|
1339
1365
|
intersection.indexer = {
|
|
1340
1366
|
key: indexers[0].key,
|
|
1341
|
-
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)),
|
|
1342
1368
|
};
|
|
1343
1369
|
}
|
|
1344
1370
|
linkMapper(intersection, mapper);
|
|
@@ -1408,7 +1434,8 @@ export function createChecker(program, resolver) {
|
|
|
1408
1434
|
if (node === globalNamespaceType.node)
|
|
1409
1435
|
return undefined;
|
|
1410
1436
|
if (node.kind === SyntaxKind.ModelExpression ||
|
|
1411
|
-
node.kind === SyntaxKind.IntersectionExpression
|
|
1437
|
+
node.kind === SyntaxKind.IntersectionExpression ||
|
|
1438
|
+
node.kind === SyntaxKind.UnionExpression) {
|
|
1412
1439
|
let parent = node.parent;
|
|
1413
1440
|
while (parent !== undefined) {
|
|
1414
1441
|
if (parent.kind === SyntaxKind.AliasStatement ||
|
|
@@ -1419,7 +1446,8 @@ export function createChecker(program, resolver) {
|
|
|
1419
1446
|
parent.kind === SyntaxKind.InterfaceStatement ||
|
|
1420
1447
|
parent.kind === SyntaxKind.UnionStatement ||
|
|
1421
1448
|
parent.kind === SyntaxKind.ModelExpression ||
|
|
1422
|
-
parent.kind === SyntaxKind.IntersectionExpression
|
|
1449
|
+
parent.kind === SyntaxKind.IntersectionExpression ||
|
|
1450
|
+
parent.kind === SyntaxKind.UnionExpression) {
|
|
1423
1451
|
return getParentNamespaceType(parent);
|
|
1424
1452
|
}
|
|
1425
1453
|
else {
|
|
@@ -1473,7 +1501,6 @@ export function createChecker(program, resolver) {
|
|
|
1473
1501
|
}
|
|
1474
1502
|
const namespace = getParentNamespaceType(node);
|
|
1475
1503
|
const name = node.id.sv;
|
|
1476
|
-
let decorators = [];
|
|
1477
1504
|
const { resolvedSymbol: parameterModelSym } = resolver.resolveMetaMemberByName(symbol, "parameters");
|
|
1478
1505
|
if (parameterModelSym?.members) {
|
|
1479
1506
|
const members = resolver.getAugmentedSymbolTable(parameterModelSym.members);
|
|
@@ -1485,78 +1512,71 @@ export function createChecker(program, resolver) {
|
|
|
1485
1512
|
}
|
|
1486
1513
|
}
|
|
1487
1514
|
}
|
|
1488
|
-
// Is this a definition or reference?
|
|
1489
|
-
let parameters, returnType, sourceOperation;
|
|
1490
|
-
if (node.signature.kind === SyntaxKind.OperationSignatureReference) {
|
|
1491
|
-
// Attempt to resolve the operation
|
|
1492
|
-
const baseOperation = checkOperationIs(node, node.signature.baseOperation, mapper);
|
|
1493
|
-
if (baseOperation) {
|
|
1494
|
-
sourceOperation = baseOperation;
|
|
1495
|
-
// Reference the same return type and create the parameters type
|
|
1496
|
-
const clone = initializeClone(baseOperation.parameters, {
|
|
1497
|
-
properties: createRekeyableMap(),
|
|
1498
|
-
});
|
|
1499
|
-
clone.properties = createRekeyableMap(Array.from(baseOperation.parameters.properties.entries()).map(([key, prop]) => [
|
|
1500
|
-
key,
|
|
1501
|
-
cloneTypeForSymbol(getMemberSymbol(parameterModelSym, prop.name), prop, {
|
|
1502
|
-
model: clone,
|
|
1503
|
-
sourceProperty: prop,
|
|
1504
|
-
}),
|
|
1505
|
-
]));
|
|
1506
|
-
parameters = finishType(clone);
|
|
1507
|
-
returnType = baseOperation.returnType;
|
|
1508
|
-
// Copy decorators from the base operation, inserting the base decorators first
|
|
1509
|
-
decorators = [...baseOperation.decorators];
|
|
1510
|
-
}
|
|
1511
|
-
else {
|
|
1512
|
-
// If we can't resolve the signature we return an empty model.
|
|
1513
|
-
parameters = createAndFinishType({
|
|
1514
|
-
kind: "Model",
|
|
1515
|
-
name: "",
|
|
1516
|
-
decorators: [],
|
|
1517
|
-
properties: createRekeyableMap(),
|
|
1518
|
-
derivedModels: [],
|
|
1519
|
-
sourceModels: [],
|
|
1520
|
-
});
|
|
1521
|
-
returnType = voidType;
|
|
1522
|
-
}
|
|
1523
|
-
}
|
|
1524
|
-
else {
|
|
1525
|
-
parameters = getTypeForNode(node.signature.parameters, mapper);
|
|
1526
|
-
returnType = getTypeForNode(node.signature.returnType, mapper);
|
|
1527
|
-
}
|
|
1528
1515
|
const operationType = createType({
|
|
1529
1516
|
kind: "Operation",
|
|
1530
1517
|
name,
|
|
1531
1518
|
namespace,
|
|
1519
|
+
parameters: null,
|
|
1520
|
+
returnType: voidType,
|
|
1532
1521
|
node,
|
|
1533
|
-
|
|
1534
|
-
returnType,
|
|
1535
|
-
decorators,
|
|
1536
|
-
sourceOperation,
|
|
1522
|
+
decorators: [],
|
|
1537
1523
|
interface: parentInterface,
|
|
1538
1524
|
});
|
|
1539
1525
|
if (links) {
|
|
1540
1526
|
linkType(links, operationType, mapper);
|
|
1541
1527
|
}
|
|
1542
|
-
decorators.push(...checkDecorators(operationType, node, mapper));
|
|
1543
|
-
operationType.parameters.namespace = namespace;
|
|
1544
1528
|
const parent = node.parent;
|
|
1545
|
-
|
|
1546
|
-
|
|
1547
|
-
|
|
1548
|
-
|
|
1549
|
-
|
|
1550
|
-
|
|
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 });
|
|
1551
1536
|
}
|
|
1552
|
-
|
|
1553
|
-
|
|
1554
|
-
|
|
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
|
+
});
|
|
1555
1561
|
}
|
|
1556
|
-
|
|
1557
|
-
|
|
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();
|
|
1558
1567
|
}
|
|
1559
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
|
+
}
|
|
1560
1580
|
return operationType;
|
|
1561
1581
|
}
|
|
1562
1582
|
function checkOperationIs(operation, opReference, mapper) {
|
|
@@ -2416,6 +2436,20 @@ export function createChecker(program, resolver) {
|
|
|
2416
2436
|
checkSourceFile(file);
|
|
2417
2437
|
}
|
|
2418
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);
|
|
2419
2453
|
}
|
|
2420
2454
|
function checkDuplicateSymbols() {
|
|
2421
2455
|
program.reportDuplicateSymbols(resolver.symbols.global.exports);
|
|
@@ -2520,65 +2554,67 @@ export function createChecker(program, resolver) {
|
|
|
2520
2554
|
}
|
|
2521
2555
|
}
|
|
2522
2556
|
const isBase = checkModelIs(node, node.is, mapper);
|
|
2523
|
-
|
|
2524
|
-
|
|
2525
|
-
|
|
2526
|
-
|
|
2527
|
-
|
|
2528
|
-
|
|
2529
|
-
|
|
2530
|
-
|
|
2531
|
-
|
|
2532
|
-
|
|
2533
|
-
|
|
2534
|
-
|
|
2535
|
-
|
|
2536
|
-
|
|
2537
|
-
|
|
2538
|
-
|
|
2539
|
-
|
|
2540
|
-
|
|
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
|
+
}
|
|
2541
2588
|
}
|
|
2542
|
-
}
|
|
2543
|
-
if (isBase) {
|
|
2544
|
-
type.baseModel = isBase.baseModel;
|
|
2545
|
-
}
|
|
2546
|
-
else if (node.extends) {
|
|
2547
|
-
type.baseModel = checkClassHeritage(node, node.extends, mapper);
|
|
2548
2589
|
if (type.baseModel) {
|
|
2549
|
-
|
|
2590
|
+
type.baseModel.derivedModels.push(type);
|
|
2550
2591
|
}
|
|
2551
|
-
|
|
2552
|
-
|
|
2553
|
-
|
|
2554
|
-
|
|
2555
|
-
|
|
2556
|
-
|
|
2557
|
-
|
|
2558
|
-
|
|
2559
|
-
|
|
2560
|
-
|
|
2561
|
-
|
|
2562
|
-
|
|
2563
|
-
|
|
2564
|
-
|
|
2565
|
-
|
|
2566
|
-
|
|
2567
|
-
|
|
2568
|
-
|
|
2569
|
-
|
|
2570
|
-
|
|
2571
|
-
|
|
2572
|
-
|
|
2573
|
-
}
|
|
2574
|
-
if (indexer) {
|
|
2575
|
-
type.indexer = indexer;
|
|
2576
|
-
}
|
|
2577
|
-
lateBindMemberContainer(type);
|
|
2578
|
-
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
|
+
});
|
|
2579
2615
|
return type;
|
|
2580
2616
|
}
|
|
2581
|
-
function
|
|
2617
|
+
function shouldRunDecorators(node, mapper) {
|
|
2582
2618
|
// Node is not a template we should create the type.
|
|
2583
2619
|
if (node.templateParameters.length === 0) {
|
|
2584
2620
|
return true;
|
|
@@ -2597,22 +2633,17 @@ export function createChecker(program, resolver) {
|
|
|
2597
2633
|
// we're not instantiating this model and we've already checked it
|
|
2598
2634
|
return links.declaredType;
|
|
2599
2635
|
}
|
|
2600
|
-
const
|
|
2601
|
-
const
|
|
2602
|
-
kind: "Model",
|
|
2603
|
-
name: "",
|
|
2604
|
-
node: node,
|
|
2605
|
-
properties,
|
|
2606
|
-
indexer: undefined,
|
|
2607
|
-
namespace: getParentNamespaceType(node),
|
|
2608
|
-
decorators: [],
|
|
2609
|
-
derivedModels: [],
|
|
2610
|
-
sourceModels: [],
|
|
2611
|
-
});
|
|
2636
|
+
const type = initModel(node);
|
|
2637
|
+
const properties = type.properties;
|
|
2612
2638
|
linkType(links, type, mapper);
|
|
2613
2639
|
linkMapper(type, mapper);
|
|
2614
|
-
|
|
2615
|
-
|
|
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;
|
|
2616
2647
|
}
|
|
2617
2648
|
/** Find the indexer that applies to this model. Either defined on itself or from a base model */
|
|
2618
2649
|
function findIndexer(model) {
|
|
@@ -3331,6 +3362,23 @@ export function createChecker(program, resolver) {
|
|
|
3331
3362
|
}
|
|
3332
3363
|
return isType;
|
|
3333
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
|
+
}
|
|
3334
3382
|
function checkSpreadProperty(parentModelSym, targetNode, parentModel, mapper) {
|
|
3335
3383
|
const targetType = getTypeForNode(targetNode, mapper);
|
|
3336
3384
|
if (targetType.kind === "TemplateParameter" || isErrorType(targetType)) {
|
|
@@ -3344,13 +3392,6 @@ export function createChecker(program, resolver) {
|
|
|
3344
3392
|
reportCheckerDiagnostic(createDiagnostic({ code: "spread-model", target: targetNode }), mapper);
|
|
3345
3393
|
return [[], undefined];
|
|
3346
3394
|
}
|
|
3347
|
-
if (parentModel === targetType) {
|
|
3348
|
-
reportCheckerDiagnostic(createDiagnostic({
|
|
3349
|
-
code: "spread-model",
|
|
3350
|
-
messageId: "selfSpread",
|
|
3351
|
-
target: targetNode,
|
|
3352
|
-
}));
|
|
3353
|
-
}
|
|
3354
3395
|
parentModel.sourceModels.push({ usage: "spread", model: targetType });
|
|
3355
3396
|
const props = [];
|
|
3356
3397
|
// copy each property
|
|
@@ -3422,15 +3463,16 @@ export function createChecker(program, resolver) {
|
|
|
3422
3463
|
type.decorators = checkDecorators(type, prop, mapper);
|
|
3423
3464
|
const parentTemplate = getParentTemplateNode(prop);
|
|
3424
3465
|
linkMapper(type, mapper);
|
|
3425
|
-
|
|
3466
|
+
let runDecorators = false;
|
|
3467
|
+
if (!parentTemplate || shouldRunDecorators(parentTemplate, mapper)) {
|
|
3426
3468
|
const docComment = docFromCommentForSym.get(sym);
|
|
3427
3469
|
if (docComment) {
|
|
3428
3470
|
type.decorators.unshift(createDocFromCommentDecorator("self", docComment));
|
|
3429
3471
|
}
|
|
3430
|
-
|
|
3472
|
+
runDecorators = true;
|
|
3431
3473
|
}
|
|
3432
3474
|
pendingResolutions.finish(sym, ResolutionKind.Type);
|
|
3433
|
-
return type;
|
|
3475
|
+
return finishType(type, { skipDecorators: !runDecorators });
|
|
3434
3476
|
}
|
|
3435
3477
|
function createDocFromCommentDecorator(key, doc) {
|
|
3436
3478
|
return {
|
|
@@ -3806,13 +3848,10 @@ export function createChecker(program, resolver) {
|
|
|
3806
3848
|
type.namespace?.scalars.set(type.name, type);
|
|
3807
3849
|
}
|
|
3808
3850
|
linkMapper(type, mapper);
|
|
3809
|
-
if (shouldCreateTypeForTemplate(node, mapper)) {
|
|
3810
|
-
finishType(type);
|
|
3811
|
-
}
|
|
3812
3851
|
if (isInTypeSpecNamespace(type)) {
|
|
3813
3852
|
stdTypes[type.name] = type;
|
|
3814
3853
|
}
|
|
3815
|
-
return type;
|
|
3854
|
+
return finishType(type, { skipDecorators: !shouldRunDecorators(node, mapper) });
|
|
3816
3855
|
}
|
|
3817
3856
|
function checkScalarExtends(scalar, extendsRef, mapper) {
|
|
3818
3857
|
const symId = getNodeSym(scalar);
|
|
@@ -3879,13 +3918,12 @@ export function createChecker(program, resolver) {
|
|
|
3879
3918
|
parameters: node.parameters.map((x) => checkFunctionParameter(x, mapper, false)),
|
|
3880
3919
|
});
|
|
3881
3920
|
linkMapper(member, mapper);
|
|
3882
|
-
if (shouldCreateTypeForTemplate(node.parent, mapper)) {
|
|
3883
|
-
finishType(member);
|
|
3884
|
-
}
|
|
3885
3921
|
if (links) {
|
|
3886
3922
|
linkType(links, member, mapper);
|
|
3887
3923
|
}
|
|
3888
|
-
return finishType(member
|
|
3924
|
+
return finishType(member, {
|
|
3925
|
+
skipDecorators: !shouldRunDecorators(node.parent, mapper),
|
|
3926
|
+
});
|
|
3889
3927
|
}
|
|
3890
3928
|
function checkAlias(node, mapper) {
|
|
3891
3929
|
const links = getSymbolLinks(node.symbol);
|
|
@@ -4054,15 +4092,14 @@ export function createChecker(program, resolver) {
|
|
|
4054
4092
|
interfaceType.operations.set(key, value);
|
|
4055
4093
|
}
|
|
4056
4094
|
linkMapper(interfaceType, mapper);
|
|
4057
|
-
if (shouldCreateTypeForTemplate(node, mapper)) {
|
|
4058
|
-
finishType(interfaceType);
|
|
4059
|
-
}
|
|
4060
4095
|
if (mapper === undefined) {
|
|
4061
4096
|
interfaceType.namespace?.interfaces.set(interfaceType.name, interfaceType);
|
|
4062
4097
|
}
|
|
4063
4098
|
lateBindMemberContainer(interfaceType);
|
|
4064
4099
|
lateBindMembers(interfaceType);
|
|
4065
|
-
return interfaceType
|
|
4100
|
+
return finishType(interfaceType, {
|
|
4101
|
+
skipDecorators: !shouldRunDecorators(node, mapper),
|
|
4102
|
+
});
|
|
4066
4103
|
}
|
|
4067
4104
|
function checkInterfaceMembers(node, mapper, interfaceType) {
|
|
4068
4105
|
const ownMembers = new Map();
|
|
@@ -4104,15 +4141,12 @@ export function createChecker(program, resolver) {
|
|
|
4104
4141
|
unionType.decorators = checkDecorators(unionType, node, mapper);
|
|
4105
4142
|
checkUnionVariants(unionType, node, variants, mapper);
|
|
4106
4143
|
linkMapper(unionType, mapper);
|
|
4107
|
-
if (shouldCreateTypeForTemplate(node, mapper)) {
|
|
4108
|
-
finishType(unionType);
|
|
4109
|
-
}
|
|
4110
4144
|
if (mapper === undefined) {
|
|
4111
4145
|
unionType.namespace?.unions.set(unionType.name, unionType);
|
|
4112
4146
|
}
|
|
4113
4147
|
lateBindMemberContainer(unionType);
|
|
4114
4148
|
lateBindMembers(unionType);
|
|
4115
|
-
return unionType;
|
|
4149
|
+
return finishType(unionType, { skipDecorators: !shouldRunDecorators(node, mapper) });
|
|
4116
4150
|
}
|
|
4117
4151
|
function checkUnionVariants(parentUnion, node, variants, mapper) {
|
|
4118
4152
|
for (const variantNode of node.options) {
|
|
@@ -4147,13 +4181,12 @@ export function createChecker(program, resolver) {
|
|
|
4147
4181
|
});
|
|
4148
4182
|
variantType.decorators = checkDecorators(variantType, variantNode, mapper);
|
|
4149
4183
|
linkMapper(variantType, mapper);
|
|
4150
|
-
if (shouldCreateTypeForTemplate(variantNode.parent, mapper)) {
|
|
4151
|
-
finishType(variantType);
|
|
4152
|
-
}
|
|
4153
4184
|
if (links) {
|
|
4154
4185
|
linkType(links, variantType, mapper);
|
|
4155
4186
|
}
|
|
4156
|
-
return variantType
|
|
4187
|
+
return finishType(variantType, {
|
|
4188
|
+
skipDecorators: !shouldRunDecorators(variantNode.parent, mapper),
|
|
4189
|
+
});
|
|
4157
4190
|
}
|
|
4158
4191
|
function isMemberNode(node) {
|
|
4159
4192
|
return node.symbol && !!(node.symbol.flags & 65536 /* SymbolFlags.Member */);
|
|
@@ -4268,6 +4301,19 @@ export function createChecker(program, resolver) {
|
|
|
4268
4301
|
createType(typeDef);
|
|
4269
4302
|
return finishType(typeDef);
|
|
4270
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
|
+
}
|
|
4271
4317
|
/**
|
|
4272
4318
|
* Given the own-properties of a type, returns a fully-initialized type.
|
|
4273
4319
|
*/
|
|
@@ -4275,6 +4321,7 @@ export function createChecker(program, resolver) {
|
|
|
4275
4321
|
stats.createdTypes++;
|
|
4276
4322
|
Object.setPrototypeOf(typeDef, typePrototype);
|
|
4277
4323
|
typeDef.isFinished = false;
|
|
4324
|
+
typeDef.creating = true;
|
|
4278
4325
|
// If the type has an associated syntax node, check any directives that
|
|
4279
4326
|
// might be attached.
|
|
4280
4327
|
const createdType = typeDef;
|
|
@@ -4284,9 +4331,29 @@ export function createChecker(program, resolver) {
|
|
|
4284
4331
|
}
|
|
4285
4332
|
return createdType;
|
|
4286
4333
|
}
|
|
4287
|
-
function finishType(typeDef) {
|
|
4334
|
+
function finishType(typeDef, options = {}) {
|
|
4288
4335
|
stats.finishedTypes++;
|
|
4289
|
-
|
|
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);
|
|
4290
4357
|
}
|
|
4291
4358
|
function getLiteralType(node) {
|
|
4292
4359
|
return createLiteralType(node.value, node);
|
|
@@ -4409,12 +4476,9 @@ export function createChecker(program, resolver) {
|
|
|
4409
4476
|
* recursively by the caller.
|
|
4410
4477
|
*/
|
|
4411
4478
|
function cloneType(type, additionalProps = {}) {
|
|
4412
|
-
|
|
4413
|
-
if (type.isFinished) {
|
|
4414
|
-
clone = finishType(clone);
|
|
4415
|
-
}
|
|
4479
|
+
const clone = initializeClone(type, additionalProps);
|
|
4416
4480
|
compilerAssert(clone.kind === type.kind, "cloneType must not change type kind");
|
|
4417
|
-
return clone;
|
|
4481
|
+
return finishType(clone, { skipDecorators: !type.isFinished });
|
|
4418
4482
|
}
|
|
4419
4483
|
/**
|
|
4420
4484
|
* Clone a type linking to the given symbol.
|
|
@@ -4470,7 +4534,7 @@ export function createChecker(program, resolver) {
|
|
|
4470
4534
|
break;
|
|
4471
4535
|
}
|
|
4472
4536
|
program.literalTypes.set(value, type);
|
|
4473
|
-
return type;
|
|
4537
|
+
return finishType(type);
|
|
4474
4538
|
}
|
|
4475
4539
|
/**
|
|
4476
4540
|
* Check if the source type can be assigned to the target type and emit diagnostics
|
|
@@ -4705,7 +4769,7 @@ export function filterModelProperties(program, model, filter) {
|
|
|
4705
4769
|
typekit.type.finishType(newProperty);
|
|
4706
4770
|
}
|
|
4707
4771
|
}
|
|
4708
|
-
return
|
|
4772
|
+
return program.checker.finishType(newModel);
|
|
4709
4773
|
}
|
|
4710
4774
|
/**
|
|
4711
4775
|
* Gets the property from the nearest base type that is overridden by the
|
|
@@ -4751,9 +4815,6 @@ function countPropertiesInherited(model, filter) {
|
|
|
4751
4815
|
}
|
|
4752
4816
|
return count;
|
|
4753
4817
|
}
|
|
4754
|
-
export function finishTypeForProgram(program, typeDef) {
|
|
4755
|
-
return finishTypeForProgramAndChecker(program, program.checker.typePrototype, typeDef);
|
|
4756
|
-
}
|
|
4757
4818
|
function linkMapper(typeDef, mapper) {
|
|
4758
4819
|
if (mapper) {
|
|
4759
4820
|
compilerAssert(!typeDef.templateMapper, "Mapper provided but template arguments already set.");
|
|
@@ -4827,16 +4888,6 @@ function getDocContent(content) {
|
|
|
4827
4888
|
}
|
|
4828
4889
|
return docs.join("");
|
|
4829
4890
|
}
|
|
4830
|
-
function finishTypeForProgramAndChecker(program, typePrototype, typeDef) {
|
|
4831
|
-
if ("decorators" in typeDef) {
|
|
4832
|
-
for (const decApp of typeDef.decorators) {
|
|
4833
|
-
applyDecoratorToType(program, decApp, typeDef);
|
|
4834
|
-
}
|
|
4835
|
-
}
|
|
4836
|
-
Object.setPrototypeOf(typeDef, typePrototype);
|
|
4837
|
-
typeDef.isFinished = true;
|
|
4838
|
-
return typeDef;
|
|
4839
|
-
}
|
|
4840
4891
|
function reportDeprecation(program, target, message, reportFunc) {
|
|
4841
4892
|
if (program.compilerOptions.ignoreDeprecated !== true) {
|
|
4842
4893
|
reportFunc(createDiagnostic({
|