idlize

Форк
0
/
PeerMethod.ts 
172 строки · 5.8 Кб
1
/*
2
 * Copyright (c) 2024 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

17
import { capitalize } from "../util"
18
import { ArgConvertor, OptionConvertor, RetConvertor } from "./Convertors"
19
import { Method, MethodModifier, mangleMethodName } from "./LanguageWriters"
20
import { DeclarationTable, DeclarationTarget, FieldRecord, PrimitiveType, StructVisitor } from "./DeclarationTable"
21

22
export class PeerMethod {
23
    constructor(
24
        public originalParentName: string,
25
        public declarationTargets: DeclarationTarget[],
26
        public argConvertors: ArgConvertor[],
27
        public retConvertor: RetConvertor,
28
        public isCallSignature: boolean,
29
        public isOverloaded: boolean,
30
        public method: Method
31
    ) { }
32

33
    public hasReceiver(): boolean {
34
        return !this.method.modifiers?.includes(MethodModifier.STATIC)
35
    }
36

37
    get overloadedName(): string {
38
        return this.isOverloaded ? mangleMethodName(this.method) : this.method.name
39
    }
40

41
    get fullMethodName(): string {
42
        return this.isCallSignature ? this.overloadedName : this.peerMethodName
43
    }
44

45
    get peerMethodName() {
46
        const name = this.overloadedName
47
        if (!this.hasReceiver()) return name
48
        if (name.startsWith("set") ||
49
            name.startsWith("get") ||
50
            name.startsWith("_set")
51
        ) return name
52
        return `set${capitalize(name)}`
53
    }
54

55
    get implNamespaceName(): string {
56
        return `${capitalize(this.originalParentName)}Modifier`
57
    }
58

59
    get implName(): string {
60
        return `${capitalize(this.overloadedName)}Impl`
61
    }
62

63
    get toStringName(): string {
64
        return this.method.name
65
    }
66

67
    get dummyReturnValue(): string | undefined {
68
        return undefined
69
    }
70

71
    get retType(): string {
72
        return this.maybeCRetType(this.retConvertor) ?? "void"
73
    }
74

75
    get receiverType(): string {
76
        return "Ark_NodeHandle"
77
    }
78

79
    get apiCall(): string {
80
        return "GetNodeModifiers()"
81
    }
82

83
    get apiKind(): string {
84
        return "Modifier"
85
    }
86

87
    maybeCRetType(retConvertor: RetConvertor): string | undefined {
88
        if (retConvertor.isVoid) return undefined
89
        return retConvertor.nativeType()
90
    }
91

92
    generateAPIParameters(): string[] {
93
        const args = this.argConvertors.map(it => {
94
            let isPointer = it.isPointerType()
95
            return `${isPointer ? "const ": ""}${it.nativeType(false)}${isPointer ? "*": ""} ${it.param}`
96
        })
97
        const receiver = this.generateReceiver()
98
        if (receiver) return [`${receiver.argType} ${receiver.argName}`, ...args]
99
        return args
100
    }
101

102
    generateReceiver(): {argName: string, argType: string} | undefined {
103
        if (!this.hasReceiver()) return undefined
104
        return {
105
            argName: "node",
106
            argType: PrimitiveType.NativePointer.getText()
107
        }
108
    }
109

110
    static markOverloads(methods: PeerMethod[]): void {
111
        for (const peerMethod of methods)
112
            peerMethod.isOverloaded = false
113

114
        for (const peerMethod of methods) {
115
            if (peerMethod.isOverloaded) continue
116
            const sameNamedMethods = methods.filter(it => it.method.name === peerMethod.method.name)
117
            if (sameNamedMethods.length <= 1) continue
118
            sameNamedMethods.forEach((method) => method.isOverloaded = true)
119
        }
120
    }
121
}
122

123
export class MethodSeparatorVisitor {
124
    constructor(
125
        protected readonly declarationTable: DeclarationTable,
126
        protected readonly method: PeerMethod,
127
    ) {}
128

129
    protected onPushUnionScope(argIndex: number, field: FieldRecord, selectorValue: number): void {}
130
    protected onPopUnionScope(argIndex: number) {}
131
    protected onPushOptionScope(argIndex: number, target: DeclarationTarget, exists: boolean): void {}
132
    protected onPopOptionScope(argIndex: number): void {}
133
    protected onVisitInseparableArg(argIndex: number) {}
134
    protected onVisitInseparable() {}
135

136
    private visitArg(argIndex: number): void {
137
        if (argIndex >= this.method.argConvertors.length) {
138
            this.onVisitInseparable()
139
            return
140
        }
141

142
        const visitor: StructVisitor = {
143
            visitUnionField: (field: FieldRecord, selectorValue: number) => {
144
                this.onPushUnionScope(argIndex, field, selectorValue)
145
                this.declarationTable.visitDeclaration(field.declaration, visitor)
146
                this.onPopUnionScope(argIndex)
147
            },
148
            visitInseparable: () => {
149
                this.onVisitInseparableArg(argIndex)
150
                this.visitArg(argIndex + 1)
151
            }
152
        }
153
        if (this.method.argConvertors[argIndex] instanceof OptionConvertor) {
154
            // todo does we have optionals only on root?
155
            const conv = this.method.argConvertors[argIndex] as OptionConvertor
156
            const target = this.declarationTable.toTarget(conv.type)
157

158
            this.onPushOptionScope(argIndex, target, true)
159
            this.declarationTable.visitDeclaration(target, visitor)
160
            this.onPopOptionScope(argIndex)
161

162
            this.onPushOptionScope(argIndex, target, false)
163
            visitor.visitInseparable()
164
            this.onPopOptionScope(argIndex)
165
        } else
166
            this.declarationTable.visitDeclaration(this.method.declarationTargets[argIndex], visitor)
167
    }
168

169
    visit(): void {
170
        this.visitArg(0)
171
    }
172
}

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

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

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

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