diff --git a/README.md b/README.md index f0e025f..e1a9585 100644 --- a/README.md +++ b/README.md @@ -25,7 +25,7 @@ interface { const doc = parse(source, undefined, { noLocation: true }); const errors = validate(doc, ...CommonRules); -if (errors.length > 0) { +if (errors.length > 0) { errors.map(e => console.log(e.message)); } else { const context = new Context({}); diff --git a/package.json b/package.json index 498cce0..935386e 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@apexlang/core", - "version": "0.0.16", + "version": "0.0.17", "description": "Apex language JavaScript support", "keywords": [ "apex", diff --git a/src/model/index.ts b/src/model/index.ts new file mode 100644 index 0000000..214e938 --- /dev/null +++ b/src/model/index.ts @@ -0,0 +1,3 @@ +export * from "./model.js"; +export * from "./kinds.js"; +export * from "./visitor.js"; diff --git a/src/model/kinds.ts b/src/model/kinds.ts new file mode 100644 index 0000000..c8a8902 --- /dev/null +++ b/src/model/kinds.ts @@ -0,0 +1,25 @@ +export enum Kind { + // Models + Namespace = "Namespace", + Import = "Import", + Alias = "Alias", + Interface = "Interface", + Role = "Role", + Operation = "Operation", + Parameter = "Parameter", + Type = "Type", + Field = "Field", + Union = "Union", + Enum = "Enum", + EnumValue = "EnumValue", + Directive = "Directive", + Require = "Require", + Annotation = "Annotation", + Argument = "Argument", + Void = "Void", + Primitive = "Primitive", + List = "List", + Map = "Map", + Optional = "Optional", + Stream = "Stream", +} diff --git a/src/model/model.ts b/src/model/model.ts new file mode 100644 index 0000000..b95b22a --- /dev/null +++ b/src/model/model.ts @@ -0,0 +1,645 @@ +import { + NamespaceDefinition, + StringValue, + Annotation as AnnotationDef, + Argument as ArgumentDef, + AliasDefinition, + TypeDefinition, + FieldDefinition, + Value, + ValuedDefinition, + ParameterDefinition, + InterfaceDefinition, + RoleDefinition, + OperationDefinition, + UnionDefinition, + EnumDefinition, + EnumValueDefinition, + DirectiveDefinition, + DirectiveRequire, +} from "../ast/index.js"; +import { Kind } from "./kinds.js"; +import { Context, Visitor } from "./visitor.js"; +import { + Type as ASTType, + ListType as ASTListType, + MapType as ASTMapType, + Optional as ASTOptional, +} from "../ast/index.js"; + +class Base { + readonly kind: Kind; + + constructor(kind: Kind) { + this.kind = kind; + } +} + +export enum PrimitiveName { + ID = "ID", + String = "string", + U8 = "u8", + U16 = "u16", + U32 = "u32", + U64 = "u64", + I8 = "i8", + I16 = "i16", + I32 = "i32", + I64 = "i64", + F32 = "f32", + F64 = "f64", + DateTime = "datetime", + Bool = "bool", + Bytes = "bytes", +} + +export class Void extends Base { + constructor() { + super(Kind.Void); + } +} + +export const VoidValue = new Void(); + +export interface Named { + readonly name: string; +} + +export class Primitive extends Base { + readonly name: PrimitiveName; + + constructor(name: PrimitiveName) { + super(Kind.Primitive); + this.name = name; + } +} + +export const primitives: { [name: string]: Primitive } = { + ID: new Primitive(PrimitiveName.ID), + string: new Primitive(PrimitiveName.String), + u8: new Primitive(PrimitiveName.U8), + u16: new Primitive(PrimitiveName.U16), + u32: new Primitive(PrimitiveName.U32), + u64: new Primitive(PrimitiveName.U64), + i8: new Primitive(PrimitiveName.I8), + i16: new Primitive(PrimitiveName.I16), + i32: new Primitive(PrimitiveName.I32), + i64: new Primitive(PrimitiveName.I64), + f32: new Primitive(PrimitiveName.F32), + f64: new Primitive(PrimitiveName.F64), + datetime: new Primitive(PrimitiveName.DateTime), + bool: new Primitive(PrimitiveName.Bool), + bytes: new Primitive(PrimitiveName.Bytes), +}; + +export class List extends Base { + readonly type: AnyType; + + constructor(tr: TypeResolver, def: ASTListType) { + super(Kind.List); + this.type = tr(def.type); + } +} + +export class Map extends Base { + readonly keyType: AnyType; + readonly valueType: AnyType; + + constructor(tr: TypeResolver, def: ASTMapType) { + super(Kind.Map); + this.keyType = tr(def.keyType); + this.valueType = tr(def.valueType); + } +} + +export class Optional extends Base { + readonly type: AnyType; + + constructor(tr: TypeResolver, def: ASTOptional) { + super(Kind.Optional); + this.type = tr(def.type); + } +} + +export class Stream extends Base { + type: AnyType; + + constructor(tr: TypeResolver, def: ASTOptional) { + super(Kind.Stream); + this.type = tr(def.type); + } +} + +export type AnyType = + | Primitive + | Alias + | Type + | Union + | Enum + | List + | Map + | Optional + | Stream + | Void; + +export abstract class Annotated extends Base { + readonly annotations: Annotation[]; + + constructor(kind: Kind, annotations: AnnotationDef[]) { + super(kind); + this.annotations = annotations.map((v) => new Annotation(v)); + } + + annotation( + name: string, + callback?: (annotation: Annotation) => void + ): Annotation | undefined { + return getAnnotation(name, this.annotations, callback); + } +} + +export type TypeResolver = (name: ASTType) => AnyType; + +export class Namespace extends Annotated { + readonly node: NamespaceDefinition; + readonly name: string; + readonly description?: string; + + readonly directives: { [name: string]: Directive }; + readonly aliases: { [name: string]: Alias }; + readonly interfaces: Interface[]; + readonly roles: { [name: string]: Role }; + readonly types: { [name: string]: Type }; + readonly enums: { [name: string]: Enum }; + readonly unions: { [name: string]: Union }; + readonly allTypes: { [name: string]: AnyType }; + + constructor(tr: TypeResolver, node: NamespaceDefinition) { + super(Kind.Namespace, node.annotations); + this.node = node; + this.name = node.name.value; + this.description = optionalString(node.description); + this.directives = {}; + this.interfaces = []; + this.roles = {}; + this.types = {}; + this.enums = {}; + this.unions = {}; + this.aliases = {}; + this.allTypes = {}; + } + + public accept(context: Context, visitor: Visitor): void { + context = context.clone({ namespace: this }); + visitor.visitNamespaceBefore(context); + visitor.visitNamespace(context); + + visitor.visitDirectivesBefore(context); + for (let name in this.directives) { + const item = this.directives[name]; + item.accept(context.clone({ directive: item }), visitor); + } + visitor.visitDirectivesAfter(context); + + visitor.visitAliasesBefore(context); + for (let name in this.aliases) { + const item = this.aliases[name]; + item.accept(context.clone({ alias: item }), visitor); + } + visitor.visitAliasesAfter(context); + + visitor.visitAllOperationsBefore(context); + + this.interfaces.map((iface) => { + iface.accept(context.clone({ interfaceDef: iface }), visitor); + }); + + visitor.visitRolesBefore(context); + for (let name in this.roles) { + const item = this.roles[name]; + item.accept(context.clone({ role: item }), visitor); + } + visitor.visitRolesAfter(context); + + visitor.visitAllOperationsAfter(context); + + visitor.visitTypesBefore(context); + for (let name in this.types) { + const item = this.types[name]; + if (!item.annotation("novisit")) { + item.accept(context.clone({ type: item }), visitor); + } + } + visitor.visitTypesAfter(context); + + visitor.visitUnionsBefore(context); + for (let name in this.unions) { + const item = this.unions[name]; + item.accept(context.clone({ union: item }), visitor); + } + visitor.visitUnionsAfter(context); + + visitor.visitEnumsBefore(context); + for (let name in this.enums) { + const item = this.enums[name]; + if (!item.annotation("novisit")) { + item.accept(context.clone({ enumDef: item }), visitor); + } + } + visitor.visitEnumsAfter(context); + + visitor.visitNamespaceAfter(context); + } +} + +export class Alias extends Annotated implements Named { + readonly node: AliasDefinition; + readonly name: string; + readonly description?: string; + readonly type: AnyType; + + constructor(tr: TypeResolver, node: AliasDefinition) { + super(Kind.Alias, node.annotations); + this.node = node; + this.name = node.name.value; + this.description = optionalString(node.description); + this.type = tr(node.type); + } + + public accept(context: Context, visitor: Visitor): void { + visitor.visitAlias(context); + } +} + +export class Type extends Annotated implements Named { + readonly node: TypeDefinition; + readonly name: string; + readonly description?: string; + readonly fields: Field[]; + + constructor(tr: TypeResolver, node: TypeDefinition) { + super(Kind.Type, node.annotations); + this.node = node; + this.name = node.name.value; + this.description = optionalString(node.description); + this.fields = node.fields.map((v) => new Field(tr, v)); + } + + public accept(context: Context, visitor: Visitor): void { + visitor.visitTypeBefore(context); + visitor.visitType(context); + + context = context.clone({ fields: this.fields }); + visitor.visitTypeFieldsBefore(context); + context.fields!.map((field, index) => { + field.accept(context.clone({ field: field, fieldIndex: index }), visitor); + }); + visitor.visitTypeFieldsAfter(context); + visitor.visitTypeAfter(context); + } +} + +export abstract class Valued extends Annotated implements Named { + readonly name: string; + readonly description?: string; + readonly type: AnyType; + readonly default?: Value; + + constructor(tr: TypeResolver, kind: Kind, node: ValuedDefinition) { + super(kind, node.annotations); + this.name = node.name.value; + this.description = optionalString(node.description); + this.type = tr(node.type); + } +} + +export class Field extends Valued { + readonly node: FieldDefinition; + + constructor(tr: TypeResolver, node: FieldDefinition) { + super(tr, Kind.Field, node); + this.node = node; + } + + public accept(context: Context, visitor: Visitor): void { + visitor.visitTypeField(context); + } +} + +export class Interface extends Annotated { + readonly node: InterfaceDefinition; + readonly description?: string; + readonly operations: Operation[]; + + constructor(tr: TypeResolver, node: InterfaceDefinition) { + super(Kind.Interface, node.annotations); + this.node = node; + this.description = optionalString(node.description); + this.operations = node.operations.map((v) => new Operation(tr, v)); + } + + public accept(context: Context, visitor: Visitor): void { + visitor.visitInterfaceBefore(context); + visitor.visitInterface(context); + + context = context.clone({ operations: this.operations }); + visitor.visitOperationsBefore(context); + context.operations!.map((operation) => { + operation.accept(context.clone({ operation: operation }), visitor); + }); + + visitor.visitOperationsAfter(context); + visitor.visitInterfaceAfter(context); + } +} + +export class Role extends Annotated implements Named { + readonly node: InterfaceDefinition; + readonly name: string; + readonly description?: string; + readonly operations: Operation[]; + + constructor(tr: TypeResolver, node: RoleDefinition) { + super(Kind.Role, node.annotations); + this.node = node; + this.name = node.name.value; + this.description = optionalString(node.description); + this.operations = node.operations.map((v) => new Operation(tr, v)); + } + + public accept(context: Context, visitor: Visitor): void { + visitor.visitRoleBefore(context); + visitor.visitRole(context); + + context = context.clone({ operations: this.operations }); + visitor.visitOperationsBefore(context); + context.operations!.map((operation) => { + operation.accept(context.clone({ operation: operation }), visitor); + }); + + visitor.visitOperationsAfter(context); + visitor.visitRoleAfter(context); + } +} + +export class Operation extends Annotated implements Named { + readonly node: OperationDefinition; + readonly name: string; + readonly description?: string; + readonly parameters: Parameter[]; + readonly type: AnyType; + readonly unary: boolean; + + constructor(tr: TypeResolver, node: OperationDefinition) { + super(Kind.Operation, node.annotations); + this.node = node; + this.name = node.name.value; + this.description = optionalString(node.description); + this.parameters = node.parameters.map((v) => new Parameter(tr, v)); + this.type = tr(node.type); + this.unary = node.unary; + } + + public isUnary(): boolean { + return this.unary && this.parameters && this.parameters.length == 1; + } + + public unaryOp(): Parameter { + return this.parameters[0]; + } + + public accept(context: Context, visitor: Visitor): void { + visitor.visitOperationBefore(context); + visitor.visitOperation(context); + + context = context.clone({ parameters: this.parameters }); + visitor.visitParametersBefore(context); + context.parameters!.map((parameter, index) => { + parameter.accept( + context.clone({ parameter: parameter, parameterIndex: index }), + visitor + ); + }); + + visitor.visitParametersAfter(context); + visitor.visitOperationAfter(context); + } +} + +export class Parameter extends Valued { + readonly node: ParameterDefinition; + + constructor(tr: TypeResolver, node: ParameterDefinition) { + super(tr, Kind.Parameter, node); + this.node = node; + } + + public accept(context: Context, visitor: Visitor): void { + if (context.operation != undefined) { + visitor.visitParameter(context); + } else if (context.directive != undefined) { + visitor.visitDirectiveParameter(context); + } + } +} + +export class Union extends Annotated implements Named { + readonly node: UnionDefinition; + readonly name: string; + readonly description?: string; + readonly types: AnyType[]; + + constructor(tr: TypeResolver, node: UnionDefinition) { + super(Kind.Union, node.annotations); + this.node = node; + this.name = node.name.value; + this.description = optionalString(node.description); + this.types = node.types.map((v) => tr(v)); + } + + public accept(context: Context, visitor: Visitor): void { + visitor.visitUnion(context); + } +} + +export class Enum extends Annotated implements Named { + readonly node: EnumDefinition; + readonly name: string; + readonly description?: string; + readonly values: EnumValue[]; + + constructor(tr: TypeResolver, node: EnumDefinition) { + super(Kind.Enum, node.annotations); + this.node = node; + this.name = node.name.value; + this.description = optionalString(node.description); + this.values = node.values.map((v) => new EnumValue(tr, v)); + } + + public accept(context: Context, visitor: Visitor): void { + visitor.visitEnumBefore(context); + visitor.visitEnum(context); + + context = context.clone({ enumValues: this.values }); + visitor.visitEnumValuesBefore(context); + context.enumValues!.map((enumValue) => { + enumValue.accept(context.clone({ enumValue: enumValue }), visitor); + }); + + visitor.visitEnumValuesAfter(context); + visitor.visitEnumAfter(context); + } +} + +export class EnumValue extends Annotated implements Named { + readonly node: EnumValueDefinition; + readonly name: string; + readonly description?: string; + readonly index: number; + readonly display?: string; + + constructor(tr: TypeResolver, node: EnumValueDefinition) { + super(Kind.EnumValue, node.annotations); + this.node = node; + this.name = node.name.value; + this.description = optionalString(node.description); + this.index = node.index.value; + this.display = optionalString(node.display); + } + + public accept(context: Context, visitor: Visitor): void { + visitor.visitEnumValue(context); + } +} + +export class Directive extends Base implements Named { + readonly node: DirectiveDefinition; + readonly name: string; + readonly description?: string; + readonly parameters: Parameter[]; + readonly locations: string[]; + readonly requires: Require[]; + + constructor(tr: TypeResolver, node: DirectiveDefinition) { + super(Kind.Directive); + this.node = node; + this.name = node.name.value; + this.description = optionalString(node.description); + this.parameters = node.parameters.map((v) => new Parameter(tr, v)); + this.locations = node.locations.map((v) => v.value); + this.requires = node.requires.map((v) => new Require(tr, v)); + } + + public hasLocation(location: string): boolean { + for (let l of this.locations) { + if (l == location) { + return true; + } + } + return false; + } + + public accept(context: Context, visitor: Visitor): void { + visitor.visitDirectiveBefore(context); + visitor.visitDirective(context); + + context = context.clone({ parameters: this.parameters }); + visitor.visitDirectiveParametersBefore(context); + context.parameters!.map((parameter, index) => { + parameter.accept( + context.clone({ parameter: parameter, parameterIndex: index }), + visitor + ); + }); + + visitor.visitDirectiveParametersAfter(context); + visitor.visitDirectiveAfter(context); + } +} + +export class Require extends Base { + readonly node: DirectiveRequire; + readonly directive: string; + readonly locations: string[]; + + constructor(tr: TypeResolver, node: DirectiveRequire) { + super(Kind.Require); + this.node = node; + this.directive = node.directive.value; + this.locations = node.locations.map((v) => v.value); + } + + public hasLocation(location: string): boolean { + for (let l of this.locations) { + if (l == location) { + return true; + } + } + return false; + } +} + +export class Annotation extends Base implements Named { + readonly node: AnnotationDef; + readonly name: string; + readonly arguments: Argument[]; + + constructor(node: AnnotationDef) { + super(Kind.Annotation); + this.node = node; + this.name = node.name.value; + this.arguments = node.arguments.map((v) => new Argument(v)); + } + + convert(): T { + let obj: { [k: string]: any } = {}; + this.arguments.map((arg) => { + obj[arg.name] = arg.value.getValue(); + }); + return obj as T; + } + + public accept(context: Context, visitor: Visitor): void { + visitor.visitAnnotation(context); + } +} + +export class Argument extends Base implements Named { + readonly node: ArgumentDef; + readonly name: string; + readonly value: Value; + + constructor(node: ArgumentDef) { + super(Kind.Argument); + this.node = node; + this.name = node.name.value; + this.value = node.value; + } +} + +function optionalString(value?: StringValue): string | undefined { + if (value == undefined) { + return undefined; + } + + return value.value; +} + +function getAnnotation( + name: string, + annotations?: Annotation[], + callback?: (annotation: Annotation) => void +): Annotation | undefined { + if (annotations == undefined) { + return undefined; + } + for (let a of annotations!) { + if (a.name === name) { + if (callback != undefined) { + callback(a); + } + return a; + } + } + return undefined; +} diff --git a/src/model/visitor.ts b/src/model/visitor.ts new file mode 100644 index 0000000..0f23a7e --- /dev/null +++ b/src/model/visitor.ts @@ -0,0 +1,1240 @@ +import { + Namespace, + AnyType, + Interface, + Role, + Enum, + Union, + Parameter, + Field, + Operation, + EnumValue, + Directive, + Alias, + Type as MObject, + Optional, + List, + Map, + Stream, + primitives, + VoidValue, +} from "./model.js"; +import { + Document, + Annotation, + NamespaceDefinition, + DirectiveDefinition, + AliasDefinition, + InterfaceDefinition, + RoleDefinition, + TypeDefinition, + EnumDefinition, + UnionDefinition, + Named, + Name, +} from "../ast/index.js"; +import autoBind from "../auto-bind.js"; +import { ApexError } from "../error/index.js"; +import { Kind } from "../ast/index.js"; +import { + Type as ASTType, + Kind as ASTKind, + ListType as ASTListType, + MapType as ASTMapType, + Optional as ASTOptional, + Stream as ASTStream, +} from "../ast/index.js"; + +export class Writer { + private code: string = ""; + + write(source: string) { + this.code += source; + } + + string(): string { + return this.code; + } +} + +export type ObjectMap = { [key: string]: T }; + +interface NamedParameters { + namespace?: Namespace; + directive?: Directive; + alias?: Alias; + interfaceDef?: Interface; + role?: Role; + type?: MObject; + operations?: Operation[]; + operation?: Operation; + parameters?: Parameter[]; + parameter?: Parameter; + parameterIndex?: number; + fields?: Field[]; + field?: Field; + fieldIndex?: number; + enumDef?: Enum; + enumValues?: EnumValue[]; + enumValue?: EnumValue; + union?: Union; + annotation?: Annotation; +} + +class ErrorHolder { + errors: ApexError[]; + + constructor() { + this.errors = new Array(); + } + + reportError(error: ApexError): void { + this.errors.push(error); + } +} + +export class Context { + config: ObjectMap; + document?: Document; + + // Top-level definitions + namespaces: Namespace[]; + + // Drill-down definitions + namespace: Namespace; + namespacePos: number = 9999; + directive?: Directive; + alias?: Alias; + interface?: Interface; + role?: Role; + type?: MObject; + operations?: Operation[]; + operation?: Operation; + parameters?: Parameter[]; + parameter?: Parameter; + parameterIndex?: number; + fields?: Field[]; + field?: Field; + fieldIndex?: number; + enum?: Enum; + enumValues?: EnumValue[]; + enumValue?: EnumValue; + union?: Union; + + annotations?: Annotation[]; + annotation?: Annotation; + + private errors: ErrorHolder; + private typeMap: { + [name: string]: + | AliasDefinition + | TypeDefinition + | UnionDefinition + | EnumDefinition; + }; + + constructor(config: ObjectMap, document?: Document, other?: Context) { + this.config = config || {}; + this.namespace = new Namespace( + this.getType.bind(this), + new NamespaceDefinition( + undefined, + new Name(undefined, "undefined"), + undefined + ) + ); + + if (other != undefined) { + this.document = other.document; + this.namespace = other.namespace; + this.namespaces = other.namespaces; + // this.annotations = other.annotations; + // this.annotation = other.annotation; + + this.errors = other.errors; + this.typeMap = other.typeMap; + } else { + this.namespaces = []; + // this.annotations = []; + + this.errors = new ErrorHolder(); + this.typeMap = {}; + } + + if (this.document == undefined && document != undefined) { + this.document = document!; + this.parseDocument(); + } else if (!other) { + throw new Error("document or context is required"); + } + + autoBind(this); + } + + clone({ + namespace, + directive, + alias, + interfaceDef, + role, + type, + operations, + operation, + parameters, + parameter, + parameterIndex, + fields, + field, + fieldIndex, + enumDef, + enumValues, + enumValue, + union, + annotation, + }: NamedParameters): Context { + var context = new Context(this.config, undefined, this); + + context.namespace = namespace || this.namespace; + context.namespacePos = this.namespacePos; + context.directive = directive || this.directive; + context.alias = alias || this.alias; + context.interface = interfaceDef || this.interface; + context.role = role || this.role; + context.type = type || this.type; + context.operations = operations || this.operations; + context.operation = operation || this.operation; + context.parameters = parameters || this.parameters; + context.parameter = parameter || this.parameter; + context.parameterIndex = parameterIndex || this.parameterIndex; + context.fields = fields || this.fields; + context.field = field || this.field; + context.fieldIndex = fieldIndex || this.fieldIndex; + context.enum = enumDef || this.enum; + context.enumValues = enumValues || this.enumValues; + context.enumValue = enumValue || this.enumValue; + context.union = union || this.union; + context.annotation = annotation || this.annotation; + + return context; + } + + private parseDocument() { + this.document!.definitions.forEach((value, index) => { + switch (value.getKind()) { + // There is one namespace per document. + case Kind.NamespaceDefinition: + const namespace = new Namespace( + this.getType.bind(this), + value as NamespaceDefinition + ); + this.namespaces.push(namespace); + this.namespace = namespace; + this.namespacePos = index; + break; + case Kind.AliasDefinition: + const aliasDef = value as AliasDefinition; + this.typeMap[aliasDef.name.value] = aliasDef; + break; + case Kind.TypeDefinition: + const typeDef = value as TypeDefinition; + this.typeMap[typeDef.name.value] = typeDef; + break; + case Kind.EnumDefinition: + const enumDef = value as EnumDefinition; + this.typeMap[enumDef.name.value] = enumDef; + break; + case Kind.UnionDefinition: + const unionDef = value as UnionDefinition; + this.typeMap[unionDef.name.value] = unionDef; + break; + } + }); + + if (!this.namespace || this.namespace.name == "undefined") { + throw new Error("namespace not found"); + } + + this.document!.definitions.forEach((value, index) => { + switch (value.getKind()) { + case Kind.DirectiveDefinition: + const directiveDef = value as DirectiveDefinition; + const directive = new Directive( + this.getType.bind(this), + directiveDef + ); + this.namespace.directives[directive.name] = directive; + break; + case Kind.AliasDefinition: + const aliasDef = value as AliasDefinition; + if (!this.namespace.allTypes[aliasDef.name.value]) { + const alias = new Alias(this.getType.bind(this), aliasDef); + this.namespace.aliases[alias.name] = alias; + this.namespace.allTypes[alias.name] = alias; + } + break; + case Kind.InterfaceDefinition: + const iface = new Interface( + this.getType.bind(this), + value as InterfaceDefinition + ); + this.namespace.interfaces.push(iface); + break; + case Kind.RoleDefinition: + const role = new Role( + this.getType.bind(this), + value as RoleDefinition + ); + this.namespace.roles[role.name] = role; + break; + case Kind.TypeDefinition: + const typeDef = value as TypeDefinition; + if (!this.namespace.allTypes[typeDef.name.value]) { + const type = new MObject(this.getType.bind(this), typeDef); + this.namespace.types[type.name] = type; + this.namespace.allTypes[type.name] = type; + } + break; + case Kind.EnumDefinition: + const enumDef = value as EnumDefinition; + if (!this.namespace.allTypes[enumDef.name.value]) { + const enumInst = new Enum(this.getType.bind(this), enumDef); + this.namespace.enums[enumInst.name] = enumInst; + this.namespace.allTypes[enumInst.name] = enumInst; + } + break; + case Kind.UnionDefinition: + const unionDef = value as UnionDefinition; + if (!this.namespace.allTypes[unionDef.name.value]) { + const union = new Union(this.getType.bind(this), unionDef); + this.namespace.unions[union.name] = union; + this.namespace.allTypes[union.name] = union; + } + break; + } + }); + } + + reportError(error: ApexError): void { + this.errors.reportError(error); + } + + getErrors(): ApexError[] { + return this.errors.errors; + } + + getType(t: ASTType): AnyType { + switch (t.getKind()) { + case ASTKind.Named: + const name = (t as Named).name.value; + if (name === "void") { + return VoidValue; + } + + let namedType = this.namespace!.allTypes[name]; + if (namedType != undefined) { + return namedType; + } + + namedType = primitives[name]; + if (namedType != undefined) { + return namedType; + } + + const anyTypeDef = this.typeMap[name]; + switch (anyTypeDef.getKind()) { + case ASTKind.AliasDefinition: + const alias = new Alias( + this.getType.bind(this), + anyTypeDef as AliasDefinition + ); + this.namespace!.aliases[name] = alias; + this.namespace!.allTypes[name] = alias; + return alias; + case ASTKind.TypeDefinition: + const type = new MObject( + this.getType.bind(this), + anyTypeDef as TypeDefinition + ); + this.namespace!.types[name] = type; + this.namespace!.allTypes[name] = type; + return type; + case ASTKind.UnionDefinition: + const union = new Union( + this.getType.bind(this), + anyTypeDef as UnionDefinition + ); + this.namespace!.unions[name] = union; + this.namespace!.allTypes[name] = union; + return union; + case ASTKind.EnumDefinition: + const enumDef = (namedType = new Enum( + this.getType.bind(this), + anyTypeDef as EnumDefinition + )); + this.namespace!.enums[name] = enumDef; + this.namespace!.allTypes[name] = enumDef; + return enumDef; + } + + if (namedType != undefined) { + this.namespace!.allTypes[name] = namedType; + return namedType; + } + + break; + case ASTKind.Optional: + const optional = t as ASTOptional; + return new Optional(this.getType.bind(this), optional); + case ASTKind.ListType: + const list = t as ASTListType; + return new List(this.getType.bind(this), list); + case ASTKind.MapType: + const map = t as ASTMapType; + return new Map(this.getType.bind(this), map); + case ASTKind.Stream: + const stream = t as ASTStream; + return new Stream(this.getType.bind(this), stream); + } + + throw new Error("could not resolve type: " + t); + } + + accept(context: Context, visitor: Visitor): void { + context.namespaces.map((namespace) => { + namespace.accept(context.clone({ namespace: namespace }), visitor); + }); + } +} + +export interface Visitor { + visitNamespaceBefore(context: Context): void; + visitNamespace(context: Context): void; + visitNamespaceAfter(context: Context): void; + + visitImportsBefore(context: Context): void; + visitImport(context: Context): void; + visitImportsAfter(context: Context): void; + + visitDirectivesBefore(context: Context): void; + visitDirectiveBefore(context: Context): void; + visitDirective(context: Context): void; + visitDirectiveParametersBefore(context: Context): void; + visitDirectiveParameter(context: Context): void; + visitDirectiveParametersAfter(context: Context): void; + visitDirectiveAfter(context: Context): void; + visitDirectivesAfter(context: Context): void; + + visitAliasesBefore(context: Context): void; + visitAliasBefore(context: Context): void; + visitAlias(context: Context): void; + visitAliasAfter(context: Context): void; + visitAliasesAfter(context: Context): void; + + visitAllOperationsBefore(context: Context): void; + visitInterfaceBefore(context: Context): void; + visitInterface(context: Context): void; + visitRolesBefore(context: Context): void; + visitRoleBefore(context: Context): void; + visitRole(context: Context): void; + visitOperationsBefore(context: Context): void; + visitOperationBefore(context: Context): void; + visitOperation(context: Context): void; + visitParametersBefore(context: Context): void; + visitParameter(context: Context): void; + visitParametersAfter(context: Context): void; + visitOperationAfter(context: Context): void; + visitOperationsAfter(context: Context): void; + visitInterfaceAfter(context: Context): void; + visitRoleAfter(context: Context): void; + visitRolesAfter(context: Context): void; + visitAllOperationsAfter(context: Context): void; + + visitTypesBefore(context: Context): void; + visitTypeBefore(context: Context): void; + visitType(context: Context): void; + visitTypeFieldsBefore(context: Context): void; + visitTypeField(context: Context): void; + visitTypeFieldsAfter(context: Context): void; + visitTypeAfter(context: Context): void; + visitTypesAfter(context: Context): void; + + visitEnumsBefore(context: Context): void; + visitEnumBefore(context: Context): void; + visitEnum(context: Context): void; + visitEnumValuesBefore(context: Context): void; + visitEnumValue(context: Context): void; + visitEnumValuesAfter(context: Context): void; + visitEnumAfter(context: Context): void; + visitEnumsAfter(context: Context): void; + + visitUnionsBefore(context: Context): void; + visitUnion(context: Context): void; + visitUnionsAfter(context: Context): void; + + visitAnnotationsBefore(context: Context): void; + visitAnnotationBefore(context: Context): void; + visitAnnotation(context: Context): void; + visitAnnotationArgumentsBefore(context: Context): void; + visitAnnotationArgument(context: Context): void; + visitAnnotationArgumentsAfter(context: Context): void; + visitAnnotationAfter(context: Context): void; + visitAnnotationsAfter(context: Context): void; +} + +export type Callbacks = { [name: string]: { [name: string]: VisitorCallback } }; +export type VisitorCallback = (_context: Context) => void; + +export abstract class AbstractVisitor implements Visitor { + callbacks: Callbacks = {}; + + setCallback(phase: string, purpose: string, callback: VisitorCallback): void { + var purposes = this.callbacks[phase]; + if (purposes == undefined) { + purposes = {}; + this.callbacks[phase] = purposes; + } + purposes[purpose] = callback; + } + + triggerCallbacks(context: Context, phase: string): void { + var purposes = this.callbacks[phase]; + if (purposes == undefined) { + return; + } + for (let name of Object.keys(purposes)) { + const callback = purposes[name]; + callback(context); + } + } + + public visitNamespaceBefore(context: Context): void { + this.triggerNamespaceBefore(context); + } + public triggerNamespaceBefore(context: Context): void { + this.triggerCallbacks(context, "NamespaceBefore"); + } + public visitNamespace(context: Context): void { + this.triggerNamespace(context); + } + public triggerNamespace(context: Context): void { + this.triggerCallbacks(context, "Namespace"); + } + public visitNamespaceAfter(context: Context): void { + this.triggerNamespaceAfter(context); + } + public triggerNamespaceAfter(context: Context): void { + this.triggerCallbacks(context, "NamespaceAfter"); + } + public visitImportsBefore(context: Context): void { + this.triggerImportsBefore(context); + } + public triggerImportsBefore(context: Context): void { + this.triggerCallbacks(context, "ImportsBefore"); + } + public visitImport(context: Context): void { + this.triggerImport(context); + } + public triggerImport(context: Context): void { + this.triggerCallbacks(context, "Import"); + } + public visitImportsAfter(context: Context): void { + this.triggerImportsAfter(context); + } + public triggerImportsAfter(context: Context): void { + this.triggerCallbacks(context, "ImportsAfter"); + } + + public visitDirectivesBefore(context: Context): void { + this.triggerDirectivesBefore(context); + } + public triggerDirectivesBefore(context: Context): void { + this.triggerCallbacks(context, "DirectivesBefore"); + } + public visitDirectiveBefore(context: Context): void { + this.triggerDirectiveBefore(context); + } + public triggerDirectiveBefore(context: Context): void { + this.triggerCallbacks(context, "DirectiveBefore"); + } + public visitDirective(context: Context): void { + this.triggerDirective(context); + } + public triggerDirective(context: Context): void { + this.triggerCallbacks(context, "Directive"); + } + + public visitDirectiveParametersBefore(context: Context): void { + this.triggerDirectiveParametersBefore(context); + } + public triggerDirectiveParametersBefore(context: Context): void { + this.triggerCallbacks(context, "DirectiveParametersBefore"); + } + public visitDirectiveParameter(context: Context): void { + this.triggerDirectiveParameter(context); + } + public triggerDirectiveParameter(context: Context): void { + this.triggerCallbacks(context, "DirectiveParameter"); + } + public visitDirectiveParametersAfter(context: Context): void { + this.triggerDirectiveParametersAfter(context); + } + public triggerDirectiveParametersAfter(context: Context): void { + this.triggerCallbacks(context, "DirectiveParametersAfter"); + } + + public visitDirectiveAfter(context: Context): void { + this.triggerDirectiveBefore(context); + } + public triggerDirectiveAfter(context: Context): void { + this.triggerCallbacks(context, "DirectiveAfter"); + } + public visitDirectivesAfter(context: Context): void { + this.triggerDirectivesAfter(context); + } + public triggerDirectivesAfter(context: Context): void { + this.triggerCallbacks(context, "DirectivesAfter"); + } + + public visitAliasesBefore(context: Context): void { + this.triggerAliasesBefore(context); + } + public triggerAliasesBefore(context: Context): void { + this.triggerCallbacks(context, "AliasesBefore"); + } + public visitAliasBefore(context: Context): void { + this.triggerAliasBefore(context); + } + public triggerAliasBefore(context: Context): void { + this.triggerCallbacks(context, "AliasBefore"); + } + public visitAlias(context: Context): void { + this.triggerAlias(context); + } + public triggerAlias(context: Context): void { + this.triggerCallbacks(context, "Alias"); + } + public visitAliasAfter(context: Context): void { + this.triggerAliasBefore(context); + } + public triggerAliasAfter(context: Context): void { + this.triggerCallbacks(context, "AliasAfter"); + } + public visitAliasesAfter(context: Context): void { + this.triggerAliasesAfter(context); + } + public triggerAliasesAfter(context: Context): void { + this.triggerCallbacks(context, "AliasesAfter"); + } + + public visitAllOperationsBefore(context: Context): void { + this.triggerAllOperationsBefore(context); + } + public triggerAllOperationsBefore(context: Context): void { + this.triggerCallbacks(context, "AllOperationsBefore"); + } + public visitInterfaceBefore(context: Context): void { + this.triggerInterfaceBefore(context); + } + public triggerInterfaceBefore(context: Context): void { + this.triggerCallbacks(context, "InterfaceBefore"); + } + public visitInterface(context: Context): void { + this.triggerInterface(context); + } + public triggerInterface(context: Context): void { + this.triggerCallbacks(context, "Interface"); + } + public visitRolesBefore(context: Context): void { + this.triggerRolesBefore(context); + } + public triggerRolesBefore(context: Context): void { + this.triggerCallbacks(context, "RolesBefore"); + } + public visitRoleBefore(context: Context): void { + this.triggerRoleBefore(context); + } + public triggerRoleBefore(context: Context): void { + this.triggerCallbacks(context, "RoleBefore"); + } + public visitRole(context: Context): void { + this.triggerRole(context); + } + public triggerRole(context: Context): void { + this.triggerCallbacks(context, "Role"); + } + public visitOperationsBefore(context: Context): void { + this.triggerOperationsBefore(context); + } + public triggerOperationsBefore(context: Context): void { + this.triggerCallbacks(context, "OperationsBefore"); + } + public visitOperationBefore(context: Context): void { + this.triggerOperationBefore(context); + } + public triggerOperationBefore(context: Context): void { + this.triggerCallbacks(context, "OperationBefore"); + } + public visitOperation(context: Context): void { + this.triggerOperation(context); + } + public triggerOperation(context: Context): void { + this.triggerCallbacks(context, "Operation"); + } + public visitParametersBefore(context: Context): void { + this.triggerParametersBefore(context); + } + public triggerParametersBefore(context: Context): void { + this.triggerCallbacks(context, "ParametersBefore"); + } + public visitParameter(context: Context): void { + this.triggerParameter(context); + } + public triggerParameter(context: Context): void { + this.triggerCallbacks(context, "Parameter"); + } + public visitParametersAfter(context: Context): void { + this.triggerParametersAfter(context); + } + public triggerParametersAfter(context: Context): void { + this.triggerCallbacks(context, "ParametersAfter"); + } + public visitOperationAfter(context: Context): void { + this.triggerOperationAfter(context); + } + public triggerOperationAfter(context: Context): void { + this.triggerCallbacks(context, "OperationAfter"); + } + public visitOperationsAfter(context: Context): void { + this.triggerOperationsAfter(context); + } + public triggerOperationsAfter(context: Context): void { + this.triggerCallbacks(context, "OperationsAfter"); + } + public visitInterfaceAfter(context: Context): void { + this.triggerInterfaceAfter(context); + } + public triggerInterfaceAfter(context: Context): void { + this.triggerCallbacks(context, "InterfaceAfter"); + } + public visitRoleAfter(context: Context): void { + this.triggerRoleAfter(context); + } + public triggerRoleAfter(context: Context): void { + this.triggerCallbacks(context, "RoleAfter"); + } + public visitRolesAfter(context: Context): void { + this.triggerRolesAfter(context); + } + public triggerRolesAfter(context: Context): void { + this.triggerCallbacks(context, "RolesAfter"); + } + public visitAllOperationsAfter(context: Context): void { + this.triggerAllOperationsAfter(context); + } + public triggerAllOperationsAfter(context: Context): void { + this.triggerCallbacks(context, "AllOperationsAfter"); + } + + public visitTypesBefore(context: Context): void { + this.triggerTypesBefore(context); + } + public triggerTypesBefore(context: Context): void { + this.triggerCallbacks(context, "TypesBefore"); + } + public visitTypeBefore(context: Context): void { + this.triggerTypeBefore(context); + } + public triggerTypeBefore(context: Context): void { + this.triggerCallbacks(context, "TypeBefore"); + } + public visitType(context: Context): void { + this.triggerType(context); + } + public triggerType(context: Context): void { + this.triggerCallbacks(context, "Type"); + } + public visitTypeFieldsBefore(context: Context): void { + this.triggerTypeFieldsBefore(context); + } + public triggerTypeFieldsBefore(context: Context): void { + this.triggerCallbacks(context, "TypeFieldsBefore"); + } + public visitTypeField(context: Context): void { + this.triggerTypeField(context); + } + public triggerTypeField(context: Context): void { + this.triggerCallbacks(context, "TypeField"); + } + public visitTypeFieldsAfter(context: Context): void { + this.triggerTypeFieldsAfter(context); + } + public triggerTypeFieldsAfter(context: Context): void { + this.triggerCallbacks(context, "TypeFieldsAfter"); + } + public visitTypeAfter(context: Context): void { + this.triggerTypeAfter(context); + } + public triggerTypeAfter(context: Context): void { + this.triggerCallbacks(context, "TypeAfter"); + } + public visitTypesAfter(context: Context): void { + this.triggerTypesAfter(context); + } + public triggerTypesAfter(context: Context): void { + this.triggerCallbacks(context, "TypesAfter"); + } + + public visitEnumsBefore(context: Context): void { + this.triggerEnumsBefore(context); + } + public triggerEnumsBefore(context: Context): void { + this.triggerCallbacks(context, "EnumsBefore"); + } + public visitEnumBefore(context: Context): void { + this.triggerEnumsBefore(context); + } + public triggerEnumBefore(context: Context): void { + this.triggerCallbacks(context, "EnumBefore"); + } + public visitEnum(context: Context): void { + this.triggerEnum(context); + } + public triggerEnum(context: Context): void { + this.triggerCallbacks(context, "Enum"); + } + public visitEnumValuesBefore(context: Context): void { + this.triggerEnumValuesBefore(context); + } + public triggerEnumValuesBefore(context: Context): void { + this.triggerCallbacks(context, "EnumValuesBefore"); + } + public visitEnumValue(context: Context): void { + this.triggerEnumValue(context); + } + public triggerEnumValue(context: Context): void { + this.triggerCallbacks(context, "EnumValue"); + } + public visitEnumValuesAfter(context: Context): void { + this.triggerEnumValuesAfter(context); + } + public triggerEnumValuesAfter(context: Context): void { + this.triggerCallbacks(context, "EnumValuesAfter"); + } + public visitEnumAfter(context: Context): void { + this.triggerEnumsAfter(context); + } + public triggerEnumAfter(context: Context): void { + this.triggerCallbacks(context, "EnumAfter"); + } + public visitEnumsAfter(context: Context): void { + this.triggerEnumsAfter(context); + } + public triggerEnumsAfter(context: Context): void { + this.triggerCallbacks(context, "EnumsAfter"); + } + + public visitUnionsBefore(context: Context): void { + this.triggerUnionsBefore(context); + } + public triggerUnionsBefore(context: Context): void { + this.triggerCallbacks(context, "UnionsBefore"); + } + public visitUnion(context: Context): void { + this.triggerCallbacks(context, "Union"); + } + public triggerUnion(context: Context): void { + this.triggerCallbacks(context, "Union"); + } + public visitUnionsAfter(context: Context): void { + this.triggerUnionsAfter(context); + } + public triggerUnionsAfter(context: Context): void { + this.triggerCallbacks(context, "UnionsAfter"); + } + + public visitAnnotationsBefore(context: Context): void { + this.triggerAnnotationsBefore(context); + } + public triggerAnnotationsBefore(context: Context): void { + this.triggerCallbacks(context, "AnnotationsBefore"); + } + public visitAnnotationBefore(context: Context): void { + this.triggerAnnotationBefore(context); + } + public triggerAnnotationBefore(context: Context): void { + this.triggerCallbacks(context, "AnnotationBefore"); + } + public visitAnnotation(context: Context): void { + this.triggerAnnotation(context); + } + public triggerAnnotation(context: Context): void { + this.triggerCallbacks(context, "Annotation"); + } + + public visitAnnotationArgumentsBefore(context: Context): void { + this.triggerAnnotationArgumentsBefore(context); + } + public triggerAnnotationArgumentsBefore(context: Context): void { + this.triggerCallbacks(context, "AnnotationArgumentsBefore"); + } + public visitAnnotationArgument(context: Context): void { + this.triggerAnnotationArgument(context); + } + public triggerAnnotationArgument(context: Context): void { + this.triggerCallbacks(context, "AnnotationArgument"); + } + public visitAnnotationArgumentsAfter(context: Context): void { + this.triggerAnnotationArgumentsAfter(context); + } + public triggerAnnotationArgumentsAfter(context: Context): void { + this.triggerCallbacks(context, "AnnotationArgumentsAfter"); + } + public visitAnnotationAfter(context: Context): void { + this.triggerAnnotationAfter(context); + } + public triggerAnnotationAfter(context: Context): void { + this.triggerCallbacks(context, "AnnotationAfter"); + } + public visitAnnotationsAfter(context: Context): void { + this.triggerAnnotationsAfter(context); + } + public triggerAnnotationsAfter(context: Context): void { + this.triggerCallbacks(context, "AnnotationsAfter"); + } +} + +export class BaseVisitor extends AbstractVisitor { + writer: Writer; + + constructor(writer: Writer) { + super(); + this.writer = writer; + } + + protected write(code: string): void { + this.writer.write(code); + } +} + +export class MultiVisitor extends AbstractVisitor { + private visitors: Visitor[]; + + constructor(...visitors: Visitor[]) { + super(); + this.visitors = new Array(); + this.visitors.push(...visitors); + } + + addVisitors(...visitors: Visitor[]): void { + this.visitors.push(...visitors); + } + + public visitNamespaceBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitNamespaceBefore(context); + }); + } + public visitNamespace(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitNamespace(context); + }); + } + public visitNamespaceAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitNamespaceAfter(context); + }); + } + public visitImportsBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitImportsBefore(context); + }); + } + public visitImport(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitImport(context); + }); + } + public visitImportsAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitImportsAfter(context); + }); + } + + public visitDirectivesBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitDirectivesBefore(context); + }); + } + public visitDirectiveBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitDirectiveBefore(context); + }); + } + public visitDirective(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitDirective(context); + }); + } + public visitDirectiveParametersBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitDirectiveParametersBefore(context); + }); + } + public visitDirectiveParameter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitDirectiveParameter(context); + }); + } + public visitDirectiveParametersAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitDirectiveParametersAfter(context); + }); + } + public visitDirectiveAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitDirectiveAfter(context); + }); + } + public visitDirectivesAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitDirectivesAfter(context); + }); + } + + public visitAliasesBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitAliasesBefore(context); + }); + } + public visitAliasBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitAliasBefore(context); + }); + } + public visitAlias(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitAlias(context); + }); + } + public visitAliasAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitAliasAfter(context); + }); + } + public visitAliasesAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitAliasesAfter(context); + }); + } + + public visitAllOperationsBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitAllOperationsBefore(context); + }); + } + public visitInterfaceBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitInterfaceBefore(context); + }); + } + public visitInterface(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitInterface(context); + }); + } + public visitRolesBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitRolesBefore(context); + }); + } + public visitRoleBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitRoleBefore(context); + }); + } + public visitRole(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitRole(context); + }); + } + public visitOperationsBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitOperationsBefore(context); + }); + } + public visitOperationBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitOperationBefore(context); + }); + } + public visitOperation(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitOperation(context); + }); + } + public visitParametersBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitParametersBefore(context); + }); + } + public visitParameter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitParameter(context); + }); + } + public visitParametersAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitParametersAfter(context); + }); + } + public visitOperationAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitOperationAfter(context); + }); + } + public visitOperationsAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitOperationsAfter(context); + }); + } + public visitInterfaceAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitInterfaceAfter(context); + }); + } + public visitRoleAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitRoleAfter(context); + }); + } + public visitRolesAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitRolesAfter(context); + }); + } + public visitAllOperationsAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitAllOperationsAfter(context); + }); + } + + public visitTypesBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitTypesBefore(context); + }); + } + public visitTypeBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitTypeBefore(context); + }); + } + public visitType(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitType(context); + }); + } + public visitTypeFieldsBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitTypeFieldsBefore(context); + }); + } + public visitTypeField(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitTypeField(context); + }); + } + public visitTypeFieldsAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitTypeFieldsAfter(context); + }); + } + public visitTypeAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitTypeAfter(context); + }); + } + public visitTypesAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitTypesAfter(context); + }); + } + + public visitEnumsBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitEnumsAfter(context); + }); + } + public visitEnum(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitEnum(context); + }); + } + public visitEnumValuesBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitEnumValuesBefore(context); + }); + } + public visitEnumValue(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitEnumValue(context); + }); + } + public visitEnumValuesAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitEnumValuesAfter(context); + }); + } + public visitEnumsAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitEnumsAfter(context); + }); + } + + public visitUnionsBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitUnionsBefore(context); + }); + } + public visitUnion(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitUnion(context); + }); + } + + public visitUnionsAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitUnionsAfter(context); + }); + } + + public visitAnnotationsBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitAnnotationsBefore(context); + }); + } + public visitAnnotation(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitAnnotation(context); + }); + } + public visitAnnotationArgumentsBefore(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitAnnotationArgumentsBefore(context); + }); + } + public visitAnnotationArgument(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitAnnotationArgument(context); + }); + } + public visitAnnotationArgumentsAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitAnnotationArgumentsAfter(context); + }); + } + public visitAnnotationsAfter(context: Context): void { + this.visitors.map((visitor) => { + visitor.visitAnnotationsAfter(context); + }); + } +} diff --git a/tsconfig.json b/tsconfig.json index cce98f6..8185d41 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -5,7 +5,8 @@ "target": "ES2020" /* Specify ECMAScript target version: 'ES3' (default), 'ES5', 'ES2015', 'ES2016', 'ES2017', 'ES2018', 'ES2019', 'ES2020', or 'ESNEXT'. */, "module": "ES2020" /* Specify module code generation: 'none', 'commonjs', 'amd', 'system', 'umd', 'es2015', 'es2020', or 'ESNext'. */, "lib": [ - "es2020" + "es2020", + "dom" ] /* Specify library files to be included in the compilation. */, "declaration": true /* Generates corresponding '.d.ts' file. */, "declarationMap": true /* Generates a sourcemap for each corresponding '.d.ts' file. */,