Skip to content

Commit 5986b30

Browse files
committed
jextract: end to end run for a property import
1 parent aa2d017 commit 5986b30

File tree

8 files changed

+78
-44
lines changed

8 files changed

+78
-44
lines changed

Samples/SwiftKitSampleApp/build.gradle

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -95,7 +95,11 @@ application {
9595
task jextract(type: Exec) {
9696
description = "Extracts Java accessor sources using jextract"
9797
outputs.dir(layout.buildDirectory.dir("generated"))
98-
inputs.dir("$rootDir/Sources/ExampleSwiftLibrary")
98+
inputs.dir("$rootDir/Sources/ExampleSwiftLibrary") // monitored library
99+
100+
// any changes in the source generator sources also mean the resulting output might change
101+
inputs.dir("$rootDir/Sources/JExtractSwift")
102+
inputs.dir("$rootDir/Sources/JExtractSwiftTool")
99103

100104
workingDir = rootDir
101105
commandLine "make"

Samples/SwiftKitSampleApp/src/test/java/com/example/swift/generated/MySwiftClassTest.java

Lines changed: 20 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
package com.example.swift.generated;
1616

1717
import org.junit.jupiter.api.BeforeAll;
18+
import org.junit.jupiter.api.Test;
1819

1920
import static org.junit.jupiter.api.Assertions.assertEquals;
2021
import static org.junit.jupiter.api.Assertions.assertNotNull;
@@ -31,6 +32,24 @@ static void beforeAll() {
3132
System.setProperty("jextract.trace.downcalls", "true");
3233
}
3334

34-
// TODO: test member methods on MySwiftClass
35+
@Test
36+
void test_MySwiftClass_voidMethod() {
37+
MySwiftClass o = new MySwiftClass(12, 42);
38+
o.voidMethod();
39+
}
40+
41+
@Test
42+
void test_MySwiftClass_makeIntMethod() {
43+
MySwiftClass o = new MySwiftClass(12, 42);
44+
var got = o.makeIntMethod();
45+
assertEquals(12, got);
46+
}
47+
48+
@Test
49+
void test_MySwiftClass_property_len() {
50+
MySwiftClass o = new MySwiftClass(12, 42);
51+
var got = o.makeIntMethod();
52+
assertEquals(12, got);
53+
}
3554

3655
}

Sources/JExtractSwift/ImportedDecls+Printing.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,14 @@ extension ImportedFunc {
3434
}
3535

3636
extension VariableAccessorKind {
37+
38+
public var fieldSuffix: String {
39+
switch self {
40+
case .get: "_GET"
41+
case .set: "_SET"
42+
}
43+
}
44+
3745
public var renderDescFieldName: String {
3846
switch self {
3947
case .get: "DESC_GET"

Sources/JExtractSwift/Swift2JavaTranslator+Printing.swift

Lines changed: 24 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -129,7 +129,9 @@ extension Swift2JavaTranslator {
129129
}
130130

131131
// Properties
132-
// TODO: property accessors
132+
for varDecl in decl.variables {
133+
printVariableDowncallMethods(&printer, varDecl)
134+
}
133135

134136
// Methods
135137
for funcDecl in decl.methods {
@@ -482,8 +484,8 @@ extension Swift2JavaTranslator {
482484
decl: ImportedFunc,
483485
accessorKind: VariableAccessorKind? = nil) {
484486

485-
let addrName = accessorKind?.renderAddrFieldName ?? "ADDR"
486-
let methodNameSegment = accessorKind?.renderMethodNameSegment ?? ""
487+
let addrName = accessorKind.renderAddrFieldName
488+
let methodNameSegment = accessorKind.renderMethodNameSegment
487489
let snippet = decl.renderCommentSnippet ?? "* "
488490

489491
printer.print(
@@ -502,8 +504,8 @@ extension Swift2JavaTranslator {
502504
private func printFunctionMethodHandleMethod(_ printer: inout CodePrinter,
503505
decl: ImportedFunc,
504506
accessorKind: VariableAccessorKind? = nil) {
505-
let handleName = accessorKind?.renderHandleFieldName ?? "HANDLE"
506-
let methodNameSegment = accessorKind?.renderMethodNameSegment ?? ""
507+
let handleName = accessorKind.renderHandleFieldName
508+
let methodNameSegment = accessorKind.renderMethodNameSegment
507509
let snippet = decl.renderCommentSnippet ?? "* "
508510

509511
printer.print(
@@ -522,8 +524,8 @@ extension Swift2JavaTranslator {
522524
private func printFunctionDescriptorMethod(_ printer: inout CodePrinter,
523525
decl: ImportedFunc,
524526
accessorKind: VariableAccessorKind? = nil) {
525-
let descName = accessorKind?.renderDescFieldName ?? "DESC"
526-
let methodNameSegment = accessorKind?.renderMethodNameSegment ?? ""
527+
let descName = accessorKind.renderDescFieldName
528+
let methodNameSegment = accessorKind.renderMethodNameSegment
527529
let snippet = decl.renderCommentSnippet ?? "* "
528530

529531
printer.print(
@@ -544,10 +546,14 @@ extension Swift2JavaTranslator {
544546

545547
printer.printTypeDecl("private static class \(decl.baseIdentifier)") { printer in
546548
for accessorKind in decl.supportedAccessorKinds {
547-
printPropertyAccessorDescriptorValue(&printer, decl, accessorKind)
548-
// printFunctionDescriptorValue(&printer, decl);
549-
// printFindMemorySegmentAddrByMangledName(&printer, decl)
550-
// printMethodDowncallHandleForAddrDesc(&printer)
549+
guard let accessor = decl.accessorFunc(kind: accessorKind) else {
550+
log.warning("Skip print for \(accessorKind) of \(decl.identifier)!")
551+
continue
552+
}
553+
554+
printFunctionDescriptorValue(&printer, accessor, accessorKind: accessorKind);
555+
printFindMemorySegmentAddrByMangledName(&printer, accessor, accessorKind: accessorKind)
556+
printMethodDowncallHandleForAddrDesc(&printer, accessorKind: accessorKind)
551557
}
552558
}
553559

@@ -579,23 +585,19 @@ extension Swift2JavaTranslator {
579585
}
580586
}
581587

582-
func printFindMemorySegmentAddrByMangledName(_ printer: inout CodePrinter, _ decl: ImportedFunc) {
588+
func printFindMemorySegmentAddrByMangledName(_ printer: inout CodePrinter, _ decl: ImportedFunc,
589+
accessorKind: VariableAccessorKind? = nil) {
583590
printer.print(
584591
"""
585-
/**
586-
* {@snippet lang = Swift:
587-
* \(decl.displayName)
588-
* }
589-
*/
590-
public static final MemorySegment ADDR = \(swiftModuleName).findOrThrow("\(decl.swiftMangledName)");
592+
public static final MemorySegment \(accessorKind.renderAddrFieldName) = \(swiftModuleName).findOrThrow("\(decl.swiftMangledName)");
591593
"""
592594
);
593595
}
594596

595-
func printMethodDowncallHandleForAddrDesc(_ printer: inout CodePrinter) {
597+
func printMethodDowncallHandleForAddrDesc(_ printer: inout CodePrinter, accessorKind: VariableAccessorKind? = nil) {
596598
printer.print(
597599
"""
598-
public static final MethodHandle HANDLE = Linker.nativeLinker().downcallHandle(ADDR, DESC);
600+
public static final MethodHandle \(accessorKind.renderHandleFieldName) = Linker.nativeLinker().downcallHandle(\(accessorKind.renderAddrFieldName), \(accessorKind.renderDescFieldName));
599601
"""
600602
)
601603
}
@@ -781,7 +783,8 @@ extension Swift2JavaTranslator {
781783
public func printFunctionDescriptorValue(
782784
_ printer: inout CodePrinter,
783785
_ decl: ImportedFunc,
784-
fieldName: String = "DESC") {
786+
accessorKind: VariableAccessorKind? = nil) {
787+
let fieldName = accessorKind.renderDescFieldName
785788
printer.start("public static final FunctionDescriptor \(fieldName) = ")
786789

787790
let parameterLayoutDescriptors = javaMemoryLayoutDescriptors(
@@ -818,14 +821,4 @@ extension Swift2JavaTranslator {
818821
printer.print(");");
819822
}
820823

821-
public func printPropertyAccessorDescriptorValue(
822-
_ printer: inout CodePrinter,
823-
_ decl: ImportedVariable,
824-
_ kind: VariableAccessorKind) {
825-
guard let funcDecl = decl.accessorFunc(kind: kind) else {
826-
return
827-
}
828-
829-
printFunctionDescriptorValue(&printer, funcDecl, fieldName: kind.renderDescFieldName)
830-
}
831824
}

Sources/JExtractSwift/Swift2JavaVisitor.swift

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -131,15 +131,13 @@ final class Swift2JavaVisitor: SyntaxVisitor {
131131
}
132132

133133
override func visit(_ node: VariableDeclSyntax) -> SyntaxVisitorContinueKind {
134-
self.log.warning("NODE: \(node.debugDescription)")
135-
136134
guard let binding = node.bindings.first else {
137135
return .skipChildren
138136
}
139137

140138
let fullName = "\(binding.pattern.trimmed)"
141139

142-
// TODO filter out kinds of variables we cannot import
140+
// TODO: filter out kinds of variables we cannot import
143141

144142
self.log.info("Import variable: \(node.kind) \(fullName)")
145143

Tests/JExtractSwiftTests/FuncImportTests.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ final class MethodImportTests {
8383
expected:
8484
"""
8585
/**
86+
* Downcall to Swift:
8687
* {@snippet lang=swift :
8788
* public func helloWorld()
8889
* }
@@ -125,6 +126,7 @@ final class MethodImportTests {
125126
expected:
126127
"""
127128
/**
129+
* Downcall to Swift:
128130
* {@snippet lang=swift :
129131
* public func globalTakeInt(i: Int)
130132
* }
@@ -167,6 +169,7 @@ final class MethodImportTests {
167169
expected:
168170
"""
169171
/**
172+
* Downcall to Swift:
170173
* {@snippet lang=swift :
171174
* public func globalTakeIntLongString(i32: Int32, l: Int64, s: String)
172175
* }
@@ -209,6 +212,7 @@ final class MethodImportTests {
209212
expected:
210213
"""
211214
/**
215+
* Downcall to Swift:
212216
* {@snippet lang=swift :
213217
* public func helloMemberFunction()
214218
* }
@@ -251,6 +255,7 @@ final class MethodImportTests {
251255
expected:
252256
"""
253257
/**
258+
* Downcall to Swift:
254259
* {@snippet lang=swift :
255260
* public func helloMemberInExtension()
256261
* }
@@ -293,6 +298,7 @@ final class MethodImportTests {
293298
expected:
294299
"""
295300
/**
301+
* Downcall to Swift:
296302
* {@snippet lang=swift :
297303
* public func helloMemberFunction()
298304
* }
@@ -335,6 +341,7 @@ final class MethodImportTests {
335341
expected:
336342
"""
337343
/**
344+
* Downcall to Swift:
338345
* {@snippet lang=swift :
339346
* public func helloMemberFunction()
340347
* }
@@ -369,6 +376,7 @@ final class MethodImportTests {
369376
expected:
370377
"""
371378
/**
379+
* Downcall to Swift:
372380
* {@snippet lang=swift :
373381
* public func makeInt() -> Int
374382
* }

Tests/JExtractSwiftTests/FunctionDescriptorImportTests.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -162,8 +162,8 @@ extension FunctionDescriptorTests {
162162
}
163163

164164
func variableAccessorDescriptorTest(
165-
_ methodIdentifier: String,
166-
_ kind: VariableAccessorKind,
165+
_ identifier: String,
166+
_ accessorKind: VariableAccessorKind,
167167
javaPackage: String = "com.example.swift",
168168
swiftModuleName: String = "SwiftModule",
169169
logLevel: Logger.Level = .trace,
@@ -180,15 +180,15 @@ extension FunctionDescriptorTests {
180180
let varDecl: ImportedVariable? =
181181
st.importedTypes.values.compactMap {
182182
$0.variables.first {
183-
$0.identifier == methodIdentifier
183+
$0.identifier == identifier
184184
}
185185
}.first
186186
guard let varDecl else {
187-
fatalError("Cannot find descriptor of: \(methodIdentifier)")
187+
fatalError("Cannot find descriptor of: \(identifier)")
188188
}
189189

190190
let getOutput = CodePrinter.toString { printer in
191-
st.printPropertyAccessorDescriptorValue(&printer, varDecl, kind)
191+
st.printFunctionDescriptorValue(&printer, varDecl.accessorFunc(kind: accessorKind)!, accessorKind: accessorKind)
192192
}
193193

194194
try await body(getOutput)

Tests/JExtractSwiftTests/VariableImportTests.swift

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -67,13 +67,17 @@ final class VariableImportTests {
6767
// counterInt
6868
private static class counterInt {
6969
public static final FunctionDescriptor DESC_GET = FunctionDescriptor.of(
70-
/* -> */SWIFT_INT,
70+
/* -> */SWIFT_INT,
7171
SWIFT_POINTER
72-
);
72+
);
73+
public static final MemorySegment ADDR_GET = __FakeModule.findOrThrow("g");
74+
public static final MethodHandle HANDLE_GET = Linker.nativeLinker().downcallHandle(ADDR_GET, DESC_GET);
7375
public static final FunctionDescriptor DESC_SET = FunctionDescriptor.ofVoid(
74-
SWIFT_INT,
76+
SWIFT_INT,
7577
SWIFT_POINTER
7678
);
79+
public static final MemorySegment ADDR_SET = __FakeModule.findOrThrow("s");
80+
public static final MethodHandle HANDLE_SET = Linker.nativeLinker().downcallHandle(ADDR_SET, DESC_SET);
7781
}
7882
/**
7983
* Function descriptor for:

0 commit comments

Comments
 (0)