idlize
108 строк · 3.5 Кб
1/*
2* Copyright (c) 2022-2023 Huawei Device Co., Ltd.
3* Licensed under the Apache License, Version 2.0 (the "License");
4* you may not use this file except in compliance with the License.
5* You may obtain a copy of the License at
6*
7* http://www.apache.org/licenses/LICENSE-2.0
8*
9* Unless required by applicable law or agreed to in writing, software
10* distributed under the License is distributed on an "AS IS" BASIS,
11* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12* See the License for the specific language governing permissions and
13* limitations under the License.
14*/
15
16import * as ts from 'ohos-typescript'
17import { AbstractVisitor } from './AbstractVisitor'
18import { Importer } from './Importer'
19import { id } from './ApiUtils'
20import { CallTable, idTextOrError } from './utils'
21
22
23function statementIsLazyForEach(statement: ts.Statement): boolean {
24if (!ts.isExpressionStatement(statement)) return false
25if (!ts.isCallExpression(statement.expression)) return false
26const callee = statement.expression.expression
27if (!ts.isIdentifier(callee)) return false
28if (ts.idText(callee) != "LazyForEach") return false
29return true
30}
31
32function statementIsForEach(statement: ts.Statement): boolean {
33if (!ts.isExpressionStatement(statement)) return false
34if (!ts.isCallExpression(statement.expression)) return false
35const callee = statement.expression.expression
36if (!ts.isIdentifier(callee)) return false
37if (ts.idText(callee) != "ForEach") return false
38return true
39}
40
41export class LazyTransformer extends AbstractVisitor {
42constructor(
43sourceFile: ts.SourceFile,
44ctx: ts.TransformationContext,
45private importer: Importer,
46private callTable: CallTable
47) {
48super(sourceFile, ctx)
49}
50
51
52convertChildIfNeeded(node: ts.Statement): ts.Statement {
53if (!statementIsForEach(node)) return node
54
55return this.convertForEachToForEachByArray(node as ts.ExpressionStatement)
56}
57
58convertForEachToForEachByArray(node: ts.ExpressionStatement): ts.ExpressionStatement {
59const call = node.expression as ts.CallExpression
60const newEts = ts.factory.updateCallExpression(
61call,
62id(this.importer.withAdaptorImport("LazyForEachByArray")),
63call.typeArguments,
64call.arguments
65)
66return ts.factory.updateExpressionStatement(
67node,
68newEts
69)
70}
71
72convertToLazy(node: ts.EtsComponentExpression): ts.EtsComponentExpression {
73const newBody = node.body ?
74ts.factory.updateBlock(
75node.body,
76node.body.statements.map(it => this.convertChildIfNeeded(it))
77) : undefined
78
79const name = id("Lazy" + idTextOrError(node.expression))
80this.callTable.lazyCalls.add(name)
81return ts.factory.updateEtsComponentExpression(
82node,
83name,
84node.arguments,
85newBody
86)
87}
88
89
90visitor(beforeChildren: ts.Node): ts.Node {
91if (this.importer.__isArkoalaImplementation) return beforeChildren
92
93const node = this.visitEachChild(beforeChildren)
94if (ts.isEtsComponentExpression(node)) {
95const body = node.body
96if (!body) return node
97
98const lazy = body.statements.find(
99it => statementIsLazyForEach(it)
100)
101if (!lazy) return node
102
103this.importer.addAdaptorImport("LazyForEach")
104return this.convertToLazy(node)
105}
106return node
107}
108}
109