Skip to content

Commit

Permalink
feat(zmodel): "type" construct and strongly-typed Json fields (#1813)
Browse files Browse the repository at this point in the history
  • Loading branch information
ymc9 authored Nov 4, 2024
1 parent 3b18362 commit 00ccb73
Show file tree
Hide file tree
Showing 35 changed files with 1,822 additions and 340 deletions.
92 changes: 85 additions & 7 deletions packages/language/src/generated/ast.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ export const ZModelTerminals = {
SL_COMMENT: /\/\/[^\n\r]*/,
};

export type AbstractDeclaration = Attribute | DataModel | DataSource | Enum | FunctionDecl | GeneratorDecl | Plugin;
export type AbstractDeclaration = Attribute | DataModel | DataSource | Enum | FunctionDecl | GeneratorDecl | Plugin | TypeDef;

export const AbstractDeclaration = 'AbstractDeclaration';

Expand Down Expand Up @@ -78,10 +78,10 @@ export function isReferenceTarget(item: unknown): item is ReferenceTarget {
return reflection.isInstance(item, ReferenceTarget);
}

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

export function isRegularID(item: unknown): item is RegularID {
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)));
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)));
}

export type RegularIDWithTypeNames = 'Any' | 'BigInt' | 'Boolean' | 'Bytes' | 'DateTime' | 'Decimal' | 'Float' | 'Int' | 'Json' | 'Null' | 'Object' | 'String' | 'Unsupported' | RegularID;
Expand All @@ -90,7 +90,7 @@ export function isRegularIDWithTypeNames(item: unknown): item is RegularIDWithTy
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';
}

export type TypeDeclaration = DataModel | Enum;
export type TypeDeclaration = DataModel | Enum | TypeDef;

export const TypeDeclaration = 'TypeDeclaration';

Expand Down Expand Up @@ -305,7 +305,7 @@ export function isDataModelField(item: unknown): item is DataModelField {
}

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

export interface TypeDef extends AstNode {
readonly $container: Model;
readonly $type: 'TypeDef';
comments: Array<string>
fields: Array<TypeDefField>
name: RegularID
}

export const TypeDef = 'TypeDef';

export function isTypeDef(item: unknown): item is TypeDef {
return reflection.isInstance(item, TypeDef);
}

export interface TypeDefField extends AstNode {
readonly $container: TypeDef;
readonly $type: 'TypeDefField';
attributes: Array<DataModelFieldAttribute>
comments: Array<string>
name: RegularIDWithTypeNames
type: TypeDefFieldType
}

export const TypeDefField = 'TypeDefField';

export function isTypeDefField(item: unknown): item is TypeDefField {
return reflection.isInstance(item, TypeDefField);
}

export interface TypeDefFieldType extends AstNode {
readonly $container: TypeDefField;
readonly $type: 'TypeDefFieldType';
array: boolean
optional: boolean
reference?: Reference<TypeDef>
type?: BuiltinType
}

export const TypeDefFieldType = 'TypeDefFieldType';

export function isTypeDefFieldType(item: unknown): item is TypeDefFieldType {
return reflection.isInstance(item, TypeDefFieldType);
}

export interface UnaryExpr extends AstNode {
readonly $container: Argument | ArrayExpr | AttributeArg | BinaryExpr | ConfigArrayExpr | ConfigField | ConfigInvocationArg | FieldInitializer | FunctionDecl | MemberAccessExpr | PluginField | ReferenceArg | UnaryExpr | UnsupportedFieldType;
readonly $type: 'UnaryExpr';
Expand Down Expand Up @@ -691,14 +735,17 @@ export type ZModelAstType = {
StringLiteral: StringLiteral
ThisExpr: ThisExpr
TypeDeclaration: TypeDeclaration
TypeDef: TypeDef
TypeDefField: TypeDefField
TypeDefFieldType: TypeDefFieldType
UnaryExpr: UnaryExpr
UnsupportedFieldType: UnsupportedFieldType
}

export class ZModelAstReflection extends AbstractAstReflection {

getAllTypes(): string[] {
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'];
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'];
}

protected override computeIsSubtype(subtype: string, supertype: string): boolean {
Expand Down Expand Up @@ -729,7 +776,8 @@ export class ZModelAstReflection extends AbstractAstReflection {
return this.isSubtype(ConfigExpr, supertype);
}
case DataModel:
case Enum: {
case Enum:
case TypeDef: {
return this.isSubtype(AbstractDeclaration, supertype) || this.isSubtype(TypeDeclaration, supertype);
}
case DataModelField:
Expand Down Expand Up @@ -772,6 +820,9 @@ export class ZModelAstReflection extends AbstractAstReflection {
case 'ReferenceExpr:target': {
return ReferenceTarget;
}
case 'TypeDefFieldType:reference': {
return TypeDef;
}
default: {
throw new Error(`${referenceId} is not a valid reference id.`);
}
Expand Down Expand Up @@ -989,6 +1040,33 @@ export class ZModelAstReflection extends AbstractAstReflection {
]
};
}
case 'TypeDef': {
return {
name: 'TypeDef',
mandatory: [
{ name: 'comments', type: 'array' },
{ name: 'fields', type: 'array' }
]
};
}
case 'TypeDefField': {
return {
name: 'TypeDefField',
mandatory: [
{ name: 'attributes', type: 'array' },
{ name: 'comments', type: 'array' }
]
};
}
case 'TypeDefFieldType': {
return {
name: 'TypeDefFieldType',
mandatory: [
{ name: 'array', type: 'boolean' },
{ name: 'optional', type: 'boolean' }
]
};
}
default: {
return {
name: type,
Expand Down
Loading

0 comments on commit 00ccb73

Please sign in to comment.