Skip to content

Commit 00ccb73

Browse files
authored
feat(zmodel): "type" construct and strongly-typed Json fields (#1813)
1 parent 3b18362 commit 00ccb73

35 files changed

+1822
-340
lines changed

packages/language/src/generated/ast.ts

Lines changed: 85 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ export const ZModelTerminals = {
2020
SL_COMMENT: /\/\/[^\n\r]*/,
2121
};
2222

23-
export type AbstractDeclaration = Attribute | DataModel | DataSource | Enum | FunctionDecl | GeneratorDecl | Plugin;
23+
export type AbstractDeclaration = Attribute | DataModel | DataSource | Enum | FunctionDecl | GeneratorDecl | Plugin | TypeDef;
2424

2525
export const AbstractDeclaration = 'AbstractDeclaration';
2626

@@ -78,10 +78,10 @@ export function isReferenceTarget(item: unknown): item is ReferenceTarget {
7878
return reflection.isInstance(item, ReferenceTarget);
7979
}
8080

81-
export type RegularID = 'abstract' | 'attribute' | 'datasource' | 'enum' | 'import' | 'in' | 'model' | 'plugin' | 'view' | string;
81+
export type RegularID = 'abstract' | 'attribute' | 'datasource' | 'enum' | 'import' | 'in' | 'model' | 'plugin' | 'type' | 'view' | string;
8282

8383
export function isRegularID(item: unknown): item is RegularID {
84-
return item === 'model' || item === 'enum' || item === 'attribute' || item === 'datasource' || item === 'plugin' || item === 'abstract' || item === 'in' || item === 'view' || item === 'import' || (typeof item === 'string' && (/[_a-zA-Z][\w_]*/.test(item)));
84+
return item === 'model' || item === 'enum' || item === 'attribute' || item === 'datasource' || item === 'plugin' || item === 'abstract' || item === 'in' || item === 'view' || item === 'import' || item === 'type' || (typeof item === 'string' && (/[_a-zA-Z][\w_]*/.test(item)));
8585
}
8686

8787
export type RegularIDWithTypeNames = 'Any' | 'BigInt' | 'Boolean' | 'Bytes' | 'DateTime' | 'Decimal' | 'Float' | 'Int' | 'Json' | 'Null' | 'Object' | 'String' | 'Unsupported' | RegularID;
@@ -90,7 +90,7 @@ export function isRegularIDWithTypeNames(item: unknown): item is RegularIDWithTy
9090
return isRegularID(item) || item === 'String' || item === 'Boolean' || item === 'Int' || item === 'BigInt' || item === 'Float' || item === 'Decimal' || item === 'DateTime' || item === 'Json' || item === 'Bytes' || item === 'Null' || item === 'Object' || item === 'Any' || item === 'Unsupported';
9191
}
9292

93-
export type TypeDeclaration = DataModel | Enum;
93+
export type TypeDeclaration = DataModel | Enum | TypeDef;
9494

9595
export const TypeDeclaration = 'TypeDeclaration';
9696

@@ -305,7 +305,7 @@ export function isDataModelField(item: unknown): item is DataModelField {
305305
}
306306

307307
export interface DataModelFieldAttribute extends AstNode {
308-
readonly $container: DataModelField | EnumField;
308+
readonly $container: DataModelField | EnumField | TypeDefField;
309309
readonly $type: 'DataModelFieldAttribute';
310310
args: Array<AttributeArg>
311311
decl: Reference<Attribute>
@@ -620,6 +620,50 @@ export function isThisExpr(item: unknown): item is ThisExpr {
620620
return reflection.isInstance(item, ThisExpr);
621621
}
622622

623+
export interface TypeDef extends AstNode {
624+
readonly $container: Model;
625+
readonly $type: 'TypeDef';
626+
comments: Array<string>
627+
fields: Array<TypeDefField>
628+
name: RegularID
629+
}
630+
631+
export const TypeDef = 'TypeDef';
632+
633+
export function isTypeDef(item: unknown): item is TypeDef {
634+
return reflection.isInstance(item, TypeDef);
635+
}
636+
637+
export interface TypeDefField extends AstNode {
638+
readonly $container: TypeDef;
639+
readonly $type: 'TypeDefField';
640+
attributes: Array<DataModelFieldAttribute>
641+
comments: Array<string>
642+
name: RegularIDWithTypeNames
643+
type: TypeDefFieldType
644+
}
645+
646+
export const TypeDefField = 'TypeDefField';
647+
648+
export function isTypeDefField(item: unknown): item is TypeDefField {
649+
return reflection.isInstance(item, TypeDefField);
650+
}
651+
652+
export interface TypeDefFieldType extends AstNode {
653+
readonly $container: TypeDefField;
654+
readonly $type: 'TypeDefFieldType';
655+
array: boolean
656+
optional: boolean
657+
reference?: Reference<TypeDef>
658+
type?: BuiltinType
659+
}
660+
661+
export const TypeDefFieldType = 'TypeDefFieldType';
662+
663+
export function isTypeDefFieldType(item: unknown): item is TypeDefFieldType {
664+
return reflection.isInstance(item, TypeDefFieldType);
665+
}
666+
623667
export interface UnaryExpr extends AstNode {
624668
readonly $container: Argument | ArrayExpr | AttributeArg | BinaryExpr | ConfigArrayExpr | ConfigField | ConfigInvocationArg | FieldInitializer | FunctionDecl | MemberAccessExpr | PluginField | ReferenceArg | UnaryExpr | UnsupportedFieldType;
625669
readonly $type: 'UnaryExpr';
@@ -691,14 +735,17 @@ export type ZModelAstType = {
691735
StringLiteral: StringLiteral
692736
ThisExpr: ThisExpr
693737
TypeDeclaration: TypeDeclaration
738+
TypeDef: TypeDef
739+
TypeDefField: TypeDefField
740+
TypeDefFieldType: TypeDefFieldType
694741
UnaryExpr: UnaryExpr
695742
UnsupportedFieldType: UnsupportedFieldType
696743
}
697744

698745
export class ZModelAstReflection extends AbstractAstReflection {
699746

700747
getAllTypes(): string[] {
701-
return ['AbstractDeclaration', 'Argument', 'ArrayExpr', 'Attribute', 'AttributeArg', 'AttributeParam', 'AttributeParamType', 'BinaryExpr', 'BooleanLiteral', 'ConfigArrayExpr', 'ConfigExpr', 'ConfigField', 'ConfigInvocationArg', 'ConfigInvocationExpr', 'DataModel', 'DataModelAttribute', 'DataModelField', 'DataModelFieldAttribute', 'DataModelFieldType', 'DataSource', 'Enum', 'EnumField', 'Expression', 'FieldInitializer', 'FunctionDecl', 'FunctionParam', 'FunctionParamType', 'GeneratorDecl', 'InternalAttribute', 'InvocationExpr', 'LiteralExpr', 'MemberAccessExpr', 'Model', 'ModelImport', 'NullExpr', 'NumberLiteral', 'ObjectExpr', 'Plugin', 'PluginField', 'ReferenceArg', 'ReferenceExpr', 'ReferenceTarget', 'StringLiteral', 'ThisExpr', 'TypeDeclaration', 'UnaryExpr', 'UnsupportedFieldType'];
748+
return ['AbstractDeclaration', 'Argument', 'ArrayExpr', 'Attribute', 'AttributeArg', 'AttributeParam', 'AttributeParamType', 'BinaryExpr', 'BooleanLiteral', 'ConfigArrayExpr', 'ConfigExpr', 'ConfigField', 'ConfigInvocationArg', 'ConfigInvocationExpr', 'DataModel', 'DataModelAttribute', 'DataModelField', 'DataModelFieldAttribute', 'DataModelFieldType', 'DataSource', 'Enum', 'EnumField', 'Expression', 'FieldInitializer', 'FunctionDecl', 'FunctionParam', 'FunctionParamType', 'GeneratorDecl', 'InternalAttribute', 'InvocationExpr', 'LiteralExpr', 'MemberAccessExpr', 'Model', 'ModelImport', 'NullExpr', 'NumberLiteral', 'ObjectExpr', 'Plugin', 'PluginField', 'ReferenceArg', 'ReferenceExpr', 'ReferenceTarget', 'StringLiteral', 'ThisExpr', 'TypeDeclaration', 'TypeDef', 'TypeDefField', 'TypeDefFieldType', 'UnaryExpr', 'UnsupportedFieldType'];
702749
}
703750

704751
protected override computeIsSubtype(subtype: string, supertype: string): boolean {
@@ -729,7 +776,8 @@ export class ZModelAstReflection extends AbstractAstReflection {
729776
return this.isSubtype(ConfigExpr, supertype);
730777
}
731778
case DataModel:
732-
case Enum: {
779+
case Enum:
780+
case TypeDef: {
733781
return this.isSubtype(AbstractDeclaration, supertype) || this.isSubtype(TypeDeclaration, supertype);
734782
}
735783
case DataModelField:
@@ -772,6 +820,9 @@ export class ZModelAstReflection extends AbstractAstReflection {
772820
case 'ReferenceExpr:target': {
773821
return ReferenceTarget;
774822
}
823+
case 'TypeDefFieldType:reference': {
824+
return TypeDef;
825+
}
775826
default: {
776827
throw new Error(`${referenceId} is not a valid reference id.`);
777828
}
@@ -989,6 +1040,33 @@ export class ZModelAstReflection extends AbstractAstReflection {
9891040
]
9901041
};
9911042
}
1043+
case 'TypeDef': {
1044+
return {
1045+
name: 'TypeDef',
1046+
mandatory: [
1047+
{ name: 'comments', type: 'array' },
1048+
{ name: 'fields', type: 'array' }
1049+
]
1050+
};
1051+
}
1052+
case 'TypeDefField': {
1053+
return {
1054+
name: 'TypeDefField',
1055+
mandatory: [
1056+
{ name: 'attributes', type: 'array' },
1057+
{ name: 'comments', type: 'array' }
1058+
]
1059+
};
1060+
}
1061+
case 'TypeDefFieldType': {
1062+
return {
1063+
name: 'TypeDefFieldType',
1064+
mandatory: [
1065+
{ name: 'array', type: 'boolean' },
1066+
{ name: 'optional', type: 'boolean' }
1067+
]
1068+
};
1069+
}
9921070
default: {
9931071
return {
9941072
name: type,

0 commit comments

Comments
 (0)