idlize

Форк
0
/
HeaderPrinter.ts 
196 строк · 8.0 Кб
1
/*
2
 * Copyright (c) 2024 Huawei Device Co., Ltd.
3
 * Licensed under the Apache License, Version 2.0 (the "License");
4
 * you may not use this file except in compliance with the License.
5
 * You may obtain a copy of the License at
6
 *
7
 * http://www.apache.org/licenses/LICENSE-2.0
8
 *
9
 * Unless required by applicable law or agreed to in writing, software
10
 * distributed under the License is distributed on an "AS IS" BASIS,
11
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12
 * See the License for the specific language governing permissions and
13
 * limitations under the License.
14
 */
15

16

17
import { IndentedPrinter } from "../../IndentedPrinter";
18
import { makeAPI, makeCSerializers, makeConverterHeader } from "../FileGenerators";
19
import { PeerClass } from "../PeerClass";
20
import { PeerLibrary } from "../PeerLibrary";
21
import { PeerMethod } from "../PeerMethod";
22
import { PeerGeneratorConfig } from "../PeerGeneratorConfig";
23
import { CallbackInfo, collectCallbacks, groupCallbacks } from "./EventsPrinter";
24
import { DeclarationTable, PrimitiveType } from "../DeclarationTable";
25
import { NamedMethodSignature, Type, createLanguageWriter } from "../LanguageWriters";
26
import { Language } from "../../util";
27
import { LibaceInstall } from "../../Install";
28

29
export function generateEventReceiverName(componentName: string) {
30
    return `${PeerGeneratorConfig.cppPrefix}ArkUI${componentName}EventsReceiver`
31
}
32

33
export function generateEventSignature(table: DeclarationTable, event: CallbackInfo): NamedMethodSignature {
34
    const nodeType = new Type(table.computeTargetName(PrimitiveType.Int32, false))
35
    const argsTypes = event.args.map(it => new Type(
36
        'const ' + table.typeConvertor(it.name, it.type, it.nullable).nativeType(false),
37
        it.nullable,
38
    ))
39
    return new NamedMethodSignature(
40
        new Type('void'),
41
        [nodeType, ...argsTypes],
42
        ['nodeId', ...event.args.map(it => it.name)]
43
    )
44
}
45

46
class HeaderVisitor {
47
    constructor(
48
        private library: PeerLibrary,
49
        private api: IndentedPrinter,
50
        private modifiersList: IndentedPrinter,
51
        private accessorsList: IndentedPrinter,
52
        private eventsList: IndentedPrinter,
53
    ) {}
54

55
    private apiModifierHeader(clazz: PeerClass) {
56
        return `typedef struct ${PeerGeneratorConfig.cppPrefix}ArkUI${clazz.componentName}Modifier {`
57
    }
58

59
    private printClassProlog(clazz: PeerClass) {
60
        this.api.print(this.apiModifierHeader(clazz))
61
        this.api.pushIndent()
62
        this.modifiersList.pushIndent()
63
        this.modifiersList.print(`const ${PeerGeneratorConfig.cppPrefix}ArkUI${clazz.componentName}Modifier* (*get${clazz.componentName}Modifier)();`)
64
    }
65

66
    private printMethod(method: PeerMethod) {
67
        const apiParameters = method.generateAPIParameters().join(", ")
68
        this.api.print(`${method.retType} (*${method.fullMethodName})(${apiParameters});`)
69
    }
70

71
    private printClassEpilog(clazz: PeerClass) {
72
        if (clazz.methods.length == 0) {
73
            this.api.print("int dummy;")
74
        }
75
        this.api.popIndent()
76
        this.api.print(`} ${PeerGeneratorConfig.cppPrefix}ArkUI${clazz.componentName}Modifier;\n`)
77
        this.modifiersList.popIndent()
78
    }
79

80
    private printAccessors() {
81
        this.api.print("// Accessors\n")
82
        this.accessorsList.pushIndent()
83
        this.library.materializedClasses.forEach(c => {
84
            this.printAccessor(c.className)
85
            this.accessorsList.print(`const ${PeerGeneratorConfig.cppPrefix}ArkUI${c.className}Accessor* (*get${c.className}Accessor)();`)
86
        })
87
        this.accessorsList.popIndent()
88
    }
89

90
    private printAccessor(name: string) {
91
        const clazz = this.library.materializedClasses.get(name)
92
        if (clazz) {
93
            let peerName = `${name}Peer`
94
            let accessorName = `${PeerGeneratorConfig.cppPrefix}ArkUI${name}Accessor`
95
            this.api.print(`typedef struct ${peerName} ${peerName};`)
96
            this.api.print(`typedef struct ${accessorName} {`)
97
            this.api.pushIndent()
98

99
            let names = new Set<string>();
100
            [clazz.ctor, clazz.finalizer].concat(clazz.methods)
101
                .forEach(method => {
102
                    // TBD: handle methods with the same name like SubTabBarStyle
103
                    // of(content: ResourceStr) and
104
                    // of(content: ResourceStr | ComponentContent)
105
                    if (names.has(method.overloadedName)) {
106
                        return
107
                    }
108
                    names.add(method.overloadedName)
109
                    this.api.print(`${method.retType} (*${method.overloadedName})(${method.generateAPIParameters().join(", ")});`)
110
                })
111
            this.api.popIndent()
112
            this.api.print(`} ${accessorName};\n`)
113
        }
114
    }
115

116
    private printEventsReceiver(componentName: string, callbacks: CallbackInfo[]) {
117
        const receiver = generateEventReceiverName(componentName)
118
        this.api.print(`typedef struct ${receiver} {`)
119
        this.api.pushIndent()
120
        for (const callback of callbacks) {
121
            const signature = generateEventSignature(this.library.declarationTable, callback)
122
            const args = signature.args.map((type, index) => {
123
                return `${type.name} ${signature.argName(index)}`
124
            })
125
            this.api.print(`${signature.returnType.name} (*${callback.methodName})(${args.join(', ')});`)
126
        }
127
        this.api.popIndent()
128
        this.api.print(`} ${receiver};\n`)
129
    }
130

131
    private printEvents() {
132
        const callbacks = groupCallbacks(collectCallbacks(this.library))
133
        for (const [receiver, events] of callbacks) {
134
            this.printEventsReceiver(receiver, events)
135
        }
136

137
        this.eventsList.pushIndent()
138
        for (const [receiver, _] of callbacks) {
139
            this.eventsList.print(`const ${generateEventReceiverName(receiver)}* (*get${receiver}EventsReceiver)();`)
140
        }
141
        this.eventsList.popIndent()
142
    }
143

144
    // TODO: have a proper Peer module visitor
145
    printApiAndDeserializer() {
146
        this.library.files.forEach(file => {
147
            file.peers.forEach(clazz => {
148
                this.printClassProlog(clazz)
149
                clazz.methods.forEach(method => {
150
                    this.printMethod(method)
151
                })
152
                this.printClassEpilog(clazz)
153
            })
154
        })
155
        this.printAccessors()
156
        this.printEvents()
157
    }
158
}
159

160
export function printUserConverter(headerPath: string, namespace: string, apiVersion: string|undefined, peerLibrary: PeerLibrary) :
161
        {api: string, converterHeader: string}
162
{
163
    const apiHeader = new IndentedPrinter()
164
    const modifierList = new IndentedPrinter()
165
    const accessorList = new IndentedPrinter()
166
    const eventsList = new IndentedPrinter()
167

168
    const visitor = new HeaderVisitor(peerLibrary, apiHeader, modifierList, accessorList, eventsList)
169
    visitor.printApiAndDeserializer()
170

171
    const structs = new IndentedPrinter()
172
    const typedefs = new IndentedPrinter()
173

174
    const converterHeader = makeConverterHeader(headerPath, namespace, peerLibrary).getOutput().join("\n")
175
    makeCSerializers(peerLibrary, structs, typedefs)
176
    const api = makeAPI(apiVersion ?? "0", apiHeader.getOutput(), modifierList.getOutput(), accessorList.getOutput(), eventsList.getOutput(), structs, typedefs)
177
    return {api, converterHeader}
178
}
179

180
export function printSerializers(apiVersion: string|undefined, peerLibrary: PeerLibrary): {api: string, serializers: string} {
181
    const apiHeader = new IndentedPrinter()
182
    const modifierList = new IndentedPrinter()
183
    const accessorList = new IndentedPrinter()
184
    const eventsList = new IndentedPrinter()
185

186
    const visitor = new HeaderVisitor(peerLibrary, apiHeader, modifierList, accessorList, eventsList)
187
    visitor.printApiAndDeserializer()
188

189
    const structs = new IndentedPrinter()
190
    const typedefs = new IndentedPrinter()
191

192
    const serializers = makeCSerializers(peerLibrary, structs, typedefs)
193
    const api = makeAPI(apiVersion ?? "0", apiHeader.getOutput(), modifierList.getOutput(), accessorList.getOutput(), eventsList.getOutput(), structs, typedefs)
194

195
    return {api, serializers}
196
}

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

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

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

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