* Copyright (c) 2025 Huawei Device Co., Ltd.
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
import { Hs, D, E, Md, T, Ts } from "../../../ost";
import * as idl from "@idlizer/core/idl"
import { makePeerMethod } from "../components/peerMethod";
import { AdvancedGeneratorContext, createSpecialProducer, managedName, roles } from "../common";
import { capitalize, getSuperType, isMaterialized } from "@idlizer/core";
import { fqName, ProducerDescription } from "../../engine";
import { LWDeclaration } from "../../../ost/lws";
import { Builders } from "../../../ost/builders";
export const structureProducer = createSpecialProducer(
{ is: idl.isInterface, role: roles.managed },
(node, ctx) => {
if (node.subkind === idl.IDLInterfaceSubkind.Tuple)
return makeTuple(node, ctx)
const declName = managedName(idl.getFQName(node))
const generator = isMaterialized(node, ctx.base.library)
? makeMaterialized
: makeInterface
return {
artifact: {
reference: T.c(declName),
implementationGenerator: () => {
ctx.useCApi(node)
return generator(node, declName, ctx)
}
}
}
}
)
function makeTuple(node: idl.IDLInterface, ctx: AdvancedGeneratorContext): ProducerDescription {
return {
recursive: () => {
return {
artifact: {
reference: Ts.intersection(
node.properties.map(prop => ctx.useManaged(prop.type).reference()))
}
}
}
}
}
function makeInterface(node: idl.IDLInterface, name: string, ctx: AdvancedGeneratorContext): LWDeclaration[] {
const superType = getSuperType(node, ctx.base.library)
return [D.class(name,
node.properties.map(prop => {
const modifiers = [
...prop.isOptional ? [Md.optional()] : [],
...prop.isReadonly ? [Md.readonly()] : [],
...prop.isStatic ? [Md.static()] : [],
]
return {
name: prop.name,
type: ctx.useManaged(prop.type).reference(),
modifiers,
}
}),
node.methods.map(method => makePeerMethod(method, ctx)), {
kind: idl.isClassSubkind(node) ? 'class' : 'interface',
base: superType ? ctx.useManaged(superType).reference() : undefined
})]
}
function makeMaterialized(node: idl.IDLInterface, name: string, ctx: AdvancedGeneratorContext): LWDeclaration[] {
const syntheticMethods = [
...node.constructors.length ? [] : [idl.createConstructor([], undefined)],
...node.properties.flatMap(prop => [
idl.createMethod('get' + capitalize(prop.name), [], prop.type, undefined, {
extendedAttributes: [
{ name: idl.IDLExtendedAttributes.Accessor, value: idl.IDLAccessorAttribute.Getter },
{ name: idl.IDLExtendedAttributes.DtsName, value: prop.name }]}),
idl.createMethod('set' + capitalize(prop.name), [idl.createParameter(prop.name, prop.type)], idl.IDLVoidType, undefined, {
extendedAttributes: [
{ name: idl.IDLExtendedAttributes.Accessor, value: idl.IDLAccessorAttribute.Setter },
{ name: idl.IDLExtendedAttributes.DtsName, value: prop.name }]}),
])
]
syntheticMethods.forEach(it => it.parent = node);
[
...node.constructors,
...node.methods,
...syntheticMethods
].forEach(it => ctx.useManaged(it))
const peerType = Ts.union([T.c('Finalizable'), T.c('undefined')])
const thisType = ctx.useManaged(node).reference()
const intClass = Builders.class(name + 'Internal')
.method('fromPtr').static()
.returns(thisType)
.param('ptr').type(Ts.prim.pointer).$().block()
.return(thisType).ctor(name).args([E.v('ptr')]).$().$().$().$().$()
const matClass = Builders.class(name).implements(T.c('MaterializedBase'))
.field('peer').type(peerType).$()
.method('getPeer').returns(peerType).block()
.return(peerType).access(E.v('this')).member('peer').$().$().$().$()
.method('setPeer').private().param('peerPtr').type(Ts.prim.pointer).$().block()
.binary('=')
.left().access(E.v('this')).member('peer').$().$()
.right().ctor('Finalizable')
.arg('peerPtr').$()
.arg().call().receiverExpr(E.v(name, [Hs.isType()])).functionName('getFinalizer').$().$().$().$().$().$().$()
.method('getFinalizer').static().returns(Ts.prim.pointer).block()
.return(Ts.prim.pointer).call().function()
.access(ctx.useManagedNativeModule(node).name())
.member(fqName(node, '_', '_getFinalizer')).$().$().$().$().$().$()
.ctor().param('ptr').type(Ts.prim.pointer).$().block()
.call().receiverExpr(E.v('this')).functionName('setPeer').arg('ptr').$().$().$().$().$()
return [intClass, matClass]
}