Skip to content

Commit 6e53b3b

Browse files
authored
[JExtract] Stop using SyntaxVisitor for Swift2JavaVisitor (#290)
1 parent f716099 commit 6e53b3b

File tree

3 files changed

+77
-100
lines changed

3 files changed

+77
-100
lines changed

Sources/JExtractSwiftLib/ImportedDecls.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -37,8 +37,8 @@ package class ImportedNominalType: ImportedDecl {
3737
self.swiftNominal = swiftNominal
3838
}
3939

40-
var javaClassName: String {
41-
swiftNominal.name
40+
var swiftType: SwiftType {
41+
return .nominal(.init(nominalTypeDecl: swiftNominal))
4242
}
4343
}
4444

Sources/JExtractSwiftLib/Swift2JavaTranslator.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ extension Swift2JavaTranslator {
106106

107107
for input in self.inputs {
108108
log.trace("Analyzing \(input.filePath)")
109-
visitor.walk(input.syntax)
109+
visitor.visit(sourceFile: input.syntax)
110110
}
111111
}
112112

Sources/JExtractSwiftLib/Swift2JavaVisitor.swift

Lines changed: 74 additions & 97 deletions
Original file line numberDiff line numberDiff line change
@@ -16,98 +16,85 @@ import Foundation
1616
import SwiftParser
1717
import SwiftSyntax
1818

19-
final class Swift2JavaVisitor: SyntaxVisitor {
19+
final class Swift2JavaVisitor {
2020
let translator: Swift2JavaTranslator
2121

22-
/// Type context stack associated with the syntax.
23-
var typeContext: [(syntaxID: Syntax.ID, type: ImportedNominalType)] = []
24-
25-
/// Innermost type context.
26-
var currentType: ImportedNominalType? { typeContext.last?.type }
27-
28-
var currentSwiftType: SwiftType? {
29-
guard let currentType else { return nil }
30-
return .nominal(SwiftNominalType(nominalTypeDecl: currentType.swiftNominal))
31-
}
32-
33-
/// The current type name as a nested name like A.B.C.
34-
var currentTypeName: String? { self.currentType?.swiftNominal.qualifiedName }
35-
36-
var log: Logger { translator.log }
37-
3822
init(translator: Swift2JavaTranslator) {
3923
self.translator = translator
40-
41-
super.init(viewMode: .all)
4224
}
4325

44-
/// Push specified type to the type context associated with the syntax.
45-
func pushTypeContext(syntax: some SyntaxProtocol, importedNominal: ImportedNominalType) {
46-
typeContext.append((syntax.id, importedNominal))
47-
}
26+
var log: Logger { translator.log }
4827

49-
/// Pop type context if the current context is associated with the syntax.
50-
func popTypeContext(syntax: some SyntaxProtocol) -> Bool {
51-
if typeContext.last?.syntaxID == syntax.id {
52-
typeContext.removeLast()
53-
return true
54-
} else {
55-
return false
28+
func visit(sourceFile node: SourceFileSyntax) {
29+
for codeItem in node.statements {
30+
if let declNode = codeItem.item.as(DeclSyntax.self) {
31+
self.visit(decl: declNode, in: nil)
32+
}
5633
}
5734
}
5835

59-
override func visit(_ node: ClassDeclSyntax) -> SyntaxVisitorContinueKind {
60-
log.debug("Visit \(node.kind): '\(node.qualifiedNameForDebug)'")
61-
guard let importedNominalType = translator.importedNominalType(node, parent: self.currentType) else {
62-
return .skipChildren
36+
func visit(decl node: DeclSyntax, in parent: ImportedNominalType?) {
37+
switch node.as(DeclSyntaxEnum.self) {
38+
case .actorDecl(let node):
39+
self.visit(nominalDecl: node, in: parent)
40+
case .classDecl(let node):
41+
self.visit(nominalDecl: node, in: parent)
42+
case .structDecl(let node):
43+
self.visit(nominalDecl: node, in: parent)
44+
case .enumDecl(let node):
45+
self.visit(nominalDecl: node, in: parent)
46+
case .protocolDecl(let node):
47+
self.visit(nominalDecl: node, in: parent)
48+
case .extensionDecl(let node):
49+
self.visit(extensionDecl: node, in: parent)
50+
case .typeAliasDecl:
51+
break // TODO: Implement
52+
case .associatedTypeDecl:
53+
break // TODO: Implement
54+
55+
case .initializerDecl(let node):
56+
self.visit(initializerDecl: node, in: parent)
57+
case .functionDecl(let node):
58+
self.visit(functionDecl: node, in: parent)
59+
case .variableDecl(let node):
60+
self.visit(variableDecl: node, in: parent)
61+
case .subscriptDecl:
62+
// TODO: Implement
63+
break
64+
65+
default:
66+
break
6367
}
64-
65-
self.pushTypeContext(syntax: node, importedNominal: importedNominalType)
66-
return .visitChildren
6768
}
6869

69-
override func visitPost(_ node: ClassDeclSyntax) {
70-
if self.popTypeContext(syntax: node) {
71-
log.debug("Completed import: \(node.kind) \(node.name)")
70+
func visit(
71+
nominalDecl node: some DeclSyntaxProtocol & DeclGroupSyntax & NamedDeclSyntax & WithAttributesSyntax & WithModifiersSyntax,
72+
in parent: ImportedNominalType?
73+
) {
74+
guard let importedNominalType = translator.importedNominalType(node, parent: parent) else {
75+
return
7276
}
73-
}
74-
75-
override func visit(_ node: StructDeclSyntax) -> SyntaxVisitorContinueKind {
76-
log.debug("Visit \(node.kind): \(node.qualifiedNameForDebug)")
77-
guard let importedNominalType = translator.importedNominalType(node, parent: self.currentType) else {
78-
return .skipChildren
77+
for memberItem in node.memberBlock.members {
78+
self.visit(decl: memberItem.decl, in: importedNominalType)
7979
}
80-
81-
self.pushTypeContext(syntax: node, importedNominal: importedNominalType)
82-
return .visitChildren
8380
}
8481

85-
override func visitPost(_ node: StructDeclSyntax) {
86-
if self.popTypeContext(syntax: node) {
87-
log.debug("Completed import: \(node.kind) \(node.qualifiedNameForDebug)")
82+
func visit(extensionDecl node: ExtensionDeclSyntax, in parent: ImportedNominalType?) {
83+
guard parent != nil else {
84+
// 'extension' in a nominal type is invalid. Ignore
85+
return
8886
}
89-
}
90-
91-
override func visit(_ node: ExtensionDeclSyntax) -> SyntaxVisitorContinueKind {
92-
// Resolve the extended type of the extension as an imported nominal, and
93-
// recurse if we found it.
9487
guard let importedNominalType = translator.importedNominalType(node.extendedType) else {
95-
return .skipChildren
88+
return
9689
}
97-
98-
self.pushTypeContext(syntax: node, importedNominal: importedNominalType)
99-
return .visitChildren
100-
}
101-
102-
override func visitPost(_ node: ExtensionDeclSyntax) {
103-
if self.popTypeContext(syntax: node) {
104-
log.debug("Completed import: \(node.kind) \(node.qualifiedNameForDebug)")
90+
for memberItem in node.memberBlock.members {
91+
self.visit(decl: memberItem.decl, in: importedNominalType)
10592
}
10693
}
10794

108-
override func visit(_ node: FunctionDeclSyntax) -> SyntaxVisitorContinueKind {
95+
func visit(functionDecl node: FunctionDeclSyntax, in typeContext: ImportedNominalType?) {
10996
guard node.shouldImport(log: log) else {
110-
return .skipChildren
97+
return
11198
}
11299

113100
self.log.debug("Import function: '\(node.qualifiedNameForDebug)'")
@@ -116,12 +103,12 @@ final class Swift2JavaVisitor: SyntaxVisitor {
116103
do {
117104
signature = try SwiftFunctionSignature(
118105
node,
119-
enclosingType: self.currentSwiftType,
106+
enclosingType: typeContext?.swiftType,
120107
symbolTable: self.translator.symbolTable
121108
)
122109
} catch {
123110
self.log.debug("Failed to import: '\(node.qualifiedNameForDebug)'; \(error)")
124-
return .skipChildren
111+
return
125112
}
126113

127114
let imported = ImportedFunc(
@@ -133,22 +120,20 @@ final class Swift2JavaVisitor: SyntaxVisitor {
133120
)
134121

135122
log.debug("Record imported method \(node.qualifiedNameForDebug)")
136-
if let currentType {
137-
currentType.methods.append(imported)
123+
if let typeContext {
124+
typeContext.methods.append(imported)
138125
} else {
139126
translator.importedGlobalFuncs.append(imported)
140127
}
141-
142-
return .skipChildren
143128
}
144129

145-
override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind {
130+
func visit(variableDecl node: VariableDeclSyntax, in typeContext: ImportedNominalType?) {
146131
guard node.shouldImport(log: log) else {
147-
return .skipChildren
132+
return
148133
}
149134

150135
guard let binding = node.bindings.first else {
151-
return .skipChildren
136+
return
152137
}
153138

154139
let varName = "\(binding.pattern.trimmed)"
@@ -159,7 +144,7 @@ final class Swift2JavaVisitor: SyntaxVisitor {
159144
let signature = try SwiftFunctionSignature(
160145
node,
161146
isSet: kind == .setter,
162-
enclosingType: self.currentSwiftType,
147+
enclosingType: typeContext?.swiftType,
163148
symbolTable: self.translator.symbolTable
164149
)
165150

@@ -170,10 +155,10 @@ final class Swift2JavaVisitor: SyntaxVisitor {
170155
apiKind: kind,
171156
functionSignature: signature
172157
)
173-
158+
174159
log.debug("Record imported variable accessor \(kind == .getter ? "getter" : "setter"):\(node.qualifiedNameForDebug)")
175-
if let currentType {
176-
currentType.variables.append(imported)
160+
if let typeContext {
161+
typeContext.variables.append(imported)
177162
} else {
178163
translator.importedGlobalVariables.append(imported)
179164
}
@@ -189,18 +174,16 @@ final class Swift2JavaVisitor: SyntaxVisitor {
189174
}
190175
} catch {
191176
self.log.debug("Failed to import: \(node.qualifiedNameForDebug); \(error)")
192-
return .skipChildren
193177
}
194-
195-
return .skipChildren
196178
}
197179

198-
override func visit(_ node: InitializerDeclSyntax) -> SyntaxVisitorContinueKind {
199-
guard let currentType else {
200-
fatalError("Initializer must be within a current type, was: \(node)")
180+
func visit(initializerDecl node: InitializerDeclSyntax, in typeContext: ImportedNominalType?) {
181+
guard let typeContext else {
182+
self.log.info("Initializer must be within a current type; \(node)")
183+
return
201184
}
202185
guard node.shouldImport(log: log) else {
203-
return .skipChildren
186+
return
204187
}
205188

206189
self.log.debug("Import initializer: \(node.kind) '\(node.qualifiedNameForDebug)'")
@@ -209,12 +192,12 @@ final class Swift2JavaVisitor: SyntaxVisitor {
209192
do {
210193
signature = try SwiftFunctionSignature(
211194
node,
212-
enclosingType: self.currentSwiftType,
195+
enclosingType: typeContext.swiftType,
213196
symbolTable: self.translator.symbolTable
214197
)
215198
} catch {
216199
self.log.debug("Failed to import: \(node.qualifiedNameForDebug); \(error)")
217-
return .skipChildren
200+
return
218201
}
219202
let imported = ImportedFunc(
220203
module: translator.swiftModuleName,
@@ -224,13 +207,7 @@ final class Swift2JavaVisitor: SyntaxVisitor {
224207
functionSignature: signature
225208
)
226209

227-
currentType.initializers.append(imported)
228-
229-
return .skipChildren
230-
}
231-
232-
override func visit(_ node: DeinitializerDeclSyntax) -> SyntaxVisitorContinueKind {
233-
return .skipChildren
210+
typeContext.initializers.append(imported)
234211
}
235212
}
236213

0 commit comments

Comments
 (0)