idlize

Форк
0
/
InterfacePrinter.ts 
642 строки · 25.0 Кб
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
import * as ts from 'typescript'
17
import * as path from 'path'
18
import { PeerLibrary } from "../PeerLibrary"
19
import { LanguageWriter, createLanguageWriter, Type, Method, MethodSignature, MethodModifier, NamedMethodSignature } from '../LanguageWriters'
20
import { mapType } from '../TypeNodeNameConvertor'
21
import { Language, renameDtsToInterfaces } from '../../util'
22
import { ImportsCollector } from '../ImportsCollector'
23
import { EnumEntity, PeerFile } from '../PeerFile'
24
import { DeclarationConvertor, convertDeclaration } from '../TypeNodeConvertor'
25
import { TypeNodeConvertor, convertTypeNode } from '../TypeNodeConvertor'
26
import { IndentedPrinter } from "../../IndentedPrinter"
27
import { read } from "node:fs";
28
import { RuntimeType } from '../PeerGeneratorVisitor'
29
import { TargetFile } from './TargetFile'
30
import { ARKOALA_PACKAGE_PATH } from '../../lang/java'
31

32
export class DeclarationGenerator implements DeclarationConvertor<string> {
33
    constructor(
34
        private readonly library: PeerLibrary,
35
    ) {}
36

37
    convertClass(node: ts.ClassDeclaration): string {
38
        return this.convertDeclaration(node)
39
    }
40

41
    convertInterface(node: ts.InterfaceDeclaration): string {
42
        return this.convertDeclaration(node)
43
    }
44

45
    convertEnum(node: ts.EnumDeclaration): string {
46
        throw "Enums are processed separately"
47
    }
48

49
    convertTypeAlias(node: ts.TypeAliasDeclaration): string {
50
        const maybeTypeArguments = node.typeParameters?.length
51
            ? `<${node.typeParameters.map(it => it.getText()).join(', ')}>`
52
            : ''
53
        let type = mapType(node.type)
54
        return `export declare type ${node.name.text}${maybeTypeArguments} = ${type};`
55
    }
56

57
    private replaceImportTypeNodes(text: string): string {
58
        for (const [stub, src] of [...this.library.importTypesStubToSource.entries()].reverse()) {
59
            text = text.replaceAll(src, stub)
60
        }
61
        return text
62
    }
63

64
    private extendsClause(node: ts.ClassDeclaration | ts.InterfaceDeclaration): string {
65
        if (!node.heritageClauses?.length)
66
            return ``
67
        if (node.heritageClauses!.some(it => it.token !== ts.SyntaxKind.ExtendsKeyword))
68
            throw "Expected to have only extend clauses"
69
        if (this.library.isComponentDeclaration(node))
70
            // do not extend parent component interface to provide smooth integration
71
            return ``
72

73
        let parent = node.heritageClauses[0]!.types[0]
74
        return `extends ${parent.getText()}`
75
    }
76

77
    private declarationName(node: ts.ClassDeclaration | ts.InterfaceDeclaration): string {
78
        let name = ts.idText(node.name as ts.Identifier)
79
        let typeParams = node.typeParameters?.map(it => it.getText()).join(', ')
80
        let typeParamsClause = typeParams ? `<${typeParams}>` : ``
81
        return `${name}${typeParamsClause}`
82
    }
83

84
    private convertDeclaration(node: ts.ClassDeclaration | ts.InterfaceDeclaration): string {
85
        if (!this.library.isComponentDeclaration((node))) {
86
            return 'export ' + this.replaceImportTypeNodes(node.getText())
87
        }
88
        let printer = new IndentedPrinter()
89
        let className = this.declarationName(node)
90
        let extendsClause = this.extendsClause(node)
91

92
        let classOrInterface = ts.isClassDeclaration(node) ? `class` : `interface`
93
        if (this.library.isComponentDeclaration(node))
94
            // because we write `ArkBlank implements BlankAttributes`
95
            classOrInterface = `interface`
96
        printer.print(`export declare ${classOrInterface} ${className} ${extendsClause} {`)
97
        printer.pushIndent()
98
        this.declarationMembers(node)
99
            .forEach(it => {
100
                printer.print(`/** @memo */`)
101
                printer.print(it.getText())
102
            })
103
        printer.popIndent()
104
        printer.print(`}`)
105

106
        return this.replaceImportTypeNodes(printer.getOutput().join('\n'))
107
    }
108

109
    private declarationMembers(
110
        node: ts.ClassDeclaration | ts.InterfaceDeclaration
111
    ): readonly (ts.MethodDeclaration)[] {
112
        if (ts.isClassDeclaration(node)) {
113
            const members = node.members.filter(it => !ts.isConstructorDeclaration(it))
114
            if (members.every(ts.isMethodDeclaration))
115
                return members
116
        }
117
        if (ts.isInterfaceDeclaration(node) ) {
118
            const members = node.members.filter(it => 
119
                !ts.isConstructSignatureDeclaration(it) &&
120
                !ts.isCallSignatureDeclaration(it))
121
            if (members.length === 0)
122
                return []
123
        }
124
        throw new Error(`Encountered component with member that is not method: ${node}`)
125
    }
126
}
127

128
interface InterfacesVisitor {
129
    getInterfaces(): Map<TargetFile, LanguageWriter>
130
    printInterfaces(): void
131
}
132

133
class TSInterfacesVisitor implements InterfacesVisitor {
134
    protected readonly interfaces: Map<TargetFile, LanguageWriter> = new Map()
135
    protected readonly generator: DeclarationGenerator
136

137
    constructor(
138
        protected readonly peerLibrary: PeerLibrary,
139
    ) {
140
        this.generator = new DeclarationGenerator(peerLibrary)
141
    }
142

143
    protected generateFileBasename(originalFilename: string): string {
144
        return renameDtsToInterfaces(path.basename(originalFilename), this.peerLibrary.declarationTable.language)
145
    }
146

147
    private printImports(writer: LanguageWriter, file: PeerFile) {
148
        const imports = new ImportsCollector()
149
        imports.addFilterByBasename(this.generateFileBasename(file.originalFilename))
150
        file.importFeatures.forEach(it => imports.addFeature(it.feature, it.module))
151
        imports.print(writer)
152
    }
153

154
    protected printEnum(writer: LanguageWriter, enumEntity: EnumEntity) {
155
        writer.print(enumEntity.comment)
156
        writer.print(`export enum ${enumEntity.name} {`)
157
        writer.pushIndent()
158
        enumEntity.members.forEach((member, index) => {
159
            writer.print(member.comment)
160
            const commaOp = index < enumEntity.members.length - 1 ? ',' : ''
161
            if (member.initializerText != undefined) {
162
                writer.print(`${member.name} = ${member.initializerText}${commaOp}`)
163
            } else {
164
                writer.print(`${member.name}${commaOp}`)
165
            }
166
        })
167
        writer.popIndent()
168
        writer.print(`}`)
169
    }
170

171
    private printAssignEnumsToGlobalScope(writer: LanguageWriter, peerFile: PeerFile) {
172
        if (![Language.TS, Language.ARKTS].includes(writer.language)) return
173
        if (peerFile.enums.length != 0) {
174
            writer.print(`Object.assign(globalThis, {`)
175
            writer.pushIndent()
176
            for (const enumEntity of peerFile.enums) {
177
                writer.print(`${enumEntity.name}: ${enumEntity.name},`)
178
            }
179
            writer.popIndent()
180
            writer.print(`})`)
181
        }
182
    }
183

184
    getInterfaces(): Map<TargetFile, LanguageWriter> {
185
        return this.interfaces
186
    }
187

188
    printInterfaces() {
189
        for (const file of this.peerLibrary.files.values()) {
190
            const writer = createLanguageWriter(Language.TS)
191

192
            this.printImports(writer, file)
193
            file.declarations.forEach(it => writer.print(convertDeclaration(this.generator, it)))
194
            file.enums.forEach(it => this.printEnum(writer, it))
195
            this.printAssignEnumsToGlobalScope(writer, file)
196
            this.interfaces.set(new TargetFile(this.generateFileBasename(file.originalFilename)), writer)
197
        }
198
    }
199
}
200

201
export class JavaTypeNodeNameConvertor implements
202
    TypeNodeConvertor<string>
203
{
204
    convertUnion(node: ts.UnionTypeNode): string {
205
        let unionType = 'Union'
206
        for (const unionSubtype of node.types) {
207
            unionType = `${unionType}_${this.convert(unionSubtype)}`
208
        }
209
        return unionType
210
    }
211
    convertTypeLiteral(node: ts.TypeLiteralNode): string {
212
        const members = node.members.map(it => {
213
            if (ts.isPropertySignature(it)) {
214
                const name = this.convert(it.name)
215
                const isOptional = !!it.questionToken
216
                const type = this.convert(it.type!)
217
                if (isOptional) {
218
                    return `Opt_${type} ${name}`
219
                }
220
                return `${type} ${name}`
221
            }
222
            if (ts.isIndexSignatureDeclaration(it)) {
223
                if (it.modifiers) throw new Error('Not implemented')
224
                if (it.typeParameters) throw new Error('Not implemented')
225
                if (it.questionToken) throw new Error('Not implemented')
226
                if (it.name) throw new Error('Not implemented')
227
                const parameters = it.parameters.map(it => this.convertParameterDeclaration(it))
228
                return `[${parameters.join(', ')}]: ${this.convert(it.type)}`
229
            }
230
            throw new Error(`Unknown member type ${ts.SyntaxKind[it.kind]}`)
231
        })
232
        return `{${members.join(', ')}}`
233
    }
234
    private convertParameterDeclaration(node: ts.ParameterDeclaration): string {
235
        if (node.modifiers) throw new Error('Not implemented')
236
        if (!node.type) throw new Error('Expected ParameterDeclaration to have a type')
237
        const isOptional = !!node.questionToken
238
        const name = this.convert(node.name)
239
        const type = this.convert(node.type!)
240
        if (isOptional) {
241
            return `Opt_${type}$ ${name}`
242
        }
243
        return `${type} ${name}`
244
    }
245
    convertLiteralType(node: ts.LiteralTypeNode): string {
246
        if (node.literal.kind === ts.SyntaxKind.TrueKeyword) return 'true'
247
        if (node.literal.kind === ts.SyntaxKind.FalseKeyword) return 'false'
248
        if (node.literal.kind === ts.SyntaxKind.NullKeyword) return 'null'
249
        if (node.literal.kind === ts.SyntaxKind.StringLiteral) return `"${node.literal.text}"`
250
        throw new Error(`Unknown LiteralTypeNode ${ts.SyntaxKind[node.literal.kind]}`)
251
    }
252
    convertTuple(node: ts.TupleTypeNode): string {
253
        const members = node.elements.map(it => this.convertTupleElement(it))
254
        return `Tuple_${members.join('_')}`
255
    }
256
    protected convertTupleElement(node: ts.TypeNode): string {
257
        if (ts.isNamedTupleMember(node)) {
258
            const name = this.convert(node.name)
259
            const maybeQuestion = node.questionToken ? '?' : ''
260
            const type = this.convert(node.type!)
261
            return `${name}${maybeQuestion}: ${type}`
262
        }
263
        return this.convert(node)
264
    }
265
    convertArray(node: ts.ArrayTypeNode): string {
266
        return `${this.convert(node.elementType)}[]`
267
    }
268
    convertOptional(node: ts.OptionalTypeNode): string {
269
        return `Opt_${this.convert(node.type)}`
270
    }
271
    convertFunction(node: ts.FunctionTypeNode): string {
272
        if (node.typeParameters?.length)
273
            throw new Error('Not implemented')
274
        const parameters = node.parameters.map(it => {
275
            const name = this.convert(it.name)
276
            const maybeQuestion = it.questionToken ? '?' : ''
277
            const type = this.convert(it.type!)
278
            return `${name}${maybeQuestion}: ${type}`
279
        })
280
        return `((${parameters.join(', ')}) => ${this.convert(node.type)})`
281
    }
282
    convertTemplateLiteral(node: ts.TemplateLiteralTypeNode): string {
283
        return node.templateSpans.map(template => {
284
            return `\`\${${this.convert(template.type)}}${template.literal.rawText}\``
285
        }).join()
286
    }
287
    convertImport(node: ts.ImportTypeNode): string {
288
        const from = this.convert(node.argument)
289
        const qualifier = this.convert(node.qualifier!)
290
        const maybeTypeArguments = node.typeArguments?.length
291
            ? '_' + node.typeArguments.map(it => this.convert(it)).join('_')
292
            : ''
293
        return `IMPORT_${qualifier}${maybeTypeArguments}_FROM_${from}`
294
            .match(/[a-zA-Z]+/g)!.join('_')
295
    }
296
    convertTypeReference(node: ts.TypeReferenceNode): string {
297
        const name = this.convert(node.typeName)
298
        if (name === 'Style')
299
            return this.convert(ts.factory.createKeywordTypeNode(ts.SyntaxKind.ObjectKeyword))
300
        let types = node.typeArguments?.map(it => this.convert(it))
301
        if (name === `AttributeModifier`)
302
            types = [`object`]
303
        if (name === `ContentModifier`)
304
            types = [this.convert(ts.factory.createKeywordTypeNode(ts.SyntaxKind.AnyKeyword))]
305
        if (name === `Optional`)
306
            return `${types} | undefined`
307
        const maybeTypeArguments = !types?.length ? '' : `<${types.join(', ')}>`
308
        return `${name}${maybeTypeArguments}`
309
    }
310
    convertParenthesized(node: ts.ParenthesizedTypeNode): string {
311
        return `(${this.convert(node.type)})`
312
    }
313
    convertIndexedAccess(node: ts.IndexedAccessTypeNode): string {
314
        throw new Error('Method not implemented.')
315
    }
316
    convertTypeParameterDeclaration(node: ts.TypeParameterDeclaration): string {
317
        throw new Error('Method not implemented.')
318
    }
319
    convertStringKeyword(node: ts.TypeNode): string {
320
        return 'String'
321
    }
322
    convertNumberKeyword(node: ts.TypeNode): string {
323
        return 'Float'
324
    }
325
    convertBooleanKeyword(node: ts.TypeNode): string {
326
        return 'Boolean'
327
    }
328
    convertUndefinedKeyword(node: ts.TypeNode): string {
329
        return 'Undefined'
330
    }
331
    convertVoidKeyword(node: ts.TypeNode): string {
332
        return 'void'
333
    }
334
    convertObjectKeyword(node: ts.TypeNode): string {
335
        return 'Object'
336
    }
337
    convertAnyKeyword(node: ts.TypeNode): string {
338
        return 'any'
339
    }
340
    convertUnknownKeyword(node: ts.TypeNode): string {
341
        return `unknown`
342
    }
343

344
    // identifier
345
    convertQualifiedName(node: ts.QualifiedName): string {
346
        return `${this.convert(node.left)}.${this.convert(node.right)}`
347
    }
348
    convertIdentifier(node: ts.Identifier): string {
349
        return node.text
350
    }
351

352
    convert(node: ts.Node): string {
353
        if (ts.isQualifiedName(node)) return this.convertQualifiedName(node)
354
        if (ts.isIdentifier(node)) return this.convertIdentifier(node)
355
        if (ts.isTypeNode(node))
356
            return convertTypeNode(this, node)
357
        throw new Error(`Unknown node type ${ts.SyntaxKind[node.kind]}`)
358
    }
359
}
360

361
const nameConvertorInstance = new JavaTypeNodeNameConvertor()
362

363
// will be refactored after migration to IDL IR
364
function mapTypeJava(type: ts.TypeNode | undefined): string {
365
    type ??= ts.factory.createKeywordTypeNode(ts.SyntaxKind.VoidKeyword)
366
    return nameConvertorInstance.convert(type)
367
}
368

369
class JavaInterfacesVisitor {
370
    private readonly interfaces: Map<string, LanguageWriter> = new Map()
371

372
    constructor(
373
        private readonly peerLibrary: PeerLibrary,
374
    ) {}
375

376
    addInterface(name: string, writer: LanguageWriter) {
377
        this.interfaces.set(name, writer)
378
    }
379

380
    hasInterface(name: string): boolean {
381
        return this.interfaces.has(name)
382
    }
383

384
    getName(node: ts.NamedDeclaration): string {
385
        if (!node.name) {
386
            throw new Error(`Empty name for node\n${node}`)
387
        }
388
        return node.name.getText()
389
    }
390

391
    getMemberTargetType(node: ts.PropertyDeclaration | ts.PropertySignature): Type {
392
        const nullable = !!node.questionToken
393
        const type = mapTypeJava(node.type)
394
        if (nullable) {
395
            return new Type(`Opt_${type}`, true)
396
        }
397
        return new Type(type, false)
398
    }
399

400
    getSuperClass(node: ts.ClassDeclaration | ts.InterfaceDeclaration): string | undefined {
401
        if (!node.heritageClauses) {
402
            return
403
        }
404

405
        for (const clause of node.heritageClauses) {
406
            if (clause.token == ts.SyntaxKind.ExtendsKeyword) {
407
                return clause.types[0].expression.getText()
408
            }
409
        }
410
    }
411

412
    printPackage(writer: LanguageWriter): void {
413
        writer.print("package org.koalaui.arkoala;\n")
414
    }
415

416
    implementType(sourceType: ts.TypeNode | undefined, targetType: Type) {
417
        if (targetType.nullable) {
418
            throw new Error('Types for optional class/interface members must be implemented using implementOptionalMemberType');
419
        }
420

421
        if (!sourceType) {
422
            return
423
        }
424
        if (this.hasInterface(targetType.name)) {
425
            return
426
        }
427

428
        if (ts.isUnionTypeNode(sourceType)) {
429
            const writer = createLanguageWriter(Language.JAVA)
430
            this.printPackage(writer)
431
            this.printUnionImplementation(sourceType, targetType, writer)
432
            this.addInterface(targetType.name, writer)
433
            return
434
        }
435
        if (ts.isTupleTypeNode(sourceType)) {
436
            const writer = createLanguageWriter(Language.JAVA)
437
            this.printPackage(writer)
438
            this.printTupleImplementation(sourceType, targetType, writer)
439
            this.addInterface(targetType.name, writer)
440
            return
441
        }
442
        if (ts.isOptionalTypeNode(sourceType)) {
443
            const writer = createLanguageWriter(Language.JAVA)
444
            this.printPackage(writer)
445
            this.printOptionalTypeImplementation(sourceType, targetType, writer)
446
            this.addInterface(targetType.name, writer)
447
            return
448
        }
449
    }
450

451
    implementOptionalMemberType(sourceType: ts.TypeNode | undefined, targetType: Type) {
452
        if (!sourceType) {
453
            return
454
        }
455
        if (this.hasInterface(targetType.name)) {
456
            return
457
        }
458

459
        const writer = createLanguageWriter(Language.JAVA)
460
        this.printPackage(writer)
461
        this.printOptionalImplementation(sourceType, targetType, writer)
462
        this.addInterface(targetType.name, writer)
463
    }
464

465
    printOptionalTypeImplementation(sourceType: ts.OptionalTypeNode, targetType: Type, writer: LanguageWriter) {
466
        this.printOptionalImplementation(sourceType.type, targetType, writer)
467
    }
468

469
    private printOptionalImplementation(sourceType: ts.TypeNode, targetType: Type, writer: LanguageWriter) {
470
        writer.writeClass(targetType.name, () => {
471
            const tag = 'tag'
472
            const value = 'value'
473
            const rtType = new Type('RuntimeType')
474
            writer.writeMethodImplementation(new Method('getRuntimeType', new MethodSignature(rtType, []), [MethodModifier.PUBLIC]), () => {
475
                writer.writeStatement(
476
                    writer.makeReturn(
477
                        writer.makeTernary(
478
                            writer.makeString(`${tag} == ${writer.makeTag('UNDEFINED')}`),
479
                            writer.makeString('RuntimeType.UNDEFINED'),
480
                            writer.makeString('RuntimeType.OBJECT')
481
                        )
482
                    )
483
                )
484
            })
485

486
            writer.writeFieldDeclaration('tag', new Type('Tag'), ['public'], false)
487

488
            const targetType = new Type(mapTypeJava(sourceType))
489
            this.implementType(sourceType, targetType)
490
            writer.writeFieldDeclaration(value, targetType, ['public'], false)
491
        })
492
    }
493

494
    printUnionImplementation(sourceType: ts.UnionTypeNode, targetType: Type, writer: LanguageWriter) {
495
        writer.writeClass(targetType.name, () => {
496
            const intType = new Type('int')
497
            const selector = 'selector'
498
            writer.writeFieldDeclaration(selector, intType, ['private'], false)
499
            writer.writeMethodImplementation(new Method('getSelector', new MethodSignature(intType, []), [MethodModifier.PUBLIC]), () => {
500
                writer.writeStatement(
501
                    writer.makeReturn(
502
                        writer.makeString(selector)
503
                    )
504
                )
505
            })
506

507
            for (const [index, subType] of sourceType.types.entries()) {
508
                const subTypeTargetType = new Type(mapTypeJava(subType))
509
                this.implementType(subType, subTypeTargetType)
510
                const value = `value${index}`
511
                const param = 'param'
512

513
                writer.writeFieldDeclaration(value, subTypeTargetType, ['private'], false)
514

515
                writer.writeConstructorImplementation(
516
                    targetType.name,
517
                    new NamedMethodSignature(Type.Void, [subTypeTargetType], [param]),
518
                    () => {
519
                        writer.writeStatement(
520
                            writer.makeAssign(value, undefined, writer.makeString(param), false, false)
521
                        )
522
                        writer.writeStatement(
523
                            writer.makeAssign(selector, undefined, writer.makeString(index.toString()), false, false)
524
                        )
525
                    }
526
                )
527

528
                writer.writeMethodImplementation(
529
                    new Method(`getValue${index}`, new MethodSignature(subTypeTargetType, []), [MethodModifier.PUBLIC]),
530
                    () => {
531
                        writer.writeStatement(
532
                            writer.makeReturn(
533
                                writer.makeString(value)
534
                            )
535
                        )
536
                    }
537
                )
538
            }
539
        })
540
    }
541

542
    printTupleImplementation(sourceType: ts.TupleTypeNode, targetType: Type, writer: LanguageWriter) {
543
        writer.writeClass(targetType.name, () => {
544
            const rtType = new Type('RuntimeType')
545
            writer.writeMethodImplementation(new Method('getRuntimeType', new MethodSignature(rtType, []), [MethodModifier.PUBLIC]), () => {
546
                writer.writeStatement(
547
                    writer.makeReturn(
548
                        writer.makeString('RuntimeType.OBJECT')
549
                    )
550
                )
551
            })
552

553
            for (const [index, subType] of sourceType.elements.entries()) {
554
                const subTypeTargetType = new Type(mapTypeJava(subType))
555
                this.implementType(subType, subTypeTargetType)
556
                const value = `value${index}`
557

558
                writer.writeFieldDeclaration(value, subTypeTargetType, ['public'], false)
559
            }
560
        })
561
    }
562

563
    printClassOrInterface(node: ts.ClassDeclaration | ts.InterfaceDeclaration, writer: LanguageWriter) {
564
        const superClass = this.getSuperClass(node)
565
        writer.writeClass(this.getName(node), () => {
566
            for (const member of node.members) {
567
                if (!ts.isPropertyDeclaration(member) && !ts.isPropertySignature(member)) {
568
                    continue
569
                }
570

571
                const propertyName = this.getName(member)
572
                const propertyType = this.getMemberTargetType(member)
573
                writer.writeFieldDeclaration(propertyName, propertyType, ['public'], false)
574

575
                if (propertyType.nullable) {
576
                    this.implementOptionalMemberType(member.type, propertyType)
577
                    continue
578
                }
579
                this.implementType(member.type, propertyType)
580
            }
581
        }, superClass)
582
    }
583

584
    getInterfaces(): Map<TargetFile, LanguageWriter> {
585
        const result =  new Map<TargetFile, LanguageWriter>()
586
        for (const [name, writer] of this.interfaces) {
587
            result.set(new TargetFile(name, ARKOALA_PACKAGE_PATH), writer)
588
        }
589
        return result
590
    }
591

592
    printInterfaces() {
593
        for (const file of this.peerLibrary.files.values()) {
594
            file.declarations.forEach(it => {
595
                if (!ts.isClassDeclaration(it) && !ts.isInterfaceDeclaration(it)) {
596
                    return
597
                }
598
                const writer = createLanguageWriter(Language.JAVA)
599
                this.printPackage(writer);
600
                this.printClassOrInterface(it, writer)
601
                this.addInterface(this.getName(it), writer)
602
            })
603
        }
604
    }
605
}
606

607
class ArkTSInterfacesVisitor extends TSInterfacesVisitor {
608
    override printInterfaces() {
609
        for (const file of this.peerLibrary.files.values()) {
610
            const writer = createLanguageWriter(Language.ARKTS)
611
            file.enums.forEach(it => this.printEnum(writer, it))
612
            this.interfaces.set(new TargetFile(this.generateFileBasename(file.originalFilename)), writer)
613
        }
614
    }
615
}
616

617
function getVisitor(peerLibrary: PeerLibrary, lang: Language): InterfacesVisitor | undefined {
618
    if (lang == Language.TS) {
619
        return new TSInterfacesVisitor(peerLibrary)
620
    }
621
    if (lang == Language.JAVA) {
622
        return new JavaInterfacesVisitor(peerLibrary)
623
    }
624
    if (lang == Language.ARKTS) {
625
        return new ArkTSInterfacesVisitor(peerLibrary)
626
    }
627
}
628

629
export function printInterfaces(peerLibrary: PeerLibrary, lang: Language): Map<TargetFile, string> {
630
    const visitor = getVisitor(peerLibrary, lang)
631
    if (!visitor) {
632
        return new Map()
633
    }
634

635
    visitor.printInterfaces()
636
    const result = new Map<TargetFile, string>()
637
    for (const [key, writer] of visitor.getInterfaces()) {
638
        if (writer.getOutput().length === 0) continue
639
        result.set(key, writer.getOutput().join('\n'))
640
    }
641
    return result
642
}
643

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

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

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

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