idlize

Форк
0
/
BuilderClassPrinter.ts 
176 строк · 7.1 Кб
1
import { Language, renameClassToBuilderClass } from "../../util"
2
import { LanguageWriter, MethodModifier, Method, Type, createLanguageWriter, Field, NamedMethodSignature } from "../LanguageWriters";
3
import { PeerLibrary } from "../PeerLibrary"
4
import { BuilderClass, methodsGroupOverloads, CUSTOM_BUILDER_CLASSES } from "../BuilderClass";
5
import { collapseSameNamedMethods } from "./OverloadsPrinter";
6
import { collectDtsImports } from "../DtsImportsGenerator";
7

8
class BuilderClassFileVisitor {
9

10
    readonly printer: LanguageWriter = createLanguageWriter(this.language)
11

12
    constructor(
13
        private readonly language: Language,
14
        private readonly library: PeerLibrary,
15
        private readonly builderClass: BuilderClass,
16
        private readonly dumpSerialized: boolean,
17
    ) { }
18

19
    private printBuilderClass(clazz: BuilderClass) {
20
        const writer = this.printer
21
        clazz = processBuilderClass(clazz)
22

23
        //TODO: in the future it is necessary to import elements from generated ets files
24
        if (writer.language == Language.ARKTS) {
25
            writer.print(collectDtsImports().trim())
26
            writer.print("import { SelectedMode } from './ArkTabContentInterfaces'")
27
        }
28

29
        writer.writeClass(clazz.name, writer => {
30

31
            clazz.fields.forEach(field => {
32
                const modifiers = field.modifiers.map(it => writer.mapFiledModifier(it))
33
                writer.writeFieldDeclaration(field.name, field.type, modifiers, field.type.nullable)
34
            })
35

36

37
            clazz.constructors
38
                .forEach(ctor => {
39
                    writer.writeConstructorImplementation(ctor.name, ctor.signature, writer => {
40
                        /*
41
                        const typeFiledName = syntheticName("type")
42
                        writer.writeStatement(writer.makeAssign(`this.${typeFiledName}`, undefined, writer.makeString(`"${clazz.name}"`), false))
43
                        ctor.signature.args
44
                            .forEach((it, i) => {
45
                                const argName = ctor.signature.argName(i)
46
                                const fieldName = syntheticName(argName)
47
                                writer.writeStatement(writer.makeAssign(`this.${fieldName}`, undefined, writer.makeString(`${argName}`), false))
48
                            })
49
                        */
50
                    })
51
                })
52

53
            clazz.methods
54
                .filter(method => method.modifiers?.includes(MethodModifier.STATIC))
55
                .forEach(staticMethod => {
56
                    writer.writeMethodImplementation(staticMethod, writer => {
57
                        const sig = staticMethod.signature
58
                        const args = sig.args.map((_, i) => sig.argName(i)).join(", ")
59
                        const obj = sig.returnType.name
60
                        // TBD: Use writer.makeObjectAlloc()
61
                        writer.writeStatement(writer.makeReturn(writer.makeString(`new ${obj}(${args})`)))
62
                    })
63
                })
64

65
            clazz.methods
66
                .filter(method => !method.modifiers?.includes(MethodModifier.STATIC))
67
                .forEach(method => {
68
                    writer.writeMethodImplementation(method, writer => {
69
                        const argName = method.signature.argName(0)
70
                        const fieldName = syntheticName(method.name)
71
                        writer.writeStatement(writer.makeAssign(`this.${fieldName}`, undefined, writer.makeString(`${argName}`), false))
72
                        writer.writeStatement(writer.makeReturn(writer.makeString("this")))
73
                    })
74
                })
75
        })
76
    }
77

78
    printFile(): void {
79
        this.printBuilderClass(this.builderClass)
80
    }
81
}
82

83
class BuilderClassVisitor {
84
    readonly builderClasses: Map<string, string[]> = new Map()
85

86
    constructor(
87
        private readonly library: PeerLibrary,
88
        private readonly dumpSerialized: boolean,
89
    ) { }
90

91
    printBuilderClasses(): void {
92
        const builderClasses = [...CUSTOM_BUILDER_CLASSES, ...this.library.builderClasses.values()]
93
        console.log(`Builder classes: ${builderClasses.length}`)
94
        for (const clazz of builderClasses) {
95
            const visitor = new BuilderClassFileVisitor(
96
                this.library.declarationTable.language, this.library, clazz, this.dumpSerialized)
97
            visitor.printFile()
98
            const fileName = renameClassToBuilderClass(clazz.name, this.library.declarationTable.language)
99
            this.builderClasses.set(fileName, visitor.printer.getOutput())
100
        }
101
    }
102
}
103

104
export function printBuilderClasses(peerLibrary: PeerLibrary, dumpSerialized: boolean): Map<string, string> {
105

106
    // TODO: support other output languages
107
    if (peerLibrary.declarationTable.language != Language.TS && peerLibrary.declarationTable.language != Language.ARKTS)
108
        return new Map()
109

110
    const visitor = new BuilderClassVisitor(peerLibrary, dumpSerialized)
111
    visitor.printBuilderClasses()
112
    const result = new Map<string, string>()
113
    for (const [key, content] of visitor.builderClasses) {
114
        if (content.length === 0) continue
115
        result.set(key, content.join('\n'))
116
    }
117
    return result
118
}
119

120
function syntheticName(name: string): string {
121
    return `_${name}`
122
}
123

124
function toSyntheticField(method: Method): Field {
125
    const type = method.signature.args[0]
126
    return new Field(syntheticName(method.name), new Type(type.name, true))
127
}
128

129
function collapse(methods: Method[]): Method[] {
130
    const groups = methodsGroupOverloads(methods)
131
    return groups.map(it => it.length == 1 ? it[0] : collapseSameNamedMethods(it))
132

133
}
134

135
function processBuilderClass(clazz: BuilderClass): BuilderClass {
136

137
    const methods = collapse(clazz.methods)
138
    let constructors = collapse(clazz.constructors)
139

140
    if (!constructors || constructors.length == 0) {
141
        // make a constructor from a static method parameters
142
        const staticMethods = methods.
143
            filter(method => method.modifiers?.includes(MethodModifier.STATIC))
144

145
        if (staticMethods.length > 0) {
146
            const staticSig = staticMethods[0].signature
147
            const args = staticSig.args
148
            const ctorSig = new NamedMethodSignature(Type.Void, args, args.map((it, i) => staticSig.argName(i)))
149
            constructors = [new Method("constructor", ctorSig)]
150
        }
151
    }
152

153
    // generate synthetic properties for the constructor parameters
154
    // const ctorSig = constructors[0].signature
155
    // const ctorFields = ctorSig.args
156
    //     .map((type, i) => new Field(syntheticName(ctorSig.argName(i)), type))
157

158
    const syntheticFields = methods
159
        .filter(it => !it.modifiers?.includes(MethodModifier.STATIC))
160
        .map(it => toSyntheticField(it))
161

162
    const typeField = new Field(syntheticName("type"), new Type("string"))
163
    // TBD: Add type field and constructor fields for serialization
164
    const fields = [...clazz.fields, ...syntheticFields]
165
    //const fields = [typeField, ...clazz.fields, ...ctorFields, ...syntheticFields]
166

167
    return new BuilderClass(
168
        clazz.name,
169
        clazz.isInterface,
170
        clazz.superClass,
171
        fields,
172
        constructors,
173
        methods,
174
        clazz.importFeatures
175
    )
176
}
177

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.