idlize
176 строк · 7.1 Кб
1import { Language, renameClassToBuilderClass } from "../../util"2import { LanguageWriter, MethodModifier, Method, Type, createLanguageWriter, Field, NamedMethodSignature } from "../LanguageWriters";3import { PeerLibrary } from "../PeerLibrary"4import { BuilderClass, methodsGroupOverloads, CUSTOM_BUILDER_CLASSES } from "../BuilderClass";5import { collapseSameNamedMethods } from "./OverloadsPrinter";6import { collectDtsImports } from "../DtsImportsGenerator";7
8class BuilderClassFileVisitor {9
10readonly printer: LanguageWriter = createLanguageWriter(this.language)11
12constructor(13private readonly language: Language,14private readonly library: PeerLibrary,15private readonly builderClass: BuilderClass,16private readonly dumpSerialized: boolean,17) { }18
19private printBuilderClass(clazz: BuilderClass) {20const writer = this.printer21clazz = processBuilderClass(clazz)22
23//TODO: in the future it is necessary to import elements from generated ets files24if (writer.language == Language.ARKTS) {25writer.print(collectDtsImports().trim())26writer.print("import { SelectedMode } from './ArkTabContentInterfaces'")27}28
29writer.writeClass(clazz.name, writer => {30
31clazz.fields.forEach(field => {32const modifiers = field.modifiers.map(it => writer.mapFiledModifier(it))33writer.writeFieldDeclaration(field.name, field.type, modifiers, field.type.nullable)34})35
36
37clazz.constructors38.forEach(ctor => {39writer.writeConstructorImplementation(ctor.name, ctor.signature, writer => {40/*41const typeFiledName = syntheticName("type")
42writer.writeStatement(writer.makeAssign(`this.${typeFiledName}`, undefined, writer.makeString(`"${clazz.name}"`), false))
43ctor.signature.args
44.forEach((it, i) => {
45const argName = ctor.signature.argName(i)
46const fieldName = syntheticName(argName)
47writer.writeStatement(writer.makeAssign(`this.${fieldName}`, undefined, writer.makeString(`${argName}`), false))
48})
49*/
50})51})52
53clazz.methods54.filter(method => method.modifiers?.includes(MethodModifier.STATIC))55.forEach(staticMethod => {56writer.writeMethodImplementation(staticMethod, writer => {57const sig = staticMethod.signature58const args = sig.args.map((_, i) => sig.argName(i)).join(", ")59const obj = sig.returnType.name60// TBD: Use writer.makeObjectAlloc()61writer.writeStatement(writer.makeReturn(writer.makeString(`new ${obj}(${args})`)))62})63})64
65clazz.methods66.filter(method => !method.modifiers?.includes(MethodModifier.STATIC))67.forEach(method => {68writer.writeMethodImplementation(method, writer => {69const argName = method.signature.argName(0)70const fieldName = syntheticName(method.name)71writer.writeStatement(writer.makeAssign(`this.${fieldName}`, undefined, writer.makeString(`${argName}`), false))72writer.writeStatement(writer.makeReturn(writer.makeString("this")))73})74})75})76}77
78printFile(): void {79this.printBuilderClass(this.builderClass)80}81}
82
83class BuilderClassVisitor {84readonly builderClasses: Map<string, string[]> = new Map()85
86constructor(87private readonly library: PeerLibrary,88private readonly dumpSerialized: boolean,89) { }90
91printBuilderClasses(): void {92const builderClasses = [...CUSTOM_BUILDER_CLASSES, ...this.library.builderClasses.values()]93console.log(`Builder classes: ${builderClasses.length}`)94for (const clazz of builderClasses) {95const visitor = new BuilderClassFileVisitor(96this.library.declarationTable.language, this.library, clazz, this.dumpSerialized)97visitor.printFile()98const fileName = renameClassToBuilderClass(clazz.name, this.library.declarationTable.language)99this.builderClasses.set(fileName, visitor.printer.getOutput())100}101}102}
103
104export function printBuilderClasses(peerLibrary: PeerLibrary, dumpSerialized: boolean): Map<string, string> {105
106// TODO: support other output languages107if (peerLibrary.declarationTable.language != Language.TS && peerLibrary.declarationTable.language != Language.ARKTS)108return new Map()109
110const visitor = new BuilderClassVisitor(peerLibrary, dumpSerialized)111visitor.printBuilderClasses()112const result = new Map<string, string>()113for (const [key, content] of visitor.builderClasses) {114if (content.length === 0) continue115result.set(key, content.join('\n'))116}117return result118}
119
120function syntheticName(name: string): string {121return `_${name}`122}
123
124function toSyntheticField(method: Method): Field {125const type = method.signature.args[0]126return new Field(syntheticName(method.name), new Type(type.name, true))127}
128
129function collapse(methods: Method[]): Method[] {130const groups = methodsGroupOverloads(methods)131return groups.map(it => it.length == 1 ? it[0] : collapseSameNamedMethods(it))132
133}
134
135function processBuilderClass(clazz: BuilderClass): BuilderClass {136
137const methods = collapse(clazz.methods)138let constructors = collapse(clazz.constructors)139
140if (!constructors || constructors.length == 0) {141// make a constructor from a static method parameters142const staticMethods = methods.143filter(method => method.modifiers?.includes(MethodModifier.STATIC))144
145if (staticMethods.length > 0) {146const staticSig = staticMethods[0].signature147const args = staticSig.args148const ctorSig = new NamedMethodSignature(Type.Void, args, args.map((it, i) => staticSig.argName(i)))149constructors = [new Method("constructor", ctorSig)]150}151}152
153// generate synthetic properties for the constructor parameters154// const ctorSig = constructors[0].signature155// const ctorFields = ctorSig.args156// .map((type, i) => new Field(syntheticName(ctorSig.argName(i)), type))157
158const syntheticFields = methods159.filter(it => !it.modifiers?.includes(MethodModifier.STATIC))160.map(it => toSyntheticField(it))161
162const typeField = new Field(syntheticName("type"), new Type("string"))163// TBD: Add type field and constructor fields for serialization164const fields = [...clazz.fields, ...syntheticFields]165//const fields = [typeField, ...clazz.fields, ...ctorFields, ...syntheticFields]166
167return new BuilderClass(168clazz.name,169clazz.isInterface,170clazz.superClass,171fields,172constructors,173methods,174clazz.importFeatures175)176}
177