From 0017d43e5d2f5f9c57ec262e66dd078d762b1b13 Mon Sep 17 00:00:00 2001 From: chernishevvictor Date: Thu, 31 Oct 2024 16:24:49 +0300 Subject: [PATCH] the great refactoring review fix refactoring pass utilities add CI for libarkts add export test + CI change review fix fix CI change export test fix CI fix meson.build for libarkts fix CI for libarkts add import resolving example in tests fix CI (add build dirs in artifacts) fix CI (removed unnecessary) support type params in createFunctionDeclaration fix CI moved transformation-context, some of util, some of analysis-visitor from compiler-plugin add getOriginalNode method add new types for analysis-visitor add basic support of variable declarations and analysis-visitor add createVariableStatement and test refactoring (global class moved out) impoved FunctionDeclaration fix undefined pass in nodesVisitor support unsupported node add test for createFunctionDeclaration and support UnionType add test for updateVariableStatement fixing and refactoring update functions in nodeFactory refactoring nodeFactory (updateNode) add npm run test:STATE_CHECKED add after STATE_CHECKED test option fix test:STATE_CHECKED add assertEqualsBinaryOutput add scripts for tests in package.json small refactoring in tests review fix and CI fix add new test + add test skipping removed constructor in Node + modifierFlagsExtension global modifiers change update global.ts file full modifiers support add more functions to api add more function to api update class create/update support add typesEts.ts add to ets: StringLiteral, NumberLiteral delete class.test.ts (not gonna work now) the great refactoring: beginning --- .gitlab-ci.yml | 5 +- arkoala-arkts/libarkts/.gitlab-ci.yml | 41 + .../compatible/src/AbstractVisitor.ts | 3 +- .../compatible/src/analysis-visitor.ts | 258 ++++ .../src/builder-lambda-transformer.ts | 5 +- .../compatible/src/example-transformer.ts | 2 + .../compatible/src/function-transformer.ts | 3 +- .../compatible/src/memo-transformer.ts | 12 +- .../libarkts/compatible/src/print-visitor.ts | 4 +- .../compatible/src/transformation-context.ts | 36 + arkoala-arkts/libarkts/compatible/src/util.ts | 164 +++ arkoala-arkts/libarkts/input/export.sts | 5 + arkoala-arkts/libarkts/native/meson.build | 4 +- .../libarkts/native/src/es2panda_lib.cc | 365 ++++- arkoala-arkts/libarkts/package.json | 3 +- arkoala-arkts/libarkts/src/NativeModule.ts | 37 +- .../libarkts/src/arkts/arktsNodeByEtsNode.ts | 88 ++ arkoala-arkts/libarkts/src/arkts/enums.ts | 72 +- .../libarkts/src/arkts/etsNodeByPeer.ts | 63 + .../libarkts/src/arkts/factory/nodeFactory.ts | 1203 +++++++++++------ .../libarkts/src/arkts/factory/nodeTests.ts | 91 +- .../libarkts/src/arkts/factory/utilities.ts | 189 +-- arkoala-arkts/libarkts/src/arkts/global.ts | 132 ++ arkoala-arkts/libarkts/src/arkts/index.ts | 7 +- .../libarkts/src/arkts/nodeByPeer.ts | 57 - arkoala-arkts/libarkts/src/arkts/types.ts | 843 ++++++++---- arkoala-arkts/libarkts/src/arkts/typesEts.ts | 609 +++++++++ arkoala-arkts/libarkts/src/arkts/utilities.ts | 177 ++- .../libarkts/src/arkts/utilitiesPublic.ts | 58 +- arkoala-arkts/libarkts/src/arkts/visitor.ts | 34 +- arkoala-arkts/libarkts/src/es2panda.ts | 13 +- .../libarkts/test/es2panda/abc-gen.test.ts | 33 +- .../test/es2panda/analysis-visitor.test.ts | 38 + .../libarkts/test/es2panda/basic.test.ts | 168 +++ .../es2panda/builder-lambda-rewrite.test.ts | 32 +- .../create-function-declaration.test.ts | 348 +++-- .../test/es2panda/function-rewrite.test.ts | 2 + .../libarkts/test/es2panda/import.test.ts | 63 + .../es2panda/lambda-param-memoization.test.ts | 13 +- .../es2panda/literal-declarations.test.ts | 121 ++ .../test/es2panda/memo-rewrite.test.ts | 2 + .../test/es2panda/print-visitor.test.ts | 69 +- .../es2panda/simple-transformations.test.ts | 56 + .../update-function-declaration.test.ts | 427 +++--- arkoala-arkts/libarkts/test/test-util.ts | 131 +- incremental/compiler-plugin/.gitlab-ci.yml | 3 +- 46 files changed, 4716 insertions(+), 1373 deletions(-) create mode 100644 arkoala-arkts/libarkts/.gitlab-ci.yml create mode 100644 arkoala-arkts/libarkts/compatible/src/analysis-visitor.ts create mode 100644 arkoala-arkts/libarkts/compatible/src/transformation-context.ts create mode 100644 arkoala-arkts/libarkts/compatible/src/util.ts create mode 100644 arkoala-arkts/libarkts/input/export.sts create mode 100644 arkoala-arkts/libarkts/src/arkts/arktsNodeByEtsNode.ts create mode 100644 arkoala-arkts/libarkts/src/arkts/etsNodeByPeer.ts create mode 100644 arkoala-arkts/libarkts/src/arkts/global.ts delete mode 100644 arkoala-arkts/libarkts/src/arkts/nodeByPeer.ts create mode 100644 arkoala-arkts/libarkts/src/arkts/typesEts.ts create mode 100644 arkoala-arkts/libarkts/test/es2panda/analysis-visitor.test.ts create mode 100644 arkoala-arkts/libarkts/test/es2panda/basic.test.ts create mode 100644 arkoala-arkts/libarkts/test/es2panda/import.test.ts create mode 100644 arkoala-arkts/libarkts/test/es2panda/literal-declarations.test.ts create mode 100644 arkoala-arkts/libarkts/test/es2panda/simple-transformations.test.ts diff --git a/.gitlab-ci.yml b/.gitlab-ci.yml index eaaddce22..3d0aabdc7 100644 --- a/.gitlab-ci.yml +++ b/.gitlab-ci.yml @@ -3,6 +3,7 @@ image: "nexus.bz-openlab.ru:10443/huawei/koala-ci:0.2" stages: - prebuild - build-compiler + - build-plugin-api - build - test - idlize @@ -20,8 +21,8 @@ include: - incremental/compiler-plugin/.gitlab-ci.yml - incremental/runtime/.gitlab-ci.yml - incremental/demo-playground/.gitlab-ci.yml - - arkoala/tools/peer-generator/.gitlab-ci.yml - - arkoala-arkts/user/.gitlab-ci.yml + - arkoala/arkui/.gitlab-ci.yml + - arkoala-arkts/libarkts/.gitlab-ci.yml unmemoize arkoala-arkts/arkui: allow_failure: true diff --git a/arkoala-arkts/libarkts/.gitlab-ci.yml b/arkoala-arkts/libarkts/.gitlab-ci.yml new file mode 100644 index 000000000..baadfeb5d --- /dev/null +++ b/arkoala-arkts/libarkts/.gitlab-ci.yml @@ -0,0 +1,41 @@ +# Copyright (c) 2022-2023 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. + +build plugin-api: + stage: build + interruptible: true + extends: .linux-vm-shell-task + before_script: + - !reference [.setup, script] + - cd arkoala-arkts/libarkts + script: + - npm i && npm run compile + artifacts: + expire_in: 2 days + paths: + - arkoala-arkts/libarkts/compatible/build + - arkoala-arkts/libarkts/compatible/build_arkts + - arkoala-arkts/libarkts/native/build_es2panda + +test plugin-api: + stage: test + allow_failure: true + interruptible: true + extends: .linux-vm-shell-task + before_script: + - !reference [.setup, script] + - cd arkoala-arkts/libarkts + script: + - npm i && npm run test + needs: + - build plugin-api diff --git a/arkoala-arkts/libarkts/compatible/src/AbstractVisitor.ts b/arkoala-arkts/libarkts/compatible/src/AbstractVisitor.ts index 68ac3dd86..7d8dddbaa 100644 --- a/arkoala-arkts/libarkts/compatible/src/AbstractVisitor.ts +++ b/arkoala-arkts/libarkts/compatible/src/AbstractVisitor.ts @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +/* import * as arkts from "../../src/arkts" export abstract class AbstractVisitor { @@ -40,3 +40,4 @@ export abstract class AbstractVisitor { ) } } +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/analysis-visitor.ts b/arkoala-arkts/libarkts/compatible/src/analysis-visitor.ts new file mode 100644 index 000000000..41910f71f --- /dev/null +++ b/arkoala-arkts/libarkts/compatible/src/analysis-visitor.ts @@ -0,0 +1,258 @@ +/* + * Copyright (c) 2022-2023 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 "../../src/arkts" +import { AbstractVisitor } from "./AbstractVisitor"; + +import { Rewrite } from './transformation-context'; +import { + FunctionKind, + Tracer, + // findSourceFile, + // error, + asString, + RuntimeNames, + // isFunctionOrMethod, + // getComment, + // arrayAt, + // getDeclarationsByNode, + findFunctionDeclaration, + // isMemoEntry, + // skipParenthesizedExpression, +} from "./util" +// import { ImportExport } from './import-export'; + +function parseComment(comment: string): FunctionKind { + let kind = FunctionKind.REGULAR + if (comment.includes(RuntimeNames.ANNOTATION_INTRINSIC)) { + kind = FunctionKind.MEMO_INTRINSIC + } else if (comment.includes(RuntimeNames.ANNOTATION_ENTRY)) { + // Do nothing + } else if (comment.includes(RuntimeNames.ANNOTATION)) { + kind = FunctionKind.MEMO + } + return kind +} + +export class AnalysisVisitor extends AbstractVisitor { + constructor( + public tracer: Tracer, + // public typechecker: arkts.TypeChecker, + // public sourceFile: arkts.SourceFile, + public rewrite: Rewrite, + ctx?: arkts.TransformationContext + ) { + super(ctx) + } + + // private importExport = new ImportExport(this.typechecker, this.sourceFile) + + trace(msg: any) { + this.tracer.trace(msg) + } + + traceAnnotation(nodeName: string, kind: FunctionKind, node: arkts.Node) { + if (kind) { + this.trace(`${nodeName} HAS annotation: ${asString(node)} to ${FunctionKind[kind]}`) + } else { + this.trace(`${nodeName} doesn't have annotations: ${asString(node)}`) + } + } + + // TODO: get real annotation + getFunctionKindByIdent(node: arkts.Identifier | undefined, traceAnnotation: string): FunctionKind { + if (node === undefined) { + return FunctionKind.REGULAR + } + if (!arkts.isIdentifier(node)) { + arkts.throwError('node expected to be Identifier') + } + const kind = parseComment(node.text) + this.traceAnnotation(traceAnnotation, kind, node) + return kind + } + + updateFunctionTableByKind(node: arkts.SignatureDeclarationBase, kind: FunctionKind): void { + if (kind === FunctionKind.REGULAR) { + return + } + this.rewrite.functionTable.set(node, kind) + } + + updateFunctionTableByIdent(node: arkts.SignatureDeclarationBase, ident: arkts.Identifier | undefined, traceMessage: string): void { + if (ident === undefined) { + return + } + this.updateFunctionTableByKind(node, this.getFunctionKindByIdent(ident, traceMessage)) + } + + updateVariableTableByKind(node: arkts.VariableLikeDeclaration, kind: FunctionKind): void { + if (kind === FunctionKind.REGULAR) { + return + } + this.rewrite.variableTable.set(node, kind) + } + + updateVariableTableByIdent(node: arkts.VariableLikeDeclaration, ident: arkts.Identifier, traceMessage: string): void { + this.updateVariableTableByKind(node, this.getFunctionKindByIdent(ident, traceMessage)) + } + + updateCallTableByKind(node: arkts.CallExpression, kind: FunctionKind): void { + if (kind === FunctionKind.REGULAR) { + return + } + this.rewrite.callTable.set(node, kind) + } + + updateCallTableByIdent(node: arkts.CallExpression, ident: arkts.Identifier, traceMessage: string): void { + this.updateCallTableByKind(node, this.getFunctionKindByIdent(ident, traceMessage)) + } + + isMemoEntry(node: arkts.CallExpression): boolean { + const enclosingFunction = findFunctionDeclaration(node) + if (enclosingFunction === undefined) { + return false + } + return this.getFunctionKindByIdent(enclosingFunction.name, "isMemoEntry") === FunctionKind.MEMO + } + + processCallExpression(node: arkts.CallExpression): void { + if (arkts.isIdentifier(node.expression)) { + this.updateCallTableByIdent(node, node.expression, "CallExpression") + } else if (arkts.isPropertyAccessExpression(node.expression)) { + // TODO: fix maybe (copied from compiler-plugin) + const kind = this.getFunctionKindByIdent(node.expression.name, "CallExpression") + if (kind !== FunctionKind.REGULAR) { + this.rewrite.callTable.set(node, kind) + } + return + } + if (this.isMemoEntry(node)) { + this.rewrite.entryTable.add(node) + } + } + + processFunctionDeclaration(node: arkts.FunctionDeclaration): void { + this.updateFunctionTableByIdent(node, node.name, "FunctionDeclaration") + } + + processMethodDeclaration(node: arkts.MethodDeclaration): void { + this.updateFunctionTableByIdent(node, node.name, "MethodDeclaration") + } + + // TODO: unavailable now (ArrowFunction doesn't have a name) + processArrowFunction(node: arkts.ArrowFunction): void { + // this.updateFunctionTableByIdent(node, node.name, "ArrowFunction") + return + } + + processFunctionExpression(node: arkts.FunctionExpression): void { + this.updateFunctionTableByIdent(node, node.name, "MethodDeclaration") + } + + processParameter(node: arkts.ParameterDeclaration): void { + this.updateVariableTableByIdent(node, node.name, "ParameterDeclaration") + } + + processVariableDeclaration(node: arkts.VariableDeclaration): void { + this.updateVariableTableByIdent(node, node.name, "ParameterDeclaration") + } + + processVariableDeclarationList(node: arkts.VariableDeclarationList): void { + node.declarations.forEach(declaration => { + this.processVariableDeclaration(declaration) + }) + } + + processPropertyDeclaration(node: arkts.PropertyDeclaration): void { + // TODO: support non Identifier properties + this.updateVariableTableByIdent(node, node.name as arkts.Identifier, "PropertyDeclaration") + } + + processPropertySignature(node: arkts.PropertySignature): void { + if (node.name === undefined) { + return + } + // TODO: support non Identifier properties + this.updateVariableTableByIdent(node, node.name as arkts.Identifier, "PropertySignature") + } + + processFunctionTypeNode(node: arkts.FunctionTypeNode): void { + if (node.name === undefined) { + return + } + // TODO: support non Identifier properties + this.updateFunctionTableByIdent(node, node.name as arkts.Identifier, "FunctionTypeNode") + } + + processMethodSignature(node: arkts.MethodSignature): void { + if (node.name === undefined) { + return + } + // TODO: support non Identifier properties + this.updateFunctionTableByIdent(node, node.name as arkts.Identifier, "MethodSignature") + } + + processGetAccessorDeclaration(node: arkts.GetAccessorDeclaration): void { + this.updateFunctionTableByIdent(node, node.name, "GetAccessorDeclaration") + } + + processSetAccessorDeclaration(node: arkts.SetAccessorDeclaration): void { + this.updateFunctionTableByIdent(node, node.name, "SetAccessorDeclaration") + } + + visitor(node: arkts.Node): arkts.Node { + // TODO: comparison shouldn't work now + if (arkts.getOriginalNode(node) !== node) { + throw new Error("Analysis phase is expected to work on original nodes") + } + + if (arkts.isCallExpression(node)) { + this.processCallExpression(node) + } else if (arkts.isFunctionDeclaration(node)) { + this.processFunctionDeclaration(node) + } else if (arkts.isMethodDeclaration(node)) { + this.processMethodDeclaration(node) + } else if (arkts.isArrowFunction(node)) { + this.processArrowFunction(node) + } else if (arkts.isFunctionExpression(node)) { + this.processFunctionExpression(node) + } else if (arkts.isParameter(node)) { + this.processParameter(node) + } + // else if (arkts.isVariableDeclaration(node)) { + // this.processVariableDeclaration(node) + // } + else if (arkts.isVariableDeclarationList(node)) { + this.processVariableDeclarationList(node) + } + else if (arkts.isPropertyDeclaration(node)) { + this.processPropertyDeclaration(node) + } else if (arkts.isPropertySignature(node)) { + this.processPropertySignature(node) + } else if (arkts.isFunctionTypeNode(node)) { + this.processFunctionTypeNode(node) + } else if (arkts.isMethodSignature(node)) { + this.processMethodSignature(node) + } else if (arkts.isGetAccessorDeclaration(node)) { + this.processGetAccessorDeclaration(node) + } else if (arkts.isSetAccessorDeclaration(node)) { + this.processSetAccessorDeclaration(node) + } + + return this.visitEachChild(node) + } +} +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/builder-lambda-transformer.ts b/arkoala-arkts/libarkts/compatible/src/builder-lambda-transformer.ts index 83ff1e8ce..0a72cbefa 100644 --- a/arkoala-arkts/libarkts/compatible/src/builder-lambda-transformer.ts +++ b/arkoala-arkts/libarkts/compatible/src/builder-lambda-transformer.ts @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +/* import * as arkts from "../../src/arkts" import { AbstractVisitor } from "./AbstractVisitor"; @@ -48,7 +48,7 @@ export class BuilderLambdaTransformer extends AbstractVisitor { return node } - let instanceCalls = [] + let instanceCalls: arkts.CallExpression[] = [] let leaf: arkts.CallExpression = node while (true @@ -125,3 +125,4 @@ export class BuilderLambdaTransformer extends AbstractVisitor { ) } } +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/example-transformer.ts b/arkoala-arkts/libarkts/compatible/src/example-transformer.ts index 2c67fb066..d267f6e45 100644 --- a/arkoala-arkts/libarkts/compatible/src/example-transformer.ts +++ b/arkoala-arkts/libarkts/compatible/src/example-transformer.ts @@ -1,3 +1,4 @@ +/* import * as arkts from "../../src/arkts" import { BuilderLambdaTransformer } from "./builder-lambda-transformer" @@ -15,3 +16,4 @@ export default function exampleTransformer(program?: arkts.Program, userPluginOp } } } +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/function-transformer.ts b/arkoala-arkts/libarkts/compatible/src/function-transformer.ts index d0f436e82..6e6d61eab 100644 --- a/arkoala-arkts/libarkts/compatible/src/function-transformer.ts +++ b/arkoala-arkts/libarkts/compatible/src/function-transformer.ts @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +/* import * as arkts from "../../src/arkts" import { AbstractVisitor } from "./AbstractVisitor"; @@ -97,3 +97,4 @@ export class FunctionTransformer extends AbstractVisitor { return node } } +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/memo-transformer.ts b/arkoala-arkts/libarkts/compatible/src/memo-transformer.ts index 19c7d060d..b32004b4f 100644 --- a/arkoala-arkts/libarkts/compatible/src/memo-transformer.ts +++ b/arkoala-arkts/libarkts/compatible/src/memo-transformer.ts @@ -12,7 +12,7 @@ * See the License for the specific language governing permissions and * limitations under the License. */ - +/* import * as arkts from "../../src/arkts" import { AbstractVisitor } from "./AbstractVisitor"; @@ -100,13 +100,15 @@ function transformMethodDeclaration(node: arkts.MethodDeclaration): arkts.Node { ) ] )), - ...node.body.statements, + ...(node.body?.statements ?? []), arkts.factory.createReturnStatement( arkts.factory.createCallExpression( arkts.factory.createPropertyAccessExpression( arkts.factory.createIdentifier("__memo_scope"), arkts.factory.createIdentifier("recache") - ) + ), + undefined, + undefined ) ), ] @@ -126,10 +128,11 @@ function transformMethodDeclaration(node: arkts.MethodDeclaration): arkts.Node { ...node.parameters ], undefined, + node.body ? arkts.factory.updateBlock( node.body, bodyStatements - ) + ) : undefined ) } @@ -152,3 +155,4 @@ export class MemoTransformer extends AbstractVisitor { return node } } +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/print-visitor.ts b/arkoala-arkts/libarkts/compatible/src/print-visitor.ts index 240ba9682..7865d20e7 100644 --- a/arkoala-arkts/libarkts/compatible/src/print-visitor.ts +++ b/arkoala-arkts/libarkts/compatible/src/print-visitor.ts @@ -1,3 +1,4 @@ +/* import * as arkts from "../../src/arkts" import { AbstractVisitor } from "./AbstractVisitor"; @@ -15,7 +16,7 @@ export class PrintVisitor extends AbstractVisitor { } visitor(beforeChildren: arkts.Node): arkts.Node { - this.print(beforeChildren.constructor.name + " (mod: " + beforeChildren.modifier + ")") + this.print(beforeChildren.constructor.name + " (mods: [" + beforeChildren.modifiers + "])") const node = this.visitEachChild(beforeChildren) return node @@ -27,3 +28,4 @@ export class PrintVisitor extends AbstractVisitor { return this.result.trim() } } +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/transformation-context.ts b/arkoala-arkts/libarkts/compatible/src/transformation-context.ts new file mode 100644 index 000000000..ab4764808 --- /dev/null +++ b/arkoala-arkts/libarkts/compatible/src/transformation-context.ts @@ -0,0 +1,36 @@ +/* + * Copyright (c) 2022-2023 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 "../../src/arkts" +import { CallTable, EntryTable, FunctionKind, FunctionTable, TransformerOptions, VariableTable } from "./util" + +export class Rewrite { + public functionTable: FunctionTable + public callTable: CallTable + public variableTable: VariableTable + public entryTable: EntryTable + // public positionalIdTracker: PositionalIdTracker + + constructor(sourceFile: arkts.SourceFile, public pluginOptions: TransformerOptions) { + this.functionTable = new Map() + this.callTable = new Map() + this.variableTable = new Map() + this.entryTable = new Set() + // this.positionalIdTracker = new PositionalIdTracker(sourceFile, pluginOptions.stableForTest ?? false) + } + + public importTypesFrom: string | undefined = undefined +} +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/compatible/src/util.ts b/arkoala-arkts/libarkts/compatible/src/util.ts new file mode 100644 index 000000000..c8622f4b2 --- /dev/null +++ b/arkoala-arkts/libarkts/compatible/src/util.ts @@ -0,0 +1,164 @@ +/* + * Copyright (c) 2022-2024 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 "../../src/arkts" +import * as fs from "fs" + +export enum FunctionKind { + REGULAR, + MEMO, + MEMO_INTRINSIC, +} + +export type FunctionTable = Map +export type CallTable = Map +export type EntryTable = Set +export type VariableTable = Map + +export function isNamedDeclaration(node: arkts.Node): node is arkts.NamedDeclaration { + return ("name" in node ) +} + +export function asString(node: arkts.Node | undefined): string { + if (node === undefined) { + return "undefined node" + } + if (arkts.isIdentifier(node)) { + return node.text + } + if (isNamedDeclaration(node)) { + if (node.name === undefined) { + return `${arkts.SyntaxKind[node.kind]}(undefined name)` + } else { + return `${arkts.SyntaxKind[node.kind]}(${asString(node.name)})` + } + } else { + return `${arkts.SyntaxKind[node.kind]}` + } +} + +export function isFunctionOrMethod(node: arkts.Node): node is arkts.FunctionLikeDeclaration { + return arkts.isFunctionDeclaration(node) || + arkts.isMethodDeclaration(node) || + arkts.isFunctionExpression(node) || + arkts.isArrowFunction(node) +} + +export interface TransformerOptions { + // Emit transformed functions to the console. + trace?: boolean, + // Store the transformed functions to this directory. + keepTransformed?: string, + // Use human readable call site IDs without directory paths. + stableForTest?: boolean, + // Import context and id types from alternative source + contextImport?: string, + // Dump sources with resolved memo annotations to unmemoized directory + only_unmemoize?: boolean, + // Replace extension for output TS files + extension?: string, +} + +function baseName(path: string): string { + return path.replace(/^.*\/(.*)$/, "$1") +} + +export class Tracer { + constructor ( + public options: TransformerOptions, + // TODO: implement ts.Printer + // public printer: arkts.Printer + ) {} + + trace(msg: any) { + if (!this.options.trace) return + console.log(msg) + } + + writeTextToFile(text: string, file: string) { + fs.writeFileSync(file, text, 'utf8') + this.trace("DUMP TO: " + file) + } + + createDirs(dirs: string) { + fs.mkdirSync(dirs, { recursive: true }); + } + + dumpFileName(sourceFile: arkts.SourceFile, transformed: arkts.FunctionLikeDeclarationBase): string | undefined { + if (!this.options.keepTransformed) { + return undefined + } + + const outDir = (this.options.keepTransformed[0] == "/") ? + this.options.keepTransformed : + `${__dirname}/${this.options.keepTransformed}` + + this.createDirs(outDir) + + const sourceBaseName = baseName(sourceFile.fileName) + if (!transformed.name) return + if (!arkts.isIdentifier(transformed.name)) return + const fileName = `${transformed.name.text}_${sourceBaseName}` + return `${outDir}/${fileName}_dump` + } + + keepTransformedFunction(transformed: arkts.FunctionLikeDeclarationBase, sourceFile: arkts.SourceFile) { + const fileName = this.dumpFileName(sourceFile, transformed) + if (!fileName) return + + // TODO: implement ts.Printer + // const content = this.printer.printNode(arkts.EmitHint.Unspecified, transformed, sourceFile) + // this.writeTextToFile(content+"\n", fileName) + } +} + +export enum RuntimeNames { + // COMPUTE = "compute", + // CONTEXT = "__memo_context", + // ID = "__memo_id", + // SCOPE = "__memo_scope", + // INTERNAL_PARAMETER_STATE = "param", + // INTERNAL_VALUE = "cached", + // INTERNAL_VALUE_NEW = "recache", + // INTERNAL_SCOPE = "scope", + // INTERNAL_VALUE_OK = "unchanged", + // CONTENT = "content", + // VALUE = "value", + // __CONTEXT = "__context", + // __ID = "__id", + // __KEY = "__key", + // __STATE = "__state", + // CONTEXT_TYPE = "__memo_context_type", + // ID_TYPE = "__memo_id_type", + // TRANSFORMED_TYPE = "__memo_transformed", + // SYNTHETIC_RETURN_MARK = "__synthetic_return_value", + // CONTEXT_TYPE_DEFAULT_IMPORT = "@koalaui/runtime", + ANNOTATION = "_memo", + ANNOTATION_INTRINSIC = "_memo:intrinsic", + ANNOTATION_ENTRY = "_memo:entry", + ANNOTATION_SKIP = "_skip:memo", // skip binding to parameter changes + ANNOTATION_STABLE = "_memo:stable", // assume this should not be tracked +} + +export function findFunctionDeclaration(node: arkts.Node): arkts.FunctionDeclaration | undefined { + while (node.kind !== arkts.SyntaxKind.SourceFile) { + if (arkts.isFunctionDeclaration(node)) { + return node + } + node = node.parent + } + return undefined +} +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/input/export.sts b/arkoala-arkts/libarkts/input/export.sts new file mode 100644 index 000000000..d5f7c542e --- /dev/null +++ b/arkoala-arkts/libarkts/input/export.sts @@ -0,0 +1,5 @@ +export function foo() { + console.log("Hello, world!") +} + +export const TEST: double = 2.718281828459045; diff --git a/arkoala-arkts/libarkts/native/meson.build b/arkoala-arkts/libarkts/native/meson.build index 9a34a3677..76a002823 100644 --- a/arkoala-arkts/libarkts/native/meson.build +++ b/arkoala-arkts/libarkts/native/meson.build @@ -50,8 +50,8 @@ sources += [ interop_src / 'napi/convertors-napi.cc', ] -node_addon_api = run_command('node', '-p', 'require.resolve("node-addon-api/package.json").slice(0, -12)', check: true).stdout().strip() -node_api_headers = run_command('node', '-p', 'require.resolve("node-api-headers/package.json").slice(0, -12)', check: true).stdout().strip() +node_addon_api = '../node_modules/node-addon-api' +node_api_headers = '../node_modules/node-api-headers' include_dirs += [ interop_src / 'napi', diff --git a/arkoala-arkts/libarkts/native/src/es2panda_lib.cc b/arkoala-arkts/libarkts/native/src/es2panda_lib.cc index 957c29332..32030e7c3 100644 --- a/arkoala-arkts/libarkts/native/src/es2panda_lib.cc +++ b/arkoala-arkts/libarkts/native/src/es2panda_lib.cc @@ -104,6 +104,13 @@ KNativePointer impl_CreateConfig(KInt argc, KStringArray argvPtr) { } KOALA_INTEROP_2(CreateConfig, KNativePointer, KInt, KStringArray) +KNativePointer impl_DestroyConfig(KNativePointer configPtr) { + auto config = reinterpret_cast(configPtr); + GetImpl()->DestroyConfig(config); + return nullptr; +} +KOALA_INTEROP_1(DestroyConfig, KNativePointer, KNativePointer) + KNativePointer impl_CreateContextFromString(KNativePointer configPtr, KStringPtr sourcePtr, KStringPtr filenamePtr) { auto source = getString(sourcePtr); auto filename = getString(filenamePtr); @@ -112,6 +119,13 @@ KNativePointer impl_CreateContextFromString(KNativePointer configPtr, KStringPtr } KOALA_INTEROP_3(CreateContextFromString, KNativePointer, KNativePointer, KStringPtr, KStringPtr) +KNativePointer impl_DestroyContext(KNativePointer contextPtr) { + auto context = reinterpret_cast(contextPtr); + GetImpl()->DestroyContext(context); + return nullptr; +} +KOALA_INTEROP_1(DestroyContext, KNativePointer, KNativePointer) + KNativePointer impl_ProceedToState(KNativePointer contextPtr, KInt state) { auto context = reinterpret_cast(contextPtr); return GetImpl()->ProceedToState(context, intToState(state)); @@ -169,6 +183,14 @@ KNativePointer impl_CreateIdentifier1(KNativePointer contextPtr, KStringPtr name } KOALA_INTEROP_2(CreateIdentifier1, KNativePointer, KNativePointer, KStringPtr) +KNativePointer impl_IdentifierSetName(KNativePointer contextPtr, KNativePointer nodePtr, KStringPtr namePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + GetImpl()->IdentifierSetName(context, node, getStringCopy(namePtr)); + return node; +} +KOALA_INTEROP_3(IdentifierSetName, KNativePointer, KNativePointer, KNativePointer, KStringPtr) + KNativePointer impl_CreateIdentifier2(KNativePointer contextPtr, KStringPtr namePtr, KNativePointer typeAnnotationPtr) { auto context = reinterpret_cast(contextPtr); auto typeAnnotation = reinterpret_cast(typeAnnotationPtr); @@ -191,18 +213,32 @@ KNativePointer impl_CreateETSFunctionTypeIr(KNativePointer contextPtr, KNativePo } KOALA_INTEROP_3(CreateETSFunctionTypeIr, KNativePointer, KNativePointer, KNativePointer, KInt) +KNativePointer impl_CreateNumberLiteral(KNativePointer contextPtr, KStringPtr strPtr) { + auto context = reinterpret_cast(contextPtr); + + return GetImpl()->CreateNumberLiteral(context, getStringCopy(strPtr)); +} +KOALA_INTEROP_2(CreateNumberLiteral, KNativePointer, KNativePointer, KStringPtr) + KNativePointer impl_CreateStringLiteral(KNativePointer contextPtr, KStringPtr stringPtr) { auto context = reinterpret_cast(contextPtr); return GetImpl()->CreateStringLiteral1(context, getStringCopy(stringPtr)); } KOALA_INTEROP_2(CreateStringLiteral, KNativePointer, KNativePointer, KStringPtr) -KNativePointer impl_StringLiteralString(KNativePointer contextPtr, KNativePointer nodePtr) { +KNativePointer impl_StringLiteralStrConst(KNativePointer contextPtr, KNativePointer nodePtr) { auto context = reinterpret_cast(contextPtr); auto node = reinterpret_cast(nodePtr); return new string(GetImpl()->StringLiteralStrConst(context, node)); } -KOALA_INTEROP_2(StringLiteralString, KNativePointer, KNativePointer, KNativePointer) +KOALA_INTEROP_2(StringLiteralStrConst, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_NumberLiteralStrConst(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + return new string(GetImpl()->NumberLiteralStrConst(context, node)); +} +KOALA_INTEROP_2(NumberLiteralStrConst, KNativePointer, KNativePointer, KNativePointer) KNativePointer impl_CreateMethodDefinition( KNativePointer contextPtr, @@ -272,12 +308,18 @@ enum AstNodeKind { BinaryExpression = 20, FunctionExpression = 21, ScriptFunction = 22, + VariableDeclarator = 23, + TSTypeParameter = 24, + ETSPrimitiveType = 25, + AssignmentExpression = 26, + ETSTypeReference = 27, + TSUnionType = 28, + ETSUnionType = 29, + ClassDefinition = 30, + ETSTypeReferencePart = 31, }; static KInt GetKind(es2panda_Context* context, es2panda_AstNode* node) { - if (GetImpl()->AstNodeIsProgramConst(context, node)) { - return AstNodeKind::Program; - } if (GetImpl()->IsIdentifier(node)) { return AstNodeKind::Identifier; } @@ -341,7 +383,37 @@ static KInt GetKind(es2panda_Context* context, es2panda_AstNode* node) { if (GetImpl()->IsScriptFunction(node)) { return AstNodeKind::ScriptFunction; } + if (GetImpl()->IsVariableDeclarator(node)) { + return AstNodeKind::VariableDeclarator; + } + if (GetImpl()->IsTSTypeParameter(node)) { + return AstNodeKind::TSTypeParameter; + } + if (GetImpl()->IsETSPrimitiveType(node)) { + return AstNodeKind::ETSPrimitiveType; + } + if (GetImpl()->IsAssignmentExpression(node)) { + return AstNodeKind::AssignmentExpression; + } + if (GetImpl()->IsETSTypeReference(node)) { + return AstNodeKind::ETSTypeReference; + } + if (GetImpl()->IsTSUnionType(node)) { + return AstNodeKind::TSUnionType; + } + if (GetImpl()->IsETSUnionType(node)) { + return AstNodeKind::ETSUnionType; + } + if (GetImpl()->IsClassDefinition(node)) { + return AstNodeKind::ClassDefinition; + } + if (GetImpl()->IsETSTypeReferencePart(node)) { + return AstNodeKind::ETSTypeReferencePart; + } + if (GetImpl()->AstNodeIsProgramConst(context, node)) { + return AstNodeKind::Program; + } return 0; } @@ -375,6 +447,15 @@ KNativePointer impl_BlockStatementStatements(KNativePointer contextPtr, KNativeP } KOALA_INTEROP_2(BlockStatementStatements, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_VariableDeclarationDeclaratorsConst(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + size_t n; + auto declarators = GetImpl()->VariableDeclarationDeclaratorsConst(context, node, &n); + return new vector(declarators, declarators + n); +} +KOALA_INTEROP_2(VariableDeclarationDeclaratorsConst, KNativePointer, KNativePointer, KNativePointer) + KNativePointer impl_BlockStatementUpdateStatements(KNativePointer contextPtr, KNativePointer nodePtr, KNativePointerArray statementListPtr, KInt statementListLen, KNativePointer returnTypeLenPtr) { auto context = reinterpret_cast(contextPtr); auto node = reinterpret_cast(nodePtr); @@ -401,6 +482,14 @@ KNativePointer impl_ClassDefinitionBody(KNativePointer contextPtr, KNativePointe } KOALA_INTEROP_2(ClassDefinitionBody, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_ClassDefinitionTypeParamsConst(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return const_cast(GetImpl()->ClassDefinitionTypeParamsConst(context, node)); +} +KOALA_INTEROP_2(ClassDefinitionTypeParamsConst, KNativePointer, KNativePointer, KNativePointer) + KNativePointer impl_FunctionDeclarationFunction(KNativePointer contextPtr, KNativePointer nodePtr) { auto context = reinterpret_cast(contextPtr); auto node = reinterpret_cast(nodePtr); @@ -408,6 +497,14 @@ KNativePointer impl_FunctionDeclarationFunction(KNativePointer contextPtr, KNati } KOALA_INTEROP_2(FunctionDeclarationFunction, KNativePointer, KNativePointer, KNativePointer) +KBoolean impl_FunctionDeclarationIsAnonymousConst(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->FunctionDeclarationIsAnonymousConst(context, node); +} +KOALA_INTEROP_2(FunctionDeclarationIsAnonymousConst, KBoolean, KNativePointer, KNativePointer) + KNativePointer impl_ScriptFunctionParams(KNativePointer contextPtr, KNativePointer nodePtr) { auto context = reinterpret_cast(contextPtr); auto node = reinterpret_cast(nodePtr); @@ -417,6 +514,22 @@ KNativePointer impl_ScriptFunctionParams(KNativePointer contextPtr, KNativePoint } KOALA_INTEROP_2(ScriptFunctionParams, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_ScriptFunctionTypeParams(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->ScriptFunctionTypeParams(context, node); +} +KOALA_INTEROP_2(ScriptFunctionTypeParams, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_ScriptFunctionReturnTypeAnnotation(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->ScriptFunctionReturnTypeAnnotation(context, node); +} +KOALA_INTEROP_2(ScriptFunctionReturnTypeAnnotation, KNativePointer, KNativePointer, KNativePointer) + KNativePointer impl_ScriptFunctionId(KNativePointer contextPtr, KNativePointer nodePtr) { auto context = reinterpret_cast(contextPtr); auto node = reinterpret_cast(nodePtr); @@ -456,13 +569,124 @@ KNativePointer impl_UpdateFunctionDeclaration( KOALA_INTEROP_4(UpdateFunctionDeclaration, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KBoolean) // TODO: add param initializer -KNativePointer impl_CreateETSParameterExpression(KNativePointer contextPtr, KNativePointer identifierPtr) { +KNativePointer impl_CreateETSParameterExpression(KNativePointer contextPtr, KNativePointer identifierPtr, KNativePointer initializerPtr) { auto context = reinterpret_cast(contextPtr); auto identifier = reinterpret_cast(identifierPtr); + auto initializer = reinterpret_cast(initializerPtr); + + return GetImpl()->CreateETSParameterExpression(context, identifier, initializer); +} +KOALA_INTEROP_3(CreateETSParameterExpression, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateTSTypeParameterDeclaration( + KNativePointer contextPtr, + KNativePointerArray paramsPtr, + KInt paramsLen, + KInt requiredParams +) { + auto context = reinterpret_cast(contextPtr); + auto params = reinterpret_cast(paramsPtr); + + return GetImpl()->CreateTSTypeParameterDeclaration(context, params, paramsLen, requiredParams); +} +KOALA_INTEROP_4(CreateTSTypeParameterDeclaration, KNativePointer, KNativePointer, KNativePointerArray, KInt, KInt) + +KNativePointer impl_TSTypeParameterDeclarationParamsConst(KNativePointer contextPtr, KNativePointer nodePtr, KNativePointer returnLen) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + std::size_t params_len = 0; + auto params = GetImpl()->TSTypeParameterDeclarationParamsConst(context, node, ¶ms_len); + return new std::vector(params, params + params_len); +} +KOALA_INTEROP_3(TSTypeParameterDeclarationParamsConst, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateVariableDeclaration( + KNativePointer contextPtr, + KInt kindT, + KNativePointerArray declaratorsPtr, + KInt declaratorsLen, + KBoolean declareT +) { + auto context = reinterpret_cast(contextPtr); + auto kind = static_cast(kindT); + auto declarators = reinterpret_cast(declaratorsPtr); + auto declare = static_cast(declareT); + + return GetImpl()->CreateVariableDeclaration(context, kind, declarators, declaratorsLen, declare); +} +KOALA_INTEROP_5(CreateVariableDeclaration, KNativePointer, KNativePointer, KInt, KNativePointerArray, KInt, KBoolean) + +KNativePointer impl_UpdateVariableDeclaration( + KNativePointer contextPtr, + KNativePointer originalPtr, + KInt kindT, + KNativePointerArray declaratorsPtr, + KInt declaratorsLen, + KBoolean declareT +) { + auto context = reinterpret_cast(contextPtr); + auto original = reinterpret_cast(originalPtr); + auto kind = static_cast(kindT); + auto declarators = reinterpret_cast(declaratorsPtr); + auto declare = static_cast(declareT); + + return GetImpl()->UpdateVariableDeclaration(context, original, kind, declarators, declaratorsLen, declare); +} +KOALA_INTEROP_6(UpdateVariableDeclaration, KNativePointer, KNativePointer, KNativePointer, KInt, KNativePointerArray, KInt, KBoolean) + +KNativePointer impl_CreateVariableDeclarator( + KNativePointer contextPtr, + KInt flagT, + KNativePointer identPtr +) { + auto context = reinterpret_cast(contextPtr); + auto flag = static_cast(flagT); + auto ident = reinterpret_cast(identPtr); + + return GetImpl()->CreateVariableDeclarator(context, flag, ident); +} +KOALA_INTEROP_3(CreateVariableDeclarator, KNativePointer, KNativePointer, KInt, KNativePointer) - return GetImpl()->CreateETSParameterExpression(context, identifier, nullptr); +KNativePointer impl_VariableDeclaratorSetInit(KNativePointer contextPtr, KNativePointer nodePtr, KNativePointer initPtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto init = reinterpret_cast(initPtr); + + GetImpl()->VariableDeclaratorSetInit(context, node, init); + return node; +} +KOALA_INTEROP_3(VariableDeclaratorSetInit, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_VariableDeclaratorId(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->VariableDeclaratorId(context, node); +} +KOALA_INTEROP_2(VariableDeclaratorId, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateTSTypeParameter( + KNativePointer contextPtr, + KNativePointer namePtr, + KNativePointer constraintPtr, + KNativePointer defaultTypePtr +) { + auto context = reinterpret_cast(contextPtr); + auto name = reinterpret_cast(namePtr); + auto constraint = reinterpret_cast(constraintPtr); + auto defaultType = reinterpret_cast(defaultTypePtr); + + return GetImpl()->CreateTSTypeParameter(context, name, constraint, defaultType); } -KOALA_INTEROP_2(CreateETSParameterExpression, KNativePointer, KNativePointer, KNativePointer) +KOALA_INTEROP_4(CreateTSTypeParameter, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_TSTypeParameterName(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->TSTypeParameterName(context, node); +} +KOALA_INTEROP_2(TSTypeParameterName, KNativePointer, KNativePointer, KNativePointer) KNativePointer impl_ETSParameterExpressionIdent(KNativePointer contextPtr, KNativePointer nodePtr) { auto context = reinterpret_cast(contextPtr); @@ -656,7 +880,10 @@ KNativePointer impl_UpdateCallExpression( auto optional = static_cast(optionalT); auto trailingComma = static_cast(trailingCommaT); - return GetImpl()->UpdateCallExpression(context, node, callee, arguments, argumentsLen, typeParams, optional, trailingComma); + // auto nn = GetImpl()->UpdateCallExpression(context, node, callee, arguments, argumentsLen, typeParams, optional, trailingComma); + auto nn = GetImpl()->CreateCallExpression(context, callee, arguments, argumentsLen, typeParams, optional, trailingComma); + GetImpl()->AstNodeSetOriginalNode(context, nn, node); + return nn; } KOALA_INTEROP_8(UpdateCallExpression, KNativePointer, KNativePointer, KNativePointer, KNativePointer, KNativePointerArray, KInt, KNativePointer, KBoolean, KBoolean) @@ -710,6 +937,50 @@ KNativePointer impl_CreateFunctionSignature( } KOALA_INTEROP_5(CreateFunctionSignature, KNativePointer, KNativePointer, KNativePointer, KNativePointerArray, KInt, KNativePointer) +KNativePointer impl_CreateTSUnionType( + KNativePointer contextPtr, + KNativePointerArray typesPtr, + KInt typesLen +) { + auto context = reinterpret_cast(contextPtr); + auto types = reinterpret_cast(typesPtr); + + return GetImpl()->CreateTSUnionType(context, types, typesLen); +} +KOALA_INTEROP_3(CreateTSUnionType, KNativePointer, KNativePointer, KNativePointerArray, KInt) + +KNativePointer impl_TSUnionTypeTypesConst(KNativePointer contextPtr, KNativePointer nodePtr, KNativePointer returnLen) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + std::size_t params_len = 0; + auto params = GetImpl()->TSUnionTypeTypesConst(context, node, ¶ms_len); + + return new std::vector(params, params + params_len); +} +KOALA_INTEROP_3(TSUnionTypeTypesConst, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_CreateETSUnionTypeIr( + KNativePointer contextPtr, + KNativePointerArray typesPtr, + KInt typesLen +) { + auto context = reinterpret_cast(contextPtr); + auto types = reinterpret_cast(typesPtr); + + return GetImpl()->CreateETSUnionTypeIr(context, types, typesLen); +} +KOALA_INTEROP_3(CreateETSUnionTypeIr, KNativePointer, KNativePointer, KNativePointerArray, KInt) + +KNativePointer impl_ETSUnionTypeIrTypesConst(KNativePointer contextPtr, KNativePointer nodePtr, KNativePointer returnLen) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + std::size_t params_len = 0; + auto params = GetImpl()->ETSUnionTypeIrTypesConst(context, node, ¶ms_len); + + return new std::vector(params, params + params_len); +} +KOALA_INTEROP_3(ETSUnionTypeIrTypesConst, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + KNativePointer impl_CreateScriptFunction( KNativePointer contextPtr, KNativePointer databodyPtr, @@ -904,6 +1175,31 @@ KNativePointer impl_AstNodeSetParent( } KOALA_INTEROP_3(AstNodeSetParent, KNativePointer, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_AstNodeSetOriginalNode( + KNativePointer contextPtr, + KNativePointer astPtr, + KNativePointer originalNodePtr +) { + auto context = reinterpret_cast(contextPtr); + auto ast = reinterpret_cast(astPtr); + auto originalNode = reinterpret_cast(originalNodePtr); + + GetImpl()->AstNodeSetOriginalNode(context, ast, originalNode); + return ast; +} +KOALA_INTEROP_3(AstNodeSetOriginalNode, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + +KNativePointer impl_AstNodeOriginalNodeConst( + KNativePointer contextPtr, + KNativePointer astPtr +) { + auto context = reinterpret_cast(contextPtr); + auto ast = reinterpret_cast(astPtr); + + return GetImpl()->AstNodeOriginalNodeConst(context, ast); +} +KOALA_INTEROP_2(AstNodeOriginalNodeConst, KNativePointer, KNativePointer, KNativePointer) + KNativePointer impl_AstNodeClone( KNativePointer contextPtr, KNativePointer astPtr, @@ -1072,6 +1368,14 @@ KNativePointer impl_UpdateIdentifier2(KNativePointer contextPtr, KNativePointer } KOALA_INTEROP_4(UpdateIdentifier2, KNativePointer, KNativePointer, KNativePointer, KStringPtr, KNativePointer) +KBoolean impl_IdentifierIsPrivateIdentConst(KNativePointer contextPtr, KNativePointer nodePtr) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + + return GetImpl()->IdentifierIsPrivateIdentConst(context, node); +} +KOALA_INTEROP_2(IdentifierIsPrivateIdentConst, KBoolean, KNativePointer, KNativePointer) + KNativePointer impl_IdentifierSetReference(KNativePointer contextPtr, KNativePointer nodePtr, KBoolean isReferenceK) { auto context = reinterpret_cast(contextPtr); auto node = reinterpret_cast(nodePtr); @@ -1242,6 +1546,14 @@ KNativePointer impl_VarBinderSetContext(KNativePointer contextPtr) { } KOALA_INTEROP_1(VarBinderSetContext, KNativePointer, KNativePointer) +KNativePointer impl_CreateClassDeclaration(KNativePointer contextPtr, KNativePointer defPtr) { + auto context = reinterpret_cast(contextPtr); + auto def = reinterpret_cast(defPtr); + + return GetImpl()->CreateClassDeclaration(context, def); +} +KOALA_INTEROP_2(CreateClassDeclaration, KNativePointer, KNativePointer, KNativePointer) + KNativePointer impl_UpdateClassDeclaration(KNativePointer contextPtr, KNativePointer originalPtr, KNativePointer defPtr) { auto context = reinterpret_cast(contextPtr); auto original = reinterpret_cast(originalPtr); @@ -1251,6 +1563,20 @@ KNativePointer impl_UpdateClassDeclaration(KNativePointer contextPtr, KNativePoi } KOALA_INTEROP_3(UpdateClassDeclaration, KNativePointer, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_ClassDefinitionSetTypeParams( + KNativePointer contextPtr, + KNativePointer nodePtr, + KNativePointer typeParamsPtr +) { + auto context = reinterpret_cast(contextPtr); + auto node = reinterpret_cast(nodePtr); + auto typeParams = reinterpret_cast(typeParamsPtr); + + GetImpl()->ClassDefinitionSetTypeParams(context, node, typeParams); + return node; +} +KOALA_INTEROP_3(ClassDefinitionSetTypeParams, KNativePointer, KNativePointer, KNativePointer, KNativePointer) + KNativePointer impl_ClassDefinitionLanguageConst( KNativePointer contextPtr, KNativePointer nodePtr @@ -1273,6 +1599,27 @@ KNativePointer impl_ClassDefinitionIdent( } KOALA_INTEROP_2(ClassDefinitionIdent, KNativePointer, KNativePointer, KNativePointer) +KNativePointer impl_CreateClassDefinition1( + KNativePointer contextPtr, + KNativePointer identPtr, + KNativePointerArray bodyPtr, + KInt bodyLenT, + KInt modifiersT, + KInt flagsT, + KNativePointer langT +) { + auto context = reinterpret_cast(contextPtr); + auto ident = reinterpret_cast(identPtr); + auto body = reinterpret_cast(bodyPtr); + auto bodyLen = static_cast(bodyLenT); + auto modifiers = Es2pandaClassDefinitionModifiers(modifiersT); + auto flags = Es2pandaModifierFlags(flagsT); + auto lang = reinterpret_cast(langT); + + return GetImpl()->CreateClassDefinition1(context, ident, body, bodyLen, modifiers, flags, lang); +} +KOALA_INTEROP_7(CreateClassDefinition1, KNativePointer, KNativePointer, KNativePointer, KNativePointerArray, KInt, KInt, KInt, KNativePointer) + KNativePointer impl_UpdateClassDefinition1( KNativePointer contextPtr, KNativePointer originalPtr, diff --git a/arkoala-arkts/libarkts/package.json b/arkoala-arkts/libarkts/package.json index 42239d8bd..c910549a1 100644 --- a/arkoala-arkts/libarkts/package.json +++ b/arkoala-arkts/libarkts/package.json @@ -23,7 +23,8 @@ "compile:koala:interop": "cd ../../interop && npm run compile", "compile:native": "cd native && meson setup build_es2panda && cd build_es2panda && meson compile", "compile": "npm run compile:koala:interop && npm run compile:native", - "test": "npm run compile && backend=es2panda TS_NODE_PROJECT=./test/tsconfig.json mocha -r tsconfig-paths/register --config .mocha.json --reporter-option maxDiffSize=262144", + "test": "npm run compile && backend=es2panda TS_NODE_PROJECT=./test/tsconfig.json mocha -r tsconfig-paths/register --config .mocha.json --reporter-option maxDiffSize=0", + "test:all": "STATE_CHECKED=1 TEST_BIN=1 npm run test", "compatible": "cd compatible && npx webpack --config arkts.webpack.config.js", "webpack": "npm run compile && npm run compatible && npx webpack --config es2panda.webpack.config.js", "run:dev": "npm run run && backend=es2panda node build/api/es2panda.js", diff --git a/arkoala-arkts/libarkts/src/NativeModule.ts b/arkoala-arkts/libarkts/src/NativeModule.ts index d527d2681..5c7ce76a7 100644 --- a/arkoala-arkts/libarkts/src/NativeModule.ts +++ b/arkoala-arkts/libarkts/src/NativeModule.ts @@ -27,7 +27,9 @@ export interface NativeModule { _AstDumperModifierToString(context: KNativePointer, dumper: KNativePointer, flags: KInt): KNativePointer _CreateConfig(argc: number, argv: string[]): KNativePointer + _DestroyConfig(config: KNativePointer): void _CreateContextFromString(config: KNativePointer, source: String, filename: String): KNativePointer + _DestroyContext(context: KNativePointer): void _ProceedToState(context: KNativePointer, state: number): void _ContextProgram(context: KNativePointer): KNativePointer _ProgramAst(program: KNativePointer): KNativePointer @@ -44,12 +46,12 @@ export interface NativeModule { _SourceFileGetChildren(node: KNativePointer): KNativePointer _BlockGetStatements(node: KNativePointer): KNativePointer - _FunctionDeclarationGetIdentifier(node: KNativePointer): KNativePointer - _FunctionDeclarationGetBlock(node: KNativePointer): KNativePointer + _FunctionDeclarationIsAnonymousConst(context: KNativePointer, node: KNativePointer): KBoolean _ExpressionStatementGetExpression(context: KNativePointer, node: KNativePointer): KNativePointer _CallExpressionArguments(context: KNativePointer, node: KNativePointer, returnLen: KNativePointer): KNativePointer _CallExpressionCallee(context: KNativePointer, node: KNativePointer): KNativePointer _IdentifierGetText(node: KNativePointer): KNativePointer + _IdentifierIsPrivateIdentConst(context: KNativePointer, node: KNativePointer): KBoolean _PropertyAccessExpressionGetExpression(node: KNativePointer): KNativePointer _PropertyAccessExpressionGetName(node: KNativePointer): KNativePointer @@ -67,11 +69,14 @@ export interface NativeModule { _ScriptFunctionSetScope(context: KNativePointer, ast: KNativePointer, scope: KNativePointer): KNativePointer _ScriptFunctionDeclareConst(context: KNativePointer, node: KNativePointer): KBoolean _ScriptFunctionFlagsConst(context: KNativePointer, node: KNativePointer): KInt + _ScriptFunctionTypeParams(context: KNativePointer, node: KNativePointer): KNativePointer + _ScriptFunctionReturnTypeAnnotation(context: KNativePointer, node: KNativePointer): KNativePointer _UpdateBlockStatement(context: KNativePointer, original: KNativePointer, statementList: KNativePointerArray, statementListLen: KInt): KNativePointer _BlockStatementSetScope(context: KNativePointer, node: KNativePointer, scope: KNativePointerArray): void _CreateIdentifier1(context: KNativePointer, name: String): KNativePointer _CreateIdentifier2(context: KNativePointer, name: String, type_annotation: KNativePointer): KNativePointer _IdentifierSetReference(context: KNativePointer, node: KNativePointer, isRef: KBoolean): void + _IdentifierSetName(context: KNativePointer, node: KNativePointer, name: String): void _CreateFunctionDeclaration(context: KNativePointer, func: KNativePointer, isAnon: KBoolean): KNativePointer _UpdateFunctionDeclaration(context: KNativePointer, node: KNativePointer, func: KNativePointer, isAnon: KBoolean): KNativePointer _CreateReturnStatement1(context: KNativePointer, argument: KNativePointer): KNativePointer @@ -115,7 +120,7 @@ export interface NativeModule { _CreateExpressionStatement(context: KNativePointer, expr: KNativePointer): KNativePointer _UpdateExpressionStatement(context: KNativePointer, node: KNativePointer, expr: KNativePointer): KNativePointer - _CreateETSParameterExpression(context: KNativePointer, identifier: KNativePointer): KNativePointer + _CreateETSParameterExpression(context: KNativePointer, identifier: KNativePointer, initializer: KNativePointer): KNativePointer _CreateETSPrimitiveType(context: KNativePointer, type: KInt): KNativePointer _CreateETSTypeReference(context: KNativePointer, part: KNativePointer): KNativePointer _CreateETSTypeReferencePart(context: KNativePointer, name: KNativePointer, typeParams: KNativePointer, prev: KNativePointer): KNativePointer @@ -123,9 +128,27 @@ export interface NativeModule { _IsIdentifier(node: KNativePointer): KBoolean _IdentifierName(context: KNativePointer, node: KNativePointer): KNativePointer _ETSParameterExpressionIdent(context: KNativePointer, node: KNativePointer): KNativePointer + _CreateTSTypeParameterDeclaration(context: KNativePointer, params: KNativePointerArray, paramsLen: KInt, requiredParams: KInt): KNativePointer + _TSTypeParameterDeclarationParamsConst(context: KNativePointer, node: KNativePointer, returnTypeLen: KInt): KNativePointer + _CreateTSTypeParameter(context: KNativePointer, name: KNativePointer, constraint: KNativePointer, defaultType: KNativePointer): KNativePointer + _TSTypeParameterName(context: KNativePointer, node: KNativePointer): KNativePointer + + _CreateTSUnionType(context: KNativePointer, types: KNativePointerArray, typesLen: KInt): KNativePointer + _TSUnionTypeTypesConst(context: KNativePointer, node: KNativePointer, returnTypeLen: KNativePointer): KNativePointer + _CreateETSUnionTypeIr(context: KNativePointer, types: KNativePointerArray, typesLen: KInt): KNativePointer + _ETSUnionTypeIrTypesConst(context: KNativePointer, node: KNativePointer, returnTypeLen: KNativePointer): KNativePointer + + _CreateVariableDeclaration(context: KNativePointer, kind: KInt, declarators: KNativePointerArray, declaratorsLen: KInt, declare: KBoolean): KNativePointer + _UpdateVariableDeclaration(context: KNativePointer, original: KNativePointer, kind: KInt, declarators: KNativePointerArray, declaratorsLen: KInt, declare: KBoolean): KNativePointer + _CreateVariableDeclarator(context: KNativePointer, flag: KInt, ident: KNativePointer): KNativePointer + _VariableDeclarationDeclaratorsConst(context: KNativePointer, node: KNativePointer): KNativePointer + _VariableDeclaratorId(context: KNativePointer, node: KNativePointer): KNativePointer + _VariableDeclaratorSetInit(context: KNativePointer, node: KNativePointer, init: KNativePointer): void _CreateStringLiteral(context: KNativePointer, string: string): KNativePointer - _StringLiteralString(context: KNativePointer, node: KNativePointer): KNativePointer + _CreateNumberLiteral(context: KNativePointer, string: string): KNativePointer + _NumberLiteralStrConst(context: KNativePointer, node: KNativePointer): KNativePointer + _StringLiteralStrConst(context: KNativePointer, node: KNativePointer): KNativePointer _GetKind(context: KNativePointer, node: KNativePointer): KInt @@ -136,7 +159,11 @@ export interface NativeModule { _ClassDefinitionBody(context: KNativePointer, node: KNativePointer): KNativePointer _ClassDefinitionLanguageConst(context: KNativePointer, node: KNativePointer): KNativePointer _ClassDefinitionIdent(context: KNativePointer, node: KNativePointer): KNativePointer + _ClassDefinitionTypeParamsConst(context: KNativePointer, node: KNativePointer): KNativePointer + _CreateClassDeclaration(context: KNativePointer, def: KNativePointer): KNativePointer _UpdateClassDeclaration(context: KNativePointer, original: KNativePointer, def: KNativePointer): KNativePointer + _CreateClassDefinition1(context: KNativePointer, ident: KNativePointer, body: KNativePointerArray, bodyLen: KInt, modifiers: KInt, flags: KInt, lang: KNativePointer): KNativePointer + _ClassDefinitionSetTypeParams(context: KNativePointer, ast: KNativePointer, typeParams: KNativePointer): void _UpdateClassDefinition1(context: KNativePointer, original: KNativePointer, ident: KNativePointer, body: KNativePointerArray, bodyLen: KInt, modifiers: KInt, flags: KInt, lang: KNativePointer): KNativePointer _CreateETSFunctionTypeIr(context: KNativePointer, signature: KNativePointer, funcFlags: KInt): KNativePointer @@ -145,6 +172,8 @@ export interface NativeModule { _AstNodeDumpEtsSrcConst(context: KNativePointer, node: KNativePointer): KNativePointer _AstNodeUpdateChildren(context: KNativePointer, node: KNativePointer): void _AstNodeUpdateAll(context: KNativePointer, node: KNativePointer): void + _AstNodeSetOriginalNode(context: KNativePointer, ast: KNativePointer, originalNode: KNativePointer): void + _AstNodeOriginalNodeConst(context: KNativePointer, ast: KNativePointer): KNativePointer _VarBinderSetProgram(context: KNativePointer): void _VarBinderSetContext(context: KNativePointer): void diff --git a/arkoala-arkts/libarkts/src/arkts/arktsNodeByEtsNode.ts b/arkoala-arkts/libarkts/src/arkts/arktsNodeByEtsNode.ts new file mode 100644 index 000000000..72c2f8eac --- /dev/null +++ b/arkoala-arkts/libarkts/src/arkts/arktsNodeByEtsNode.ts @@ -0,0 +1,88 @@ +/* + * Copyright (c) 2022-2023 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 "." +import * as ets from "./typesEts" +import { throwError } from "./utilities" +import { es2pandaKind } from "./enums" + +type arktsKindsType = + | { new (node: ets.Node): arkts.Node } + | { new (node: ets.Identifier): arkts.Identifier } + | { new (node: ets.Program): arkts.SourceFile } + | { new (node: ets.StringLiteral): arkts.StringLiteral } + | { new (node: ets.NumberLiteral): arkts.NumericLiteral } + | { new (node: ets.ExpressionStatement): arkts.ExpressionStatement } + | { new (node: ets.FunctionDeclaration): arkts.FunctionDeclaration } + | { new (node: ets.ReturnStatement): arkts.ReturnStatement } + | { new (node: ets.ETSParameterExpression): arkts.ParameterDeclaration } + | { new (node: ets.CallExpression): arkts.CallExpression } + | { new (node: ets.Block): arkts.Block } + | { new (node: ets.ETSTypeReference): arkts.TypeReferenceNode } + | { new (node: ets.TSTypeParameter): arkts.TypeParameterDeclaration} + | { new (node: ets.MemberExpression): arkts.PropertyAccessExpression} + +export function classByEtsNode(node: ets.Node) { + const kinds = + new Map([ + // [es2pandaKind.UnsupportedNode, ets.UnsupportedNode], + + [es2pandaKind.Program, arkts.SourceFile], + [es2pandaKind.Identifier, arkts.Identifier], + [es2pandaKind.StringLiteral, arkts.StringLiteral], + [es2pandaKind.NumberLiteral, arkts.NumericLiteral], + [es2pandaKind.ExpressionStatement, arkts.ExpressionStatement], + [es2pandaKind.FunctionDeclaration, arkts.FunctionDeclaration], + [es2pandaKind.ReturnStatement, arkts.ReturnStatement], + [es2pandaKind.ETSParameterExpression, arkts.ParameterDeclaration], + [es2pandaKind.CallExpression, arkts.CallExpression], + [es2pandaKind.Block, arkts.Block], + [es2pandaKind.ETSTypeReference, arkts.TypeReferenceNode], + [es2pandaKind.TSTypeParameter, arkts.TypeParameterDeclaration], + [es2pandaKind.ETSPrimitiveType, arkts.KeywordTypeNode], + [es2pandaKind.MemberExpression, arkts.PropertyAccessExpression], + + // [es2pandaKind.Block, arkts.Block], + // [es2pandaKind.MethodDeclaration, arkts.MethodDeclaration], + // [es2pandaKind.ClassDeclaration, arkts.ClassDeclaration], + // [es2pandaKind.FunctionDeclaration, arkts.FunctionDeclaration], + // [es2pandaKind.PropertyDeclaration, arkts.PropertyDeclaration], + // [es2pandaKind.ETSFunctionType, arkts.FunctionTypeNode], + // [es2pandaKind.CallExpression, arkts.CallExpression], + // [es2pandaKind.ExpressionStatement, arkts.ExpressionStatement], + // [es2pandaKind.MemberExpression, arkts.PropertyAccessExpression], + // [es2pandaKind.ArrowFunctionExpression, arkts.ArrowFunction], + // [es2pandaKind.ReturnStatement, arkts.ReturnStatement], + // [es2pandaKind.Parameter, arkts.ParameterDeclaration], + // [es2pandaKind.ETSParameterExpression, arkts.ParameterDeclaration], + // [es2pandaKind.NumberLiteral, arkts.NumericLiteral], + // [es2pandaKind.VariableDeclaration, arkts.VariableStatement], + // [es2pandaKind.Program, arkts.SourceFile], + // [es2pandaKind.BinaryExpression, arkts.BinaryExpression], + // [es2pandaKind.VariableDeclarator, arkts.VariableDeclaration], + // [es2pandaKind.TSTypeParameter, arkts.TypeParameterDeclaration], + // [es2pandaKind.ETSPrimitiveType, arkts.ETSPrimitiveType], + // [es2pandaKind.AssignmentExpression, arkts.AssignmentExpression], + // [es2pandaKind.ETSTypeReference, arkts.ETSTypeReference], + // [es2pandaKind.ETSUnionType, arkts.UnionTypeNode], + // [es2pandaKind.ClassDeclaration, ets.UnsupportedNode], + ]) + + return kinds.get(node.kind) ?? throwError('UNSUPPORTED NODE:\n' + arkts.dumpJson(node.peer)) +} + +export function arktsNodeByEtsNode(node: ets.Node): arkts.Node { + return new (classByEtsNode(node))(node as any) +} diff --git a/arkoala-arkts/libarkts/src/arkts/enums.ts b/arkoala-arkts/libarkts/src/arkts/enums.ts index 719dd4d9e..81a9df0cb 100644 --- a/arkoala-arkts/libarkts/src/arkts/enums.ts +++ b/arkoala-arkts/libarkts/src/arkts/enums.ts @@ -39,7 +39,7 @@ export enum es2pandaKind { ClassDeclaration = 5, FunctionDeclaration = 6, PropertyDeclaration = 7, - Parameter = 8, + TSTypeParameterDeclaration = 8, ETSFunctionType = 9, CallExpression = 10, ExpressionStatement = 11, @@ -51,6 +51,18 @@ export enum es2pandaKind { VariableDeclaration = 17, ClassStaticBlock = 18, Program = 19, + BinaryExpression = 20, + FunctionExpression = 21, + ScriptFunction = 22, + VariableDeclarator = 23, + TSTypeParameter = 24, + ETSPrimitiveType = 25, + AssignmentExpression = 26, + ETSTypeReference = 27, + TSUnionType = 28, + ETSUnionType = 29, + ClassDefinition = 30, + ETSTypeReferencePart = 31, }; export enum Es2pandaTokenType { @@ -351,3 +363,61 @@ export enum Es2pandaClassDefinitionModifiers { CLASS_DEFINITION_MODIFIERS_CLASSDEFINITION_CHECKED = 1 << 12, CLASS_DEFINITION_MODIFIERS_DECLARATION_ID_REQUIRED = CLASS_DEFINITION_MODIFIERS_DECLARATION | CLASS_DEFINITION_MODIFIERS_ID_REQUIRED, }; + +export const enum TokenFlags { + None = 0, + /** @internal */ + PrecedingLineBreak = 1 << 0, + /** @internal */ + PrecedingJSDocComment = 1 << 1, + /** @internal */ + Unterminated = 1 << 2, + /** @internal */ + ExtendedUnicodeEscape = 1 << 3, // e.g. `\u{10ffff}` + + Scientific = 1 << 4, // e.g. `10e2` + Octal = 1 << 5, // e.g. `0777` + HexSpecifier = 1 << 6, // e.g. `0x00000000` + BinarySpecifier = 1 << 7, // e.g. `0b0110010000000000` + OctalSpecifier = 1 << 8, // e.g. `0o777` + + /** @internal */ + ContainsSeparator = 1 << 9, // e.g. `0b1100_0101` + /** @internal */ + UnicodeEscape = 1 << 10, // e.g. `\u00a0` + /** @internal */ + ContainsInvalidEscape = 1 << 11, // e.g. `\uhello` + /** @internal */ + HexEscape = 1 << 12, // e.g. `\xa0` + /** @internal */ + ContainsLeadingZero = 1 << 13, // e.g. `0888` + /** @internal */ + ContainsInvalidSeparator = 1 << 14, // e.g. `0_1` + /** @internal */ + PrecedingJSDocLeadingAsterisks = 1 << 15, + /** @internal */ + BinaryOrOctalSpecifier = BinarySpecifier | OctalSpecifier, + /** @internal */ + WithSpecifier = HexSpecifier | BinaryOrOctalSpecifier, + /** @internal */ + StringLiteralFlags = HexEscape | UnicodeEscape | ExtendedUnicodeEscape | ContainsInvalidEscape, + /** @internal */ + NumericLiteralFlags = Scientific | Octal | ContainsLeadingZero | WithSpecifier | ContainsSeparator | ContainsInvalidSeparator, + /** @internal */ + TemplateLiteralLikeFlags = HexEscape | UnicodeEscape | ExtendedUnicodeEscape | ContainsInvalidEscape, + /** @internal */ + IsInvalid = Octal | ContainsLeadingZero | ContainsInvalidSeparator | ContainsInvalidEscape, +} + +export const enum Es2pandaVariableDeclarationKind { + CONST, + LET, + VAR +} + +export const enum VariableDeclaratorFlag { + LET, + CONST, + VAR, + UNKNOWN, +} diff --git a/arkoala-arkts/libarkts/src/arkts/etsNodeByPeer.ts b/arkoala-arkts/libarkts/src/arkts/etsNodeByPeer.ts new file mode 100644 index 000000000..7f56b13bd --- /dev/null +++ b/arkoala-arkts/libarkts/src/arkts/etsNodeByPeer.ts @@ -0,0 +1,63 @@ +/* + * Copyright (c) 2022-2023 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 "." +import * as ets from "./typesEts" +import global from "./global" +import { KNativePointer } from "@koalaui/interop" +import { nativeModule } from "../NativeModule" +import { throwError } from "./utilities" +import { es2pandaKind } from "./enums" + +export function classByPeer(peer: KNativePointer): { new (peer: KNativePointer): ets.Node } { + const kinds = + new Map([ + // [es2pandaKind.UnsupportedNode, ets.UnsupportedNode], + + [es2pandaKind.Program, ets.Program], + [es2pandaKind.Identifier, ets.Identifier], + [es2pandaKind.StringLiteral, ets.StringLiteral], + [es2pandaKind.NumberLiteral, ets.NumberLiteral], + [es2pandaKind.ExpressionStatement, ets.ExpressionStatement], + [es2pandaKind.FunctionDeclaration, ets.FunctionDeclaration], + [es2pandaKind.ScriptFunction, ets.ScriptFunction], + [es2pandaKind.Block, ets.Block], + [es2pandaKind.ReturnStatement, ets.ReturnStatement], + [es2pandaKind.ETSParameterExpression, ets.ETSParameterExpression], + [es2pandaKind.ETSTypeReference, ets.ETSTypeReference], + [es2pandaKind.TSTypeParameterDeclaration, ets.TSTypeParameterDeclaration], + [es2pandaKind.ETSPrimitiveType, ets.ETSPrimitiveType], + [es2pandaKind.CallExpression, ets.CallExpression], + [es2pandaKind.MemberExpression, ets.MemberExpression], + [es2pandaKind.TSTypeParameter, ets.TSTypeParameter], + ]) + + const kind = nativeModule._GetKind(global.context, peer) + return kinds.get(kind) ?? throwError('UNSUPPORTED NODE:\n' + arkts.dumpJson(peer)) +} + +export function etsNodeByPeer(peer: KNativePointer): T { + if (peer === ets.NULLPTR) { + throwError('peer is NULLPTR') + } + return (new (classByPeer(peer))(peer)) as T +} + +export function etsNodeByPeerNullable(peer: KNativePointer): T | undefined { + if (peer === ets.NULLPTR) { + return undefined + } + return (new (classByPeer(peer))(peer)) as T +} diff --git a/arkoala-arkts/libarkts/src/arkts/factory/nodeFactory.ts b/arkoala-arkts/libarkts/src/arkts/factory/nodeFactory.ts index e8b8c1a1b..a136f1dca 100644 --- a/arkoala-arkts/libarkts/src/arkts/factory/nodeFactory.ts +++ b/arkoala-arkts/libarkts/src/arkts/factory/nodeFactory.ts @@ -1,3 +1,4 @@ +import global from "../global" import * as ts from "@koalaui/ets-tsc" import { nativeModule } from "../../NativeModule" import { @@ -6,8 +7,9 @@ import { updateScriptFunction, updateChildren, updateNode, + updateModifiers, withString, - withNodeArray, + // withNodeArray, passToken, passScriptFuncModifier, passScriptFuncModifiers, @@ -15,23 +17,31 @@ import { passModifiers, setModifierFlags, getModifierFlags, + // passTypeParams, + // identifierUpdateTypeAnnotation, + passIdentifier, } from "./utilities" import { + passNodeArray, +} from "../utilities" +import { + SyntaxKind, Es2pandaPrimitiveType, Es2pandaMethodDefinitionKind, Es2pandaModifierFlags, Es2pandaScriptFunctionFlags, Es2pandaMemberExpressionKind, Es2pandaClassDefinitionModifiers, + Es2pandaVariableDeclarationKind, + VariableDeclaratorFlag, } from "../enums" import { // util types: - Global, NULLPTR, NULLPTR_ARRAY, // ts types: - ModifierLike, + Modifier, BinaryOperatorToken, Node, @@ -44,113 +54,254 @@ import { PropertyAccessExpression, ParameterDeclaration, ReturnStatement, - IfStatement, + // IfStatement, ExpressionStatement, CallExpression, - ArrowFunction, + // ArrowFunction, TypeReferenceNode, - BinaryExpression, - ClassDeclaration, + // BinaryExpression, + // ClassDeclaration, FunctionTypeNode, TypeNode, Expression, Statement, SourceFile, - ClassElement, - MethodDeclaration, - ConstructorDeclaration, - - // ets types: - ETSPrimitiveType, + // ClassElement, + // MethodDeclaration, + // ConstructorDeclaration, + TypeParameterDeclaration, + NumericLiteral, + // VariableDeclaration, + // VariableDeclarationList, + // VariableStatement, + // UnionTypeNode, } from "../types" -import { dumpModifiers } from "../utilities" +import * as ets from "../typesEts" // TODO: add flags and base export function createNodeFactory() { return { + createSourceFile, + updateSourceFile, createIdentifier, - createIdentifierWithAnnotation, - updateIdentifier, + // updateIdentifier, createStringLiteral, + createNumericLiteral, createFunctionDeclaration, updateFunctionDeclaration, createParameterDeclaration, - createEtsPrimitiveType, + updateParameterDeclaration, createTypeReferenceNode, + updateTypeReferenceNode, createKeywordTypeNode, createBlock, updateBlock, createExpressionStatement, updateExpressionStatement, createReturnStatement, + updateReturnStatement, createPropertyAccessExpression, updatePropertyAccessExpression, createCallExpression, updateCallExpression, - createIfStatement, - createToken, - createBinaryExpression, - createArrowFunction, - updateSourceFile, - updateClassDeclaration, - createFunctionTypeNode, - createMethodDeclaration, - updateMethodDeclaration, - createConstructorDeclaration, + // createIfStatement, + // updateIfStatement, + // createToken, + // createBinaryExpression, + // updateBinaryExpression, + // createArrowFunction, + // updateArrowFunction, + // createClassDeclaration, + // updateClassDeclaration, + // createFunctionTypeNode, + // updateFunctionTypeNode, + // createMethodDeclaration, + // updateMethodDeclaration, + // createConstructorDeclaration, + createTypeParameterDeclaration, + updateTypeParameterDeclaration, + // createVariableDeclarationList, + // updateVariableDeclarationList, + // createVariableStatement, + // updateVariableStatement, + // createVariableDeclaration, + // updateVariableDeclaration, + // createUnionTypeNode, + // updateUnionTypeNode, + } + + // @api + // TODO: + function createSourceFile(source: string): SourceFile { + const node = ets.Program.create(source) + return new SourceFile(node) + } + + // TODO: fix (now doesn't create a new node) + // @api + // updateSourceFile( + // node: SourceFile, + // statements: readonly Statement[], + // isDeclarationFile?: boolean, + // referencedFiles?: readonly FileReference[], + // typeReferences?: readonly FileReference[], + // hasNoDefaultLib?: boolean, + // libReferences?: readonly FileReference[] + // ): SourceFile; + function updateSourceFile( + node: SourceFile, + statements: readonly Statement[] + ): SourceFile { + node._node.statements = passNodeArray(statements) + return new SourceFile(node._node) } // @api // createIdentifier( // text: string // ): Identifier; - function createIdentifier(name: string): Identifier { - const peer = withString(name, (_name: string) => { - return nativeModule._CreateIdentifier1(Global.context, _name) - }) - updateChildren(peer) + function createIdentifier(text: string): Identifier { + const node = ets.Identifier.create(text) + return new Identifier(node) + } - return new Identifier(peer) + // // @api + // // NOT PROVIDED + // function updateIdentifier(node: Identifier, text: string, typeAnnotation?: TypeNode | undefined): Identifier { + // return new Identifier(text, typeAnnotation?.node) + // } + + // @api + // createStringLiteral( + // text: string, + // isSingleQuote?: boolean + // ): StringLiteral; + function createStringLiteral( + str: string + ): StringLiteral { + const node = ets.StringLiteral.create(str) + return new StringLiteral(node) } // @api - // NOT PROVIDED - function createIdentifierWithAnnotation(name: string, typeAnnotation: Node): Identifier { - const peer = withString(name, (_name: string) => { - return nativeModule._CreateIdentifier2(Global.context, _name, typeAnnotation.peer) + // createNumericLiteral( + // value: string | number, + // numericLiteralFlags: TokenFlags = TokenFlags.None + // ): NumericLiteral { + function createNumericLiteral( + str: string + ): NumericLiteral { + const node = ets.NumberLiteral.create(str) + return new NumericLiteral(node) + } +/* + // @api + // createVariableDeclarationList( + // declarations: readonly VariableDeclaration[], + // flags = NodeFlags.None + // ): VariableDeclarationList + function createVariableDeclarationList( + declarations: readonly VariableDeclaration[], + flags = Es2pandaVariableDeclarationKind.CONST + ): VariableDeclarationList { + const peer = withNodeArray(declarations, _declarators => { + return nativeModule._CreateVariableDeclaration(global.context, flags, _declarators, _declarators.length, false) }) - updateChildren(peer) + return new VariableDeclarationList(updateChildren(peer)) + } - return new Identifier(peer) + // @api + // updateVariableDeclarationList( + // node: VariableDeclarationList, + // declarations: readonly VariableDeclaration[] + // ): VariableDeclarationList + function updateVariableDeclarationList( + node: VariableDeclarationList, + declarations: readonly VariableDeclaration[] + ): VariableDeclarationList { + const updated = createVariableDeclarationList(declarations) + return new VariableDeclarationList(updateNode(updated.peer, node.peer)) } - // TODO: remove this method maybe // @api - // NOT PROVIDED - function updateIdentifier(node: Identifier, name: string, typeAnnotation?: TypeNode): Identifier { - const peer = withString(name, (_name: string) => { - return (typeAnnotation === undefined) ? - nativeModule._UpdateIdentifier1(Global.context, node.peer, _name) : - nativeModule._UpdateIdentifier2(Global.context, node.peer, _name, typeAnnotation.peer) + // createVariableStatement( + // modifiers: readonly ModifierLike[] | undefined, + // declarationList: VariableDeclarationList | readonly VariableDeclaration[] + // ): VariableStatement + function createVariableStatement( + modifiers: readonly Modifier[] | undefined, + declarationList: VariableDeclarationList | readonly VariableDeclaration[] + ): VariableStatement { + const peer = withNodeArray((declarationList instanceof VariableDeclarationList) ? declarationList.declarations : declarationList, _declarators => { + // TODO: fix (const only now) + return nativeModule._CreateVariableDeclaration(global.context, Es2pandaVariableDeclarationKind.CONST, _declarators, _declarators.length, false) }) - updateNode(peer, node.peer) - updateChildren(peer) + // TODO: fix flags + // setModifierFlags(peer, Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC | Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC | Es2pandaModifierFlags.MODIFIER_FLAGS_CONST) + return new VariableStatement(updateChildren(updateModifiers(peer, modifiers))) + } - return new Identifier(peer) + // @api + // updateVariableStatement( + // node: VariableStatement, + // modifiers: readonly ModifierLike[] | undefined, + // declarationList: VariableDeclarationList + // ): VariableStatement + function updateVariableStatement( + node: VariableStatement, + modifiers: readonly Modifier[] | undefined, + declarationList: VariableDeclarationList + ): VariableStatement { + const updated = createVariableStatement(modifiers, declarationList) + return new VariableStatement(updateNode(updated.peer, updateModifiers(node.peer, modifiers))) } // @api - // createStringLiteral( - // text: string, - // isSingleQuote?: boolean - // ): StringLiteral; - function createStringLiteral(s: string): StringLiteral { - const peer = withString(s, (_s: string) => { - return nativeModule._CreateStringLiteral(Global.context, _s) - }) - updateChildren(peer) + // createVariableDeclaration( + // name: string | BindingName, + // exclamationToken: ExclamationToken | undefined, + // type: TypeNode | undefined, + // initializer: Expression | undefined + // ): VariableDeclaration + function createVariableDeclaration( + name: Identifier, + exclamationToken: undefined, + type: TypeNode | undefined, + initializer: Expression | undefined + ): VariableDeclaration { + const ident = identifierUpdateTypeAnnotation(name, type) + updateChildren(ident.peer) + // TODO: fix (const only now) + const peer = nativeModule._CreateVariableDeclarator( + global.context, + VariableDeclaratorFlag.CONST, + ident.peer + ) + if (initializer !== undefined) { + nativeModule._VariableDeclaratorSetInit(global.context, peer, initializer.peer) + } + return new VariableDeclaration(updateChildren(peer)) + } - return new StringLiteral(peer) + // @api + // function updateVariableDeclaration( + // node: VariableDeclaration, + // name: BindingName, + // exclamationToken: ExclamationToken | undefined, + // type: TypeNode | undefined, + // initializer: Expression | undefined + // ): VariableDeclaration + function updateVariableDeclaration( + node: VariableDeclaration, + name: Identifier, + exclamationToken: undefined, + type: TypeNode | undefined, + initializer: Expression | undefined + ): VariableDeclaration { + const updated = createVariableDeclaration(name, exclamationToken, type, initializer) + return new VariableDeclaration(updateNode(updated.peer, node.peer)) } +*/ // @api // createFunctionDeclaration( @@ -163,51 +314,70 @@ export function createNodeFactory() { // body: Block | undefined // ): FunctionDeclaration; function createFunctionDeclaration( - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, asteriskToken: undefined, - name: string | Identifier, - typeParameters: undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], type: TypeNode | undefined, body: Block | undefined ): FunctionDeclaration { - const peer = withString((name instanceof Identifier) ? name.text : name, (_name: string) => { - return withNodeArray(parameters, (_parameters: BigUint64Array) => { - const _context = Global.context - - const _signature = nativeModule._CreateFunctionSignature( - _context, - NULLPTR, - _parameters, - _parameters.length, - type?.peer ?? NULLPTR, - ) - - // TODO: support decl param - const _scriptFunc = createScriptFunction( - body?.peer ?? NULLPTR, - _signature, - (modifiers !== undefined) ? passScriptFuncModifiers(modifiers) : Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE, - Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC | Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC | - ((modifiers !== undefined) ? passModifiers(modifiers) : Es2pandaModifierFlags.MODIFIER_FLAGS_NONE), - false, - nativeModule._CreateIdentifier1(_context, _name) - ) - - const _newFuncDecl = - nativeModule._CreateFunctionDeclaration( - _context, - _scriptFunc, - false - ) - setModifierFlags(_newFuncDecl, getModifierFlags(_scriptFunc)) - updateChildren(_newFuncDecl) - - return _newFuncDecl - }) - }) - - return new FunctionDeclaration(peer) + return new FunctionDeclaration( + ets.FunctionDeclaration.create( + ets.ScriptFunction.create( + body?._node, + ets.FunctionSignature.create( + (typeParameters !== undefined) ? + ets.TSTypeParameterDeclaration.create( + passNodeArray(typeParameters) + ) : + undefined, + passNodeArray(parameters), + type?._node + ), + 0, + passModifiers(modifiers) | Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC | Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC, + body === undefined, + passIdentifier(name) + ), + false + ) + ) + // const peer = withString((name instanceof Identifier) ? name.text : name, (_name: string) => { + // return withNodeArray(parameters, (_parameters: BigUint64Array) => { + // const _context = global.context + + // const _signature = nativeModule._CreateFunctionSignature( + // _context, + // passTypeParams(typeParameters), + // _parameters, + // _parameters.length, + // type?.peer ?? NULLPTR, + // ) + + // const _scriptFunc = createScriptFunction( + // body?.peer ?? NULLPTR, + // _signature, + // passScriptFuncModifiers(modifiers), + // passModifiers(modifiers) | Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC | Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC, + // body === undefined, + // (name !== undefined) ? nativeModule._CreateIdentifier1(_context, _name) : undefined + // ) + + // const _newFuncDecl = + // nativeModule._CreateFunctionDeclaration( + // _context, + // _scriptFunc, + // false + // ) + // setModifierFlags(_newFuncDecl, getModifierFlags(_scriptFunc)) + + // return _newFuncDecl + // }) + // }) + // return new FunctionDeclaration(updateChildren( + // updateModifiers(peer, [...modifiers ?? [], Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC, Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC]) + // )) } // @api @@ -223,63 +393,16 @@ export function createNodeFactory() { // ): FunctionDeclaration; function updateFunctionDeclaration( node: FunctionDeclaration, - modifiers: undefined, + modifiers: readonly Modifier[] | undefined, asteriskToken: undefined, - name: Identifier, - typeParameters: undefined, + name: Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, parameters: readonly ParameterDeclaration[], - type: undefined, + type: TypeNode | undefined, body: Block | undefined ): FunctionDeclaration { - const peer = withString(name.text, (_name: string) => { - return withNodeArray(parameters, (_parameters: BigUint64Array) => { - const _context = Global.context - - const _oldFuncDecl = node.peer - const _oldScriptFunc = nativeModule._FunctionDeclarationFunction( - _context, - _oldFuncDecl - ) - const _oldSignature = nativeModule._ScriptFunctionIrSignature( - _context, - _oldScriptFunc - ) - - const _body = body ? body.peer : NULLPTR - const _signature = nativeModule._CreateFunctionSignature( - _context, - nativeModule._FunctionSignatureTypeParams(_context, _oldSignature), - _parameters, - _parameters.length, - nativeModule._FunctionSignatureReturnType(_context, _oldSignature) - ) - const _scriptFunc = updateScriptFunction( - _oldScriptFunc, - _body, - _signature, - nativeModule._ScriptFunctionFlagsConst(_context, _oldScriptFunc), - nativeModule._AstNodeModifiers(_context, _oldScriptFunc), - false, - nativeModule._UpdateIdentifier1( - _context, - nativeModule._ScriptFunctionId(_context, _oldScriptFunc), - _name - ) - ) - updateNode(_scriptFunc, _oldScriptFunc) - - return nativeModule._UpdateFunctionDeclaration( - _context, - _oldFuncDecl, - _scriptFunc, - false - ) - }) - }) - updateNode(peer, node.peer) - updateChildren(peer) - - return new FunctionDeclaration(peer) + const updated = createFunctionDeclaration(modifiers, undefined, name, typeParameters, parameters, type, body) + return new FunctionDeclaration(updateNode(updated._node, node._node)) } // @api @@ -292,80 +415,203 @@ export function createNodeFactory() { // initializer?: Expression // ): ParameterDeclaration; function createParameterDeclaration( - modifiers: undefined, + modifiers: readonly Modifier[] | undefined, dotDotDotToken: undefined, - name: Identifier, + name: string | Identifier, questionToken?: undefined, type?: TypeNode, - initializer?: undefined + initializer?: Expression ): ParameterDeclaration { - const peer = nativeModule._CreateETSParameterExpression( - Global.context, - (type === undefined) ? - name.peer : - updateIdentifier( - name, - name.text, - type - ).peer + return new ParameterDeclaration( + ets.ETSParameterExpression.create( + ets.Identifier.create( + (name instanceof Identifier) ? name._node.name : name, + type?._node + ), + initializer?._node + ) ) - updateChildren(peer) - return new ParameterDeclaration(peer) + // if (!(name instanceof Identifier)) { + // name = createIdentifier(name) + // } + // name = updateIdentifier( + // name, + // name.text, + // type + // ) + // const peer = nativeModule._CreateETSParameterExpression( + // global.context, + // name.peer, + // initializer?.peer ?? NULLPTR + // ) + // return new ParameterDeclaration(updateChildren(updateModifiers(peer, modifiers))) } - // TODO: maybe remove from api // @api - // NOT PROVIDED - function createEtsPrimitiveType(type: Es2pandaPrimitiveType): TypeNode { - const peer = nativeModule._CreateETSPrimitiveType(Global.context, type) + // function updateParameterDeclaration( + // node: ParameterDeclaration, + // modifiers: readonly ModifierLike[] | undefined, + // dotDotDotToken: DotDotDotToken | undefined, + // name: string | BindingName, + // questionToken: QuestionToken | undefined, + // type: TypeNode | undefined, + // initializer: Expression | undefined, + // ): ParameterDeclaration + function updateParameterDeclaration( + node: ParameterDeclaration, + modifiers: readonly Modifier[] | undefined, + dotDotDotToken: undefined, + name: string | Identifier, + questionToken?: undefined, + type?: TypeNode, + initializer?: Expression + ): ParameterDeclaration { + const updated = createParameterDeclaration(modifiers, dotDotDotToken, name, questionToken, type, initializer) + return new ParameterDeclaration(updateNode(updated._node, node._node)) + } - return new ETSPrimitiveType(peer) + // @api + // createTypeParameterDeclaration( + // modifiers: readonly Modifier[] | undefined, + // name: string | Identifier, + // constraint?: TypeNode, + // defaultType?: TypeNode + // ): TypeParameterDeclaration; + function createTypeParameterDeclaration( + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + constraint?: TypeNode, + defaultType?: TypeNode + ): TypeParameterDeclaration { + return new TypeParameterDeclaration( + ets.TSTypeParameter.create( + passIdentifier(name), + constraint?._node, + defaultType?._node, + passModifiers(modifiers) + ) + ) + // if (!(name instanceof Identifier)) { + // name = createIdentifier(name) + // } + // const peer = nativeModule._CreateTSTypeParameter( + // global.context, + // name.peer, + // constraint?.peer ?? NULLPTR, + // defaultType?.peer ?? NULLPTR + // ) + // return new TypeParameterDeclaration(updateChildren(updateModifiers(peer, modifiers))) } + // @api + // function updateTypeParameterDeclaration( + // node: TypeParameterDeclaration, + // modifiers: readonly Modifier[] | undefined, + // name: Identifier, + // constraint: TypeNode | undefined, + // defaultType: TypeNode | undefined + // ): TypeParameterDeclaration + function updateTypeParameterDeclaration( + node: TypeParameterDeclaration, + modifiers: readonly Modifier[] | undefined, + name: string | Identifier, + constraint?: TypeNode, + defaultType?: TypeNode + ): TypeParameterDeclaration { + const updated = createTypeParameterDeclaration(modifiers, name, constraint, defaultType) + return new TypeParameterDeclaration(updateNode(updated._node, node._node)) + } +/* + // @api + // createUnionTypeNode( + // types: readonly TypeNode[] + // ): UnionTypeNode + function createUnionTypeNode( + types: readonly TypeNode[] + ): UnionTypeNode { + const peer = withNodeArray(types, (_types: BigUint64Array) => { + return nativeModule._CreateETSUnionTypeIr(global.context, _types, _types.length) + }) + // TODO: rewrite + return new UnionTypeNode(new ets.UnionTypeNode(peer)) + } + + // @api + // function updateUnionTypeNode( + // node: UnionTypeNode, + // types: NodeArray + // ): UnionTypeNode + function updateUnionTypeNode( + node: UnionTypeNode, + types: readonly TypeNode[] + ): UnionTypeNode { + const updated = createUnionTypeNode(types) + return new UnionTypeNode(new ets.UnionTypeNode(updateNode(updated.peer, node.peer))) + } +*/ // @api // createTypeReferenceNode( // typeName: string | EntityName, // typeArguments?: readonly TypeNode[] // ): TypeReferenceNode; - function createTypeReferenceNode(identifier: Identifier, typeArguments?: undefined): TypeReferenceNode { - const typeRefPart = nativeModule._CreateETSTypeReferencePart(Global.context, identifier.peer, NULLPTR, NULLPTR) - updateChildren(typeRefPart) - const peer = nativeModule._CreateETSTypeReference(Global.context, typeRefPart) - updateChildren(peer) + function createTypeReferenceNode( + typeName: Identifier, + typeArguments?: undefined + ): TypeReferenceNode { + return new TypeReferenceNode( + ets.ETSTypeReference.create(typeName._node) + ) + } - return new TypeReferenceNode(peer) + // @api + // function updateTypeReferenceNode( + // node: TypeReferenceNode, + // typeName: EntityName, + // typeArguments: NodeArray | undefined + // ): TypeReferenceNode + function updateTypeReferenceNode( + node: TypeReferenceNode, + typeName: Identifier, + typeArguments?: undefined + ): TypeReferenceNode { + const updated = createTypeReferenceNode(typeName, typeArguments) + return new TypeReferenceNode(updateNode(updated._node, node._node)) } // @internal - function createKeywordTypeNodeFromString(keyword: string): KeywordTypeNode { - const ident = withString(keyword, (name: string) => { - return nativeModule._CreateIdentifier1(Global.context, name) - }) - nativeModule._IdentifierSetReference(Global.context, ident, true) - const typeRefPart = nativeModule._CreateETSTypeReferencePart1(Global.context, ident) - nativeModule._AstNodeSetParent(Global.context, ident, typeRefPart) - const peer = nativeModule._CreateETSTypeReference(Global.context, typeRefPart) - nativeModule._AstNodeSetParent(Global.context, typeRefPart, peer); - - return new KeywordTypeNode(peer) + function createKeywordTypeNodeFromString( + keyword: string + ): KeywordTypeNode { + return new KeywordTypeNode( + ets.ETSTypeReference.create( + ets.Identifier.create(keyword) + ) + ) } // @internal - function createKeywordTypeNodeFromKind(kind: number): KeywordTypeNode { - return new KeywordTypeNode(nativeModule._CreateETSPrimitiveType(Global.context, kind)) + function createKeywordTypeNodeFromKind( + kind: number + ): KeywordTypeNode { + return new KeywordTypeNode( + ets.ETSPrimitiveType.create(kind) + ) } // @api - // createKeywordTypeNode(kind: TKind): KeywordTypeNode; - function createKeywordTypeNode(TKind: ts.KeywordTypeSyntaxKind): KeywordTypeNode { + // createKeywordTypeNode( + // kind: TKind + // ): KeywordTypeNode; + function createKeywordTypeNode( + TKind: ts.KeywordTypeSyntaxKind + ): KeywordTypeNode { const keywords = new Map([ [ts.SyntaxKind.NumberKeyword, createKeywordTypeNodeFromString("number")], [ts.SyntaxKind.StringKeyword, createKeywordTypeNodeFromString("string")], [ts.SyntaxKind.AnyKeyword, createKeywordTypeNodeFromString("any")], [ts.SyntaxKind.VoidKeyword, createKeywordTypeNodeFromKind(8)], ]) - return keywords.get(TKind) ?? throwError('unsupported keyword') } @@ -374,13 +620,13 @@ export function createNodeFactory() { // statements: readonly Statement[], // multiLine?: boolean // ): Block; - function createBlock(statements: Statement[], multiline?: boolean): Block { - const peer = withNodeArray(statements, (_statements: BigUint64Array) => { - return nativeModule._CreateBlockStatement(Global.context, _statements, _statements.length) - }) - updateChildren(peer) - - return new Block(peer) + function createBlock( + statements: readonly Statement[], + multiline?: boolean + ): Block { + return new Block( + ets.Block.create(passNodeArray(statements)) + ) } // @api @@ -388,76 +634,110 @@ export function createNodeFactory() { // node: Block, // statements: readonly Statement[] // ): Block; - function updateBlock(node: Block, statements: Statement[], multiline?: boolean): Block { - const peer = withNodeArray(statements, (_statements: BigUint64Array) => { - return nativeModule._UpdateBlockStatement(Global.context, node.peer, _statements, _statements.length) - }) - updateNode(peer, node.peer) - updateChildren(peer) - - return new Block(peer) + function updateBlock( + node: Block, + statements: readonly Statement[] + ): Block { + const updated = createBlock(statements) + return new Block(updateNode(updated._node, node._node)) } // @api - // createExpressionStatement(expression: Expression): ExpressionStatement; - function createExpressionStatement(expression: Expression): ExpressionStatement { - const peer = nativeModule._CreateExpressionStatement(Global.context, expression.peer) - updateChildren(peer) - - return new ExpressionStatement(peer) + // createExpressionStatement( + // expression: Expression + // ): ExpressionStatement; + function createExpressionStatement( + expression: Expression + ): ExpressionStatement { + return new ExpressionStatement( + ets.ExpressionStatement.create(expression._node) + ) } // @api - // updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement; - function updateExpressionStatement(node: ExpressionStatement, expression: Expression): ExpressionStatement { - const peer = nativeModule._UpdateExpressionStatement(Global.context, node.peer, expression.peer) - updateNode(peer, node.peer) - updateChildren(peer) - - return new ExpressionStatement(peer) + // updateExpressionStatement( + // node: ExpressionStatement, + // expression: Expression + // ): ExpressionStatement; + function updateExpressionStatement( + node: ExpressionStatement, + expression: Expression + ): ExpressionStatement { + const updated = createExpressionStatement(expression) + return new ExpressionStatement(updateNode(updated._node, node._node)) } // @api - // createReturnStatement(expression?: Expression): ReturnStatement; - function createReturnStatement(expression: Expression): ReturnStatement { - const peer = nativeModule._CreateReturnStatement1(Global.context, expression.peer) - updateChildren(peer) + // createReturnStatement( + // expression?: Expression + // ): ReturnStatement; + function createReturnStatement( + expression: Expression + ): ReturnStatement { + return new ReturnStatement( + ets.ReturnStatement.create(expression._node) + ) + } - return new ReturnStatement(peer) + // @api + // function updateReturnStatement( + // node: ReturnStatement, + // expression: Expression | undefined + // ): ReturnStatement + function updateReturnStatement( + node: ReturnStatement, + expression: Expression + ): ReturnStatement { + const updated = createReturnStatement(expression) + return new ReturnStatement(updateNode(updated._node, node._node)) } // @api - // createPropertyAccessExpression(expression: Expression, name: string | MemberName): PropertyAccessExpression; - function createPropertyAccessExpression(expression: Expression, name: Identifier): PropertyAccessExpression { - const peer = nativeModule._CreateMemberExpression( - Global.context, - expression.peer, - name.peer, - Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, - false, - false + // createPropertyAccessExpression( + // expression: Expression, + // name: string | MemberName + // ): PropertyAccessExpression; + function createPropertyAccessExpression( + expression: Expression, + name: string | Identifier + ): PropertyAccessExpression { + return new PropertyAccessExpression( + ets.MemberExpression.create( + expression._node, + passIdentifier(name), + Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, + false, + false + ) ) - updateChildren(peer) - return new PropertyAccessExpression(peer) + // if (!(name instanceof Identifier)) { + // name = createIdentifier(name) + // } + // const peer = nativeModule._CreateMemberExpression( + // global.context, + // expression.peer, + // name.peer, + // Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, + // false, + // false + // ) + // return new PropertyAccessExpression(updateChildren(peer)) } // @api - // updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: MemberName): PropertyAccessExpression; - function updatePropertyAccessExpression(node: PropertyAccessExpression, expression: Expression, name: Identifier): PropertyAccessExpression { - const peer = nativeModule._UpdateMemberExpression( - Global.context, - node.peer, - expression.peer, - name.peer, - Es2pandaMemberExpressionKind.MEMBER_EXPRESSION_KIND_PROPERTY_ACCESS, - false, - false - ) - updateNode(peer, node.peer) - updateChildren(peer) - - return new PropertyAccessExpression(peer) + // updatePropertyAccessExpression( + // node: PropertyAccessExpression, + // expression: Expression, + // name: MemberName + // ): PropertyAccessExpression; + function updatePropertyAccessExpression( + node: PropertyAccessExpression, + expression: Expression, + name: Identifier + ): PropertyAccessExpression { + const updated = createPropertyAccessExpression(expression, name) + return new PropertyAccessExpression(updateNode(updated._node, node._node)) } // @api @@ -468,23 +748,33 @@ export function createNodeFactory() { // ): CallExpression; function createCallExpression( expression: Expression, - typeArguments?: undefined, - argumentsArray?: readonly Expression[] | undefined + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined ): CallExpression { - const peer = withNodeArray(argumentsArray, (_arguments: BigUint64Array) => { - return nativeModule._CreateCallExpression( - Global.context, - expression.peer, - _arguments, - _arguments.length, - NULLPTR, - false, - false + return new CallExpression( + ets.CallExpression.create( + expression._node, + (typeArguments !== undefined) ? + ets.TSTypeParameterDeclaration.create( + passNodeArray(typeArguments) + ) : + undefined, + passNodeArray(argumentsArray) ) - }) - updateChildren(peer) - - return new CallExpression(peer) + ) + // const peer = withNodeArray(argumentsArray, (_arguments: BigUint64Array) => { + // return nativeModule._CreateCallExpression( + // global.context, + // expression.peer, + // _arguments, + // _arguments.length, + // // TODO: pass typeArgs + // NULLPTR, + // false, + // false + // ) + // }) + // return new CallExpression(updateChildren(peer)) } // @api @@ -497,44 +787,52 @@ export function createNodeFactory() { function updateCallExpression( node: CallExpression, expression: Expression, - typeArguments?: undefined, - argumentsArray?: readonly Expression[] | undefined + typeArguments: readonly TypeNode[] | undefined, + argumentsArray: readonly Expression[] | undefined ): CallExpression { - const peer = withNodeArray(argumentsArray, (_arguments: BigUint64Array) => { - return nativeModule._UpdateCallExpression( - Global.context, - node.peer, - expression.peer, - _arguments, - _arguments.length, - NULLPTR, - false, - false - ) - }) - updateNode(peer, node.peer) - updateChildren(peer) - - return new CallExpression(peer) + const updated = createCallExpression(expression, typeArguments, argumentsArray) + return new CallExpression(updateNode(updated._node, node._node)) } - +/* // @api // createIfStatement( // expression: Expression, // thenStatement: Statement, // elseStatement?: Statement // ): IfStatement; - function createIfStatement(expression: Expression, thenStatement: Statement, elseStatement?: undefined): IfStatement { - const peer = nativeModule._CreateIfStatement(Global.context, expression.peer, thenStatement.peer, NULLPTR) - updateChildren(peer) + function createIfStatement( + expression: Expression, + thenStatement: Statement, + elseStatement?: undefined + ): IfStatement { + const peer = nativeModule._CreateIfStatement(global.context, expression.peer, thenStatement.peer, NULLPTR) + return new IfStatement(updateChildren(peer)) + } - return new IfStatement(peer) + // @api + // updateIfStatement( + // expression: Expression, + // thenStatement: Statement, + // elseStatement: Statement | undefined + // ): IfStatement; + function updateIfStatement( + node: IfStatement, + expression: Expression, + thenStatement: Statement, + elseStatement?: undefined + ): IfStatement { + const updated = createIfStatement(expression, thenStatement, elseStatement) + return new IfStatement(updateNode(updated.peer, node.peer)) } // TODO: fix maybe (temporary solution) // @api - // createToken(token: SyntaxKind._): _; - function createToken(token: TKind) { + // createToken( + // token: SyntaxKind._ + // ): _; + function createToken( + token: TKind + ) { return new Token(token) } @@ -544,11 +842,30 @@ export function createNodeFactory() { // operator: BinaryOperator | BinaryOperatorToken, // right: Expression // ): BinaryExpression; - function createBinaryExpression(left: Expression, operator: BinaryOperatorToken, right: Expression): BinaryExpression { - const peer = nativeModule._CreateBinaryExpression(Global.context, left.peer, right.peer, passToken(operator)) - updateChildren(peer) + function createBinaryExpression( + left: Expression, + operator: BinaryOperatorToken, + right: Expression + ): BinaryExpression { + const peer = nativeModule._CreateBinaryExpression(global.context, left.peer, right.peer, passToken(operator)) + return new BinaryExpression(updateChildren(peer)) + } - return new BinaryExpression(peer) + // @api + // function updateBinaryExpression( + // node: BinaryExpression, + // left: Expression, + // operator: BinaryOperatorToken, + // right: Expression + // ): BinaryExpression + function updateBinaryExpression( + node: BinaryExpression, + left: Expression, + operator: BinaryOperatorToken, + right: Expression + ): BinaryExpression { + const updated = createBinaryExpression(left, operator, right) + return new BinaryExpression(updateNode(updated.peer, node.peer)) } // @api @@ -561,7 +878,7 @@ export function createNodeFactory() { // body: ConciseBody // ): ArrowFunction; function createArrowFunction( - modifiers: undefined, + modifiers: readonly Modifier[] | undefined, typeParameters: undefined, parameters: readonly ParameterDeclaration[], type: undefined, @@ -569,7 +886,7 @@ export function createNodeFactory() { body: Block ) { const peer = withNodeArray(parameters, (_parameters: BigUint64Array) => { - const _context = Global.context + const _context = global.context const _body = body.peer const _signature = nativeModule._CreateFunctionSignature( @@ -597,28 +914,71 @@ export function createNodeFactory() { return _arrowFunc }) + return new ArrowFunction(updateChildren(updateModifiers(peer, modifiers))) + } - return new ArrowFunction(peer) + // @api + // function updateArrowFunction( + // node: ArrowFunction, + // modifiers: readonly Modifier[] | undefined, + // typeParameters: readonly TypeParameterDeclaration[] | undefined, + // parameters: readonly ParameterDeclaration[], + // type: TypeNode | undefined, + // equalsGreaterThanToken: EqualsGreaterThanToken, + // body: ConciseBody, + // ): ArrowFunction + function updateArrowFunction( + node: ArrowFunction, + modifiers: readonly Modifier[] | undefined, + typeParameters: undefined, + parameters: readonly ParameterDeclaration[], + type: undefined, + equalsGreaterThanToken: undefined, + body: Block, + ): ArrowFunction { + const updated = createArrowFunction(modifiers, typeParameters, parameters, type, equalsGreaterThanToken, body) + return new ArrowFunction(updateNode(updated.peer, node.peer)) } - // TODO: fix (now doesn't create a new node) // @api - // updateSourceFile( - // node: SourceFile, - // statements: readonly Statement[], - // isDeclarationFile?: boolean, - // referencedFiles?: readonly FileReference[], - // typeReferences?: readonly FileReference[], - // hasNoDefaultLib?: boolean, - // libReferences?: readonly FileReference[] - // ): SourceFile; - function updateSourceFile(node: SourceFile, statements: readonly Statement[]): SourceFile { - withNodeArray(statements, (_statements: BigUint64Array) => { - nativeModule._BlockStatementSetStatements(Global.context, node.peer, _statements, _statements.length) - }) - updateChildren(node.peer) + // function createClassDeclaration( + // modifiers: readonly ModifierLike[] | undefined, + // name: string | Identifier | undefined, + // typeParameters: readonly TypeParameterDeclaration[] | undefined, + // heritageClauses: readonly HeritageClause[] | undefined, + // members: readonly ClassElement[], + // ): ClassDeclaration + function createClassDeclaration( + modifiers: readonly Modifier[] | undefined, + name: string | Identifier | undefined, + typeParameters: readonly TypeParameterDeclaration[] | undefined, + heritageClauses: undefined, + members: readonly ClassElement[] + ) { + const peer = withNodeArray(members, (_members: BigUint64Array) => { + const _context = global.context - return node + const _newClassDefinition = nativeModule._CreateClassDefinition1( + _context, + // TODO: maybe this is wrong + passIdentifier(name), + _members, + _members.length, + Es2pandaClassDefinitionModifiers.CLASS_DEFINITION_MODIFIERS_NONE, + Es2pandaModifierFlags.MODIFIER_FLAGS_NONE, + // TODO: fix lang + NULLPTR + ) + nativeModule._ClassDefinitionSetTypeParams(_context, _newClassDefinition, passTypeParams(typeParameters)) + updateModifiers(_newClassDefinition, modifiers) + updateChildren(_newClassDefinition) + + return nativeModule._CreateClassDeclaration( + _context, + _newClassDefinition + ) + }) + return new ClassDeclaration(updateChildren(updateModifiers(peer, modifiers))) } // @api @@ -632,14 +992,18 @@ export function createNodeFactory() { // ): ClassDeclaration; function updateClassDeclaration( node: ClassDeclaration, - modifiers: undefined, + modifiers: readonly Modifier[] | undefined, name: Identifier | undefined, typeParameters: undefined, heritageClauses: undefined, members: readonly ClassElement[] ) { + // TODO: rewrite like this (impossible now because of Language param) + // const updated = createClassDeclaration(modifiers, name, typeParameters, heritageClauses, members) + // return new ClassDeclaration(updateNode(updated.peer, node.peer)) + const peer = withNodeArray(members, (_members: BigUint64Array) => { - const _context = Global.context + const _context = global.context const _classDefinition = nativeModule._ClassDeclarationDefinition( _context, @@ -655,15 +1019,16 @@ export function createNodeFactory() { _context, _classDefinition, // TODO: maybe this is wrong - (name === undefined) ? NULLPTR : name.peer, + passIdentifier(name), _members, _members.length, Es2pandaClassDefinitionModifiers.CLASS_DEFINITION_MODIFIERS_NONE, Es2pandaModifierFlags.MODIFIER_FLAGS_NONE, _lang ) + nativeModule._ClassDefinitionSetTypeParams(_context, _newClassDefinition, passTypeParams(typeParameters)) + updateModifiers(_newClassDefinition, modifiers) updateNode(_newClassDefinition, _classDefinition) - updateChildren(_newClassDefinition) return nativeModule._UpdateClassDeclaration( _context, @@ -671,10 +1036,7 @@ export function createNodeFactory() { _newClassDefinition ) }) - updateNode(peer, node.peer) - updateChildren(peer) - - return new ClassDeclaration(peer) + return new ClassDeclaration(updateNode(updateModifiers(peer, modifiers), node.peer)) } // @api @@ -690,7 +1052,7 @@ export function createNodeFactory() { ): FunctionTypeNode { const _signature = withNodeArray(parameters, (_parameters: BigUint64Array) => { return nativeModule._CreateFunctionSignature( - Global.context, + global.context, NULLPTR, _parameters, _parameters.length, @@ -699,13 +1061,28 @@ export function createNodeFactory() { }) const peer = nativeModule._CreateETSFunctionTypeIr( - Global.context, + global.context, _signature, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE ) - updateChildren(peer) + return new FunctionTypeNode(new ets.FunctionTypeNode(updateChildren(peer))) + } - return new FunctionTypeNode(peer) + // @api + // function updateFunctionTypeNode( + // node: FunctionTypeNode, + // typeParameters: NodeArray | undefined, + // parameters: NodeArray, + // type: TypeNode, + // ): FunctionTypeNode + function updateFunctionTypeNode( + node: FunctionTypeNode, + typeParameters: undefined, + parameters: readonly ParameterDeclaration[], + type: TypeNode + ): FunctionTypeNode { + const updated = createFunctionTypeNode(typeParameters, parameters, type) + return new FunctionTypeNode(new ets.FunctionTypeNode(updateNode(updated.peer, node.peer))) } // TODO: fix modifiers @@ -721,7 +1098,7 @@ export function createNodeFactory() { // body: Block | undefined // ): MethodDeclaration; function createMethodDeclaration( - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, asteriskToken: undefined, name: string | Identifier, questionToken: undefined, @@ -730,47 +1107,44 @@ export function createNodeFactory() { type: TypeNode | undefined, body: Block | undefined ): MethodDeclaration { - const peer = withString((name instanceof Identifier) ? name.text : name, (_name: string) => { - return withNodeArray(parameters, (_parameters: BigUint64Array) => { - const _context = Global.context - - const _signature = nativeModule._CreateFunctionSignature( - _context, - NULLPTR, - _parameters, - _parameters.length, - type?.peer ?? NULLPTR, - ) - - const _ident = nativeModule._CreateIdentifier1(_context, _name) - const _scriptFunc = createScriptFunction( - body?.peer ?? NULLPTR, - _signature, - (modifiers !== undefined) ? passScriptFuncModifiers(modifiers) : Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE, - (modifiers !== undefined) ? passModifiers(modifiers) : Es2pandaModifierFlags.MODIFIER_FLAGS_NONE, - false, - _ident - ) - - const _funcExpr = nativeModule._CreateFunctionExpression( - Global.context, - _scriptFunc - ) - updateChildren(_funcExpr) - - return nativeModule._CreateMethodDefinition( - _context, - Es2pandaMethodDefinitionKind.METHOD_DEFINITION_KIND_METHOD, - _ident, - _funcExpr, - (modifiers !== undefined) ? passModifiers(modifiers) : Es2pandaModifierFlags.MODIFIER_FLAGS_NONE, - false - ) - }) - }) - updateChildren(peer) + const peer = withNodeArray(parameters, (_parameters: BigUint64Array) => { + const _context = global.context - return new MethodDeclaration(peer) + const _signature = nativeModule._CreateFunctionSignature( + _context, + NULLPTR, + _parameters, + _parameters.length, + type?.peer ?? NULLPTR, + ) + + const _ident = passIdentifier(name) + + const _scriptFunc = createScriptFunction( + body?.peer ?? NULLPTR, + _signature, + passScriptFuncModifiers(modifiers), + passModifiers(modifiers), + false, + _ident + ) + + const _funcExpr = nativeModule._CreateFunctionExpression( + global.context, + _scriptFunc + ) + updateChildren(_funcExpr) + + return nativeModule._CreateMethodDefinition( + _context, + Es2pandaMethodDefinitionKind.METHOD_DEFINITION_KIND_METHOD, + _ident, + _funcExpr, + passModifiers(modifiers), + false + ) + }) + return new MethodDeclaration(updateChildren(updateModifiers(peer, modifiers))) } // @api @@ -794,58 +1168,21 @@ export function createNodeFactory() { typeParameters: undefined, parameters: readonly ParameterDeclaration[], type: undefined, - body: Block + body: Block | undefined ): MethodDeclaration { - const peer = withNodeArray(parameters, (_parameters: BigUint64Array) => { - const _context = Global.context - - const _oldFuncExpr = nativeModule._MethodDefinitionFunction(_context, node.peer) - const _oldScriptFunc = nativeModule._ArrowFunctionExpressionFunction(_context, _oldFuncExpr) - - const _signature = nativeModule._CreateFunctionSignature( - _context, - NULLPTR, - _parameters, - _parameters.length, - NULLPTR - ) - - const _scriptFunc = updateScriptFunction( - _oldScriptFunc, - body.peer, - _signature, - // TODO: fix this - // nativeModule._ScriptFunctionFlagsConst(_context, _oldScriptFunc), - Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE, - nativeModule._AstNodeModifiers(_context, _oldScriptFunc), - false, - name.peer - ) - - const _funcExpr = nativeModule._UpdateFunctionExpression( - Global.context, - _oldFuncExpr, - _scriptFunc - ) - updateChildren(_funcExpr) - - return nativeModule._UpdateMethodDefinition( - Global.context, - node.peer, - nativeModule._MethodDefinitionKindConst(_context, node.peer), - name.peer, - _funcExpr, - nativeModule._AstNodeModifiers(_context, node.peer), - false - ) - }) - updateNode(peer, node.peer) - updateChildren(peer) - - return new MethodDeclaration(peer) + const updated = createMethodDeclaration( + modifiers, + asteriskToken, + name, + questionToken, + typeParameters, + parameters, + type, + body + ) + return new MethodDeclaration(updateNode(updated.peer, node.peer)) } - // TODO: fix modifiers // @api // createConstructorDeclaration( // modifiers: readonly ModifierLike[] | undefined, @@ -853,12 +1190,12 @@ export function createNodeFactory() { // body: Block | undefined // ): ConstructorDeclaration; function createConstructorDeclaration( - modifiers: readonly ModifierLike[] | undefined, + modifiers: readonly Modifier[] | undefined, parameters: readonly ParameterDeclaration[], body: Block | undefined ): ConstructorDeclaration { const peer = withNodeArray(parameters, (_parameters: BigUint64Array) => { - const _context = Global.context + const _context = global.context const _signature = nativeModule._CreateFunctionSignature( _context, @@ -874,15 +1211,15 @@ export function createNodeFactory() { body?.peer ?? NULLPTR, _signature, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_CONSTRUCTOR | - ((modifiers !== undefined) ? passScriptFuncModifiers(modifiers) : Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE), + passScriptFuncModifiers(modifiers), Es2pandaModifierFlags.MODIFIER_FLAGS_CONSTRUCTOR | - ((modifiers !== undefined) ? passModifiers(modifiers) : Es2pandaModifierFlags.MODIFIER_FLAGS_NONE), + passModifiers(modifiers), false, _ident ) const _funcExpr = nativeModule._CreateFunctionExpression( - Global.context, + global.context, _scriptFunc ) updateChildren(_funcExpr) @@ -893,14 +1230,30 @@ export function createNodeFactory() { _ident, _funcExpr, Es2pandaModifierFlags.MODIFIER_FLAGS_CONSTRUCTOR | - ((modifiers !== undefined) ? passModifiers(modifiers) : Es2pandaModifierFlags.MODIFIER_FLAGS_NONE), + passModifiers(modifiers), false ) }) - updateChildren(peer) + return new ConstructorDeclaration(updateChildren(updateModifiers(peer, [...modifiers ?? [], Es2pandaModifierFlags.MODIFIER_FLAGS_CONSTRUCTOR]))) + } - return new ConstructorDeclaration(peer) + // @api + // function updateConstructorDeclaration( + // node: ConstructorDeclaration, + // modifiers: readonly ModifierLike[] | undefined, + // parameters: readonly ParameterDeclaration[], + // body: Block | undefined, + // ): ConstructorDeclaration + function updateConstructorDeclaration( + node: ConstructorDeclaration, + modifiers: readonly Modifier[] | undefined, + parameters: readonly ParameterDeclaration[], + body: Block | undefined + ): ConstructorDeclaration { + const updated = createConstructorDeclaration(modifiers, parameters, body) + return new ConstructorDeclaration(updateNode(updated.peer, node.peer)) } +*/ } export const factory = createNodeFactory(); diff --git a/arkoala-arkts/libarkts/src/arkts/factory/nodeTests.ts b/arkoala-arkts/libarkts/src/arkts/factory/nodeTests.ts index 2afce8fa4..5e1fe28c6 100644 --- a/arkoala-arkts/libarkts/src/arkts/factory/nodeTests.ts +++ b/arkoala-arkts/libarkts/src/arkts/factory/nodeTests.ts @@ -9,24 +9,33 @@ import { FunctionDeclaration, Block, KeywordTypeNode, - PropertyAccessExpression, + // PropertyAccessExpression, ParameterDeclaration, ReturnStatement, - IfStatement, + // IfStatement, ExpressionStatement, CallExpression, - ArrowFunction, + // ArrowFunction, TypeReferenceNode, - BinaryExpression, + // BinaryExpression, BinaryOperatorToken, - ClassDeclaration, + // ClassDeclaration, FunctionTypeNode, TypeNode, Expression, Statement, SourceFile, - ClassElement, - MethodDeclaration, + // ClassElement, + // MethodDeclaration, + // FunctionExpression, + // VariableDeclaration, + // VariableDeclarationList, + // PropertyDeclaration, + // PropertySignature, + // MethodSignature, + // GetAccessorDeclaration, + // SetAccessorDeclaration, + // VariableStatement, } from "../types" export function isIdentifier(node: Node): node is Identifier { @@ -37,17 +46,17 @@ export function isCallExpression(node: Node): node is CallExpression { return node.kind === SyntaxKind.CallExpression } -export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression { - return node.kind === SyntaxKind.PropertyAccessExpression -} +// export function isPropertyAccessExpression(node: Node): node is PropertyAccessExpression { +// return node.kind === SyntaxKind.PropertyAccessExpression +// } export function isFunctionDeclaration(node: Node): node is FunctionDeclaration { return node.kind === SyntaxKind.FunctionDeclaration } -export function isMethodDeclaration(node: Node): node is MethodDeclaration { - return node.kind === SyntaxKind.MethodDeclaration -} +// export function isMethodDeclaration(node: Node): node is MethodDeclaration { +// return node.kind === SyntaxKind.MethodDeclaration +// } export function isSourceFile(node: Node): node is SourceFile { return node.kind === SyntaxKind.SourceFile @@ -57,10 +66,58 @@ export function isExpressionStatement(node: Node): node is ExpressionStatement { return node.kind === SyntaxKind.ExpressionStatement } -export function isArrowFunction(node: Node): node is ArrowFunction { - return node.kind === SyntaxKind.ArrowFunction +// export function isArrowFunction(node: Node): node is ArrowFunction { +// return node.kind === SyntaxKind.ArrowFunction +// } + +// export function isClassDeclaration(node: Node): node is ClassDeclaration { +// return node.kind === SyntaxKind.ClassDeclaration +// } + +export function isBlock(node: Node): node is Block { + return node.kind === SyntaxKind.Block } -export function isClassDeclaration(node: Node): node is ClassDeclaration { - return node.kind === SyntaxKind.ClassDeclaration +// export function isFunctionExpression(node: Node): node is FunctionExpression { +// return node.kind === SyntaxKind.FunctionExpression +// } + +export function isParameter(node: Node): node is ParameterDeclaration { + return node.kind === SyntaxKind.Parameter } + +// export function isVariableDeclaration(node: Node): node is VariableDeclaration { +// return node.kind === SyntaxKind.VariableDeclaration +// } + +// export function isVariableDeclarationList(node: Node): node is VariableDeclarationList { +// return node.kind === SyntaxKind.VariableDeclarationList +// } + +// export function isPropertyDeclaration(node: Node): node is PropertyDeclaration { +// return node.kind === SyntaxKind.PropertyDeclaration +// } + +// export function isPropertySignature(node: Node): node is PropertySignature { +// return node.kind === SyntaxKind.PropertySignature +// } + +export function isFunctionTypeNode(node: Node): node is FunctionTypeNode { + return node.kind === SyntaxKind.FunctionType +} + +// export function isMethodSignature(node: Node): node is MethodSignature { +// return node.kind === SyntaxKind.MethodSignature +// } + +// export function isGetAccessorDeclaration(node: Node): node is GetAccessorDeclaration { +// return node.kind === SyntaxKind.GetAccessor +// } + +// export function isSetAccessorDeclaration(node: Node): node is SetAccessorDeclaration { +// return node.kind === SyntaxKind.SetAccessor +// } + +// export function isVariableStatement(node: Node): node is VariableStatement { +// return node.kind === SyntaxKind.VariableStatement +// } diff --git a/arkoala-arkts/libarkts/src/arkts/factory/utilities.ts b/arkoala-arkts/libarkts/src/arkts/factory/utilities.ts index 49f9f1102..2966c7fc5 100644 --- a/arkoala-arkts/libarkts/src/arkts/factory/utilities.ts +++ b/arkoala-arkts/libarkts/src/arkts/factory/utilities.ts @@ -15,41 +15,77 @@ import { nativeModule } from "../../NativeModule" import { KNativePointer, KInt, KBoolean } from "@koalaui/interop" -import * as arkts from "../types" +import * as arkts from "../." +import * as ets from "../typesEts" +import global from "../global" import { - SyntaxKind, TokenSyntaxKind, Es2pandaModifierFlags, Es2pandaScriptFunctionFlags, - Es2pandaTokenType, } from "../enums" -import { throwError } from "../utilities" +import { + throwError, + packModifiers, +} from "../utilities" + export { throwError } from "../utilities" export function setParent(node: KNativePointer, parent: KNativePointer) { - nativeModule._AstNodeSetParent(arkts.Global.context, node, parent) + nativeModule._AstNodeSetParent(global.context, node, parent) } export function getModifierFlags(node: KNativePointer): KInt { - return nativeModule._AstNodeModifiers(arkts.Global.context, node) + return nativeModule._AstNodeModifiers(global.context, node) } export function setModifierFlags(node: KNativePointer, flags: KInt) { - nativeModule._AstNodeClearModifier(arkts.Global.context, node, arkts.ALL_FLAGS) - nativeModule._AstNodeAddModifier(arkts.Global.context, node, flags) + nativeModule._AstNodeClearModifier(global.context, node, arkts.ALL_FLAGS) + nativeModule._AstNodeAddModifier(global.context, node, flags) } export function updateAllChildren(peer: KNativePointer) { - nativeModule._AstNodeUpdateAll(arkts.Global.context, peer) + nativeModule._AstNodeUpdateAll(global.context, peer) } -export function updateChildren(peer: KNativePointer) { - nativeModule._AstNodeUpdateChildren(arkts.Global.context, peer) +export function updateChildren(peer: KNativePointer): KNativePointer { + if (peer === arkts.NULLPTR) { + throwError('updateChildren called on NULLPTR') + } + nativeModule._AstNodeUpdateChildren(global.context, peer) + return peer } // TODO: update scopes and other data -export function updateNode(peer: KNativePointer, original: KNativePointer) { - setModifierFlags(peer, getModifierFlags(original)) +export function updateNode(node: T, original: T): T { + if (node.peer === arkts.NULLPTR) { + throwError('updateNode called on NULLPTR') + } + nativeModule._AstNodeSetOriginalNode(global.context, node.peer, original.peer) + nativeModule._AstNodeSetParent(global.context, node.peer, nativeModule._AstNodeParent(global.context, original.peer)) + nativeModule._AstNodeUpdateChildren(global.context, node.peer) + setModifierFlags(node.peer, getModifierFlags(original.peer)) + // new flags may change children + updateChildren(node.peer) + // switch (classByPeer(peer)) { + // case arkts.ClassDeclaration: { + // // TODO: update Language + // break + // } + // } + return node +} + +export function updateNodeModifiers(node: T, modifiers: ReadonlyArray | undefined): T { + // node.modifiers = modifiers + return node +} + +export function updateModifiers(peer: KNativePointer, modifiers: ReadonlyArray | undefined): KNativePointer { + if (modifiers === undefined) { + return peer + } + setModifierFlags(peer, packModifiers(modifiers)) + return peer } export function createScriptFunction( @@ -63,7 +99,7 @@ export function createScriptFunction( ident: KNativePointer | undefined ): KNativePointer { const peer = nativeModule._CreateScriptFunction( - arkts.Global.context, + global.context, body, signature, functionFlags, @@ -71,7 +107,7 @@ export function createScriptFunction( declare ) if (ident !== undefined) { - nativeModule._ScriptFunctionSetIdent(arkts.Global.context, peer, ident) + nativeModule._ScriptFunctionSetIdent(global.context, peer, ident) } updateChildren(peer) return peer @@ -89,7 +125,7 @@ export function updateScriptFunction( ident: KNativePointer | undefined ): KNativePointer { const peer = nativeModule._UpdateScriptFunction( - arkts.Global.context, + global.context, original, body, signature, @@ -98,7 +134,7 @@ export function updateScriptFunction( declare ) if (ident !== undefined) { - nativeModule._ScriptFunctionSetIdent(arkts.Global.context, peer, ident) + nativeModule._ScriptFunctionSetIdent(global.context, peer, ident) } updateChildren(peer) return peer @@ -111,85 +147,72 @@ export function withString( return exec(data ?? "") } -export function withNodeArray( - data: readonly arkts.Node[] | undefined, - exec: (nodes: BigUint64Array) => TOut -): TOut { - const _data = new BigUint64Array((data === undefined) ? [] : data.map(node => BigInt(node.peer))) - return exec(_data) -} - -// TODO: rewrite this maybe -class Global { - private static _tokenKinds?: Map - - public static get tokenKinds(): Map { - if (this._tokenKinds === undefined) { - this._tokenKinds = - new Map([ - [SyntaxKind.PlusToken, Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_PLUS], - ]) - } - return this._tokenKinds +// export function withNodeArray( +// data: readonly arkts.Node[] | undefined, +// exec: (nodes: BigUint64Array) => TOut +// ): TOut { +// if ((data !== undefined) && data.map(node => node.peer).includes(arkts.NULLPTR)) { +// throwError('trying to pass NULLPTR in function withNodeArray') +// } +// const _data = new BigUint64Array((data === undefined) ? [] : data.map(node => BigInt(node.peer))) +// return exec(_data) +// } + +export function passIdentifier(node: arkts.Identifier | string): ets.Identifier +export function passIdentifier(node: arkts.Identifier | string | undefined): ets.Identifier | undefined +export function passIdentifier(node: arkts.Identifier | string | undefined): ets.Identifier | undefined { + if (node === undefined) { + return undefined } - - private static _scriptFunctionFlags?: Map - - public static get scriptFunctionFlags(): Map { - if (this._scriptFunctionFlags === undefined) { - this._scriptFunctionFlags = - new Map([ - [SyntaxKind.StaticKeyword, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_STATIC_BLOCK], - [SyntaxKind.AsyncKeyword, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_ASYNC], - [SyntaxKind.PublicKeyword, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE], - ]) - } - return this._scriptFunctionFlags - } - - private static _modifierFlags?: Map - - public static get modifierFlags(): Map { - if (this._modifierFlags === undefined) { - this._modifierFlags = - new Map([ - [SyntaxKind.StaticKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC], - [SyntaxKind.AsyncKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_ASYNC], - [SyntaxKind.PublicKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC], - ]) - } - return this._modifierFlags + if (node instanceof arkts.Identifier) { + return node._node } + return ets.Identifier.create(node) } export function passToken(token: arkts.Token): KInt { - return Global.tokenKinds.get(token.kind) ?? throwError('unsupported token') + return global.tokenKinds.get(token.kind) ?? throwError('unsupported token') } -export function passScriptFuncModifier(modifierToken: arkts.ModifierLike) { - return Global.scriptFunctionFlags.get(modifierToken.kind) ?? throwError('unsupported ScriptFunction flag') +export function passScriptFuncModifier(modifierToken: arkts.Modifier): Es2pandaScriptFunctionFlags { + return global.scriptFunctionFlags.get(modifierToken.kind) ?? throwError(`Unsupported ScriptFunction flag: ${modifierToken.kind}`) } -export function passScriptFuncModifiers(modifiers: readonly arkts.ModifierLike[]): KInt { - let flags = Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE - - modifiers.forEach(flag => { - flags = flags | passScriptFuncModifier(flag) - }) +export function passScriptFuncModifiers(modifiers: readonly arkts.Modifier[] | undefined): KInt { + return modifiers?.reduce( + (prev, curr) => prev | passScriptFuncModifier(curr), + Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE + ) ?? Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE +} - return flags +export function passModifier(modifierToken: arkts.Modifier): Es2pandaModifierFlags { + return global.modifierFlags.get(modifierToken.kind) ?? throwError(`Unsupported Modifier flag: ${modifierToken.kind}`) } -export function passModifier(modifierToken: arkts.ModifierLike) { - return Global.modifierFlags.get(modifierToken.kind) ?? throwError('unsupported Modifier flag') +export function passModifiers(modifiers: readonly arkts.Modifier[] | undefined): KInt { + return modifiers?.reduce( + (prev, curr) => prev | passModifier(curr), + Es2pandaModifierFlags.MODIFIER_FLAGS_NONE + ) ?? Es2pandaModifierFlags.MODIFIER_FLAGS_NONE } -export function passModifiers(modifiers: readonly arkts.ModifierLike[]): KInt { - let flags = Es2pandaModifierFlags.MODIFIER_FLAGS_NONE +// // TODO: support unrequired params (with ?) +// export function passTypeParams(params: readonly arkts.TypeParameterDeclaration[] | undefined): KNativePointer { +// if (params === undefined) { +// return arkts.NULLPTR +// } - modifiers.forEach(flag => { - flags = flags | passModifier(flag) - }) +// const peer = withNodeArray(params, (_params: BigUint64Array) => { +// return nativeModule._CreateTSTypeParameterDeclaration(global.context, _params, _params.length, _params.length) +// }) +// updateChildren(peer) - return flags -} +// return peer +// } + +// export function identifierUpdateTypeAnnotation(node: arkts.Identifier, type: arkts.TypeNode | undefined): arkts.Identifier { +// const peer = withString(node.text, (_text: string) => { +// return nativeModule._UpdateIdentifier2(global.context, node.peer, _text, type?.peer ?? arkts.NULLPTR) +// }) +// return new arkts.Identifier(node.text, type?.node) +// } diff --git a/arkoala-arkts/libarkts/src/arkts/global.ts b/arkoala-arkts/libarkts/src/arkts/global.ts new file mode 100644 index 000000000..83d093a31 --- /dev/null +++ b/arkoala-arkts/libarkts/src/arkts/global.ts @@ -0,0 +1,132 @@ +import { KNativePointer } from "@koalaui/interop" +import { + SyntaxKind, + es2pandaKind, + TokenSyntaxKind, + Es2pandaScriptFunctionFlags, + Es2pandaTokenType, + Es2pandaModifierFlags, +} from "./enums" +import * as util from "./utilities" +import * as arkts from "./types" +import * as ets from "./typesEts" + +// TODO: idk how to write +// type ModifierKinds = arkts.ModifierSyntaxKind | SyntaxKind.UnknownKeyword | SyntaxKind.ConstructorKeyword + +export default class global { + private static _config?: KNativePointer + public static set config(config: KNativePointer) { + if (global._config !== undefined) { + throw new Error('Global.config already initialized') + } + global._config = config + } + public static get config(): KNativePointer { + return global._config ?? util.throwError('Global.config not initialized') + } + + public static isInitializedConfig(): boolean { + return (global._config !== undefined) + } + + private static _context?: KNativePointer + public static set context(context: KNativePointer) { + global._context = context + } + public static get context(): KNativePointer { + return global._context ?? util.throwError('Global.context not initialized') + } + + public static isInitializedContext(): boolean { + return (global._context !== undefined) + } + + private static _tokenKinds?: Map + + public static get tokenKinds(): Map { + if (this._tokenKinds === undefined) { + this._tokenKinds = + new Map([ + [SyntaxKind.PlusToken, Es2pandaTokenType.TOKEN_TYPE_PUNCTUATOR_PLUS], + ]) + } + return this._tokenKinds + } + + private static _scriptFunctionFlags?: Map + + public static get scriptFunctionFlags(): Map { + if (this._scriptFunctionFlags === undefined) { + this._scriptFunctionFlags = + new Map([ + [SyntaxKind.StaticKeyword, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_STATIC_BLOCK], + [SyntaxKind.AsyncKeyword, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_ASYNC], + [SyntaxKind.PublicKeyword, Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_NONE], + ]) + } + return this._scriptFunctionFlags + } + + private static _modifierFlags?: Map + + public static get modifierFlags(): Map { + if (this._modifierFlags === undefined) { + this._modifierFlags = + new Map([ + // [SyntaxKind.UnknownKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_NONE], + // [SyntaxKind.ConstructorKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_CONSTRUCTOR], + + [SyntaxKind.AbstractKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_ABSTRACT], + // TODO: unsupported + // [SyntaxKind.AccessorKeyword, Es2pandaModifierFlags.], + [SyntaxKind.AsyncKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_ASYNC], + [SyntaxKind.ConstKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_CONST], + [SyntaxKind.DeclareKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_DECLARE], + [SyntaxKind.DefaultKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_DEFAULT_EXPORT], + [SyntaxKind.ExportKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_EXPORT], + [SyntaxKind.InKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_IN], + [SyntaxKind.PrivateKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_PRIVATE], + [SyntaxKind.ProtectedKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_PROTECTED], + [SyntaxKind.PublicKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC], + [SyntaxKind.OutKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_OUT], + [SyntaxKind.OverrideKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_OVERRIDE], + [SyntaxKind.ReadonlyKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_READONLY], + [SyntaxKind.StaticKeyword, Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC], + ]) + } + return this._modifierFlags + } + + private static _translateModifiers?: Map + + public static get translateModifiers(): Map { + if (this._translateModifiers === undefined) { + this._translateModifiers = + new Map([ + // [Es2pandaModifierFlags.MODIFIER_FLAGS_NONE, SyntaxKind.UnknownKeyword], + // [Es2pandaModifierFlags.MODIFIER_FLAGS_CONSTRUCTOR, SyntaxKind.ConstructorKeyword], + + [Es2pandaModifierFlags.MODIFIER_FLAGS_ABSTRACT, SyntaxKind.AbstractKeyword], + // TODO: unsupported + // [Es2pandaModifierFlags. , SyntaxKind.AccessorKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_ASYNC, SyntaxKind.AsyncKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_CONST, SyntaxKind.ConstKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_DECLARE, SyntaxKind.DeclareKeyword], + // TODO: choose one + // [Es2pandaModifierFlags.MODIFIER_FLAGS_DEFAULT_EXPORT, SyntaxKind.DefaultClause], + // [Es2pandaModifierFlags.MODIFIER_FLAGS_DEFAULT_EXPORT, SyntaxKind.DefaultKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_EXPORT, SyntaxKind.ExportKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_IN, SyntaxKind.InKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_PRIVATE, SyntaxKind.PrivateKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_PROTECTED, SyntaxKind.ProtectedKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_PUBLIC, SyntaxKind.PublicKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_OUT, SyntaxKind.OutKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_OVERRIDE, SyntaxKind.OverrideKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_READONLY, SyntaxKind.ReadonlyKeyword], + [Es2pandaModifierFlags.MODIFIER_FLAGS_STATIC, SyntaxKind.StaticKeyword], + ]) + } + return this._translateModifiers + } +} diff --git a/arkoala-arkts/libarkts/src/arkts/index.ts b/arkoala-arkts/libarkts/src/arkts/index.ts index 4ee61c3be..97b574710 100644 --- a/arkoala-arkts/libarkts/src/arkts/index.ts +++ b/arkoala-arkts/libarkts/src/arkts/index.ts @@ -19,9 +19,10 @@ export * from "./utilitiesPublic" export * from "./utilities" export * from "./factory/nodeFactory" export * from "./factory/nodeTests" -export { - visitEachChild, -} from "./visitor" +export * from "./global" +// export { +// visitEachChild, +// } from "./visitor" export { SyntaxKind, ContextState, diff --git a/arkoala-arkts/libarkts/src/arkts/nodeByPeer.ts b/arkoala-arkts/libarkts/src/arkts/nodeByPeer.ts deleted file mode 100644 index fbda61f60..000000000 --- a/arkoala-arkts/libarkts/src/arkts/nodeByPeer.ts +++ /dev/null @@ -1,57 +0,0 @@ -/* - * Copyright (c) 2022-2023 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 "./types" -import { KNativePointer } from "@koalaui/interop" -import { es2pandaKind } from "./enums" -import { nativeModule } from "../NativeModule" - -// TODO: rewrite this maybe -class Global { - private static _kinds?: Map - - public static get kinds(): Map { - if (this._kinds === undefined) { - this._kinds = - new Map([ - [es2pandaKind.Identifier, arkts.Identifier], - [es2pandaKind.StringLiteral, arkts.StringLiteral], - [es2pandaKind.Block, arkts.Block], - [es2pandaKind.MethodDeclaration, arkts.MethodDeclaration], - [es2pandaKind.ClassDeclaration, arkts.ClassDeclaration], - [es2pandaKind.FunctionDeclaration, arkts.FunctionDeclaration], - [es2pandaKind.PropertyDeclaration, arkts.PropertyDeclaration], - [es2pandaKind.ETSFunctionType, arkts.FunctionTypeNode], - [es2pandaKind.CallExpression, arkts.CallExpression], - [es2pandaKind.ExpressionStatement, arkts.ExpressionStatement], - [es2pandaKind.MemberExpression, arkts.PropertyAccessExpression], - [es2pandaKind.ArrowFunctionExpression, arkts.ArrowFunction], - [es2pandaKind.ReturnStatement, arkts.ReturnStatement], - [es2pandaKind.Parameter, arkts.ParameterDeclaration], - [es2pandaKind.ETSParameterExpression, arkts.ParameterDeclaration], - [es2pandaKind.NumberLiteral, arkts.NumericLiteral], - [es2pandaKind.VariableDeclaration, arkts.VariableStatement], - [es2pandaKind.Program, arkts.SourceFile], - ]) - } - return this._kinds - } -} - -// TODO: maybe rewrite to (new Node(peer)) -export function nodeByPeer(peer: KNativePointer): arkts.Node { - const kind = nativeModule._GetKind(arkts.Global.context, peer) - return new (Global.kinds.get(kind) ?? arkts.UnsupportedNode)(peer) -} diff --git a/arkoala-arkts/libarkts/src/arkts/types.ts b/arkoala-arkts/libarkts/src/arkts/types.ts index 864f51ef3..e8211d429 100644 --- a/arkoala-arkts/libarkts/src/arkts/types.ts +++ b/arkoala-arkts/libarkts/src/arkts/types.ts @@ -2,26 +2,39 @@ import * as ts from "@koalaui/ets-tsc" import { nativeModule } from "../NativeModule" import { KInt, KNativePointer, withStringResult } from "@koalaui/interop" -import * as util from "./utilities" -import { todo } from "./utilities" +// import * as util from "./utilities" +import { + todo, + passEtsNode, + passString, + unpackNodeArray, + unpackNode, + unpackNullableNode, + arktsNodeByEtsNode, + throwError, +} from "./utilities" +import { factory } from "./factory/nodeFactory" +import global from "./global" +import * as ets from "./typesEts" import { Es2pandaModifierFlags, - Es2pandaTokenType, + SyntaxKind, } from "./enums" export const NULLPTR: KNativePointer = BigInt(0) export const NULLPTR_ARRAY = new BigUint64Array([NULLPTR]) +export const EMPTY_MODIFIERS = [] as ReadonlyArray as NodeArray + export const UNSUPPORTED_KIND = 0 -export const ALL_FLAGS: KInt = - Object.values(Es2pandaModifierFlags).filter( - (value: any) => { return (typeof value) === 'number' } - ).reduce( - (prev: KInt, next: KInt): KInt => (prev | next), - 0 as KInt - ) +export const ALL_FLAGS: KInt = Object.values(Es2pandaModifierFlags).filter( + (value: any) => { return (typeof value) === 'number' } + ).reduce( + (prev: KInt, next: KInt): KInt => (prev | next), + 0 as KInt + ) // TODO: write implementation export interface TransformationContext {} @@ -29,66 +42,51 @@ export interface TransformationContext {} // TODO: write implementation export interface Program {} -export class Global { - private static _config?: KNativePointer - - public static set config(config: KNativePointer) { - if (Global._config !== undefined) { - throw new Error('Global.config already initialized') - } - Global._config = config - } - - public static get config(): KNativePointer { - return Global._config ?? util.throwError('Global.config not initialized') - } - - public static isInitializedConfig(): boolean { - return (Global._config !== undefined) - } - - private static _context?: KNativePointer - - public static set context(context: KNativePointer) { - Global._context = context - } - - public static get context(): KNativePointer { - return Global._context ?? util.throwError('Global.context not initialized') - } - - public static isInitializedContext(): boolean { - return (Global._context !== undefined) - } -} - export type NodeArray = ts.NodeArray +// TODO: should be interface export abstract class Node implements ts.Node { - peer: KNativePointer + // peer: KNativePointer = NULLPTR + + // abstract readonly node: ets.Node + + // get parent(): Node { + // const _parent = nativeModule._AstNodeParent(global.context, this.peer) + // if (_parent === NULLPTR) { + // util.throwError('BAD ACCESS: PARENT IS NULLPTR') + // } + // return util.nodeByPeer(_parent) + // } + + // set parent(node: Node) { + // nativeModule._AstNodeSetParent(global.context, this.peer, node.peer) + // } + + // private _modifiers?: KInt + parent: any + + readonly _node?: ets.Node + + // get modifiers(): NodeArray { + // if (this._modifiers === undefined) { + // this._modifiers = nativeModule._AstNodeModifiers(global.context, this.peer) + // } + // // TODO: rewrite + // return util.unpackModifiers(this._modifiers) as NodeArray + // } + + // set modifiers(flags: ReadonlyArray | undefined) { + // nativeModule._AstNodeClearModifier(global.context, this.peer, ALL_FLAGS) + // this._modifiers = flags + // if (flags === undefined) { + // return + // } + // nativeModule._AstNodeAddModifier(global.context, this.peer, util.packModifiers(this._modifiers)) + // } + + abstract kind: SyntaxKind - protected constructor(peer: KNativePointer) { - this.peer = peer - } - - get parent(): Node { - return util.nodeByPeer(nativeModule._AstNodeParent(Global.context, this.peer)) - } - - set parent(node: Node) { - nativeModule._AstNodeSetParent(Global.context, this.peer, node.peer) - } - - get modifier(): Es2pandaModifierFlags { - return nativeModule._AstNodeModifiers(Global.context, this.peer) - } - - set modifier(flags: Es2pandaModifierFlags) { - nativeModule._AstNodeClearModifier(Global.context, this.peer, ALL_FLAGS) - nativeModule._AstNodeAddModifier(Global.context, this.peer, flags as KInt) - } - - // TODO: implement + // TODO: support minimal interface getSourceFile(): ts.SourceFile { throw new Error("Method not implemented.") } getChildCount(sourceFile?: ts.SourceFile | undefined): number { throw new Error("Method not implemented.") } getChildAt(index: number, sourceFile?: ts.SourceFile | undefined): ts.Node { throw new Error("Method not implemented.") } @@ -105,23 +103,23 @@ export abstract class Node implements ts.Node { getLastToken(sourceFile?: ts.SourceFile | undefined): ts.Node | undefined { throw new Error("Method not implemented.") } forEachChild(cbNode: (node: ts.Node) => T | undefined, cbNodeArray?: ((nodes: ts.NodeArray) => T | undefined) | undefined): T | undefined { throw new Error("Method not implemented.") } - // TODO: support minimal interface get symbol(): ts.Symbol { return todo() } get flags(): ts.NodeFlags { return todo() } get pos(): number { return todo() } get end(): number { return todo() } - abstract kind: ts.SyntaxKind } // TODO: add all tokens export type BinaryOperator = | ts.SyntaxKind.PlusToken + | ts.SyntaxKind.MinusToken export type BinaryOperatorToken = Token; // TODO: rethink maybe (temporary solution) -export class Token { +export class Token extends Node { constructor(kind: TKind) { + super() this.kind = kind } @@ -129,107 +127,151 @@ export class Token { } export type ModifierSyntaxKind = - | ts.SyntaxKind.AbstractKeyword - | ts.SyntaxKind.AccessorKeyword - | ts.SyntaxKind.AsyncKeyword - | ts.SyntaxKind.ConstKeyword - | ts.SyntaxKind.DeclareKeyword - | ts.SyntaxKind.DefaultKeyword - | ts.SyntaxKind.ExportKeyword - | ts.SyntaxKind.InKeyword - | ts.SyntaxKind.PrivateKeyword - | ts.SyntaxKind.ProtectedKeyword - | ts.SyntaxKind.PublicKeyword - | ts.SyntaxKind.ReadonlyKeyword - | ts.SyntaxKind.OutKeyword - | ts.SyntaxKind.OverrideKeyword - | ts.SyntaxKind.StaticKeyword; - -// TODO: rethink maybe (temporary solution) -export class ModifierToken extends Token { - constructor(kind: TKind) { - super(kind) + // | SyntaxKind.ConstructorKeyword + | SyntaxKind.AbstractKeyword + | SyntaxKind.AccessorKeyword + | SyntaxKind.AsyncKeyword + | SyntaxKind.ConstKeyword + | SyntaxKind.DeclareKeyword + | SyntaxKind.DefaultKeyword + | SyntaxKind.ExportKeyword + | SyntaxKind.InKeyword + | SyntaxKind.PrivateKeyword + | SyntaxKind.ProtectedKeyword + | SyntaxKind.PublicKeyword + | SyntaxKind.ReadonlyKeyword + | SyntaxKind.OutKeyword + | SyntaxKind.OverrideKeyword + | SyntaxKind.StaticKeyword; + +export class Modifier extends Node { + constructor(kind: ModifierSyntaxKind) { + super() this.kind = kind } - readonly kind: TKind; + public toString(): string { + return `${global.modifierFlags.get(this.kind)}` + } + + kind: ModifierSyntaxKind } -export type AbstractKeyword = ModifierToken; -export type AccessorKeyword = ModifierToken; -export type AsyncKeyword = ModifierToken; -export type ConstKeyword = ModifierToken; -export type DeclareKeyword = ModifierToken; -export type DefaultKeyword = ModifierToken; -export type ExportKeyword = ModifierToken; -export type InKeyword = ModifierToken; -export type PrivateKeyword = ModifierToken; -export type ProtectedKeyword = ModifierToken; -export type PublicKeyword = ModifierToken; -export type ReadonlyKeyword = ModifierToken; -export type OutKeyword = ModifierToken; -export type OverrideKeyword = ModifierToken; -export type StaticKeyword = ModifierToken; - -export type Modifier = - | AbstractKeyword - | AccessorKeyword - | AsyncKeyword - | ConstKeyword - | DeclareKeyword - | DefaultKeyword - | ExportKeyword - | InKeyword - | PrivateKeyword - | ProtectedKeyword - | PublicKeyword - | OutKeyword - | OverrideKeyword - | ReadonlyKeyword - | StaticKeyword; - -// export type ModifierLike = Modifier | Decorator; -export type ModifierLike = Modifier; +// export class FunctionDeclaration extends Node implements ts.FunctionDeclaration, FunctionLikeDeclarationBase { +export class FunctionDeclaration extends Node implements ts.FunctionDeclaration { + constructor(_node: ets.FunctionDeclaration) { + super() + this._node = _node + this.name = unpackNode(this._node.name) + this.body = unpackNode(this._node.body) + this.typeParameters = unpackNodeArray(this._node.typeParamsDecl?.parameters) + this.type = unpackNode(this._node.type) + this.parameters = unpackNodeArray(this._node.parameters) + } -export class FunctionDeclaration extends Node implements ts.FunctionDeclaration { + readonly _node: ets.FunctionDeclaration + + readonly name?: Identifier | undefined + readonly body?: Block | undefined + readonly typeParameters?: NodeArray | undefined; + readonly type?: TypeNode | undefined + readonly parameters: NodeArray + readonly kind: ts.SyntaxKind.FunctionDeclaration = ts.SyntaxKind.FunctionDeclaration + + // TODO: support minimal interface + asteriskToken?: ts.AsteriskToken | undefined + modifiers?: ts.NodeArray | undefined + _functionLikeDeclarationBrand: any + _declarationBrand: any + _statementBrand: any + questionToken?: ts.QuestionToken | undefined + exclamationToken?: ts.ExclamationToken | undefined + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined +} +/* +// TODO: find the difference between this and FunctionDeclaration +export class FunctionExpression extends NodeBase implements ts.FunctionExpression, FunctionLikeDeclarationBase { constructor(peer: KNativePointer) { super(peer) } private get _scriptFunction() { - return nativeModule._FunctionDeclarationFunction(Global.context, this.peer) + return nativeModule._FunctionDeclarationFunction(global.context, this.peer) } get name(): Identifier { - return util.nodeByPeer(nativeModule._ScriptFunctionId(Global.context, this._scriptFunction)) as Identifier + return util.nodeByPeer(nativeModule._ScriptFunctionId(global.context, this._scriptFunction)) as Identifier } get body(): Block { - return util.nodeByPeer(nativeModule._ScriptFunctionBody(Global.context, this._scriptFunction)) as Block + return util.nodeByPeer(nativeModule._ScriptFunctionBody(global.context, this._scriptFunction)) as Block } get parameters(): NodeArray { - const params = nativeModule._ScriptFunctionParams(Global.context, this._scriptFunction) + const params = nativeModule._ScriptFunctionParams(global.context, this._scriptFunction) return util.unpack(params) as NodeArray } // TODO: support minimal interface + _primaryExpressionBrand: any + _memberExpressionBrand: any + _leftHandSideExpressionBrand: any + _updateExpressionBrand: any + _unaryExpressionBrand: any + _expressionBrand: any + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined _functionLikeDeclarationBrand: any + asteriskToken?: ts.AsteriskToken | undefined + questionToken?: ts.QuestionToken | undefined + exclamationToken?: ts.ExclamationToken | undefined + typeParameters?: NodeArray | undefined + type?: TypeNode | undefined _declarationBrand: any - _statementBrand: any - kind: ts.SyntaxKind.FunctionDeclaration = ts.SyntaxKind.FunctionDeclaration + kind: ts.SyntaxKind.FunctionExpression = ts.SyntaxKind.FunctionExpression } +*/ export class Identifier extends Node implements ts.Identifier, Expression { - constructor(peer: KNativePointer) { - super(peer) + constructor(_node: ets.Identifier) { + super() + this._node = _node + this.text = this._node.name } - get text(): string { - return withStringResult(nativeModule._IdentifierName(Global.context, this.peer)) ?? util.throwError(`COULDN'T GET: _IdentifierName`) + readonly _node: ets.Identifier + readonly text: string + readonly kind: ts.SyntaxKind.Identifier = ts.SyntaxKind.Identifier + + // TODO: support minimal interface + get escapedText(): ts.__String { return todo() } + _primaryExpressionBrand: any + _memberExpressionBrand: any + _leftHandSideExpressionBrand: any + _updateExpressionBrand: any + _unaryExpressionBrand: any + _expressionBrand: any + _declarationBrand: any +} + +export class PrivateIdentifier extends Node implements ts.PrivateIdentifier, Expression { + constructor(_node: ets.Identifier) { + super() + this._node = _node + this.text = this._node.name + if (!this._node.isPrivate) { + throwError('identifier expected to be private') + } } + readonly _node: ets.Identifier + readonly text: string + readonly kind: ts.SyntaxKind.PrivateIdentifier = ts.SyntaxKind.PrivateIdentifier + // TODO: support minimal interface get escapedText(): ts.__String { return todo() } _primaryExpressionBrand: any @@ -239,7 +281,6 @@ export class Identifier extends Node implements ts.Identifier, Expression { _unaryExpressionBrand: any _expressionBrand: any _declarationBrand: any - kind: ts.SyntaxKind.Identifier = ts.SyntaxKind.Identifier } // TODO: should be interface, not abstract class @@ -249,38 +290,35 @@ export abstract class Statement extends Node implements ts.Statement { } export class Block extends Node implements ts.Block { - constructor(peer: KNativePointer) { - super(peer) - } + constructor(_node: ets.Block) { + super() + this._node = _node - private _statements?: NodeArray - get statements(): NodeArray { - if (this._statements === undefined) { - const statementsPtr = nativeModule._BlockStatementStatements(Global.context, this.peer) - this._statements = util.unpack(statementsPtr) as NodeArray - } - return this._statements + this.statements = unpackNodeArray(this._node.statements) } + readonly _node: ets.Block + + readonly statements: NodeArray + readonly kind: ts.SyntaxKind.Block = ts.SyntaxKind.Block + // TODO: support minimal interface _statementBrand: any - kind: ts.SyntaxKind.Block = ts.SyntaxKind.Block } export class SourceFile extends Node implements ts.SourceFile { - constructor(peer: KNativePointer) { - super(peer) - } + constructor(_node: ets.Program) { + super() + this._node = _node - private _statements?: NodeArray - get statements(): NodeArray { - if (this._statements === undefined) { - const statementsPtr = nativeModule._BlockStatementStatements(Global.context, this.peer) - this._statements = util.unpack(statementsPtr) as NodeArray - } - return this._statements + this.statements = unpackNodeArray(this._node.statements) } + readonly _node: ets.Program + + readonly statements: NodeArray + readonly kind: ts.SyntaxKind.SourceFile = ts.SyntaxKind.SourceFile + moduleName: string | undefined getLineAndCharacterOfPosition(pos: number): ts.LineAndCharacter { throw new Error("Method not implemented.") } getLineEndOfPosition(pos: number): number { throw new Error("Method not implemented.") } @@ -301,15 +339,25 @@ export class SourceFile extends Node implements ts.SourceFile { get hasNoDefaultLib(): boolean { return todo() } get languageVersion(): ts.ScriptTarget { return todo() } _declarationBrand: any - kind: ts.SyntaxKind.SourceFile = ts.SyntaxKind.SourceFile + impliedNodeFormat?: ts.ModuleKind.CommonJS | ts.ModuleKind.ESNext | undefined + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined + modifiers?: ts.NodeArray | undefined } export abstract class Expression extends Node implements ts.Expression { + abstract readonly _node: ets.Node + + // TODO: support minimal interface _expressionBrand: any kind: any } export abstract class LeftHandSideExpression extends Node implements ts.LeftHandSideExpression, Expression { + abstract readonly _node: ets.Node + + // TODO: support minimal interface _leftHandSideExpressionBrand: any _updateExpressionBrand: any _unaryExpressionBrand: any @@ -318,40 +366,32 @@ export abstract class LeftHandSideExpression extends Node implements ts.LeftHand } export class ExpressionStatement extends Node implements ts.ExpressionStatement, Statement { - constructor(peer: KNativePointer) { - super(peer) + constructor(_node: ets.ExpressionStatement) { + super() + this._node = _node + this.expression = arktsNodeByEtsNode(this._node.expression) as Expression } - get expression(): Expression { - return util.nodeByPeer(nativeModule._ExpressionStatementGetExpression(Global.context, this.peer)) as Expression - } + readonly _node: ets.ExpressionStatement + readonly kind: ts.SyntaxKind.ExpressionStatement = ts.SyntaxKind.ExpressionStatement + readonly expression: Expression // TODO: support minimal interface _statementBrand: any - kind: ts.SyntaxKind.ExpressionStatement = ts.SyntaxKind.ExpressionStatement } export class CallExpression extends Node implements ts.CallExpression, LeftHandSideExpression { - constructor(peer: KNativePointer) { - super(peer) - } - - private _expression?: LeftHandSideExpression - get expression(): LeftHandSideExpression { - if (this._expression === undefined) { - this._expression = util.nodeByPeer(nativeModule._CallExpressionCallee(Global.context, this.peer)) as LeftHandSideExpression - } - return this._expression + constructor(_node: ets.CallExpression) { + super() + this._node = _node + this.expression = arktsNodeByEtsNode(this._node.expression) as LeftHandSideExpression + this.arguments = unpackNodeArray(this._node.arguments) } - private _arguments?: NodeArray - get arguments(): NodeArray { - if (this._arguments === undefined) { - const argumentsPtr = nativeModule._CallExpressionArguments(Global.context, this.peer, NULLPTR) - this._arguments = util.unpack(argumentsPtr) as NodeArray - } - return this._arguments - } + readonly _node: ets.CallExpression + readonly kind: ts.SyntaxKind.CallExpression = ts.SyntaxKind.CallExpression + readonly expression: LeftHandSideExpression + readonly arguments: NodeArray // TODO: support minimal interface _leftHandSideExpressionBrand: any @@ -359,29 +399,20 @@ export class CallExpression extends Node implements ts.CallExpression, LeftHandS _unaryExpressionBrand: any _expressionBrand: any _declarationBrand: any - kind: ts.SyntaxKind.CallExpression = ts.SyntaxKind.CallExpression } export class PropertyAccessExpression extends Node implements ts.PropertyAccessExpression, Expression { - constructor(peer: KNativePointer) { - super(peer) + constructor(_node: ets.MemberExpression) { + super() + this._node = _node + this.expression = unpackNode(this._node.object) + this.name = unpackNode(this._node.property) } - private _name?: Identifier - get name() { - if (this._name === undefined) { - this._name = util.nodeByPeer(nativeModule._MemberExpressionProperty(Global.context, this.peer)) as Identifier - } - return this._name - } + readonly _node: ets.MemberExpression - private _expression?: LeftHandSideExpression - get expression(): LeftHandSideExpression { - if (this._expression === undefined) { - this._expression = util.nodeByPeer(nativeModule._MemberExpressionObject(Global.context, this.peer)) as LeftHandSideExpression - } - return this._expression - } + readonly expression: LeftHandSideExpression + readonly name: Identifier // TODO: support minimal interface _memberExpressionBrand: any @@ -394,14 +425,16 @@ export class PropertyAccessExpression extends Node implements ts.PropertyAccessE } export class StringLiteral extends Node implements ts.StringLiteral { - constructor(peer: KNativePointer) { - super(peer) - } + constructor(_node: ets.StringLiteral) { + super() + this._node = _node - get text(): string { - return withStringResult(nativeModule._StringLiteralString(Global.context, this.peer)) ?? util.throwError(`COULDN'T GET: _StringLiteralString`) + this.text = this._node.str } + readonly _node: ets.StringLiteral + readonly text: string + // TODO: support minimal interface _literalExpressionBrand: any _primaryExpressionBrand: any @@ -413,29 +446,37 @@ export class StringLiteral extends Node implements ts.StringLiteral { _declarationBrand: any kind: ts.SyntaxKind.StringLiteral = ts.SyntaxKind.StringLiteral } - -export class ClassDeclaration extends Node implements ts.ClassDeclaration { +/* +export class ClassDeclaration extends NodeBase implements ts.ClassDeclaration { constructor(peer: KNativePointer) { super(peer) - this._definition = nativeModule._ClassDeclarationDefinition(Global.context, peer) - this.members = util.unpack(nativeModule._ClassDefinitionBody(Global.context, this._definition)) as NodeArray - this.name = util.nodeByPeer(nativeModule._ClassDefinitionIdent(Global.context, this._definition)) as Identifier + + this._definition = nativeModule._ClassDeclarationDefinition(global.context, peer) + this.members = util.unpack(nativeModule._ClassDefinitionBody(global.context, this._definition)) as NodeArray + this.name = util.nodeByPeer(nativeModule._ClassDefinitionIdent(global.context, this._definition)) as Identifier + + const _typeParamDecl = nativeModule._ClassDefinitionTypeParamsConst(global.context, this._definition) + this._typeParameters = (_typeParamDecl !== NULLPTR) ? nativeModule._TSTypeParameterDeclarationParamsConst(global.context, _typeParamDecl, NULLPTR) : NULLPTR + this.typeParameters = (this._typeParameters !== NULLPTR) ? (util.unpack(this._typeParameters) as NodeArray) : undefined } private _definition readonly members: NodeArray + readonly name: Identifier + private readonly _typeParameters: KNativePointer + readonly typeParameters?: NodeArray | undefined; + // TODO: support minimal interface _declarationBrand: any _statementBrand: any kind: ts.SyntaxKind.ClassDeclaration = ts.SyntaxKind.ClassDeclaration } - +*/ export abstract class ClassElement extends Node implements ts.ClassElement { - // tsc: readonly name?: PropertyName - readonly name?: Identifier + readonly name?: PropertyName // TODO: support minimal interface _declarationBrand: any @@ -443,14 +484,88 @@ export abstract class ClassElement extends Node implements ts.ClassElement { kind: any } +export type MemberName = Identifier | PrivateIdentifier; + +// TODO: support +// export type PropertyName = Identifier | StringLiteral | NumericLiteral | ts.ComputedPropertyName | PrivateIdentifier; +export type PropertyName = Identifier | StringLiteral | NumericLiteral | PrivateIdentifier; + +// TODO: support +export type DeclarationName = + | PropertyName + // | JsxAttributeName + // | StringLiteralLike + // | ElementAccessExpression + // | BindingPattern + // | EntityNameExpression; + +export interface Declaration extends Node { + _declarationBrand: any +} + + +export abstract class NamedDeclaration extends Node implements ts.NamedDeclaration, Declaration { + name?: DeclarationName + _declarationBrand: any +} +/* +export type SignatureDeclaration = ts.CallSignatureDeclaration | ts.ConstructSignatureDeclaration | MethodSignature | ts.IndexSignatureDeclaration | FunctionTypeNode | ts.ConstructorTypeNode | ts.JSDocFunctionType | FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | ts.AccessorDeclaration | FunctionExpression | ArrowFunction; + +export interface SignatureDeclarationBase extends NamedDeclaration { + readonly kind: SignatureDeclaration["kind"]; + readonly name?: PropertyName; + readonly typeParameters?: NodeArray | undefined; + readonly parameters: NodeArray; + readonly type?: TypeNode | undefined; +} + +export type VariableLikeDeclaration = ts.VariableDeclaration | ParameterDeclaration | ts.BindingElement | PropertyDeclaration | ts.PropertyAssignment | PropertySignature | ts.JsxAttribute | ts.ShorthandPropertyAssignment | ts.EnumMember | ts.JSDocPropertyTag | ts.JSDocParameterTag; + +export interface FunctionLikeDeclarationBase extends SignatureDeclarationBase { + _functionLikeDeclarationBrand: any; + readonly asteriskToken?: ts.AsteriskToken | undefined; + readonly questionToken?: ts.QuestionToken | undefined; + readonly exclamationToken?: ts.ExclamationToken | undefined; + readonly body?: Block | Expression | undefined; +} + +// TODO: support +// export type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | ts.GetAccessorDeclaration | ts.SetAccessorDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction; +export type FunctionLikeDeclaration = FunctionDeclaration | MethodDeclaration | ConstructorDeclaration | FunctionExpression | ArrowFunction; + +export class MethodSignature extends NodeBase implements ts.MethodSignature, SignatureDeclarationBase { + constructor(peer: KNativePointer) { + super(peer) + } + + // TODO: support minimal interface + get parent(): any { return todo() } + // name: PropertyName + name: any + typeParameters?: NodeArray | undefined + // parameters: NodeArray + parameters: any + type?: TypeNode | undefined + _declarationBrand: any + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined + _typeElementBrand: any + questionToken?: ts.QuestionToken | undefined + kind: ts.SyntaxKind.MethodSignature = ts.SyntaxKind.MethodSignature +} + // ets: MethodDefinition -export class MethodDeclaration extends Node implements ts.MethodDeclaration, ClassElement { +export class MethodDeclaration extends NodeBase implements ts.MethodDeclaration, FunctionLikeDeclarationBase, ClassElement { constructor(peer: KNativePointer) { super(peer) - this._scriptFunction = nativeModule._MethodDefinitionFunction(Global.context, peer) - this.name = util.nodeByPeer(nativeModule._ScriptFunctionId(Global.context, this._scriptFunction)) as Identifier - this.parameters = util.unpack(nativeModule._ScriptFunctionParams(Global.context, this._scriptFunction)) as NodeArray - this.body = util.nodeByPeer(nativeModule._ScriptFunctionBody(Global.context, this._scriptFunction)) as Block + + this._scriptFunction = nativeModule._MethodDefinitionFunction(global.context, peer) + this.name = util.nodeByPeer(nativeModule._ScriptFunctionId(global.context, this._scriptFunction)) as Identifier + this.parameters = util.unpack(nativeModule._ScriptFunctionParams(global.context, this._scriptFunction)) as NodeArray + if (util.scriptFunctionHasBody(this._scriptFunction)) { + this.body = util.nodeByPeer(nativeModule._ScriptFunctionBody(global.context, this._scriptFunction)) as Block + } } // tsc: readonly name?: PropertyName @@ -459,7 +574,7 @@ export class MethodDeclaration extends Node implements ts.MethodDeclaration, Cla readonly parameters: NodeArray // tsc: readonly body?: FunctionBody | undefined - readonly body: Block + readonly body?: Block | undefined private readonly _scriptFunction: KNativePointer @@ -473,13 +588,14 @@ export class MethodDeclaration extends Node implements ts.MethodDeclaration, Cla } // ets: MethodDefinition -export class ConstructorDeclaration extends Node implements ts.ConstructorDeclaration, ClassElement { +export class ConstructorDeclaration extends NodeBase implements ts.ConstructorDeclaration, FunctionLikeDeclarationBase, ClassElement { constructor(peer: KNativePointer) { super(peer) - this._scriptFunction = nativeModule._MethodDefinitionFunction(Global.context, peer) - this.name = util.nodeByPeer(nativeModule._ScriptFunctionId(Global.context, this._scriptFunction)) as Identifier - this.parameters = util.unpack(nativeModule._ScriptFunctionParams(Global.context, this._scriptFunction)) as NodeArray - this.body = util.nodeByPeer(nativeModule._ScriptFunctionBody(Global.context, this._scriptFunction)) as Block + + this._scriptFunction = nativeModule._MethodDefinitionFunction(global.context, peer) + this.name = util.nodeByPeer(nativeModule._ScriptFunctionId(global.context, this._scriptFunction)) as Identifier + this.parameters = util.unpack(nativeModule._ScriptFunctionParams(global.context, this._scriptFunction)) as NodeArray + this.body = util.nodeByPeer(nativeModule._ScriptFunctionBody(global.context, this._scriptFunction)) as Block } // tsc: readonly name?: PropertyName @@ -501,101 +617,262 @@ export class ConstructorDeclaration extends Node implements ts.ConstructorDeclar kind: ts.SyntaxKind.Constructor = ts.SyntaxKind.Constructor } -export class PropertyDeclaration extends Node implements ts.PropertyDeclaration { +export class PropertySignature extends NodeBase implements ts.TypeElement { + constructor(peer: KNativePointer) { + super(peer) + } + + // TODO: support minimal interface + _typeElementBrand: any + name?: PropertyName | undefined + questionToken?: ts.QuestionToken | undefined + _declarationBrand: any + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined + kind: ts.SyntaxKind.PropertySignature = ts.SyntaxKind.PropertySignature +} + +export class PropertyDeclaration extends NodeBase implements ts.PropertyDeclaration, ClassElement { constructor(peer: KNativePointer) { super(peer) } // TODO: support minimal interface get parent(): any { return todo() } - get name(): ts.PropertyName { return todo() } + get name(): PropertyName { return todo() } _classElementBrand: any _declarationBrand: any kind: ts.SyntaxKind.PropertyDeclaration = ts.SyntaxKind.PropertyDeclaration } -export class ParameterDeclaration extends Node implements ts.ParameterDeclaration { +export class GetAccessorDeclaration extends NodeBase implements ts.GetAccessorDeclaration, FunctionLikeDeclarationBase, ClassElement { constructor(peer: KNativePointer) { super(peer) } // TODO: support minimal interface get parent(): any { return todo() } - get name(): ts.BindingName { return todo() } + // name: PropertyName + name: any + body?: Block | undefined + _functionLikeDeclarationBrand: any + asteriskToken?: ts.AsteriskToken | undefined + questionToken?: ts.QuestionToken | undefined + exclamationToken?: ts.ExclamationToken | undefined + typeParameters?: NodeArray | undefined + // parameters: NodeArray + parameters: any + type?: TypeNode | undefined _declarationBrand: any - kind: ts.SyntaxKind.Parameter = ts.SyntaxKind.Parameter + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined + _classElementBrand: any + _typeElementBrand: any + _objectLiteralBrand: any + kind: ts.SyntaxKind.GetAccessor = ts.SyntaxKind.GetAccessor } -export class ETSPrimitiveType extends Node implements ts.Node, TypeNode { +export class SetAccessorDeclaration extends NodeBase implements ts.SetAccessorDeclaration, FunctionLikeDeclarationBase, ClassElement { constructor(peer: KNativePointer) { super(peer) } // TODO: support minimal interface - _typeNodeBrand: any - kind: ts.SyntaxKind.Unknown = ts.SyntaxKind.Unknown + get parent(): any { return todo() } + // name: PropertyName + name: any + body?: Block | undefined + _functionLikeDeclarationBrand: any + asteriskToken?: ts.AsteriskToken | undefined + questionToken?: ts.QuestionToken | undefined + exclamationToken?: ts.ExclamationToken | undefined + typeParameters?: NodeArray | undefined + // parameters: NodeArray + parameters: any + type?: TypeNode | undefined + _declarationBrand: any + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined + _classElementBrand: any + _typeElementBrand: any + _objectLiteralBrand: any + kind: ts.SyntaxKind.SetAccessor = ts.SyntaxKind.SetAccessor +} +*/ +export class ParameterDeclaration extends Node implements ts.ParameterDeclaration, NamedDeclaration { + constructor(_node: ets.ETSParameterExpression) { + super() + this._node = _node + } + + readonly _node: ets.ETSParameterExpression + + readonly kind: ts.SyntaxKind.Parameter = ts.SyntaxKind.Parameter + + // TODO: support minimal interface + get name(): Identifier { return todo() } + _declarationBrand: any +} +/* +export type BindingName = Identifier | ts.BindingPattern; + +// ets: VariableDeclaratorId +export class VariableDeclaration extends NodeBase implements ts.VariableDeclaration, NamedDeclaration { + constructor(peer: KNativePointer) { + super(peer) + + this.name = util.nodeByPeer(nativeModule._VariableDeclaratorId(global.context, this.peer)) as Identifier + } + + name: Identifier + + // TODO: support minimal interface + get parent(): any { return todo() } + exclamationToken?: ts.ExclamationToken | undefined + type?: ts.TypeNode | undefined + initializer?: ts.Expression | undefined + _declarationBrand: any + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined + kind: ts.SyntaxKind.VariableDeclaration = ts.SyntaxKind.VariableDeclaration +} + +export class VariableDeclarationList extends NodeBase implements ts.VariableDeclarationList { + constructor(peer: KNativePointer) { + super(peer) + + this.declarations = util.unpack(nativeModule._VariableDeclarationDeclaratorsConst(global.context, this.peer)) as NodeArray + } + + // TODO: support minimal interface + get parent(): any { return todo() } + readonly declarations: NodeArray + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined + kind: ts.SyntaxKind.VariableDeclarationList = ts.SyntaxKind.VariableDeclarationList +} +*/ +export class TypeParameterDeclaration extends Node implements ts.TypeParameterDeclaration { + constructor(_node: ets.TSTypeParameter) { + super() + this._node = _node + this.name = unpackNode(this._node.name) + } + + readonly _node: ets.TSTypeParameter + + readonly name: Identifier + + readonly kind: ts.SyntaxKind.TypeParameter = ts.SyntaxKind.TypeParameter + + // TODO: support minimal interface + constraint?: ts.TypeNode | undefined + default?: ts.TypeNode | undefined + expression?: ts.Expression | undefined + _declarationBrand: any + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined } // TODO: should be interface, not abstract class export abstract class TypeNode extends Node implements ts.TypeNode { + // TODO: support minimal interface _typeNodeBrand: any kind: any } export class KeywordTypeNode extends Node implements ts.KeywordTypeNode, TypeNode { - constructor(peer: KNativePointer) { - super(peer) + constructor(_node: ets.ETSPrimitiveType | ets.ETSTypeReference) { + super() + this._node = _node } + readonly _node: ets.ETSPrimitiveType | ets.ETSTypeReference + + readonly kind: ts.KeywordTypeSyntaxKind = ts.SyntaxKind.UnknownKeyword + // TODO: support minimal interface _typeNodeBrand: any - kind: ts.KeywordTypeSyntaxKind = ts.SyntaxKind.UnknownKeyword } export class TypeReferenceNode extends Node implements ts.TypeReferenceNode, TypeNode { - constructor(peer: KNativePointer) { - super(peer) + constructor(_node: ets.Node) { + super() + this._node = _node } + readonly _node: ets.Node + + readonly kind: ts.SyntaxKind.TypeReference = ts.SyntaxKind.TypeReference + // TODO: support minimal interface _typeNodeBrand: any typeName: any - kind: ts.SyntaxKind.TypeReference = ts.SyntaxKind.TypeReference } +// export class FunctionTypeNode extends Node implements ts.FunctionTypeNode, TypeNode, SignatureDeclarationBase { export class FunctionTypeNode extends Node implements ts.FunctionTypeNode, TypeNode { - constructor(peer: KNativePointer) { - super(peer) + constructor(_node: ets.Node) { + super() + this._node = _node } + readonly _node: ets.Node + + readonly kind: ts.SyntaxKind.FunctionType = ts.SyntaxKind.FunctionType + // TODO: support minimal interface - get parent(): any { return todo() } - get parameters(): ts.NodeArray { return todo() } + readonly name?: PropertyName; + get parameters(): NodeArray { return todo() } type: any _typeNodeBrand: any _declarationBrand: any - kind: ts.SyntaxKind.FunctionType = ts.SyntaxKind.FunctionType } -export class ReturnStatement extends Node implements ts.ReturnStatement, Statement { - constructor(peer: KNativePointer) { - super(peer) +export class UnionTypeNode extends Node implements ts.UnionTypeNode, TypeNode { + constructor(_node: ets.UnionTypeNode) { + super() + this._node = _node + this.types = unpackNodeArray(this._node.types) } - private _expression?: Expression - get expression(): Expression | undefined { - if (this._expression === undefined) { - this._expression = util.nodeByPeer(nativeModule._ReturnStatementArgument(Global.context, this.peer)) as Expression - } - return this._expression + readonly _node: ets.UnionTypeNode + + readonly types: NodeArray + + readonly kind: ts.SyntaxKind.UnionType = ts.SyntaxKind.UnionType + + // TODO: support minimal interface + _typeNodeBrand: any + locals?: ts.SymbolTable | undefined + skipCheck?: boolean | undefined + decorators?: undefined +} + +export class ReturnStatement extends Node implements ts.ReturnStatement, Statement { + constructor(_node: ets.ReturnStatement) { + super() + this._node = _node + this.expression = unpackNullableNode(this._node.argument) } + readonly _node: ets.ReturnStatement + + readonly expression: Expression | undefined + + readonly kind: ts.SyntaxKind.ReturnStatement = ts.SyntaxKind.ReturnStatement + // TODO: support minimal interface _statementBrand: any - kind: ts.SyntaxKind.ReturnStatement = ts.SyntaxKind.ReturnStatement } - -export class IfStatement extends Node implements ts.IfStatement { +/* +export class IfStatement extends NodeBase implements ts.IfStatement { constructor(peer: KNativePointer) { super(peer) } @@ -607,7 +884,7 @@ export class IfStatement extends Node implements ts.IfStatement { kind: ts.SyntaxKind.IfStatement = ts.SyntaxKind.IfStatement } -export class BinaryExpression extends Node implements ts.BinaryExpression { +export class BinaryExpression extends NodeBase implements ts.BinaryExpression { constructor(peer: KNativePointer) { super(peer) } @@ -621,12 +898,27 @@ export class BinaryExpression extends Node implements ts.BinaryExpression { kind: ts.SyntaxKind.BinaryExpression = ts.SyntaxKind.BinaryExpression } -export class ArrowFunction extends Node implements ts.ArrowFunction { +export class AssignmentExpression extends NodeBase implements ts.AssignmentExpression { constructor(peer: KNativePointer) { super(peer) - this._scriptFunction = nativeModule._ArrowFunctionExpressionFunction(Global.context, this.peer) - this.parameters = util.unpack(nativeModule._ScriptFunctionParams(Global.context, this._scriptFunction)) as NodeArray - this.body = util.nodeByPeer(nativeModule._ScriptFunctionBody(Global.context, this._scriptFunction)) as Block + } + + // TODO: support minimal interface + right: any + _expressionBrand: any + _declarationBrand: any + readonly left: any + readonly operatorToken: any + kind: ts.SyntaxKind.BinaryExpression = ts.SyntaxKind.BinaryExpression +} + +export class ArrowFunction extends NodeBase implements ts.ArrowFunction { + constructor(peer: KNativePointer) { + super(peer) + + this._scriptFunction = nativeModule._ArrowFunctionExpressionFunction(global.context, this.peer) + this.parameters = util.unpack(nativeModule._ScriptFunctionParams(global.context, this._scriptFunction)) as NodeArray + this.body = util.nodeByPeer(nativeModule._ScriptFunctionBody(global.context, this._scriptFunction)) as Block } get name(): never { @@ -645,16 +937,21 @@ export class ArrowFunction extends Node implements ts.ArrowFunction { _declarationBrand: any readonly kind: ts.SyntaxKind.ArrowFunction = ts.SyntaxKind.ArrowFunction } +*/ +export class NumericLiteral extends Node implements ts.NumericLiteral, Declaration { + constructor(_node: ets.NumberLiteral) { + super() + this._node = _node -export class NumericLiteral extends Node implements ts.NumericLiteral { - constructor(peer: KNativePointer) { - super(peer) + this.text = this._node.str } + readonly _node: ets.NumberLiteral + readonly text: string + // TODO: support minimal interface _literalExpressionBrand: any _declarationBrand: any - text: any _primaryExpressionBrand: any _memberExpressionBrand: any _leftHandSideExpressionBrand: any @@ -663,26 +960,32 @@ export class NumericLiteral extends Node implements ts.NumericLiteral { _expressionBrand: any readonly kind: ts.SyntaxKind.NumericLiteral = ts.SyntaxKind.NumericLiteral } - -export class VariableStatement extends Node implements ts.VariableStatement { +/* +// ets: VariableDeclaration +export class VariableStatement extends NodeBase implements ts.VariableStatement { constructor(peer: KNativePointer) { super(peer) + + this.declarationList = factory.createVariableDeclarationList(util.unpack(nativeModule._VariableDeclarationDeclaratorsConst(global.context, this.peer)) as NodeArray) } // TODO: support minimal interface - modifiers?: ts.NodeArray | undefined - declarationList: any + readonly declarationList: VariableDeclarationList; _statementBrand: any locals?: ts.SymbolTable | undefined skipCheck?: boolean | undefined decorators?: undefined readonly kind: ts.SyntaxKind.VariableStatement = ts.SyntaxKind.VariableStatement } +*/ export class UnsupportedNode extends Node implements ts.Node { - constructor(peer: KNativePointer) { - super(peer) + constructor(_node: ets.Node) { + super() + this._node = _node } + readonly _node: ets.Node + kind: ts.SyntaxKind = UNSUPPORTED_KIND } diff --git a/arkoala-arkts/libarkts/src/arkts/typesEts.ts b/arkoala-arkts/libarkts/src/arkts/typesEts.ts new file mode 100644 index 000000000..73dbd63f1 --- /dev/null +++ b/arkoala-arkts/libarkts/src/arkts/typesEts.ts @@ -0,0 +1,609 @@ +import { nativeModule } from "../NativeModule" +import { KInt, KNativePointer as KPtr, withStringResult, withStringArray, KNativePointer } from "@koalaui/interop" +import * as util from "./utilities" +import global from "./global" +import * as arkts from "." +import { + Es2pandaPrimitiveType, + Es2pandaModifierFlags, + SyntaxKind, + Es2pandaScriptFunctionFlags, + es2pandaKind, +} from "./enums" +import { + throwError, + passString, + passEtsNode, + passEtsNodeArray, + unpackEtsNode, + unpackEtsNodeArray, + etsNodeByPeer, + etsNodeByPeerNullable, +} from "./utilities" +import { updateChildren } from "./factory/utilities" + +export const NULLPTR: KPtr = BigInt(0) + +export const NULLPTR_ARRAY = new BigUint64Array([NULLPTR]) + +export const ALL_FLAGS: KInt = Object.values(Es2pandaModifierFlags).filter( + (value: any) => { return (typeof value) === 'number' } + ).reduce( + (prev: KInt, next: KInt): KInt => (prev | next), + 0 as KInt + ) + +function assertValidPeer(peer: KPtr, expectedKind: es2pandaKind): void { + if (peer === NULLPTR) { + throwError(`invalid peer: NULLPTR`) + } + const peerKind = nativeModule._GetKind(global.context, peer) + if (peerKind !== expectedKind) { + throwError(`invalid kind of peer: ${peerKind} expected: ${expectedKind}`) + } +} + +export abstract class EtsObject { + constructor(peer: KPtr) { + this.peer = peer + } + + // pointer associated with native object + readonly peer: KPtr +} + +export abstract class Node extends EtsObject { + constructor(peer: KPtr) { + if (peer === NULLPTR) { + throw new Error('trying to create new Node on NULLPTR') + } + super(peer) + this.kind = nativeModule._GetKind(global.context, this.peer) + nativeModule._AstNodeUpdateChildren(global.context, peer) + } + + readonly kind: es2pandaKind + + dumpJson(): string { + return withStringResult(nativeModule._AstNodeDumpJsonConst(global.context, this.peer)) ?? throwError('failed to dump Json') + } + + dumpSrc(): string { + return withStringResult(nativeModule._AstNodeDumpEtsSrcConst(global.context, this.peer)) ?? throwError('failed to dump Src') + } + + dumpModifierFlags(): string { + return withStringResult(nativeModule._AstNodeDumpModifiers(global.context, this.peer)) ?? throwError('failed to dump ModifierFlags') + } + + get parent(): KPtr { + const _parent = nativeModule._AstNodeParent(global.context, this.peer) + if (_parent === NULLPTR) { + util.throwError('BAD ACCESS: PARENT IS NULLPTR') + } + return _parent + } + + set parent(peer: KPtr) { + nativeModule._AstNodeSetParent(global.context, this.peer, peer) + } + + get modifierFlags(): KInt { + return nativeModule._AstNodeModifiers(global.context, this.peer) + } + + set modifierFlags(flags: KInt | undefined) { + nativeModule._AstNodeClearModifier(global.context, this.peer, ALL_FLAGS) + nativeModule._AstNodeAddModifier(global.context, this.peer, flags ?? Es2pandaModifierFlags.MODIFIER_FLAGS_NONE) + } +} + +// export abstract class Node extends EtsNode { +// constructor(peer: KPtr) { +// super(peer) +// this.kind = nativeModule._GetKind(global.context, this.peer) +// updateChildren(this.peer) +// } + +// readonly kind: es2pandaKind +// } + +// export abstract class CompatibleNode extends EtsNode { +// constructor(peer: KPtr, related: arkts.Node) { +// super(peer) +// this.kind = nativeModule._GetKind(global.context, this.peer) +// updateChildren(this.peer) +// this.related = related +// } + +// readonly kind: es2pandaKind +// readonly related: arkts.Node +// } + +export abstract class UnsupportedNode extends Node { + constructor(peer: KPtr) { + super(peer) + throw new Error('trying to create UnsupportedNode') + } +} + +export class Config extends EtsObject { + constructor(peer: KPtr) { + super(peer) + } +} + +export class Context extends EtsObject { + constructor(peer: KPtr) { + super(peer) + } +} + +export class Program extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.Program) + super(peer) + } + + static create( + source: string + ): Program { + if (!global.isInitializedConfig()) { + global.config = withStringArray(["", "--arktsconfig", "./arktsconfig.json", "./input/main.sts"], (stringArray: string[]) => { + return nativeModule._CreateConfig(4, stringArray) + }) + } + global.context = nativeModule._CreateContextFromString(global.config, passString(source), passString("./input/main.sts")) + + // TODO: rewrite this maybe + arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_PARSED) + + return new Program(nativeModule._ProgramAst(nativeModule._ContextProgram(global.context))) + } + + get statements(): readonly Node[] { + return unpackEtsNodeArray(nativeModule._BlockStatementStatements(global.context, this.peer)) + } + + set statements(nodes: readonly Node[]) { + nativeModule._BlockStatementSetStatements(global.context, this.peer, passEtsNodeArray(nodes), nodes.length) + } +} + +export class ExpressionStatement extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ExpressionStatement) + super(peer) + this.expression = etsNodeByPeer(nativeModule._ExpressionStatementGetExpression(global.context, this.peer)) + } + + static create(expression: Node): ExpressionStatement { + return new ExpressionStatement(nativeModule._CreateExpressionStatement(global.context, expression.peer)) + } + + readonly expression: Node +} + +export class CallExpression extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.CallExpression) + super(peer) + this.expression = unpackEtsNode(nativeModule._CallExpressionCallee(global.context, this.peer)) + this.arguments = unpackEtsNodeArray(nativeModule._CallExpressionArguments(global.context, this.peer, NULLPTR)) + } + + static create( + expression: Node, + typeParamsDecl: TSTypeParameterDeclaration | undefined, + args: Node[] | undefined + ): CallExpression { + return new CallExpression( + nativeModule._CreateCallExpression( + global.context, + passEtsNode(expression), + passEtsNodeArray(args), + args?.length ?? 0, + passEtsNode(typeParamsDecl), + false, + false + ) + ) + } + + readonly expression: Node + readonly arguments: readonly Node[] +} + +export class MemberExpression extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.MemberExpression) + super(peer) + this.object = unpackEtsNode(nativeModule._MemberExpressionObject(global.context, this.peer)) + this.property = unpackEtsNode(nativeModule._MemberExpressionProperty(global.context, this.peer)) + } + + static create( + object: Node, + property: Node, + kind: KInt, + computed: boolean, + optional: boolean + ): MemberExpression { + return new MemberExpression( + nativeModule._CreateMemberExpression( + global.context, + passEtsNode(object), + passEtsNode(property), + kind, + computed, + optional + ) + ) + } + + readonly object: Node + readonly property: Node +} + +export class ETSPrimitiveType extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ETSPrimitiveType) + super(peer) + } + + static create( + type: Es2pandaPrimitiveType + ): ETSPrimitiveType { + return new ETSPrimitiveType( + nativeModule._CreateETSPrimitiveType(global.context, type) + ) + } + + // readonly type: Es2pandaPrimitiveType +} + +export class ETSTypeReference extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ETSTypeReference) + super(peer) + } + + static create( + typeName: Identifier + ): ETSTypeReference { + return new ETSTypeReference( + nativeModule._CreateETSTypeReference( + global.context, + ETSTypeReferencePart.create(typeName).peer + ) + ) + } + + // readonly typeName: Identifier + // readonly typeRefPart: TypeReferencePart +} + +export class ETSTypeReferencePart extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ETSTypeReferencePart) + super(peer) + } + + // TODO: support type params and prev + static create(typeName: Identifier) { + typeName.setReference(true) + // TODO: support type params and prev + return new ETSTypeReferencePart( + nativeModule._CreateETSTypeReferencePart( + global.context, + typeName.peer, + NULLPTR, + NULLPTR + ) + ) + } + + // readonly typeName: Identifier +} + +export class UnionTypeNode extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.TSUnionType) + super(peer) + this.types = unpackEtsNodeArray(nativeModule._ETSUnionTypeIrTypesConst(global.context, this.peer, NULLPTR)) + } + + readonly types: readonly Node[] +} + +export class FunctionTypeNode extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ETSFunctionType) + super(peer) + } +} + +export class Identifier extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.Identifier) + super(peer) + this.isPrivate = nativeModule._IdentifierIsPrivateIdentConst(global.context, this.peer) + } + + static create(name: string, typeAnnotation?: Node): Identifier { + if (typeAnnotation === undefined) { + return new Identifier(nativeModule._CreateIdentifier1(global.context, passString(name))) + } else { + return new Identifier(nativeModule._CreateIdentifier2(global.context, passString(name), typeAnnotation.peer)) + } + } + + // TODO: return (string | undefined) maybe + get name(): string { + return withStringResult(nativeModule._IdentifierName(global.context, this.peer)) ?? util.throwError('name is undefined') + } + + set name(name: string) { + nativeModule._IdentifierSetName(global.context, this.peer, passString(name)) + } + + readonly isPrivate: boolean + + setReference(isRef: boolean): void { + nativeModule._IdentifierSetReference(global.context, this.peer, isRef) + } + + // TODO: + // typeAnnotation() + // isOptional() + // setOptional() + // setTsVariables() +} + +export class StringLiteral extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.StringLiteral) + super(peer) + this.str = withStringResult(nativeModule._StringLiteralStrConst(global.context, this.peer)) ?? util.throwError('str is undefined') + } + + static create(str: string): StringLiteral { + return new StringLiteral(nativeModule._CreateStringLiteral(global.context, passString(str))) + } + + readonly str: string +} + +export class NumberLiteral extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.NumberLiteral) + super(peer) + this.str = withStringResult(nativeModule._NumberLiteralStrConst(global.context, this.peer)) ?? util.throwError('str is undefined') + } + + static create(str: string): NumberLiteral { + return new NumberLiteral(nativeModule._CreateNumberLiteral(global.context, passString(str))) + } + + readonly str: string +} + +export class FunctionSignature extends EtsObject { + constructor(peer: KPtr) { + super(peer) + } + + static create( + typeParamsDecl: TSTypeParameterDeclaration | undefined, + params: Node[], + returnTypeAnnotation: Node | undefined, + ): FunctionSignature { + return new FunctionSignature( + nativeModule._CreateFunctionSignature( + global.context, + passEtsNode(typeParamsDecl), + passEtsNodeArray(params), + params.length, + passEtsNode(returnTypeAnnotation) + ) + ) + } +} + +export class ScriptFunction extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ScriptFunction) + super(peer) + } + + static create( + body: Node | undefined, + signature: FunctionSignature, + functionFlags: Es2pandaScriptFunctionFlags, + modifierFlags: Es2pandaModifierFlags, + declare: boolean, + ident: Identifier | undefined + ): ScriptFunction { + const peer = nativeModule._CreateScriptFunction( + global.context, + passEtsNode(body), + signature.peer, + functionFlags, + modifierFlags, + declare + ) + if (ident !== undefined) { + nativeModule._ScriptFunctionSetIdent(global.context, peer, ident.peer) + updateChildren(peer) + } + return new ScriptFunction(peer) + } +} + +export class FunctionDeclaration extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.FunctionDeclaration) + super(peer) + this.scriptFunction = etsNodeByPeer(nativeModule._FunctionDeclarationFunction(global.context, this.peer)) + this.parameters = unpackEtsNodeArray(nativeModule._ScriptFunctionParams(global.context, this.scriptFunction.peer)) + this.name = etsNodeByPeerNullable(nativeModule._ScriptFunctionId(global.context, this.scriptFunction.peer)) + this.body = etsNodeByPeerNullable(nativeModule._ScriptFunctionBody(global.context, this.scriptFunction.peer)) + this.typeParamsDecl = etsNodeByPeerNullable(nativeModule._ScriptFunctionTypeParams(global.context, this.scriptFunction.peer)) + this.type = etsNodeByPeerNullable(nativeModule._ScriptFunctionReturnTypeAnnotation(global.context, this.scriptFunction.peer)) + this.isAnon = nativeModule._FunctionDeclarationIsAnonymousConst(global.context, this.peer) + } + + static create( + scriptFunction: ScriptFunction, + isAnon: boolean + ): FunctionDeclaration { + const node = new FunctionDeclaration( + nativeModule._CreateFunctionDeclaration( + global.context, + scriptFunction.peer, + isAnon + ) + ) + // TODO: maybe wrong + node.modifierFlags = scriptFunction.modifierFlags + return node + } + + readonly scriptFunction: ScriptFunction + readonly parameters: readonly Node[] + readonly name?: Identifier + readonly body?: Block + readonly typeParamsDecl?: TSTypeParameterDeclaration + readonly type?: Node + readonly isAnon: boolean +} + +// export class FunctionExpression extends Node { +// constructor( +// expression: Node +// ) { +// super(nativeModule._CreateFunctionExpression( +// global.context, +// expression.peer +// )) +// this.expression = expression +// } + +// readonly expression: Node +// } + +export class Block extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.Block) + super(peer) + this.statements = unpackEtsNodeArray(nativeModule._BlockStatementStatements(global.context, this.peer)) + } + + static create( + statements: Node[] + ): Block { + return new Block( + nativeModule._CreateBlockStatement( + global.context, + passEtsNodeArray(statements), + statements.length + ) + ) + } + + readonly statements: readonly Node[] +} + +export class ETSParameterExpression extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ETSParameterExpression) + super(peer) + } + + static create( + identifier: Identifier, + initializer: Node | undefined + ): ETSParameterExpression { + return new ETSParameterExpression( + nativeModule._CreateETSParameterExpression( + global.context, + passEtsNode(identifier), + passEtsNode(initializer) + ) + ) + } +} + +export class TSTypeParameterDeclaration extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.TSTypeParameterDeclaration) + super(peer) + this.parameters = unpackEtsNodeArray(nativeModule._TSTypeParameterDeclarationParamsConst(global.context, this.peer, NULLPTR)) + } + + static create( + parameters: TSTypeParameter[], + ): TSTypeParameterDeclaration { + return new TSTypeParameterDeclaration( + nativeModule._CreateTSTypeParameterDeclaration( + global.context, + passEtsNodeArray(parameters), + parameters.length, + // TODO: fix + parameters.length + ) + ) + } + + readonly parameters: readonly TSTypeParameter[] +} + +export class TSTypeParameter extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.TSTypeParameter) + super(peer) + this.name = etsNodeByPeer(nativeModule._TSTypeParameterName(global.context, this.peer)) + } + + static create( + name: Identifier, + constraint: Node | undefined, + defaultType: Node | undefined, + modifierFlags: KInt, + ): TSTypeParameter { + const peer = nativeModule._CreateTSTypeParameter( + global.context, + passEtsNode(name), + passEtsNode(constraint), + passEtsNode(defaultType) + ) + nativeModule._AstNodeClearModifier(global.context, peer, ALL_FLAGS) + nativeModule._AstNodeAddModifier(global.context, peer, modifierFlags) + return new TSTypeParameter(peer) + } + + readonly name: Identifier +} + +export class ReturnStatement extends Node { + constructor(peer: KPtr) { + assertValidPeer(peer, es2pandaKind.ReturnStatement) + super(peer) + this.argument = etsNodeByPeerNullable( + nativeModule._ReturnStatementArgument(global.context, this.peer) + ) + } + + static create( + argument: Node + ): ReturnStatement { + return new ReturnStatement( + nativeModule._CreateReturnStatement1( + global.context, + passEtsNode(argument) + ) + ) + } + + readonly argument: Node | undefined +} diff --git a/arkoala-arkts/libarkts/src/arkts/utilities.ts b/arkoala-arkts/libarkts/src/arkts/utilities.ts index ef8db6e8c..2d9e1fdd6 100644 --- a/arkoala-arkts/libarkts/src/arkts/utilities.ts +++ b/arkoala-arkts/libarkts/src/arkts/utilities.ts @@ -13,13 +13,25 @@ * limitations under the License. */ -import { nativeModule } from "../NativeModule" -import { fromPtrArray, KNativePointer, withStringResult, withString } from "@koalaui/interop" +import { KNativePointerArray, nativeModule } from "../NativeModule" +import { fromPtrArray, KNativePointer, withStringResult, withString, KInt } from "@koalaui/interop" import { NativePtrDecoder } from "../node/Platform" -import * as arkts from "./types" +import global from "./global" +import * as arkts from "." +import { + Es2pandaModifierFlags, + Es2pandaScriptFunctionFlags, +} from "./enums" +import * as ets from "./typesEts" -import { nodeByPeer } from "./nodeByPeer" -export { nodeByPeer } from "./nodeByPeer" +import { arktsNodeByEtsNode } from "./arktsNodeByEtsNode" +export { arktsNodeByEtsNode } from "./arktsNodeByEtsNode" + +import { etsNodeByPeer } from "./etsNodeByPeer" +export { etsNodeByPeer } from "./etsNodeByPeer" + +import { etsNodeByPeerNullable } from "./etsNodeByPeer" +export { etsNodeByPeerNullable } from "./etsNodeByPeer" export function throwError(error: string): never { throw new Error(error) @@ -29,45 +41,156 @@ export function todo(): any { throwError("Not yet implemented") } -/** TODO batch this */ -export function unpack(arrayPtr: KNativePointer): ReadonlyArray { - const array = (new NativePtrDecoder).decode(arrayPtr) +// /** TODO batch this */ +// export function unpack(arrayPtr: KNativePointer): ReadonlyArray { +// if (arrayPtr === arkts.NULLPTR) { +// return [] +// } +// const array = (new NativePtrDecoder).decode(arrayPtr) - return fromPtrArray(array, (peer: KNativePointer) => { - return nodeByPeer(peer) +// return fromPtrArray(array, (peer: KNativePointer) => { +// return nodeByPeer(peer) +// }) +// } + +export function contextProgram(): KNativePointer { + return nativeModule._ContextProgram(global.context) +} + +// export function programAst(program: KNativePointer) { +// return nodeByPeer(nativeModule._ProgramAst(program)) +// } + +export function dumpJson(peer: KNativePointer): string { + return withStringResult(nativeModule._AstNodeDumpJsonConst(global.context, peer)) ?? throwError(`COULDN'T DUMP TO JSON`) +} + +// export function dumpJsonNode(node: arkts.Node): string { +// return dumpJson(node.peer) +// } + +// export function dumpSrcNode(node: arkts.Node): string { +// return withStringResult(nativeModule._AstNodeDumpEtsSrcConst(global.context, node.peer)) ?? throwError(`COULDN'T DUMP TO SOURCE`) +// } + +// export function dumpModifiers(peer: KNativePointer): string { +// return withStringResult(nativeModule._AstNodeDumpModifiers(global.context, peer)) ?? throwError(`COULDN'T DUMP MODIFIERS`) +// } + +// export function dumpModifiersNode(node: arkts.Node): string { +// return dumpModifiers(node.peer) +// } + +export function createAstDumper(peer: KNativePointer, source: string): KNativePointer { + return withString(source, (_source: string) => { + return nativeModule._CreateAstDumper(global.context, peer, _source) }) } -export function contextProgram(): KNativePointer { - return nativeModule._ContextProgram(arkts.Global.context) +export function scriptFunctionHasBody(peer: KNativePointer): boolean { + const flags = nativeModule._ScriptFunctionFlagsConst(global.context, peer) + return true + && ((flags & Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_EXTERNAL) === 0) + && ((flags & Es2pandaScriptFunctionFlags.SCRIPT_FUNCTION_FLAGS_EXTERNAL_OVERLOAD) === 0) } -export function programAst(program: KNativePointer) { - return nodeByPeer(nativeModule._ProgramAst(program)) +function* bits(flags: KInt) { + let bit: KInt = 1 + while (flags >= bit) { + if ((flags & bit) > 0) { + yield bit + } + bit <<= 1 + } } -export function dumpJson(peer: KNativePointer): string { - return withStringResult(nativeModule._AstNodeDumpJsonConst(arkts.Global.context, peer)) ?? throwError(`COULDN'T DUMP TO JSON`) +export function packModifiers(modifiers: ReadonlyArray): KInt { + return modifiers.map( + (mod: arkts.Modifier | undefined | Es2pandaModifierFlags): Es2pandaModifierFlags => { + if (mod === undefined) { + return Es2pandaModifierFlags.MODIFIER_FLAGS_NONE + } + if (typeof mod === 'object') { + return (global.modifierFlags.get(mod.kind) ?? throwError(`Unsupported modifier: ${mod.kind}`)) + } + return mod + }).reduce( + (prev, curr) => (prev | curr), + Es2pandaModifierFlags.MODIFIER_FLAGS_NONE + ) } -export function dumpJsonNode(node: arkts.Node): string { - return dumpJson(node.peer) +export function unpackModifiers(modifiers: KInt): ReadonlyArray { + let mods: arkts.Modifier[] = [] + for (const bit of bits(modifiers)) { + mods.push(new arkts.Modifier(global.translateModifiers.get(bit) ?? throwError(`Unsupported modifier: ${bit}`))) + } + return mods } -export function dumpSrcNode(node: arkts.Node): string { - return withStringResult(nativeModule._AstNodeDumpEtsSrcConst(arkts.Global.context, node.peer)) ?? throwError(`COULDN'T DUMP TO SOURCE`) +export function passString(str: string): string { + return withString(str, (_str: string) => _str) } -export function dumpModifiers(peer: KNativePointer): string { - return withStringResult(nativeModule._AstNodeDumpModifiers(arkts.Global.context, peer)) ?? throwError(`COULDN'T DUMP MODIFIERS`) +export function passEtsNode(node: ets.Node | undefined): KNativePointer { + return node?.peer ?? ets.NULLPTR } -export function dumpModifiersNode(node: arkts.Node): string { - return dumpModifiers(node.peer) +export function passEtsNodeArray(nodes: readonly ets.Node[] | undefined): BigUint64Array { + return new BigUint64Array((nodes === undefined) ? [] : nodes.map(node => BigInt(node.peer))) } -export function createAstDumper(peer: KNativePointer, source: string): KNativePointer { - return withString(source, (_source: string) => { - return nativeModule._CreateAstDumper(arkts.Global.context, peer, _source) +export function passNodeArray(nodes: readonly arkts.Node[]): T[] +export function passNodeArray(nodes: readonly arkts.Node[] | undefined): T[] | undefined +export function passNodeArray(nodes: readonly arkts.Node[] | undefined): T[] | undefined { + if (nodes === undefined) { + return undefined + } + return nodes.map((node: arkts.Node) => ((node._node as T) ?? throwError('trying to pass non-compatible node'))) +} + +export function unpackEtsNode(peer: KNativePointer): ets.Node { + if (peer === ets.NULLPTR) { + throwError('nodePtr is NULLPTR') + } + return etsNodeByPeer(peer) +} + +export function unpackEtsNodeArray(nodesPtr: KNativePointer): readonly T[] { + if (nodesPtr === ets.NULLPTR) { + return [] + } + const array = (new NativePtrDecoder).decode(nodesPtr) + + return fromPtrArray(array, (peer: KNativePointer) => { + return etsNodeByPeer(peer) }) } + +export function unpackNode(node: ets.Node): T +export function unpackNode(node: ets.Node | undefined): T | undefined +export function unpackNode(node: ets.Node | undefined): T | undefined { + if (node === undefined) { + return undefined + } + // TODO: add asserts + return arktsNodeByEtsNode(node) as T +} + +export function unpackNullableNode(node: ets.Node | undefined): T | undefined { + if (node === undefined) { + return undefined + } + // TODO: add asserts + return arktsNodeByEtsNode(node) as T +} + +export function unpackNodeArray(nodes: readonly ets.Node[]): arkts.NodeArray +export function unpackNodeArray(nodes: readonly ets.Node[] | undefined): arkts.NodeArray | undefined +export function unpackNodeArray(nodes: readonly ets.Node[] | undefined): arkts.NodeArray | undefined { + if (nodes === undefined) { + return undefined + } + // TODO: add asserts + return nodes.map((node: ets.Node) => arktsNodeByEtsNode(node)) as ReadonlyArray as arkts.NodeArray +} diff --git a/arkoala-arkts/libarkts/src/arkts/utilitiesPublic.ts b/arkoala-arkts/libarkts/src/arkts/utilitiesPublic.ts index 8ac100d1a..42d4dc1f4 100644 --- a/arkoala-arkts/libarkts/src/arkts/utilitiesPublic.ts +++ b/arkoala-arkts/libarkts/src/arkts/utilitiesPublic.ts @@ -15,11 +15,12 @@ import { nativeModule } from "../NativeModule" import { KNativePointer, withString, withStringArray, withStringResult } from "@koalaui/interop" -import * as arkts from "./types" +import * as arkts from "." +import global from "./global" import { ContextState, } from "./enums" -import { nodeByPeer } from "./nodeByPeer" +// import { nodeByPeer } from "./nodeByPeer" import { throwError } from "./utilities" export function createConfig(input: string[]): KNativePointer { @@ -37,9 +38,14 @@ export function createContextFromString(config: KNativePointer, source: string, } export function proceedToState(state: ContextState): void { - nativeModule._ProceedToState(arkts.Global.context, state) - if (nativeModule._ContextState(arkts.Global.context) === ContextState.ES2PANDA_STATE_ERROR) { - const errorMessage = withStringResult(nativeModule._ContextErrorMessage(arkts.Global.context)) + if (state <= nativeModule._ContextState(global.context)) { + return + } + nativeModule._ProceedToState(global.context, state) + if (nativeModule._ContextState(global.context) === ContextState.ES2PANDA_STATE_ERROR) { + // TODO: maybe shoudn't do it here + nativeModule._DestroyContext(global.context) + const errorMessage = withStringResult(nativeModule._ContextErrorMessage(global.context)) if (errorMessage === undefined) { throwError(`COULDN'T GET: _ContextErrorMessage`) } @@ -48,22 +54,30 @@ export function proceedToState(state: ContextState): void { } export function startChecker(): boolean { - return nativeModule._CheckerStartChecker(arkts.Global.context) + return nativeModule._CheckerStartChecker(global.context) } -export function getDecl(node: arkts.Node): arkts.Node | undefined { - let decl = node.peer - decl = nativeModule._AstNodeVariableConst(arkts.Global.context, decl) - if (decl === arkts.NULLPTR) { - return undefined - } - decl = nativeModule._VariableDeclaration(arkts.Global.context, decl) - if (decl === arkts.NULLPTR) { - return undefined - } - decl = nativeModule._DeclNode(arkts.Global.context, decl) - if (decl === arkts.NULLPTR) { - return undefined - } - return nodeByPeer(decl) -} +// export function getDecl(node: arkts.Node): arkts.Node | undefined { +// let decl = node.peer +// decl = nativeModule._AstNodeVariableConst(global.context, decl) +// if (decl === arkts.NULLPTR) { +// return undefined +// } +// decl = nativeModule._VariableDeclaration(global.context, decl) +// if (decl === arkts.NULLPTR) { +// return undefined +// } +// decl = nativeModule._DeclNode(global.context, decl) +// if (decl === arkts.NULLPTR) { +// return undefined +// } +// return nodeByPeer(decl) +// } + +// export function getOriginalNode(node: arkts.Node): arkts.Node { +// const peer = nativeModule._AstNodeOriginalNodeConst(global.context, node.peer) +// if (peer === arkts.NULLPTR) { +// return node +// } +// return nodeByPeer(peer) +// } diff --git a/arkoala-arkts/libarkts/src/arkts/visitor.ts b/arkoala-arkts/libarkts/src/arkts/visitor.ts index fd0164fb7..081368085 100644 --- a/arkoala-arkts/libarkts/src/arkts/visitor.ts +++ b/arkoala-arkts/libarkts/src/arkts/visitor.ts @@ -2,10 +2,10 @@ import * as arkts from "./types" import { factory } from "./factory/nodeFactory" import * as util from "./utilities" import { SyntaxKind } from "./enums" - +/* type Visitor = (node: arkts.Node) => arkts.Node -// TODO: rethink +// TODO: rethink (remove as) function nodeVisitor(node: T, visitor: Visitor): T { if (node === undefined) { return node @@ -13,12 +13,12 @@ function nodeVisitor(node: T, visitor: Visitor return visitor(node) as T } -// TODO: rethink -function nodesVisitor(nodes: arkts.NodeArray | undefined, visitor: Visitor): T[] { +// TODO: rethink (remove as) +function nodesVisitor | undefined>(nodes: TIn, visitor: Visitor): T[] | TIn { if (nodes === undefined) { - return [] + return nodes } - return nodes.map((node: T) => (visitor(node) as T)) + return nodes.map(node => visitor(node) as T) } type VisitEachChildFunction = (node: T, visitor: Visitor) => T @@ -33,6 +33,8 @@ type HasChildren = | arkts.ClassDeclaration | arkts.MethodDeclaration | arkts.Block + | arkts.VariableStatement + | arkts.VariableDeclarationList type VisitEachChildTable = { [TNode in HasChildren as TNode["kind"]]: VisitEachChildFunction } @@ -47,12 +49,12 @@ const visitEachChildTable: VisitEachChildTable = { [SyntaxKind.FunctionDeclaration]: function (node: arkts.FunctionDeclaration, visitor: Visitor) { return factory.updateFunctionDeclaration( node, - undefined, + node.modifiers, undefined, nodeVisitor(node.name, visitor), - undefined, + nodesVisitor(node.typeParameters, visitor), nodesVisitor(node.parameters, visitor), - undefined, + nodeVisitor(node.type, visitor), nodeVisitor(node.body, visitor), ) }, @@ -106,6 +108,19 @@ const visitEachChildTable: VisitEachChildTable = { nodesVisitor(node.statements, visitor), ) }, + [SyntaxKind.VariableStatement]: function (node: arkts.VariableStatement, visitor: Visitor) { + return factory.updateVariableStatement( + node, + undefined, + nodeVisitor(node.declarationList, visitor), + ) + }, + [SyntaxKind.VariableDeclarationList]: function (node: arkts.VariableDeclarationList, visitor: Visitor) { + return factory.updateVariableDeclarationList( + node, + nodesVisitor(node.declarations, visitor), + ) + }, } function nodeHasChildren(node: arkts.Node): node is HasChildren { @@ -122,3 +137,4 @@ export function visitEachChild( } return (visitFunc === undefined) ? node : visitFunc(node, visitor); } +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/src/es2panda.ts b/arkoala-arkts/libarkts/src/es2panda.ts index 1040dea0d..4f9f9683a 100644 --- a/arkoala-arkts/libarkts/src/es2panda.ts +++ b/arkoala-arkts/libarkts/src/es2panda.ts @@ -2,7 +2,11 @@ import { Command } from "commander" import * as fs from "fs" import * as path from "path" import * as arkts from "./arkts" -import { generateBinAndRun } from "../test/test-util" +import global from "./arkts/global" +import { + generateBin, + runAbc, +} from "../test/test-util" function parseCommandLineArgs() { const commander = new Command() @@ -25,13 +29,13 @@ function parseCommandLineArgs() { function es2panda(configPath: string, filePath: string, transform: (ast: arkts.Node) => arkts.Node) { const source = fs.readFileSync(filePath).toString() - arkts.Global.config = arkts.createConfig([ + global.config = arkts.createConfig([ '_', '--arktsconfig', configPath, filePath ]) - arkts.Global.context = arkts.createContextFromString(arkts.Global.config, source, filePath) + global.context = arkts.createContextFromString(global.config, source, filePath) arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_PARSED) const program = arkts.contextProgram() const ast = arkts.programAst(program) @@ -39,7 +43,8 @@ function es2panda(configPath: string, filePath: string, transform: (ast: arkts.N transform(ast) // TODO: this should be called after executing all plugins - generateBinAndRun() + generateBin() + runAbc() } function plugins(configPath: string): Promise<((ast: arkts.Node) => arkts.Node)[]> { diff --git a/arkoala-arkts/libarkts/test/es2panda/abc-gen.test.ts b/arkoala-arkts/libarkts/test/es2panda/abc-gen.test.ts index 7791c6af8..91662b7bc 100644 --- a/arkoala-arkts/libarkts/test/es2panda/abc-gen.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/abc-gen.test.ts @@ -1,9 +1,10 @@ +/* import * as util from "../test-util" import * as arkts from "../../src/arkts" // tests for abc generation suite(util.getSuiteTitle(__filename), () => { - test("updating-expression-statement", function() { + test.only("updating-expression-statement", function() { const sample_in = ` function foo(lambda: (instance: string) => string): void { @@ -18,20 +19,22 @@ suite(util.getSuiteTitle(__filename), () => { const sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) util.assert(arkts.isSourceFile(sourceFile)) - const expressionStatement = sourceFile.statements[1] - util.assert(arkts.isExpressionStatement(expressionStatement)) + console.log(arkts.dumpJsonNode(sourceFile)) - const newStatements = [ - sourceFile.statements[0], - arkts.factory.updateExpressionStatement( - expressionStatement, - expressionStatement.expression - ) - ] + // const expressionStatement = sourceFile.statements[1] + // util.assert(arkts.isExpressionStatement(expressionStatement)) - arkts.factory.updateSourceFile(sourceFile, newStatements) + // const newStatements = [ + // sourceFile.statements[0], + // arkts.factory.updateExpressionStatement( + // expressionStatement, + // expressionStatement.expression + // ) + // ] + + // arkts.factory.updateSourceFile(sourceFile, newStatements) - // util.generateBinAndRun() + // util.assertEqualsBinaryOuptut('ABC', this) }) test("updating-function-declaration", function() { @@ -69,10 +72,9 @@ suite(util.getSuiteTitle(__filename), () => { arkts.factory.updateSourceFile(sourceFile, newStatements) - // util.generateBinAndRun() + util.assertEqualsBinaryOuptut('A', this) }) - // failing now test("updating-lambda-call", function() { const sample_in = ` @@ -117,6 +119,7 @@ suite(util.getSuiteTitle(__filename), () => { ] arkts.factory.updateSourceFile(sourceFile, newStatements) - // util.generateBinAndRun() + util.assertEqualsBinaryOuptut('', this) }) }) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/analysis-visitor.test.ts b/arkoala-arkts/libarkts/test/es2panda/analysis-visitor.test.ts new file mode 100644 index 000000000..e1df89b02 --- /dev/null +++ b/arkoala-arkts/libarkts/test/es2panda/analysis-visitor.test.ts @@ -0,0 +1,38 @@ +/* +import * as util from "../test-util" +import * as arkts from "../../src/arkts" +import { AnalysisVisitor } from "../../compatible/src/analysis-visitor" +import { Tracer } from "../../compatible/src/util" +import { Rewrite } from "../../compatible/src/transformation-context" + +suite(util.getSuiteTitle(__filename), () => { + test("sample-1", function() { + const sample_in = + ` + const _memo_x: string = "A" + + function _memo_foo() {} + + _memo_foo() + ` + + util.getDefaultSetup(sample_in) + + // arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_CHECKED) + + let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + util.assert(arkts.isSourceFile(sourceFile)) + + const options = {} + + const tracer = new Tracer(options) + const rewrite = new Rewrite(sourceFile, options) + + sourceFile = new AnalysisVisitor(tracer, rewrite).visitor(sourceFile) + + util.assert(rewrite.functionTable.size === 1) + util.assert(rewrite.callTable.size === 1) + util.assert(rewrite.variableTable.size === 1) + }) +}) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/basic.test.ts b/arkoala-arkts/libarkts/test/es2panda/basic.test.ts new file mode 100644 index 000000000..73d9e448e --- /dev/null +++ b/arkoala-arkts/libarkts/test/es2panda/basic.test.ts @@ -0,0 +1,168 @@ +import * as util from "../test-util" +import * as arkts from "../../src/arkts" +import { factory } from "../../src/arkts" + +suite(util.getSuiteTitle(__filename), () => { + test("sample-1", function() { + const sample_in = + ` + ` + + let sourceFile = arkts.factory.createSourceFile(sample_in) + + sourceFile = arkts.factory.updateSourceFile( + sourceFile, + [ + arkts.factory.createExpressionStatement( + arkts.factory.createIdentifier("abc") + ) + ] + ) + + util.assertEqualsAfter( + sourceFile, + ` + abc + ` + ) + }) + + test("sample-2", function() { + const sample_in = + ` + ` + + let sourceFile = arkts.factory.createSourceFile(sample_in) + + sourceFile = arkts.factory.updateSourceFile( + sourceFile, + [ + arkts.factory.createFunctionDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier("test"), + undefined, + [], + undefined, + arkts.factory.createBlock( + [], + true + ) + ) + ] + ) + + util.assertEqualsAfter( + sourceFile, + ` + function test() {} + ` + ) + }) + + test("sample-3", function() { + const sample_in = + ` + ` + + let sourceFile = factory.createSourceFile(sample_in) + + sourceFile = factory.updateSourceFile( + sourceFile, + [ + factory.createFunctionDeclaration( + undefined, + undefined, + factory.createIdentifier("test"), + undefined, + [ + factory.createParameterDeclaration( + undefined, + undefined, + factory.createIdentifier("x"), + undefined, + factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword), + undefined + ) + ], + factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), + factory.createBlock( + [ + factory.createReturnStatement( + factory.createNumericLiteral("0") + ) + ], + true + ) + ) + ] + ) + + util.assertEqualsAfter( + sourceFile, + ` + function test(x: string): number { + return 0; + } + ` + ) + }) + + test("sample-4", function() { + const sample_in = + ` + ` + + let sourceFile = factory.createSourceFile(sample_in) + + sourceFile = factory.updateSourceFile( + sourceFile, + [ + factory.createFunctionDeclaration( + undefined, + undefined, + factory.createIdentifier("test"), + [ + factory.createTypeParameterDeclaration( + undefined, + factory.createIdentifier("T"), + factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword), + undefined + ) + ], + [ + factory.createParameterDeclaration( + undefined, + undefined, + factory.createIdentifier("x"), + undefined, + factory.createTypeReferenceNode( + factory.createIdentifier("T"), + undefined + ), + undefined + ) + ], + factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword), + factory.createBlock( + [ + factory.createReturnStatement( + factory.createStringLiteral("aaa") + ) + ], + true + ) + ) + ] + ) + + util.assertEqualsAfter( + sourceFile, + ` + function test(x: T): string { + return "aaa" + } + ` + ) + }) +}) diff --git a/arkoala-arkts/libarkts/test/es2panda/builder-lambda-rewrite.test.ts b/arkoala-arkts/libarkts/test/es2panda/builder-lambda-rewrite.test.ts index 3de1f3019..4fa6c351a 100644 --- a/arkoala-arkts/libarkts/test/es2panda/builder-lambda-rewrite.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/builder-lambda-rewrite.test.ts @@ -1,3 +1,4 @@ +/* import * as util from "../test-util" import * as arkts from "../../src/arkts" import { BuilderLambdaTransformer } from "../../compatible/src/builder-lambda-transformer" @@ -68,12 +69,12 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` _Foo(((instance: string) => {}), "label") - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) @@ -143,14 +144,14 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` _Foo(((instance: string) => { instance.bar().qux(); }), "label1", "label2") - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) @@ -173,14 +174,14 @@ suite(util.getSuiteTitle(__filename), () => { sourceFile = builderLambdaTransformer.visitor(sourceFile) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` foo(((instance: string) => { return instance; }), "label") - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) @@ -203,14 +204,14 @@ suite(util.getSuiteTitle(__filename), () => { sourceFile = builderLambdaTransformer.visitor(sourceFile) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` foo(((instance: string) => { return instance.bar().qux(); }), "label1", "label2") - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) @@ -241,9 +242,8 @@ suite(util.getSuiteTitle(__filename), () => { sourceFile = builderLambdaTransformer.visitor(sourceFile) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` function Foo(builder: ((instance: string)=> string), arg1: string): void { console.log(((arg1) + (builder("ABC")))); @@ -252,7 +252,9 @@ suite(util.getSuiteTitle(__filename), () => { Foo(((instance: string) => { return instance.charAt(1); }), "> second_char_of_ABC: ") - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) }) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/create-function-declaration.test.ts b/arkoala-arkts/libarkts/test/es2panda/create-function-declaration.test.ts index e9c926481..dc8eb00a0 100644 --- a/arkoala-arkts/libarkts/test/es2panda/create-function-declaration.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/create-function-declaration.test.ts @@ -9,9 +9,7 @@ suite(util.getSuiteTitle(__filename), () => { const sample_in = `` - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) const funcDecl = arkts.factory.createFunctionDeclaration( @@ -34,23 +32,19 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` function test_func() {} - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) test("empty-function-with-param", function() { - // function test_func(x: long) { - // // empty - // } - - util.getDefaultSetup('') + const sample_in = `` - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) const funcParams = [ @@ -59,7 +53,7 @@ suite(util.getSuiteTitle(__filename), () => { undefined, arkts.factory.createIdentifier("x"), undefined, - arkts.factory.createEtsPrimitiveType(arkts.Es2pandaPrimitiveType.PRIMITIVE_TYPE_INT), + arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), undefined ) ] @@ -83,12 +77,12 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, - ` - function test_func(x: long) {} ` + function test_func(x: number) {} + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) @@ -97,9 +91,9 @@ suite(util.getSuiteTitle(__filename), () => { // // empty // } - util.getDefaultSetup('') + const sample_in = `` - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) const funcParams = [ @@ -132,37 +126,164 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` function test_func(x: string) {} - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) - test("async-empty-function", function() { - // async function test_func() {} + // test("async-empty-function", function() { + // // async function test_func() {} + + // const sample_in = `` + + // util.getDefaultSetup(sample_in) + + // let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + // util.assert(arkts.isSourceFile(sourceFile)) + + // const funcDecl = arkts.factory.createFunctionDeclaration( + // [ + // arkts.factory.createToken(arkts.SyntaxKind.AsyncKeyword) + // ], + // undefined, + // arkts.factory.createIdentifier("test_func"), + // undefined, + // [], + // undefined, + // arkts.factory.createBlock( + // [], + // true + // ) + // ) + + // sourceFile = arkts.factory.updateSourceFile( + // sourceFile, + // [ + // funcDecl + // ] + // ) + + // util.assertEqualsAfter( + // sourceFile, + // ` + // async function test_func() {} + // `, + // arkts.ContextState.ES2PANDA_STATE_PARSED, + // ) + // }) + + // test("empty-method-with-public-static-modifiers", function() { + // // class A { + // // static test_func() { + // // } + // // } + + // const sample_in = + // ` + // class A { + // } + // ` + + // let sourceFile = arkts.factory.createSourceFile(sample_in) + // util.assert(arkts.isSourceFile(sourceFile)) + + // let classDecl = sourceFile.statements[0] + // util.assert(arkts.isClassDeclaration(classDecl)) + + // classDecl = arkts.factory.updateClassDeclaration( + // classDecl, + // undefined, + // arkts.factory.createIdentifier("A"), + // undefined, + // undefined, + // [ + // arkts.factory.createMethodDeclaration( + // [ + // arkts.factory.createToken(arkts.SyntaxKind.PublicKeyword), + // arkts.factory.createToken(arkts.SyntaxKind.StaticKeyword) + // ], + // undefined, + // arkts.factory.createIdentifier("test_func"), + // undefined, + // undefined, + // [], + // undefined, + // arkts.factory.createBlock( + // [], + // false + // ) + // ), + // arkts.factory.createConstructorDeclaration( + // [ + // arkts.factory.createToken(arkts.SyntaxKind.PublicKeyword) + // ], + // [], + // arkts.factory.createBlock( + // [], + // false + // ) + // ) + // ] + // ) + + // sourceFile = arkts.factory.updateSourceFile( + // sourceFile, + // [ + // classDecl + // ] + // ) + + // util.assertEqualsAfter( + // sourceFile, + // ` + // class A { + // public static test_func() {} + + // public constructor() {} + + // } + // `, + // arkts.ContextState.ES2PANDA_STATE_PARSED, + // ) + // }) + + test("function-with-type-parameters", function() { + // function test_func(): void {} - const sample_in = `` - - util.getDefaultSetup(sample_in) + const sample_in = + ` + ` - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) const funcDecl = arkts.factory.createFunctionDeclaration( - [ - arkts.factory.createToken(arkts.SyntaxKind.AsyncKeyword) - ], undefined, - arkts.factory.createIdentifier("test_func"), undefined, + arkts.factory.createIdentifier("test_func"), + [ + arkts.factory.createTypeParameterDeclaration( + undefined, + arkts.factory.createIdentifier("T"), + undefined, + undefined + ), + arkts.factory.createTypeParameterDeclaration( + undefined, + arkts.factory.createIdentifier("K"), + undefined, + undefined + ) + ], [], - undefined, + arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.VoidKeyword), arkts.factory.createBlock( - [], - true + [], + true ) ) @@ -173,89 +294,142 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, - ` - async function test_func() {} ` + function test_func(): void {} + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) - test("empty-method-with-public-static-modifiers", function() { - // class A { - // static test_func() { - // } - // } - + // // TODO: change 0 -> 777 (waiting fix) + // test("sample-1", function() { + // const sample_in = + // ` + // console.log("OK") + // ` + + // let sourceFile = arkts.factory.createSourceFile(sample_in) + // util.assert(arkts.isSourceFile(sourceFile)) + + // const funcDecl = arkts.factory.createFunctionDeclaration( + // undefined, + // undefined, + // arkts.factory.createIdentifier("foo"), + // undefined, + // [ + // arkts.factory.createParameterDeclaration( + // undefined, + // undefined, + // arkts.factory.createIdentifier("x"), + // undefined, + // arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), + // arkts.factory.createNumericLiteral("0") + // ), + // arkts.factory.createParameterDeclaration( + // undefined, + // undefined, + // arkts.factory.createIdentifier("y"), + // undefined, + // arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword), + // arkts.factory.createStringLiteral("abc") + // ) + // ], + // arkts.factory.createUnionTypeNode([ + // arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), + // arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword) + // ]), + // arkts.factory.createBlock( + // [arkts.factory.createReturnStatement(arkts.factory.createBinaryExpression( + // arkts.factory.createIdentifier("x"), + // arkts.factory.createToken(arkts.SyntaxKind.PlusToken), + // arkts.factory.createIdentifier("y") + // ))], + // true + // ) + // ) + + // sourceFile = arkts.factory.updateSourceFile( + // sourceFile, + // [ + // funcDecl, + // sourceFile.statements[0] + // ] + // ) + + // util.assertEqualsAfter( + // sourceFile, + // ` + // function foo(x: number = 0, y: string = "abc"): number | string { + // return x + y + // } + // console.log("OK") + // ` + // ) + // }) + + // TODO: change 0 -> 777 (waiting fix) + test("sample-2", function() { const sample_in = ` - class A { - } + // console.log("OK") ` - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) - let classDecl = sourceFile.statements[0] - util.assert(arkts.isClassDeclaration(classDecl)) - - classDecl = arkts.factory.updateClassDeclaration( - classDecl, + const funcDecl = arkts.factory.createFunctionDeclaration( undefined, - arkts.factory.createIdentifier("A"), undefined, + arkts.factory.createIdentifier("foo"), undefined, [ - arkts.factory.createMethodDeclaration( - [ - arkts.factory.createToken(arkts.SyntaxKind.PublicKeyword), - arkts.factory.createToken(arkts.SyntaxKind.StaticKeyword) - ], - undefined, - arkts.factory.createIdentifier("test_func"), + arkts.factory.createParameterDeclaration( undefined, undefined, - [], + arkts.factory.createIdentifier("x"), undefined, - arkts.factory.createBlock( - [], - false - ) + arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), + arkts.factory.createNumericLiteral("0") ), - arkts.factory.createConstructorDeclaration( - [ - arkts.factory.createToken(arkts.SyntaxKind.PublicKeyword) - ], - [], - arkts.factory.createBlock( - [], - false - ) + arkts.factory.createParameterDeclaration( + undefined, + undefined, + arkts.factory.createIdentifier("y"), + undefined, + arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword), + arkts.factory.createStringLiteral("abc") ) - ] + ], + arkts.factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), + arkts.factory.createBlock( + [ + arkts.factory.createReturnStatement( + arkts.factory.createIdentifier("x") + ) + ], + true + ) ) sourceFile = arkts.factory.updateSourceFile( sourceFile, [ - classDecl + funcDecl, + // sourceFile.statements[0] ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` - class A { - public static test_func() {} - - public constructor() {} - + function foo(x: number = 0, y: string = "abc"): number { + return x } - ` + // console.log("OK") + `, + arkts.ContextState.ES2PANDA_STATE_PARSED ) }) }) diff --git a/arkoala-arkts/libarkts/test/es2panda/function-rewrite.test.ts b/arkoala-arkts/libarkts/test/es2panda/function-rewrite.test.ts index 0c4441260..bc7d406c2 100644 --- a/arkoala-arkts/libarkts/test/es2panda/function-rewrite.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/function-rewrite.test.ts @@ -1,3 +1,4 @@ +/* import * as util from "../test-util" import * as arkts from "../../src/arkts" import { FunctionTransformer } from "../../compatible/src/function-transformer" @@ -43,3 +44,4 @@ suite(util.getSuiteTitle(__filename), () => { // arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_BIN_GENERATED) }) }) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/import.test.ts b/arkoala-arkts/libarkts/test/es2panda/import.test.ts new file mode 100644 index 000000000..f08f11cd1 --- /dev/null +++ b/arkoala-arkts/libarkts/test/es2panda/import.test.ts @@ -0,0 +1,63 @@ +/* +import * as util from "../test-util" +import * as arkts from "../../src/arkts" + +suite(util.getSuiteTitle(__filename), () => { + // TODO: doesn't running now, but compiles (config gets only one file) + test("sample-1", function() { + const sample_in = + ` + import { TEST } from "./export" + console.log(TEST) + ` + + // util.getDefaultSetup(sample_in) + + // util.generateBinAndRun() + }) + + test("sample-2", function() { + const sample_in = + ` + import { power as F } from "std/math" + console.log(F(2, 10)) + ` + + // util.getDefaultSetup(sample_in) + + // arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_CHECKED) + + // const classDecl = arkts.nodeByPeer(util.getStatement(1)) + // util.assert(arkts.isClassDeclaration(classDecl)) + + // const method = classDecl.members[1] + // util.assert(arkts.isMethodDeclaration(method)) + + // const body = method.body! + // util.assert(arkts.isBlock(body)) + + // const exprStatement = body.statements[0] + // util.assert(arkts.isExpressionStatement(exprStatement)) + + // const callExpr = exprStatement.expression + // util.assert(arkts.isCallExpression(callExpr)) + + // const F = callExpr.arguments[0] + // util.assert(arkts.isCallExpression(F)) + + // const ident = F.expression + // util.assert(arkts.isIdentifier(ident)) + + // console.log(arkts.dumpJsonNode(ident)) + + // const decl = arkts.getDecl(ident) + // if (decl !== undefined) { + // console.log(arkts.dumpJsonNode(decl)) + // } else { + // console.log(decl) + // } + + // util.generateBinAndRun() + }) +}) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/lambda-param-memoization.test.ts b/arkoala-arkts/libarkts/test/es2panda/lambda-param-memoization.test.ts index decf399ba..b99f10ecf 100644 --- a/arkoala-arkts/libarkts/test/es2panda/lambda-param-memoization.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/lambda-param-memoization.test.ts @@ -1,3 +1,4 @@ +/* import * as util from "../test-util" import * as arkts from "../../src/arkts" @@ -66,13 +67,16 @@ suite(util.getSuiteTitle(__filename), () => { arkts.factory.createPropertyAccessExpression( arkts.factory.createIdentifier("__memo_scope"), arkts.factory.createIdentifier("recache") - ) + ), + undefined, + undefined ) ) ] testFunc = util.addMemoParamsToFunctionDeclaration(testFunc) util.assert(arkts.isFunctionDeclaration(testFunc)) + util.assert(testFunc.body !== undefined) const newLambdaParams = [ arkts.factory.createParameterDeclaration( @@ -136,9 +140,8 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` function foo(__memo_context: __memo_context_type, __memo_id: __memo_id_type, content: ((__memo_context: __memo_context_type, __memo_id: __memo_id_type)=> void)) { if (__memo_scope.unchanged) { @@ -147,7 +150,9 @@ suite(util.getSuiteTitle(__filename), () => { content(__memo_context, ((__memo_id) + ("key_id_main.ts"))); return __memo_scope.recache(); } - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) }) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/literal-declarations.test.ts b/arkoala-arkts/libarkts/test/es2panda/literal-declarations.test.ts new file mode 100644 index 000000000..8ad947830 --- /dev/null +++ b/arkoala-arkts/libarkts/test/es2panda/literal-declarations.test.ts @@ -0,0 +1,121 @@ +/* +import * as util from "../test-util" +import * as arkts from "../../src/arkts" +import { factory } from "../../src/arkts" + +suite(util.getSuiteTitle(__filename), () => { + // TODO: change 0 -> 777 (waiting fix) + test("const-number", function() { + const sample_in = + ` + function f() {} + ` + + util.getDefaultSetup(sample_in) + + let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + util.assert(arkts.isSourceFile(sourceFile)) + + const varDecl = factory.createVariableStatement( + undefined, + factory.createVariableDeclarationList( + [factory.createVariableDeclaration( + factory.createIdentifier("x"), + undefined, + factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), + factory.createNumericLiteral("0") + )] + ) + ) + + const f = sourceFile.statements[0] + util.assert(arkts.isFunctionDeclaration(f)) + + sourceFile = factory.updateSourceFile( + sourceFile, + [ + factory.updateFunctionDeclaration( + f, + f.modifiers, + undefined, + f.name, + f.typeParameters, + f.parameters, + f.type, + factory.createBlock([ + varDecl + ]) + ) + ] + ) + + util.assertEqualsAfter( + sourceFile, + ` + function f() { + const x: number = 0 + } + ` + ) + }) + + test("declaration-list", function() { + // const x: number = 0, y: string = "a", z = 0 + + const sample_in = `const x = 1` + + util.getDefaultSetup(sample_in) + + let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + util.assert(arkts.isSourceFile(sourceFile)) + + const varStatement = sourceFile.statements[0] + util.assert(arkts.isVariableStatement(varStatement)) + + sourceFile = arkts.factory.updateSourceFile( + sourceFile, + [ + factory.updateVariableStatement( + varStatement, + [ + // TODO: not ok maybe (not my fault) + factory.createToken(arkts.SyntaxKind.PublicKeyword), + factory.createToken(arkts.SyntaxKind.StaticKeyword), + factory.createToken(arkts.SyntaxKind.ConstKeyword), + ], + factory.createVariableDeclarationList( + [ + factory.createVariableDeclaration( + factory.createIdentifier("x"), + undefined, + factory.createKeywordTypeNode(arkts.SyntaxKind.NumberKeyword), + factory.createNumericLiteral("0") + ), + factory.createVariableDeclaration( + factory.createIdentifier("y"), + undefined, + factory.createKeywordTypeNode(arkts.SyntaxKind.StringKeyword), + factory.createStringLiteral("a") + ), + factory.createVariableDeclaration( + factory.createIdentifier("z"), + undefined, + undefined, + factory.createNumericLiteral("0") + ) + ], + undefined + ) + ) + ] + ) + + util.assertEqualsAfter( + sourceFile, + ` + const x: number = 0, y: string = "a", z = 0 + ` + ) + }) +}) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/memo-rewrite.test.ts b/arkoala-arkts/libarkts/test/es2panda/memo-rewrite.test.ts index de19f47f3..ba23e21cd 100644 --- a/arkoala-arkts/libarkts/test/es2panda/memo-rewrite.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/memo-rewrite.test.ts @@ -1,3 +1,4 @@ +/* import * as util from "../test-util" import * as arkts from "../../src/arkts" import { MemoTransformer } from "../../compatible/src/memo-transformer" @@ -25,3 +26,4 @@ suite(util.getSuiteTitle(__filename), () => { // console.log(arkts.dumpSrcNode(sourceFile)) }) }) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/print-visitor.test.ts b/arkoala-arkts/libarkts/test/es2panda/print-visitor.test.ts index e38afc82c..151267112 100644 --- a/arkoala-arkts/libarkts/test/es2panda/print-visitor.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/print-visitor.test.ts @@ -1,3 +1,4 @@ +/* import * as arkts from "../../src/arkts" import * as util from "../test-util" import { PrintVisitor } from "../../compatible/src/print-visitor" @@ -24,38 +25,41 @@ suite(util.getSuiteTitle(__filename), () => { ` const expected = ` - SourceFile (mod: 0) - ClassDeclaration (mod: 5) - Identifier (mod: 0) - PropertyDeclaration (mod: 4) - MethodDeclaration (mod: 4) - Identifier (mod: 0) - Block (mod: 0) - ExpressionStatement (mod: 0) - UnsupportedNode (mod: 0) - MethodDeclaration (mod: 0) - Identifier (mod: 0) - Block (mod: 0) - ClassDeclaration (mod: 5) - Identifier (mod: 0) - MethodDeclaration (mod: 0) - Identifier (mod: 0) - Block (mod: 0) - FunctionDeclaration (mod: 5) - Identifier (mod: 0) - Block (mod: 0) - FunctionDeclaration (mod: 5) - Identifier (mod: 0) - Block (mod: 0) - FunctionDeclaration (mod: 5) - Identifier (mod: 0) - Block (mod: 0) - VariableStatement (mod: 0) - ExpressionStatement (mod: 0) - CallExpression (mod: 0) - PropertyAccessExpression (mod: 0) - Identifier (mod: 0) - Identifier (mod: 0) + SourceFile (mods: []) + ClassDeclaration (mods: [1,4]) + Identifier (mods: []) + PropertyDeclaration (mods: [4]) + MethodDeclaration (mods: [4]) + Identifier (mods: []) + Block (mods: []) + ExpressionStatement (mods: []) + AssignmentExpression (mods: []) + MethodDeclaration (mods: []) + Identifier (mods: []) + Block (mods: []) + ClassDeclaration (mods: [1,4]) + Identifier (mods: []) + MethodDeclaration (mods: []) + Identifier (mods: []) + Block (mods: []) + FunctionDeclaration (mods: [1,4]) + Identifier (mods: []) + Block (mods: []) + FunctionDeclaration (mods: [1,4]) + Identifier (mods: []) + Block (mods: []) + FunctionDeclaration (mods: [1,4]) + Identifier (mods: []) + ETSPrimitiveType (mods: []) + Block (mods: []) + VariableStatement (mods: []) + VariableDeclarationList (mods: []) + VariableDeclaration (mods: []) + ExpressionStatement (mods: []) + CallExpression (mods: []) + PropertyAccessExpression (mods: []) + Identifier (mods: []) + Identifier (mods: []) ` util.getDefaultSetup(source) @@ -66,3 +70,4 @@ suite(util.getSuiteTitle(__filename), () => { util.assert.equal(util.alignText(output), util.alignText(expected)) }) }) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/simple-transformations.test.ts b/arkoala-arkts/libarkts/test/es2panda/simple-transformations.test.ts new file mode 100644 index 000000000..c85a28a2b --- /dev/null +++ b/arkoala-arkts/libarkts/test/es2panda/simple-transformations.test.ts @@ -0,0 +1,56 @@ +/* +import * as util from "../test-util" +import * as arkts from "../../src/arkts" + +suite(util.getSuiteTitle(__filename), () => { + test("sample-1", function() { + const sample_in = + ` + class A {} + + let x: AB + + console.log("ok") + ` + + util.getDefaultSetup(sample_in) + + let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + util.assert(arkts.isSourceFile(sourceFile)) + + const varDecl = sourceFile.statements[1] + util.assert(arkts.isVariableStatement(varDecl)) + + const declList = varDecl.declarationList + util.assert(arkts.isVariableDeclarationList(declList)) + + const x = declList.declarations[0] + util.assert(arkts.isVariableDeclaration(x)) + + sourceFile = arkts.factory.updateSourceFile( + sourceFile, + [ + sourceFile.statements[0], + arkts.factory.updateVariableStatement( + varDecl, + undefined, + // declList + arkts.factory.createVariableDeclarationList( + [arkts.factory.createVariableDeclaration( + arkts.factory.createIdentifier("x"), + undefined, + arkts.factory.createTypeReferenceNode( + arkts.factory.createIdentifier("A") + ), + undefined + )] + ) + ), + sourceFile.statements[2] + ] + ) + + util.assertEqualsBinaryOuptut('ok', this) + }) +}) +*/ \ No newline at end of file diff --git a/arkoala-arkts/libarkts/test/es2panda/update-function-declaration.test.ts b/arkoala-arkts/libarkts/test/es2panda/update-function-declaration.test.ts index 7755959f7..77b384bec 100644 --- a/arkoala-arkts/libarkts/test/es2panda/update-function-declaration.test.ts +++ b/arkoala-arkts/libarkts/test/es2panda/update-function-declaration.test.ts @@ -15,9 +15,7 @@ suite(util.getSuiteTitle(__filename), () => { } ` - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) let testFunc = sourceFile.statements[0] @@ -51,9 +49,8 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` function new_test_func(x: number, y: string) {} ` @@ -73,12 +70,10 @@ suite(util.getSuiteTitle(__filename), () => { } ` - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) - let testFunc = arkts.nodeByPeer(util.getStatement(0)) + let testFunc = sourceFile.statements[0] util.assert(arkts.isFunctionDeclaration(testFunc)) testFunc = util.addMemoParamsToFunctionDeclaration(testFunc) @@ -91,12 +86,12 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` function foo(__memo_context: __memo_context_type, __memo_id: __memo_id_type, x: number) {} - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) @@ -108,18 +103,17 @@ suite(util.getSuiteTitle(__filename), () => { const sample_in = ` - function foo() { + function foo(x: string) { // empty } ` - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) - let testFunc = arkts.nodeByPeer(util.getStatement(0)) + let testFunc = sourceFile.statements[0] util.assert(arkts.isFunctionDeclaration(testFunc)) + util.assert(testFunc.body !== undefined) let body_statements = [ ...testFunc.body.statements, @@ -148,12 +142,11 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` - function foo() { - x; + function foo(x: string) { + x } ` ) @@ -172,13 +165,12 @@ suite(util.getSuiteTitle(__filename), () => { } ` - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) - let testFunc = arkts.nodeByPeer(util.getStatement(0)) + let testFunc = sourceFile.statements[0] util.assert(arkts.isFunctionDeclaration(testFunc)) + util.assert(testFunc.body !== undefined) let body_statements = [ ...testFunc.body.statements, @@ -212,23 +204,20 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` function foo() { __memo_scope.recache; } - ` + `, + arkts.ContextState.ES2PANDA_STATE_PARSED, ) }) // body memo rewrite (adding return statement) test("add-return-statement-to-function-body", function() { // function foo() { - // // if (__memo_scope.unchanged) - // // return __memo_scope.cached - // // content(__memo_context, __memo_id + "key_id_main.ts") // return __memo_scope.recache() // } @@ -239,13 +228,12 @@ suite(util.getSuiteTitle(__filename), () => { } ` - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) + let sourceFile = arkts.factory.createSourceFile(sample_in) util.assert(arkts.isSourceFile(sourceFile)) - let testFunc = arkts.nodeByPeer(util.getStatement(0)) + let testFunc = sourceFile.statements[0] util.assert(arkts.isFunctionDeclaration(testFunc)) + util.assert(testFunc.body !== undefined) let body_statements = [ ...testFunc.body.statements, @@ -254,7 +242,9 @@ suite(util.getSuiteTitle(__filename), () => { arkts.factory.createPropertyAccessExpression( arkts.factory.createIdentifier("__memo_scope"), arkts.factory.createIdentifier("recache") - ) + ), + undefined, + undefined ) ) ] @@ -281,196 +271,195 @@ suite(util.getSuiteTitle(__filename), () => { ] ) - util.assertAstEqualsAfter( + util.assertEqualsAfter( sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, ` function foo() { return __memo_scope.recache(); } - ` - ) - }) - - // body memo rewrite (adding if statement) - test("add-if-statement-to-function-body", function() { - // function foo() { - // if (__memo_scope.unchanged) - // return __memo_scope.cached - // // content(__memo_context, __memo_id + "key_id_main.ts") - // // return __memo_scope.recache() - // } - - const sample_in = - ` - function foo() { - // empty - } - ` - - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) - util.assert(arkts.isSourceFile(sourceFile)) - - let testFunc = arkts.nodeByPeer(util.getStatement(0)) - util.assert(arkts.isFunctionDeclaration(testFunc)) - - let body_statements = [ - arkts.factory.createIfStatement( - arkts.factory.createPropertyAccessExpression( - arkts.factory.createIdentifier("__memo_scope"), - arkts.factory.createIdentifier("unchanged") - ), - arkts.factory.createBlock([ - arkts.factory.createReturnStatement( - arkts.factory.createPropertyAccessExpression( - arkts.factory.createIdentifier("__memo_scope"), - arkts.factory.createIdentifier("cached") - ) - ) - ]), - undefined - ), - ...testFunc.body.statements - ] - - testFunc = arkts.factory.updateFunctionDeclaration( - testFunc, - undefined, - undefined, - testFunc.name, - undefined, - testFunc.parameters, - undefined, - arkts.factory.updateBlock( - testFunc.body, - body_statements - ) - ) - util.assert(arkts.isFunctionDeclaration(testFunc)) - - sourceFile = arkts.factory.updateSourceFile( - sourceFile, - [ - testFunc - ] - ) - - util.assertAstEqualsAfter( - sourceFile, + `, arkts.ContextState.ES2PANDA_STATE_PARSED, - ` - function foo() { - if (__memo_scope.unchanged) { - return __memo_scope.cached; - } - } - ` ) }) - // body memo rewrite - test("function-declaration-memo-rewrite", function() { - // function foo(__memo_context: __memo_context_type, __memo_id: __memo_id_type) { - // if (__memo_scope.unchanged) - // return __memo_scope.cached - // content(__memo_context, __memo_id + "key_id_main.ts") - // return __memo_scope.recache() - // } - - const sample_in = - ` - function foo() { - // empty - } - ` - - util.getDefaultSetup(sample_in) - - let sourceFile = arkts.nodeByPeer(util.AstProvider.provideAst()) - util.assert(arkts.isSourceFile(sourceFile)) - - let testFunc = arkts.nodeByPeer(util.getStatement(0)) - util.assert(arkts.isFunctionDeclaration(testFunc)) - - let body_statements = [ - arkts.factory.createIfStatement( - arkts.factory.createPropertyAccessExpression( - arkts.factory.createIdentifier("__memo_scope"), - arkts.factory.createIdentifier("unchanged") - ), - arkts.factory.createBlock([ - arkts.factory.createReturnStatement( - arkts.factory.createPropertyAccessExpression( - arkts.factory.createIdentifier("__memo_scope"), - arkts.factory.createIdentifier("cached") - ) - ) - ]), - undefined - ), - arkts.factory.createExpressionStatement( - arkts.factory.createCallExpression( - arkts.factory.createIdentifier("content"), - undefined, - [ - arkts.factory.createIdentifier("__memo_context"), - arkts.factory.createBinaryExpression( - arkts.factory.createIdentifier("__memo_id"), - arkts.factory.createToken(arkts.SyntaxKind.PlusToken), - arkts.factory.createStringLiteral("key_id_main.ts") - ) - ] - )), - arkts.factory.createReturnStatement( - arkts.factory.createCallExpression( - arkts.factory.createPropertyAccessExpression( - arkts.factory.createIdentifier("__memo_scope"), - arkts.factory.createIdentifier("recache") - ) - ) - ), - ...testFunc.body.statements - ] - - testFunc = util.addMemoParamsToFunctionDeclaration(testFunc) - util.assert(arkts.isFunctionDeclaration(testFunc)) - - testFunc = arkts.factory.updateFunctionDeclaration( - testFunc, - undefined, - undefined, - testFunc.name, - undefined, - testFunc.parameters, - undefined, - arkts.factory.updateBlock( - testFunc.body, - body_statements - ) - ) - util.assert(arkts.isFunctionDeclaration(testFunc)) - - sourceFile = arkts.factory.updateSourceFile( - sourceFile, - [ - testFunc - ] - ) - - util.assertAstEqualsAfter( - sourceFile, - arkts.ContextState.ES2PANDA_STATE_PARSED, - ` - function foo(__memo_context: __memo_context_type, __memo_id: __memo_id_type) { - if (__memo_scope.unchanged) { - return __memo_scope.cached; - } - content(__memo_context, ((__memo_id) + ("key_id_main.ts"))); - return __memo_scope.recache(); - } - ` - ) - }) + // // body memo rewrite (adding if statement) + // test("add-if-statement-to-function-body", function() { + // // function foo() { + // // if (__memo_scope.unchanged) + // // return __memo_scope.cached + // // } + + // const sample_in = + // ` + // function foo() { + // // empty + // } + // ` + + // let sourceFile = arkts.factory.createSourceFile(sample_in) + // util.assert(arkts.isSourceFile(sourceFile)) + + // let testFunc = sourceFile.statements[0] + // util.assert(arkts.isFunctionDeclaration(testFunc)) + // util.assert(testFunc.body !== undefined) + + // let body_statements = [ + // arkts.factory.createIfStatement( + // arkts.factory.createPropertyAccessExpression( + // arkts.factory.createIdentifier("__memo_scope"), + // arkts.factory.createIdentifier("unchanged") + // ), + // arkts.factory.createBlock([ + // arkts.factory.createReturnStatement( + // arkts.factory.createPropertyAccessExpression( + // arkts.factory.createIdentifier("__memo_scope"), + // arkts.factory.createIdentifier("cached") + // ) + // ) + // ]), + // undefined + // ), + // ...testFunc.body.statements + // ] + + // testFunc = arkts.factory.updateFunctionDeclaration( + // testFunc, + // undefined, + // undefined, + // testFunc.name, + // undefined, + // testFunc.parameters, + // undefined, + // arkts.factory.updateBlock( + // testFunc.body, + // body_statements + // ) + // ) + // util.assert(arkts.isFunctionDeclaration(testFunc)) + + // sourceFile = arkts.factory.updateSourceFile( + // sourceFile, + // [ + // testFunc + // ] + // ) + + // util.assertEqualsAfter( + // sourceFile, + // ` + // function foo() { + // if (__memo_scope.unchanged) { + // return __memo_scope.cached; + // } + // } + // `, + // arkts.ContextState.ES2PANDA_STATE_PARSED, + // ) + // }) + + // // body memo rewrite + // test("function-declaration-memo-rewrite", function() { + // // function foo(__memo_context: __memo_context_type, __memo_id: __memo_id_type) { + // // if (__memo_scope.unchanged) + // // return __memo_scope.cached + // // content(__memo_context, __memo_id + "key_id_main.ts") + // // return __memo_scope.recache() + // // } + + // const sample_in = + // ` + // function foo() { + // // empty + // } + // ` + + // let sourceFile = arkts.factory.createSourceFile(sample_in) + // util.assert(arkts.isSourceFile(sourceFile)) + + // let testFunc = sourceFile.statements[0] + // util.assert(arkts.isFunctionDeclaration(testFunc)) + // util.assert(testFunc.body !== undefined) + + // let body_statements = [ + // arkts.factory.createIfStatement( + // arkts.factory.createPropertyAccessExpression( + // arkts.factory.createIdentifier("__memo_scope"), + // arkts.factory.createIdentifier("unchanged") + // ), + // arkts.factory.createBlock([ + // arkts.factory.createReturnStatement( + // arkts.factory.createPropertyAccessExpression( + // arkts.factory.createIdentifier("__memo_scope"), + // arkts.factory.createIdentifier("cached") + // ) + // ) + // ]), + // undefined + // ), + // arkts.factory.createExpressionStatement( + // arkts.factory.createCallExpression( + // arkts.factory.createIdentifier("content"), + // undefined, + // [ + // arkts.factory.createIdentifier("__memo_context"), + // arkts.factory.createBinaryExpression( + // arkts.factory.createIdentifier("__memo_id"), + // arkts.factory.createToken(arkts.SyntaxKind.PlusToken), + // arkts.factory.createStringLiteral("key_id_main.ts") + // ) + // ] + // )), + // arkts.factory.createReturnStatement( + // arkts.factory.createCallExpression( + // arkts.factory.createPropertyAccessExpression( + // arkts.factory.createIdentifier("__memo_scope"), + // arkts.factory.createIdentifier("recache") + // ), + // undefined, + // undefined + // ) + // ), + // ...testFunc.body.statements + // ] + + // testFunc = util.addMemoParamsToFunctionDeclaration(testFunc) + // util.assert(arkts.isFunctionDeclaration(testFunc)) + // util.assert(testFunc.body !== undefined) + + // testFunc = arkts.factory.updateFunctionDeclaration( + // testFunc, + // undefined, + // undefined, + // testFunc.name, + // undefined, + // testFunc.parameters, + // undefined, + // arkts.factory.updateBlock( + // testFunc.body, + // body_statements + // ) + // ) + // util.assert(arkts.isFunctionDeclaration(testFunc)) + + // sourceFile = arkts.factory.updateSourceFile( + // sourceFile, + // [ + // testFunc + // ] + // ) + + // util.assertEqualsAfter( + // sourceFile, + // ` + // function foo(__memo_context: __memo_context_type, __memo_id: __memo_id_type) { + // if (__memo_scope.unchanged) { + // return __memo_scope.cached; + // } + // content(__memo_context, ((__memo_id) + ("key_id_main.ts"))); + // return __memo_scope.recache(); + // } + // `, + // arkts.ContextState.ES2PANDA_STATE_PARSED, + // ) + // }) }) diff --git a/arkoala-arkts/libarkts/test/test-util.ts b/arkoala-arkts/libarkts/test/test-util.ts index 55f12bc4a..4148c831d 100644 --- a/arkoala-arkts/libarkts/test/test-util.ts +++ b/arkoala-arkts/libarkts/test/test-util.ts @@ -14,26 +14,18 @@ */ import * as arkts from "../src/arkts" +import * as ets from "../src/arkts/typesEts" import * as path from "path" import { KNativePointer } from "@koalaui/interop" import { nativeModule } from "../src/NativeModule" import { NativePtrDecoder } from "../src/node/Platform" import { assert } from "chai" -import { PrintVisitor } from "../compatible/src/print-visitor" +// import { PrintVisitor } from "../compatible/src/print-visitor" +import { exec } from "child_process" +import global from "../src/arkts/global" -class DefaultConfig { - static readonly configFile = "./arktsconfig.json" - static readonly sourceFile = "./input/main.sts" - static readonly config = ["", "--arktsconfig", this.configFile, this.sourceFile] -} - -export function getDefaultSetup(source: string): void { - if (!arkts.Global.isInitializedConfig()) { - arkts.Global.config = arkts.createConfig(DefaultConfig.config) - } - arkts.Global.context = arkts.createContextFromString(arkts.Global.config, source, DefaultConfig.sourceFile) - arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_PARSED) -} +export { nativeModule } from "../src/NativeModule" +export { assert } from "chai" class defaultTransformationContext implements arkts.TransformationContext { } @@ -42,13 +34,6 @@ export function getDefaultTransformationContext(): arkts.TransformationContext { return new defaultTransformationContext() } -export class AstProvider { - public static provideAst(): KNativePointer { - const program = arkts.contextProgram() - return arkts.programAst(program).peer - } -} - export function alignText(text: string): string { const lines = text.replace(/\t/gy, ' ').split('\n') @@ -69,45 +54,55 @@ export function alignText(text: string): string { return lines.map(str => str.slice((shift === -1) ? 0 : shift)).join('\n').trim() } -export function printVisitorOutput(node: arkts.Node): string { - return (new PrintVisitor(getDefaultTransformationContext())).astToString(node) -} - -export function getStatement(index: number): KNativePointer { - const peer = AstProvider.provideAst() - return (new NativePtrDecoder()).decode(nativeModule._BlockStatementStatements(arkts.Global.context, peer))[index] -} +// export function printVisitorOutput(node: arkts.Node): string { +// return (new PrintVisitor(getDefaultTransformationContext())).astToString(node) +// } export function getSuiteTitle(fileName: string) { return path.basename(fileName).split('.')[0] } -export function assertEqualsSource(sourceResult: string, sourceExpect: string) { +export function assertEqualsSource(sourceResult: string, sourceExpect: string, message?: string) { assert.equal( sourceResult.trim().split('\n').map((line: string) => line.trim()).join('\n'), - sourceExpect.trim().split('\n').map((line: string) => line.trim()).join('\n') + sourceExpect.trim().split('\n').map((line: string) => line.trim()).join('\n'), + message ) } -export function assertAstEqualsAfter(node: arkts.Node, state: arkts.ContextState, source: string) { - const ast = arkts.dumpJsonNode(node) - const src = arkts.dumpSrcNode(node) - const mods = arkts.dumpModifiers(node.peer) - - const _oldContext = arkts.Global.context - arkts.Global.context = arkts.createContextFromString(arkts.Global.config, source, DefaultConfig.sourceFile) - arkts.proceedToState(state) - const peer = AstProvider.provideAst() - arkts.Global.context = _oldContext - - assert.equal(ast, arkts.dumpJson(peer)) - assertEqualsSource(src, arkts.dumpSrcNode(arkts.nodeByPeer(peer))) - assert.equal(mods, arkts.dumpModifiers(peer)) +export function assertEqualsAfter(node: arkts.SourceFile, source: string, state?: arkts.ContextState) { + const finalState: arkts.ContextState = (() => { + if (state !== undefined) { + return state + } + if (process.env.STATE_CHECKED !== undefined) { + return arkts.ContextState.ES2PANDA_STATE_CHECKED + } + return arkts.ContextState.ES2PANDA_STATE_PARSED + })() + + arkts.proceedToState(finalState) + + const ast = node._node.dumpJson() + const src = node._node.dumpSrc() + const mods = node._node.dumpModifierFlags() + + nativeModule._DestroyContext(global.context) + const sourceFile = arkts.factory.createSourceFile(source) + arkts.proceedToState(finalState) + const root = sourceFile._node + try { + assert.equal(ast, root.dumpJson(), 'Error on JSON comparison') + assertEqualsSource(src, root.dumpSrc(), 'Error on SOURCE comparison') + assert.equal(mods, root.dumpModifierFlags(), 'Error on MODIFIERS comparison') + } finally { + nativeModule._DestroyContext(global.context) + } } -export function dumpFirst() { - return arkts.dumpJson(getStatement(0)) -} +// export function dumpFirst() { +// return arkts.dumpJson(getStatement(0)) +// } export function addMemoParamsToFunctionDeclaration(func: arkts.FunctionDeclaration): arkts.FunctionDeclaration { return arkts.factory.updateFunctionDeclaration( @@ -144,15 +139,17 @@ export function addMemoParamsToFunctionDeclaration(func: arkts.FunctionDeclarati ) } -export function generateBinAndRun() { +export function generateBin(): void { arkts.proceedToState(arkts.ContextState.ES2PANDA_STATE_BIN_GENERATED) - const { exec } = require('child_process') exec('rm ./native/main.abc') exec('mv ./main.abc ./native/main.abc') +} + +export function runAbc(): void { exec( 'npm run run:abc', - (err: any, stdout: any, stderr: any) => { - if (err) { + (error: any, stdout: string, stderr: string) => { + if (error) { console.log('failed to run abc') return; } @@ -162,5 +159,31 @@ export function generateBinAndRun() { ) } -export { nativeModule } from "../src/NativeModule" -export { assert } from "chai" +export function assertEqualsBinaryOuptut(output: string, ctx: Mocha.Context): void { + if (process.env.TEST_BIN === undefined) { + ctx.skip() + } + try { + generateBin() + exec( + 'npm run run:abc', + (error: any, stdout: string, stderr: string) => { + if (error) { + console.log('failed to run abc') + return; + } + const lines = stdout.trim().split('\n') + assert(lines.length >= 2) + assert.equal(lines[0], '> run:abc') + assert.equal(stderr, '') + if (lines.length === 2) { + assert.equal('', output.trim()) + } else { + assert.equal(lines.splice(2).join('\n').trim(), output.trim()) + } + } + ) + } finally { + nativeModule._DestroyContext(global.context) + } +} diff --git a/incremental/compiler-plugin/.gitlab-ci.yml b/incremental/compiler-plugin/.gitlab-ci.yml index a99749601..0e816c80b 100644 --- a/incremental/compiler-plugin/.gitlab-ci.yml +++ b/incremental/compiler-plugin/.gitlab-ci.yml @@ -12,7 +12,7 @@ # limitations under the License. build compiler-plugin: - stage: build-compiler + stage: build interruptible: true extends: .linux-vm-shell-task before_script: @@ -41,4 +41,3 @@ test compiler-plugin: - build compat - build common - build compiler-plugin - -- Gitee