idlize
133 строки · 6.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
16import { IndentedPrinter } from "../../IndentedPrinter";17import { generateEventsBridgeSignature } from "./EventsPrinter";18import { nativeModuleDeclaration, nativeModuleEmptyDeclaration } from "../FileGenerators";19import { LanguageWriter, Method, NamedMethodSignature, StringExpression, Type, createLanguageWriter } from "../LanguageWriters";20import { PeerClass, PeerClassBase } from "../PeerClass";21import { PeerLibrary } from "../PeerLibrary";22import { PeerMethod } from "../PeerMethod";23
24class NativeModuleVisitor {25readonly nativeModule: LanguageWriter26readonly nativeModuleEmpty: LanguageWriter27
28constructor(29private readonly library: PeerLibrary,30) {31this.nativeModule = createLanguageWriter(library.declarationTable.language)32this.nativeModuleEmpty = createLanguageWriter(library.declarationTable.language)33}34
35private printPeerMethods(peer: PeerClass) {36peer.methods.forEach(it => printPeerMethod(peer, it, this.nativeModule, this.nativeModuleEmpty))37}38
39private printMaterializedMethods(nativeModule: LanguageWriter, nativeModuleEmpty: LanguageWriter) {40this.library.materializedClasses.forEach(clazz => {41printPeerMethod(clazz, clazz.ctor, nativeModule, nativeModuleEmpty, Type.Pointer)42printPeerMethod(clazz, clazz.finalizer, nativeModule, nativeModuleEmpty, Type.Pointer)43clazz.methods.forEach(method => {44const returnType = method.tsReturnType()45// TODO: DotIndicator and DigitIndicator implements Indicator46const subType = returnType?.name.includes(method.originalParentName)47printPeerMethod(clazz, method, nativeModule, nativeModuleEmpty,48returnType === Type.This || subType ? Type.Pointer : returnType)49})50})51}52
53private printEventMethods(nativeModule: LanguageWriter, nativeModuleEmpty: LanguageWriter) {54let method = generateEventsBridgeSignature(nativeModule.language)55method = new Method(`_${method.name}`, method.signature, method.modifiers)56nativeModule.writeNativeMethodDeclaration(method.name, method.signature)57nativeModuleEmpty.writeMethodImplementation(method, writer => {58writer.writePrintLog(method.name)59writer.writeStatement(writer.makeReturn(new StringExpression(`0`)))60})61}62
63print(): void {64console.log(`Materialized classes: ${this.library.materializedClasses.size}`)65this.nativeModule.pushIndent()66this.nativeModuleEmpty.pushIndent()67for (const file of this.library.files) {68for (const peer of file.peersToGenerate.values()) {69this.printPeerMethods(peer)70}71}72this.printMaterializedMethods(this.nativeModule, this.nativeModuleEmpty)73this.printEventMethods(this.nativeModule, this.nativeModuleEmpty)74this.nativeModule.popIndent()75this.nativeModuleEmpty.popIndent()76}77}
78
79function printPeerMethod(clazz: PeerClassBase, method: PeerMethod, nativeModule: LanguageWriter, nativeModuleEmpty: LanguageWriter,80returnType?: Type81) {82const component = clazz.generatedName(method.isCallSignature)83clazz.setGenerationContext(`${method.isCallSignature ? "" : method.overloadedName}()`)84let serializerArgCreated = false85let args: ({name: string, type: string})[] = []86for (let i = 0; i < method.argConvertors.length; ++i) {87let it = method.argConvertors[i]88if (it.useArray) {89if (!serializerArgCreated) {90const array = `thisSerializer`91args.push({ name: `thisArray`, type: 'Uint8Array' }, { name: `thisLength`, type: 'int32' })92serializerArgCreated = true93}94} else {95// TODO: use language as argument of interop type.96args.push({ name: `${it.param}`, type: it.interopType(nativeModule.language) })97}98}99let maybeReceiver = method.hasReceiver() ? [{ name: 'ptr', type: 'KPointer' }] : []100const parameters = NamedMethodSignature.make(returnType?.name ?? 'void', maybeReceiver.concat(args))101let name = `_${component}_${method.overloadedName}`102nativeModule.writeNativeMethodDeclaration(name, parameters)103nativeModuleEmpty.writeMethodImplementation(new Method(name, parameters), (printer) => {104printer.writePrintLog(name)105if (returnType !== undefined && returnType.name !== Type.Void.name) {106printer.writeStatement(printer.makeReturn(printer.makeString(getReturnValue(returnType))))107}108})109clazz.setGenerationContext(undefined)110}
111
112export function printNativeModule(peerLibrary: PeerLibrary, nativeBridgePath: string): string {113const lang = peerLibrary.declarationTable.language114const visitor = new NativeModuleVisitor(peerLibrary)115visitor.print()116return nativeModuleDeclaration(visitor.nativeModule, nativeBridgePath, false, lang)117}
118
119export function printNativeModuleEmpty(peerLibrary: PeerLibrary): string {120const visitor = new NativeModuleVisitor(peerLibrary)121visitor.print()122return nativeModuleEmptyDeclaration(visitor.nativeModuleEmpty.getOutput())123}
124
125function getReturnValue(type: Type): string {126switch(type.name) {127case Type.Boolean.name : return "false"128case Type.Number.name: return "1"129case Type.Pointer.name: return "-1"130case "string": return `"some string"`131}132throw new Error(`Unknown return type: ${type.name}`)133}
134