Skip to content

Commit 2977c8a

Browse files
committed
Subscripts support.
1 parent 99ae030 commit 2977c8a

File tree

2 files changed

+219
-77
lines changed

2 files changed

+219
-77
lines changed

Sources/JExtractSwiftLib/Swift2JavaVisitor.swift

Lines changed: 109 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -13,9 +13,9 @@
1313
//===----------------------------------------------------------------------===//
1414

1515
import Foundation
16+
import SwiftJavaConfigurationShared
1617
import SwiftParser
1718
import SwiftSyntax
18-
import SwiftJavaConfigurationShared
1919

2020
final class Swift2JavaVisitor {
2121
let translator: Swift2JavaTranslator
@@ -53,19 +53,18 @@ final class Swift2JavaVisitor {
5353
case .extensionDecl(let node):
5454
self.visit(extensionDecl: node, in: parent, sourceFilePath: sourceFilePath)
5555
case .typeAliasDecl:
56-
break // TODO: Implement; https://github.com/swiftlang/swift-java/issues/338
56+
break // TODO: Implement; https://github.com/swiftlang/swift-java/issues/338
5757
case .associatedTypeDecl:
58-
break // TODO: Implement associated types
58+
break // TODO: Implement associated types
5959

6060
case .initializerDecl(let node):
6161
self.visit(initializerDecl: node, in: parent)
6262
case .functionDecl(let node):
6363
self.visit(functionDecl: node, in: parent, sourceFilePath: sourceFilePath)
6464
case .variableDecl(let node):
6565
self.visit(variableDecl: node, in: parent, sourceFilePath: sourceFilePath)
66-
case .subscriptDecl:
67-
// TODO: Implement subscripts
68-
break
66+
case .subscriptDecl(let node):
67+
self.visit(subscriptDecl: node, in: parent)
6968
case .enumCaseDecl(let node):
7069
self.visit(enumCaseDecl: node, in: parent)
7170

@@ -75,7 +74,8 @@ final class Swift2JavaVisitor {
7574
}
7675

7776
func visit(
78-
nominalDecl node: some DeclSyntaxProtocol & DeclGroupSyntax & NamedDeclSyntax & WithAttributesSyntax & WithModifiersSyntax,
77+
nominalDecl node: some DeclSyntaxProtocol & DeclGroupSyntax & NamedDeclSyntax
78+
& WithAttributesSyntax & WithModifiersSyntax,
7979
in parent: ImportedNominalType?,
8080
sourceFilePath: String
8181
) {
@@ -115,7 +115,7 @@ final class Swift2JavaVisitor {
115115
}
116116

117117
func visit(
118-
functionDecl node: FunctionDeclSyntax,
118+
functionDecl node: FunctionDeclSyntax,
119119
in typeContext: ImportedNominalType?,
120120
sourceFilePath: String
121121
) {
@@ -154,7 +154,7 @@ final class Swift2JavaVisitor {
154154
}
155155

156156
func visit(
157-
enumCaseDecl node: EnumCaseDeclSyntax,
157+
enumCaseDecl node: EnumCaseDeclSyntax,
158158
in typeContext: ImportedNominalType?
159159
) {
160160
guard let typeContext else {
@@ -200,7 +200,7 @@ final class Swift2JavaVisitor {
200200
}
201201

202202
func visit(
203-
variableDecl node: VariableDeclSyntax,
203+
variableDecl node: VariableDeclSyntax,
204204
in typeContext: ImportedNominalType?,
205205
sourceFilePath: String
206206
) {
@@ -216,37 +216,21 @@ final class Swift2JavaVisitor {
216216

217217
self.log.debug("Import variable: \(node.kind) '\(node.qualifiedNameForDebug)'")
218218

219-
func importAccessor(kind: SwiftAPIKind) throws {
220-
let signature = try SwiftFunctionSignature(
221-
node,
222-
isSet: kind == .setter,
223-
enclosingType: typeContext?.swiftType,
224-
lookupContext: translator.lookupContext
225-
)
226-
227-
let imported = ImportedFunc(
228-
module: translator.swiftModuleName,
229-
swiftDecl: node,
230-
name: varName,
231-
apiKind: kind,
232-
functionSignature: signature
233-
)
234-
235-
log.debug("Record imported variable accessor \(kind == .getter ? "getter" : "setter"):\(node.qualifiedNameForDebug)")
236-
if let typeContext {
237-
typeContext.variables.append(imported)
238-
} else {
239-
translator.importedGlobalVariables.append(imported)
240-
}
241-
}
242-
243219
do {
244220
let supportedAccessors = node.supportedAccessorKinds(binding: binding)
245221
if supportedAccessors.contains(.get) {
246-
try importAccessor(kind: .getter)
222+
try importAccessor(
223+
from: DeclSyntax(node),
224+
in: typeContext,
225+
kind: .getter,
226+
name: varName)
247227
}
248228
if supportedAccessors.contains(.set) {
249-
try importAccessor(kind: .setter)
229+
try importAccessor(
230+
from: DeclSyntax(node),
231+
in: typeContext,
232+
kind: .setter,
233+
name: varName)
250234
}
251235
} catch {
252236
self.log.debug("Failed to import: \(node.qualifiedNameForDebug); \(error)")
@@ -289,10 +273,87 @@ final class Swift2JavaVisitor {
289273
typeContext.initializers.append(imported)
290274
}
291275

276+
private func visit(
277+
subscriptDecl node: SubscriptDeclSyntax,
278+
in typeContext: ImportedNominalType?,
279+
) {
280+
guard node.shouldExtract(config: config, log: log, in: typeContext) else {
281+
return
282+
}
283+
284+
guard let accessorBlock = node.accessorBlock else {
285+
return
286+
}
287+
288+
let name = "subscript"
289+
let accessors = accessorBlock.supportedAccessorKinds()
290+
do {
291+
if accessors.contains(.get) {
292+
try importAccessor(
293+
from: DeclSyntax(node),
294+
in: typeContext,
295+
kind: .getter,
296+
name: name)
297+
}
298+
if accessors.contains(.set) {
299+
try importAccessor(
300+
from: DeclSyntax(node),
301+
in: typeContext,
302+
kind: .setter,
303+
name: name)
304+
}
305+
} catch {
306+
self.log.debug("Failed to import: \(node.qualifiedNameForDebug); \(error)")
307+
}
308+
}
309+
310+
private func importAccessor(
311+
from node: DeclSyntax,
312+
in typeContext: ImportedNominalType?,
313+
kind: SwiftAPIKind,
314+
name: String
315+
) throws {
316+
let signature: SwiftFunctionSignature
317+
318+
switch node.as(DeclSyntaxEnum.self) {
319+
case .variableDecl(let varNode):
320+
signature = try SwiftFunctionSignature(
321+
varNode,
322+
isSet: kind == .setter,
323+
enclosingType: typeContext?.swiftType,
324+
lookupContext: translator.lookupContext)
325+
case .subscriptDecl(let subscriptNode):
326+
signature = try SwiftFunctionSignature(
327+
subscriptNode,
328+
isSet: kind == .setter,
329+
enclosingType: typeContext?.swiftType,
330+
lookupContext: translator.lookupContext)
331+
default:
332+
return
333+
}
334+
335+
let imported = ImportedFunc(
336+
module: translator.swiftModuleName,
337+
swiftDecl: node,
338+
name: name,
339+
apiKind: kind,
340+
functionSignature: signature
341+
)
342+
343+
log.debug(
344+
"Record imported variable accessor \(kind == .getter ? "getter" : "setter"):\(node.qualifiedNameForDebug)"
345+
)
346+
if let typeContext {
347+
typeContext.variables.append(imported)
348+
} else {
349+
translator.importedGlobalVariables.append(imported)
350+
}
351+
}
352+
292353
private func synthesizeRawRepresentableConformance(
293354
enumDecl node: EnumDeclSyntax,
294355
in parent: ImportedNominalType?
295-
) {
356+
) {
296357
guard let imported = translator.importedNominalType(node, parent: parent) else {
297358
return
298359
}
@@ -304,15 +365,21 @@ final class Swift2JavaVisitor {
304365
),
305366
inheritanceType.isRawTypeCompatible
306367
{
307-
if !imported.variables.contains(where: { $0.name == "rawValue" && $0.functionSignature.result.type != inheritanceType }) {
368+
if !imported.variables.contains(where: {
369+
$0.name == "rawValue" && $0.functionSignature.result.type != inheritanceType
370+
}) {
308371
let decl: DeclSyntax = "public var rawValue: \(raw: inheritanceType.description) { get }"
309372
self.visit(decl: decl, in: imported, sourceFilePath: imported.sourceFilePath)
310373
}
311374

312375
// FIXME: why is this un-used
313376
imported.variables.first?.signatureString
314377

315-
if !imported.initializers.contains(where: { $0.functionSignature.parameters.count == 1 && $0.functionSignature.parameters.first?.parameterName == "rawValue" && $0.functionSignature.parameters.first?.type == inheritanceType }) {
378+
if !imported.initializers.contains(where: {
379+
$0.functionSignature.parameters.count == 1
380+
&& $0.functionSignature.parameters.first?.parameterName == "rawValue"
381+
&& $0.functionSignature.parameters.first?.type == inheritanceType
382+
}) {
316383
let decl: DeclSyntax = "public init?(rawValue: \(raw: inheritanceType))"
317384
self.visit(decl: decl, in: imported, sourceFilePath: imported.sourceFilePath)
318385
}
@@ -330,7 +397,9 @@ extension DeclSyntaxProtocol where Self: WithModifiersSyntax & WithAttributesSyn
330397
}
331398

332399
guard meetsRequiredAccessLevel else {
333-
log.debug("Skip import '\(self.qualifiedNameForDebug)': not at least \(config.effectiveMinimumInputAccessLevelMode)")
400+
log.debug(
401+
"Skip import '\(self.qualifiedNameForDebug)': not at least \(config.effectiveMinimumInputAccessLevelMode)"
402+
)
334403
return false
335404
}
336405
guard !attributes.contains(where: { $0.isJava }) else {

0 commit comments

Comments
 (0)