idlize

Форк
0
/
CallTransformer.ts 
128 строк · 5.0 Кб
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

16
import * as ts from 'ohos-typescript'
17
import { AbstractVisitor } from './AbstractVisitor'
18
import { getDeclarationsByNode, hasDecorator } from './ApiUtils'
19
import { asString, CallTable, findBuilderLambdaRedirect, isGlobalBuilder, hasLocalDeclaration, isBuiltinComponentName, CustomDialogDecorator, ComponentDecorator } from './utils'
20
import { Importer } from './Importer'
21
import { ImportExport } from './import-export'
22

23

24
export class CallTransformer extends AbstractVisitor {
25
    constructor(
26
        sourceFile: ts.SourceFile,
27
        ctx: ts.TransformationContext,
28
        private typechecker: ts.TypeChecker,
29
        private callTable: CallTable,
30
        private importer: Importer
31
    ) {
32
        super(sourceFile, ctx)
33
    }
34

35
    private importExport = new ImportExport(this.typechecker, this.sourceFile)
36

37
    refersToGlobalBuilder(call: ts.CallExpression): boolean {
38
        const callee = call.expression
39
        if (ts.isIdentifier(callee)) {
40
            const declarations = getDeclarationsByNode(this.typechecker, callee)
41
            if (declarations.length == 0) return false
42
            const firstDeclaration = declarations[0]
43
            if (ts.isFunctionDeclaration(firstDeclaration) &&
44
                isGlobalBuilder(firstDeclaration)
45
            ) return true
46
        }
47
        return false
48
    }
49

50
    getImportModuileSpecifier(node: ts.Identifier): ts.StringLiteral|undefined {
51
        const declarations = getDeclarationsByNode(this.typechecker, node)
52
        const declaration = declarations[0]
53
        if (!declaration) return undefined
54
        let importDeclaration = undefined
55
        if (ts.isImportSpecifier(declaration)) {
56
            importDeclaration = declaration.parent.parent.parent
57
        } else if (ts.isImportClause(declaration)) {
58
            importDeclaration = declaration.parent
59
        }
60
        if (!importDeclaration || !ts.isImportDeclaration(importDeclaration)) {
61
            return undefined
62
        }
63
        const moduleSpecifier = importDeclaration.moduleSpecifier
64
        if (!ts.isStringLiteral(moduleSpecifier)) return undefined
65
        return moduleSpecifier
66
    }
67

68
    isLegacyCall(node: ts.Identifier): boolean {
69
        if (!this.importer.__isArkoalaImplementation) return false
70

71
        const moduleSpecifier = this.getImportModuileSpecifier(node)
72
        if (!moduleSpecifier) return false
73
        const moduleSym = this.typechecker.getSymbolAtLocation(moduleSpecifier)
74
        if (moduleSym === undefined) return false
75
        return moduleSym.escapedName.toString().includes("library") || // TODO: don't forget to erase for production
76
           (this.importer.moduleInfo?.(moduleSym.escapedName.toString())?.isLegacy ?? false)
77
    }
78

79
    isComponentStructCall(node: ts.Identifier): boolean {
80
        const declaration = this.importExport.findRealDeclaration(node)
81
        if (!declaration) return false
82
        return ts.isStructDeclaration(declaration) && hasDecorator(declaration, ComponentDecorator)
83
    }
84

85
    visitor(beforeChildren: ts.Node): ts.Node {
86
        const node = this.visitEachChild(beforeChildren)
87

88
        /**
89
         * Function call is treated as ETS Component call when:
90
         *   - it is listed in ETS components
91
         *   - it is not user defined
92
         */
93
        if (ts.isCallExpression(node) && ts.isIdentifier(node.expression)) {
94

95
            const func = node.expression
96
            const name = ts.idText(func)
97
            if (isBuiltinComponentName(this.ctx, name)) {
98
                if (hasLocalDeclaration(this.typechecker, func)) {
99
                    return node
100
                }
101
                return ts.factory.createEtsComponentExpression(
102
                    node.expression,
103
                    node.arguments,
104
                    undefined
105
                )
106
            }
107

108
            const builderLambdaRedirect = findBuilderLambdaRedirect(this.typechecker, node)
109
            if (builderLambdaRedirect) {
110
                this.callTable.builderLambdas.set(node, builderLambdaRedirect)
111
            }
112

113
            if (this.refersToGlobalBuilder(node)) {
114
                this.callTable.globalBuilderCalls.add(node)
115
            }
116

117
            if (this.isLegacyCall(node.expression)) {
118
                this.callTable.legacyCalls.add(node)
119
            }
120

121
            if (this.isComponentStructCall(node.expression)) {
122
                this.callTable.structCalls.add(ts.getOriginalNode(node) as ts.CallExpression)
123
            }
124
        }
125

126
        return node
127
    }
128
}
129

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.