idlize

Форк
0
102 строки · 3.6 Кб
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 'typescript';
17
import { ScopedVisitor } from './ScopedVisitor';
18
import {
19
    FunctionKind,
20
    Tracer,
21
    parameterStateName as localStateName,
22
    PositionalIdTracker,
23
    runtimeIdentifier,
24
    RuntimeNames,
25
    isMemoKind,
26
    getSymbolByNode,
27
    getDeclarationsByNode,
28
    isStableClass,
29
} from "./util"
30

31
export class ThisTransformer extends ScopedVisitor<boolean> {
32
    constructor(
33
        public tracer: Tracer,
34
        public typechecker: ts.TypeChecker,
35
        public sourceFile: ts.SourceFile,
36
        public positionalIdTracker: PositionalIdTracker,
37
        public functionTable: Map<ts.SignatureDeclarationBase, FunctionKind>,
38
        ctx: ts.TransformationContext
39
    ) {
40
        super(functionTable, ctx)
41
    }
42

43
    transformThisUse(node: ts.ThisExpression): ts.PropertyAccessExpression {
44
        const newName = localStateName("this")
45
        return ts.factory.createPropertyAccessExpression(
46
            ts.factory.createIdentifier(newName),
47
            runtimeIdentifier(RuntimeNames.VALUE)
48
        )
49
    }
50

51
    override withFunctionScope<T>(kind: FunctionKind, isInMemoMethod: boolean, body: ()=>T): T {
52
        let result: T
53
        this.functionScopes.push(kind, isInMemoMethod)
54
        result = body()
55
        this.functionScopes.pop()
56
        return result
57
    }
58

59
    isThisExpression(node: ts.Node): node is ts.ThisExpression {
60
        return node.kind == ts.SyntaxKind.ThisKeyword
61
    }
62

63
    isInMemoMethod(): boolean {
64
        return this.functionScopes.peek()?.data ?? false
65
    }
66

67
    isStableClass(node: ts.ThisExpression): boolean {
68
        const declarations = getDeclarationsByNode(this.typechecker, node)
69
        const firstDeclaration = declarations[0]
70
        if (!firstDeclaration) return false
71
        if (!ts.isClassDeclaration(firstDeclaration)) return false
72
        return isStableClass(this.sourceFile, firstDeclaration)
73
    }
74

75
    visitor(node: ts.Node): ts.Node {
76
        if (ts.isArrowFunction(node)) {
77
            return this.withFunctionScope(this.currentKind(), this.isInMemoMethod(), () => {
78
                return this.visitEachChild(node)
79
            })
80
        }  else if (ts.isFunctionDeclaration(node)) {
81
            return this.withFunctionScope(this.currentKind(), false, () => {
82
                return this.visitEachChild(node)
83
            })
84
        }  else if (ts.isMethodDeclaration(node)) {
85
            const kind = this.declarationKind(node)
86
            const isInMemoMethod = this.isInMemoMethod() || isMemoKind(kind)
87
            const transformedWithChildren = this.withFunctionScope(kind, isInMemoMethod, ()=>{
88
                return this.visitEachChild(node)
89
            })
90
            return transformedWithChildren
91

92
        } else if (this.isThisExpression(node)) {
93
            if (!this.isStableClass(node) && this.isInMemoMethod()) {
94
                const transformed = node.parent ?
95
                    this.transformThisUse(node) :
96
                    node
97
                return this.visitEachChild(transformed)
98
            }
99
        }
100
        return this.visitEachChild(node)
101
    }
102
}
103

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

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

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

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