diff --git a/arkoala-arkts/libarkts/plugins/src/DtsGenerator.ts b/arkoala-arkts/libarkts/plugins/src/DtsGenerator.ts new file mode 100644 index 0000000000000000000000000000000000000000..9002023efc0f803006ca5165a3cf3f65f67e6c08 --- /dev/null +++ b/arkoala-arkts/libarkts/plugins/src/DtsGenerator.ts @@ -0,0 +1,106 @@ +/* + * Copyright (c) 2022-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 * as arkts from "@koalaui/libarkts" +import { AbstractVisitor } from "./AbstractVisitor" +import * as fs from 'fs' + + +export default function dtsGenerator( +// userPluginOptions?: TransformerOptions +) { + + return (node: arkts.AstNode) => { + const dtsTransformer = new DtsTransformer() + + const dtsAst = dtsTransformer.visitor(node) + fs.writeFileSync("foo.d.sts", dtsAst.dumpSrc(), 'utf-8') + + // The original node is left intact. + // We just produce d.sts as a side product. + return node + } + +} + +export class DtsTransformer extends AbstractVisitor { + visitor(beforeChildren: arkts.AstNode): arkts.AstNode { + const node = this.visitEachChild(beforeChildren) + if (arkts.isClassDefinition(node)) { + return arkts.factory.updateClassDefinition( + node, + node.ident, + node.typeParams, + node.superTypeParams, + node.implements, + undefined, + node.super, + node.body, + node.modifiers, + arkts.classDefinitionFlags(node) | arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_DECLARE + ) + } + if (arkts.isScriptFunction(node)) { + return arkts.factory.updateScriptFunction( + node, + // Drop body + undefined, + node.scriptFunctionFlags, + node.modifiers | arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_DECLARE, + true, + node.ident, + node.parameters, + node.typeParamsDecl, + node.returnTypeAnnotation ?? this.deduceType(node) + ) + } + if (arkts.isClassProperty(node)) { + return arkts.factory.updateClassProperty( + node, + node.key, + // Drop initializer + undefined, + node.typeAnnotation, + node.modifiers, + node.isComputed + ) + } + return node + } + deduceType(node: arkts.ScriptFunction): arkts.TypeNode|undefined { + // const name = node.ident?.name + // if (name == "_$init$_") { + // // Somehow createTSVoid doesn't work :-() + // return arkts.factory.createTypeReferenceFromId(arkts.factory.createIdentifier("void")) + // } + // return undefined + + if (this.isConstructor(node)) { + return undefined + } + + // TODO: as a quick workaround, + // if no type is specified assume void. + return arkts.factory.createTypeReference( + arkts.factory.createTypeReferencePart( + arkts.factory.createIdentifier("void") + ) + ) + } + isConstructor(node: arkts.ScriptFunction): boolean { + return (node.modifiers & arkts.Es2pandaModifierFlags.MODIFIER_FLAGS_CONSTRUCTOR) != 0 || + node.ident?.name == "constructor" + } +} diff --git a/arkoala-arkts/libarkts/plugins/tsconfig.json b/arkoala-arkts/libarkts/plugins/tsconfig.json index cd92c8cd00759dc0e6858e88f78197d08f676ddf..c1a377c90756ac02fe276948267c657f84fe4ed8 100644 --- a/arkoala-arkts/libarkts/plugins/tsconfig.json +++ b/arkoala-arkts/libarkts/plugins/tsconfig.json @@ -9,6 +9,7 @@ "include": [ "./src/printer-plugin.ts", "./src/AbstractVisitor.ts", + "./src/DtsGenerator.ts", "./src/print-visitor.ts", "./src/no-visitor.ts" ]