idlize
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
17import { IndentedPrinter } from "../../IndentedPrinter";18import { makeAPI, makeCSerializers, makeConverterHeader } from "../FileGenerators";19import { PeerClass } from "../PeerClass";20import { PeerLibrary } from "../PeerLibrary";21import { PeerMethod } from "../PeerMethod";22import { PeerGeneratorConfig } from "../PeerGeneratorConfig";23import { CallbackInfo, collectCallbacks, groupCallbacks } from "./EventsPrinter";24import { DeclarationTable, PrimitiveType } from "../DeclarationTable";25import { NamedMethodSignature, Type, createLanguageWriter } from "../LanguageWriters";26import { Language } from "../../util";27import { LibaceInstall } from "../../Install";28
29export function generateEventReceiverName(componentName: string) {30return `${PeerGeneratorConfig.cppPrefix}ArkUI${componentName}EventsReceiver`31}
32
33export function generateEventSignature(table: DeclarationTable, event: CallbackInfo): NamedMethodSignature {34const nodeType = new Type(table.computeTargetName(PrimitiveType.Int32, false))35const argsTypes = event.args.map(it => new Type(36'const ' + table.typeConvertor(it.name, it.type, it.nullable).nativeType(false),37it.nullable,38))39return new NamedMethodSignature(40new Type('void'),41[nodeType, ...argsTypes],42['nodeId', ...event.args.map(it => it.name)]43)44}
45
46class HeaderVisitor {47constructor(48private library: PeerLibrary,49private api: IndentedPrinter,50private modifiersList: IndentedPrinter,51private accessorsList: IndentedPrinter,52private eventsList: IndentedPrinter,53) {}54
55private apiModifierHeader(clazz: PeerClass) {56return `typedef struct ${PeerGeneratorConfig.cppPrefix}ArkUI${clazz.componentName}Modifier {`57}58
59private printClassProlog(clazz: PeerClass) {60this.api.print(this.apiModifierHeader(clazz))61this.api.pushIndent()62this.modifiersList.pushIndent()63this.modifiersList.print(`const ${PeerGeneratorConfig.cppPrefix}ArkUI${clazz.componentName}Modifier* (*get${clazz.componentName}Modifier)();`)64}65
66private printMethod(method: PeerMethod) {67const apiParameters = method.generateAPIParameters().join(", ")68this.api.print(`${method.retType} (*${method.fullMethodName})(${apiParameters});`)69}70
71private printClassEpilog(clazz: PeerClass) {72if (clazz.methods.length == 0) {73this.api.print("int dummy;")74}75this.api.popIndent()76this.api.print(`} ${PeerGeneratorConfig.cppPrefix}ArkUI${clazz.componentName}Modifier;\n`)77this.modifiersList.popIndent()78}79
80private printAccessors() {81this.api.print("// Accessors\n")82this.accessorsList.pushIndent()83this.library.materializedClasses.forEach(c => {84this.printAccessor(c.className)85this.accessorsList.print(`const ${PeerGeneratorConfig.cppPrefix}ArkUI${c.className}Accessor* (*get${c.className}Accessor)();`)86})87this.accessorsList.popIndent()88}89
90private printAccessor(name: string) {91const clazz = this.library.materializedClasses.get(name)92if (clazz) {93let peerName = `${name}Peer`94let accessorName = `${PeerGeneratorConfig.cppPrefix}ArkUI${name}Accessor`95this.api.print(`typedef struct ${peerName} ${peerName};`)96this.api.print(`typedef struct ${accessorName} {`)97this.api.pushIndent()98
99let names = new Set<string>();100[clazz.ctor, clazz.finalizer].concat(clazz.methods)101.forEach(method => {102// TBD: handle methods with the same name like SubTabBarStyle103// of(content: ResourceStr) and104// of(content: ResourceStr | ComponentContent)105if (names.has(method.overloadedName)) {106return107}108names.add(method.overloadedName)109this.api.print(`${method.retType} (*${method.overloadedName})(${method.generateAPIParameters().join(", ")});`)110})111this.api.popIndent()112this.api.print(`} ${accessorName};\n`)113}114}115
116private printEventsReceiver(componentName: string, callbacks: CallbackInfo[]) {117const receiver = generateEventReceiverName(componentName)118this.api.print(`typedef struct ${receiver} {`)119this.api.pushIndent()120for (const callback of callbacks) {121const signature = generateEventSignature(this.library.declarationTable, callback)122const args = signature.args.map((type, index) => {123return `${type.name} ${signature.argName(index)}`124})125this.api.print(`${signature.returnType.name} (*${callback.methodName})(${args.join(', ')});`)126}127this.api.popIndent()128this.api.print(`} ${receiver};\n`)129}130
131private printEvents() {132const callbacks = groupCallbacks(collectCallbacks(this.library))133for (const [receiver, events] of callbacks) {134this.printEventsReceiver(receiver, events)135}136
137this.eventsList.pushIndent()138for (const [receiver, _] of callbacks) {139this.eventsList.print(`const ${generateEventReceiverName(receiver)}* (*get${receiver}EventsReceiver)();`)140}141this.eventsList.popIndent()142}143
144// TODO: have a proper Peer module visitor145printApiAndDeserializer() {146this.library.files.forEach(file => {147file.peers.forEach(clazz => {148this.printClassProlog(clazz)149clazz.methods.forEach(method => {150this.printMethod(method)151})152this.printClassEpilog(clazz)153})154})155this.printAccessors()156this.printEvents()157}158}
159
160export function printUserConverter(headerPath: string, namespace: string, apiVersion: string|undefined, peerLibrary: PeerLibrary) :161{api: string, converterHeader: string}162{
163const apiHeader = new IndentedPrinter()164const modifierList = new IndentedPrinter()165const accessorList = new IndentedPrinter()166const eventsList = new IndentedPrinter()167
168const visitor = new HeaderVisitor(peerLibrary, apiHeader, modifierList, accessorList, eventsList)169visitor.printApiAndDeserializer()170
171const structs = new IndentedPrinter()172const typedefs = new IndentedPrinter()173
174const converterHeader = makeConverterHeader(headerPath, namespace, peerLibrary).getOutput().join("\n")175makeCSerializers(peerLibrary, structs, typedefs)176const api = makeAPI(apiVersion ?? "0", apiHeader.getOutput(), modifierList.getOutput(), accessorList.getOutput(), eventsList.getOutput(), structs, typedefs)177return {api, converterHeader}178}
179
180export function printSerializers(apiVersion: string|undefined, peerLibrary: PeerLibrary): {api: string, serializers: string} {181const apiHeader = new IndentedPrinter()182const modifierList = new IndentedPrinter()183const accessorList = new IndentedPrinter()184const eventsList = new IndentedPrinter()185
186const visitor = new HeaderVisitor(peerLibrary, apiHeader, modifierList, accessorList, eventsList)187visitor.printApiAndDeserializer()188
189const structs = new IndentedPrinter()190const typedefs = new IndentedPrinter()191
192const serializers = makeCSerializers(peerLibrary, structs, typedefs)193const api = makeAPI(apiVersion ?? "0", apiHeader.getOutput(), modifierList.getOutput(), accessorList.getOutput(), eventsList.getOutput(), structs, typedefs)194
195return {api, serializers}196}