Enable the use of recursive type references in model definitions

This commit is contained in:
David Wilson 2021-03-24 15:50:28 -07:00
Родитель dc240c6c82
Коммит 1ca2a4a549
1 изменённых файлов: 26 добавлений и 3 удалений

Просмотреть файл

@ -76,14 +76,23 @@ export class MultiKeyMap<T> {
}
}
interface PendingModelInfo {
id: IdentifierNode;
type: ModelType;
}
export function createChecker(program: Program) {
let templateInstantiation: Array<Type> = [];
let instantiatingTemplate: Node | undefined;
let currentSymbolId = 0;
const symbolLinks = new Map<number, SymbolLinks>();
// for our first act, issue errors for duplicate symbols
// This variable holds on to the model type that is currently
// being instantiated in checkModelStatement so that it is
// possible to have recursive type references in properties.
let pendingModelType: PendingModelInfo | undefined = undefined;
// for our first act, issue errors for duplicate symbols
reportDuplicateSymbols(program.globalNamespace.exports!);
for (const file of program.sourceFiles) {
for (const ns of file.namespaces) {
@ -207,6 +216,8 @@ export function createChecker(program: Program) {
if (symbolLinks.declaredType) {
return symbolLinks.declaredType;
} else if (pendingModelType && pendingModelType.id.sv === sym.node.id.sv) {
return pendingModelType.type;
}
return checkModelStatement(sym.node);
@ -550,16 +561,25 @@ export function createChecker(program: Program) {
}
const baseModels = checkClassHeritage(node.heritage);
const properties = checkModelProperties(node);
const type: ModelType = {
kind: "Model",
name: node.id.sv,
node: node,
properties,
properties: new Map<string, ModelTypeProperty>(),
baseModels: baseModels,
namespace: getParentNamespaceType(node),
};
// Hold on to the model type that's being defined so that it
// can be referenced
pendingModelType = {
id: node.id,
type,
};
// Evaluate the properties after
type.properties = checkModelProperties(node);
if (
(instantiatingThisTemplate &&
templateInstantiation.every((t) => t.kind !== "TemplateParameter")) ||
@ -573,6 +593,9 @@ export function createChecker(program: Program) {
links.instantiations = new MultiKeyMap();
}
// The model is fully created now
pendingModelType = undefined;
return type;
}