Skip to content

Commit 04cf92c

Browse files
authored
Small cleanups (#666)
* Small cleanups I really liked the FishBox tbh, kinda silly, but let's rename PetBox to ToolBox :) Also, change isJava macro detection to isSwiftJavaMacro, except the export one. * Remove the translateTupleElementResult again * docs had mistake that feature was supported in wrong jextract mode
1 parent 6fdc080 commit 04cf92c

8 files changed

Lines changed: 41 additions & 67 deletions

File tree

Sources/JExtractSwiftLib/Convenience/SwiftSyntax+Extensions.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -131,7 +131,7 @@ extension AttributeListSyntax.Element {
131131
/// Whether this node has `SwiftJava` wrapping attributes (types that wrap Java classes).
132132
/// These are skipped during jextract because they represent Java->Swift wrappers.
133133
/// Note: `@JavaExport` is NOT included here — it forces export of Swift types to Java.
134-
var isJava: Bool {
134+
var isSwiftJavaMacro: Bool {
135135
guard case let .attribute(attr) = self else {
136136
// FIXME: Handle #if.
137137
return false

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaTranslation.swift

Lines changed: 0 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1195,39 +1195,6 @@ extension JNISwift2JavaGenerator {
11951195
)
11961196
}
11971197

1198-
/// Translate a single element type for tuple results on the Java side.
1199-
private func translateTupleElementResult(
1200-
type: SwiftType,
1201-
genericParameters: [SwiftGenericParameterDeclaration],
1202-
genericRequirements: [SwiftGenericRequirement],
1203-
) throws -> (JavaType, JavaNativeConversionStep) {
1204-
switch type {
1205-
case .nominal(let nominalType):
1206-
if let knownType = nominalType.nominalTypeDecl.knownTypeKind {
1207-
guard let javaType = JNIJavaTypeTranslator.translate(knownType: knownType, config: self.config) else {
1208-
throw JavaTranslationError.unsupportedSwiftType(type)
1209-
}
1210-
// Primitives: just read from array
1211-
return (javaType, .placeholder)
1212-
}
1213-
1214-
guard !nominalType.isSwiftJavaWrapper else {
1215-
throw JavaTranslationError.unsupportedSwiftType(type)
1216-
}
1217-
1218-
let javaType = try translateGenericTypeParameter(
1219-
type,
1220-
genericParameters: genericParameters,
1221-
genericRequirements: genericRequirements,
1222-
)
1223-
// JExtract class: wrap memory address
1224-
return (.long, .constructSwiftValue(.placeholder, javaType))
1225-
1226-
default:
1227-
throw JavaTranslationError.unsupportedSwiftType(type)
1228-
}
1229-
}
1230-
12311198
func translateOptionalResult(
12321199
wrappedType swiftType: SwiftType,
12331200
resultName: String,

Sources/JExtractSwiftLib/Swift2JavaVisitor.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -631,7 +631,7 @@ extension DeclSyntaxProtocol where Self: WithModifiersSyntax & WithAttributesSyn
631631
)
632632
return false
633633
}
634-
guard !attributes.contains(where: { $0.isJava }) else {
634+
guard !attributes.contains(where: { $0.isSwiftJavaMacro }) else {
635635
log.debug("Skip import '\(self.qualifiedNameForDebug)': is Java")
636636
return false
637637
}

Sources/JExtractSwiftLib/SwiftTypes/SwiftType.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -258,7 +258,7 @@ extension SwiftNominalType.Parent: CustomStringConvertible {
258258

259259
extension SwiftNominalType {
260260
var isSwiftJavaWrapper: Bool {
261-
nominalTypeDecl.syntax?.attributes.contains(where: \.isJava) ?? false
261+
nominalTypeDecl.syntax?.attributes.contains(where: \.isSwiftJavaMacro) ?? false
262262
}
263263

264264
var isProtocol: Bool {

Sources/JExtractSwiftLib/SwiftTypes/SwiftTypeLookupContext.swift

Lines changed: 14 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -110,16 +110,23 @@ class SwiftTypeLookupContext {
110110
case .protocolDecl(let node):
111111
typeDecl = try nominalTypeDeclaration(for: node, sourceFilePath: sourceFilePath)
112112
case .extensionDecl(let node):
113-
// For extensions, we have to perform a unqualified lookup,
114-
// as the extentedType is just the identifier of the type.
113+
// For extensions, we need to resolve the extended type to find the
114+
// actual nominal type declaration. The extended type might be a simple
115+
// identifier (e.g. `extension Foo`) or a member type
116+
// (e.g. `extension P256._ARCV1`).
115117

116-
guard case .identifierType(let id) = Syntax(node.extendedType).as(SyntaxEnum.self),
118+
if case .identifierType(let id) = Syntax(node.extendedType).as(SyntaxEnum.self),
117119
let lookupResult = try unqualifiedLookup(name: Identifier(id.name)!, from: node)
118-
else {
119-
throw TypeLookupError.notType(Syntax(node))
120+
{
121+
typeDecl = lookupResult
122+
} else {
123+
// For member types (e.g. P256._ARCV1), resolve through SwiftType
124+
let swiftType = try SwiftType(node.extendedType, lookupContext: self)
125+
guard let nominalDecl = swiftType.asNominalTypeDeclaration else {
126+
throw TypeLookupError.notType(Syntax(node))
127+
}
128+
typeDecl = nominalDecl
120129
}
121-
122-
typeDecl = lookupResult
123130
case .typeAliasDecl:
124131
fatalError("typealias not implemented")
125132
case .associatedTypeDecl:

Sources/SwiftJavaConfigurationShared/Configuration.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -123,9 +123,9 @@ public struct Configuration: Codable {
123123
/// "base": "Box",
124124
/// "typeArgs": {"Element": "Fish"}
125125
/// },
126-
/// "PetBox": {
126+
/// "ToolBox": {
127127
/// "base": "Box",
128-
/// "typeArgs": {"Element": "Pet"}
128+
/// "typeArgs": {"Element": "Tool"}
129129
/// }
130130
/// }
131131
/// }

Sources/SwiftJavaDocumentation/Documentation.docc/SupportedFeatures.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@ SwiftJava's `swift-java jextract` tool automates generating Java bindings from S
6363
| Dictionaries: `[String: Int]`, `[K:V]` |||
6464
| Generic type: `struct S<T>` |||
6565
| Functions or properties using generic type param: `struct S<T> { func f(_: T) {} }` |||
66-
| Generic type specialization and conditional extensions: `struct S<T>{} extension S where T == Value {}` || |
66+
| Generic type specialization and conditional extensions: `struct S<T>{} extension S where T == Value {}` || |
6767
| Static functions or properties in generic type |||
6868
| Generic parameters in functions: `func f<T: A & B>(x: T)` |||
6969
| Generic return values in functions: `func f<T: A & B>() -> T` |||

Tests/JExtractSwiftTests/SpecializationTests.swift

Lines changed: 21 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ struct SpecializationTests {
4343
public var name: String
4444
}
4545
46-
public struct Pet {
46+
public struct Tool {
4747
public var name: String
4848
}
4949
@@ -52,7 +52,7 @@ struct SpecializationTests {
5252
}
5353
5454
public typealias FishBox = Box<Fish>
55-
public typealias PetBox = Box<Pet>
55+
public typealias ToolBox = Box<Tool>
5656
"""#
5757

5858
// ==== -----------------------------------------------------------------------
@@ -67,7 +67,7 @@ struct SpecializationTests {
6767

6868
// Both specialized types should be registered
6969
#expect(translator.importedTypes["FishBox"] != nil, "FishBox should be in importedTypes")
70-
#expect(translator.importedTypes["PetBox"] != nil, "PetBox should be in importedTypes")
70+
#expect(translator.importedTypes["ToolBox"] != nil, "ToolBox should be in importedTypes")
7171

7272
// The base generic type remains in importedTypes (not removed)
7373
let baseBox = try #require(translator.importedTypes["Box"])
@@ -78,16 +78,16 @@ struct SpecializationTests {
7878

7979
// Specialized types link back to their base
8080
let fishBox = try #require(translator.importedTypes["FishBox"])
81-
let petBox = try #require(translator.importedTypes["PetBox"])
81+
let toolBox = try #require(translator.importedTypes["ToolBox"])
8282
#expect(fishBox.isSpecialization)
83-
#expect(petBox.isSpecialization)
83+
#expect(toolBox.isSpecialization)
8484

8585
// Verify effective names are distinct
8686
#expect(fishBox.effectiveJavaName == "FishBox")
87-
#expect(petBox.effectiveJavaName == "PetBox")
87+
#expect(toolBox.effectiveJavaName == "ToolBox")
8888

8989
#expect(fishBox.effectiveSwiftTypeName == "Box<Fish>")
90-
#expect(petBox.effectiveSwiftTypeName == "Box<Pet>")
90+
#expect(toolBox.effectiveSwiftTypeName == "Box<Tool>")
9191

9292
// Verify new generic-model properties
9393
#expect(fishBox.genericParameterNames == ["Element"])
@@ -96,14 +96,14 @@ struct SpecializationTests {
9696
#expect(fishBox.baseTypeName == "Box")
9797
#expect(fishBox.specializedTypeName == "FishBox")
9898

99-
#expect(petBox.genericParameterNames == ["Element"])
100-
#expect(petBox.genericArguments == ["Element": "Pet"])
101-
#expect(petBox.isFullySpecialized)
102-
#expect(petBox.baseTypeName == "Box")
103-
#expect(petBox.specializedTypeName == "PetBox")
99+
#expect(toolBox.genericParameterNames == ["Element"])
100+
#expect(toolBox.genericArguments == ["Element": "Tool"])
101+
#expect(toolBox.isFullySpecialized)
102+
#expect(toolBox.baseTypeName == "Box")
103+
#expect(toolBox.specializedTypeName == "ToolBox")
104104

105105
// Both wrappers delegate to the same base type
106-
#expect(fishBox.specializationBaseType === petBox.specializationBaseType, "Both should wrap the same base Box type")
106+
#expect(fishBox.specializationBaseType === toolBox.specializationBaseType, "Both should wrap the same base Box type")
107107
#expect(fishBox.specializationBaseType === translator.importedTypes["Box"], "Base should be the original Box")
108108
}
109109

@@ -119,7 +119,7 @@ struct SpecializationTests {
119119
#expect(specializations.count == 2, "Should have exactly 2 specializations for Box")
120120

121121
let javaNames = specializations.map(\.effectiveJavaName).sorted()
122-
#expect(javaNames == ["FishBox", "PetBox"])
122+
#expect(javaNames == ["FishBox", "ToolBox"])
123123
}
124124

125125
// ==== -----------------------------------------------------------------------
@@ -151,29 +151,29 @@ struct SpecializationTests {
151151
)
152152
}
153153

154-
@Test("PetBox Java class has base methods but not Fish-constrained methods")
155-
func petBoxJavaClass() throws {
154+
@Test("ToolBox Java class has base methods but not Fish-constrained methods")
155+
func toolBoxJavaClass() throws {
156156
try assertOutput(
157157
input: multiSpecializationInput,
158158
.jni,
159159
.java,
160160
detectChunkByInitialLines: 1,
161161
expectedChunks: [
162162
// Class declaration
163-
"public final class PetBox implements JNISwiftInstance {",
163+
"public final class ToolBox implements JNISwiftInstance {",
164164
// Base method from Box<Element>
165165
"public long count()",
166166
],
167167
)
168168

169-
// Verify observeTheFish does NOT appear inside PetBox's class body
169+
// Verify observeTheFish does NOT appear inside ToolBox's class body
170170
var config = Configuration()
171171
config.swiftModule = "SwiftModule"
172172
let translator = Swift2JavaTranslator(config: config)
173173
try translator.analyze(path: "/fake/Fake.swiftinterface", text: multiSpecializationInput)
174-
let petBox = try #require(translator.importedTypes["PetBox"])
175-
let methodNames = petBox.methods.map(\.name)
176-
#expect(!methodNames.contains("observeTheFish"), "PetBox should not have Fish-constrained method")
174+
let toolBox = try #require(translator.importedTypes["ToolBox"])
175+
let methodNames = toolBox.methods.map(\.name)
176+
#expect(!methodNames.contains("observeTheFish"), "ToolBox should not have Fish-constrained method")
177177
}
178178

179179
@Test("Single specialization generates expected Java class")

0 commit comments

Comments
 (0)