Skip to content

Commit 94d5f34

Browse files
authored
[JExtract/JNI] Add support for variables (#306)
* add support for variables * prefix boolean variables with `is` to match Java conventions * add confined arena constructor with current thread * add variable tests * PR feedback * add test for isWarm
1 parent 7bec685 commit 94d5f34

File tree

15 files changed

+584
-22
lines changed

15 files changed

+584
-22
lines changed

Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftClass.swift

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,31 @@ public class MySwiftClass {
1616
let x: Int64
1717
let y: Int64
1818

19+
public let constant: Int64 = 100
20+
public var mutable: Int64 = 0
21+
public var product: Int64 {
22+
return x * y
23+
}
24+
public var throwingVariable: Int64 {
25+
get throws {
26+
throw MySwiftClassError.swiftError
27+
}
28+
}
29+
public var mutableDividedByTwo: Int64 {
30+
get {
31+
return mutable / 2
32+
}
33+
set {
34+
mutable = newValue * 2
35+
}
36+
}
37+
public let warm: Bool = false
38+
public var getAsync: Int64 {
39+
get async {
40+
return 42
41+
}
42+
}
43+
1944
public static func method() {
2045
p("Hello from static method in a class!")
2146
}

Samples/JExtractJNISampleApp/Sources/MySwiftLibrary/MySwiftLibrary.swift

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,8 @@
2323
import Darwin.C
2424
#endif
2525

26+
public var globalVariable: Int64 = 0
27+
2628
public func helloWorld() {
2729
p("\(#function)")
2830
}
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
11
{
22
"javaPackage": "com.example.swift",
3-
"mode": "jni"
3+
"mode": "jni",
44
}

Samples/JExtractJNISampleApp/src/main/java/com/example/swift/HelloJava2SwiftJNI.java

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -41,10 +41,12 @@ static void examples() {
4141

4242
MySwiftClass.method();
4343

44-
try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) {
44+
try (var arena = new ConfinedSwiftMemorySession()) {
4545
MySwiftClass myClass = MySwiftClass.init(10, 5, arena);
4646
MySwiftClass myClass2 = MySwiftClass.init(arena);
4747

48+
System.out.println("myClass.isWarm: " + myClass.isWarm());
49+
4850
try {
4951
myClass.throwingFunction();
5052
} catch (Exception e) {

Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftClassTest.java

Lines changed: 62 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -22,43 +22,100 @@
2222
public class MySwiftClassTest {
2323
@Test
2424
void init_noParameters() {
25-
try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) {
25+
try (var arena = new ConfinedSwiftMemorySession()) {
2626
MySwiftClass c = MySwiftClass.init(arena);
2727
assertNotNull(c);
2828
}
2929
}
3030

3131
@Test
3232
void init_withParameters() {
33-
try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) {
33+
try (var arena = new ConfinedSwiftMemorySession()) {
3434
MySwiftClass c = MySwiftClass.init(1337, 42, arena);
3535
assertNotNull(c);
3636
}
3737
}
3838

3939
@Test
4040
void sum() {
41-
try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) {
41+
try (var arena = new ConfinedSwiftMemorySession()) {
4242
MySwiftClass c = MySwiftClass.init(20, 10, arena);
4343
assertEquals(30, c.sum());
4444
}
4545
}
4646

4747
@Test
4848
void xMultiplied() {
49-
try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) {
49+
try (var arena = new ConfinedSwiftMemorySession()) {
5050
MySwiftClass c = MySwiftClass.init(20, 10, arena);
5151
assertEquals(200, c.xMultiplied(10));
5252
}
5353
}
5454

5555
@Test
5656
void throwingFunction() {
57-
try (var arena = new ConfinedSwiftMemorySession(Thread.currentThread())) {
57+
try (var arena = new ConfinedSwiftMemorySession()) {
5858
MySwiftClass c = MySwiftClass.init(20, 10, arena);
5959
Exception exception = assertThrows(Exception.class, () -> c.throwingFunction());
6060

6161
assertEquals("swiftError", exception.getMessage());
6262
}
6363
}
64+
65+
@Test
66+
void constant() {
67+
try (var arena = new ConfinedSwiftMemorySession()) {
68+
MySwiftClass c = MySwiftClass.init(20, 10, arena);
69+
assertEquals(100, c.getConstant());
70+
}
71+
}
72+
73+
@Test
74+
void mutable() {
75+
try (var arena = new ConfinedSwiftMemorySession()) {
76+
MySwiftClass c = MySwiftClass.init(20, 10, arena);
77+
assertEquals(0, c.getMutable());
78+
c.setMutable(42);
79+
assertEquals(42, c.getMutable());
80+
}
81+
}
82+
83+
@Test
84+
void product() {
85+
try (var arena = new ConfinedSwiftMemorySession()) {
86+
MySwiftClass c = MySwiftClass.init(20, 10, arena);
87+
assertEquals(200, c.getProduct());
88+
}
89+
}
90+
91+
@Test
92+
void throwingVariable() {
93+
try (var arena = new ConfinedSwiftMemorySession()) {
94+
MySwiftClass c = MySwiftClass.init(20, 10, arena);
95+
96+
Exception exception = assertThrows(Exception.class, () -> c.getThrowingVariable());
97+
98+
assertEquals("swiftError", exception.getMessage());
99+
}
100+
}
101+
102+
@Test
103+
void mutableDividedByTwo() {
104+
try (var arena = new ConfinedSwiftMemorySession()) {
105+
MySwiftClass c = MySwiftClass.init(20, 10, arena);
106+
assertEquals(0, c.getMutableDividedByTwo());
107+
c.setMutable(20);
108+
assertEquals(10, c.getMutableDividedByTwo());
109+
c.setMutableDividedByTwo(5);
110+
assertEquals(10, c.getMutable());
111+
}
112+
}
113+
114+
@Test
115+
void isWarm() {
116+
try (var arena = new ConfinedSwiftMemorySession()) {
117+
MySwiftClass c = MySwiftClass.init(20, 10, arena);
118+
assertFalse(c.isWarm());
119+
}
120+
}
64121
}

Samples/JExtractJNISampleApp/src/test/java/com/example/swift/MySwiftLibraryTest.java

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -54,4 +54,11 @@ void call_writeString_jextract() {
5454

5555
assertEquals(string.length(), reply);
5656
}
57+
58+
@Test
59+
void globalVariable() {
60+
assertEquals(0, MySwiftLibrary.getGlobalVariable());
61+
MySwiftLibrary.setGlobalVariable(100);
62+
assertEquals(100, MySwiftLibrary.getGlobalVariable());
63+
}
5764
}

Sources/JExtractSwiftLib/Convenience/String+Extensions.swift

Lines changed: 11 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,4 +22,14 @@ extension String {
2222

2323
return "\(f.uppercased())\(String(dropFirst()))"
2424
}
25-
}
25+
26+
/// Returns whether the string is of the format `isX`
27+
var hasJavaBooleanNamingConvention: Bool {
28+
guard self.hasPrefix("is"), self.count > 2 else {
29+
return false
30+
}
31+
32+
let thirdCharacterIndex = self.index(self.startIndex, offsetBy: 2)
33+
return self[thirdCharacterIndex].isUppercase
34+
}
35+
}

Sources/JExtractSwiftLib/FFM/FFMSwift2JavaGenerator+JavaTranslation.swift

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -127,8 +127,8 @@ extension FFMSwift2JavaGenerator {
127127

128128
// Name.
129129
let javaName = switch decl.apiKind {
130-
case .getter: "get\(decl.name.toCamelCase)"
131-
case .setter: "set\(decl.name.toCamelCase)"
130+
case .getter: decl.javaGetterName
131+
case .setter: decl.javaSetterName
132132
case .function, .initializer: decl.name
133133
}
134134

Sources/JExtractSwiftLib/ImportedDecls.swift

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -154,3 +154,21 @@ extension ImportedFunc: Hashable {
154154
return lhs === rhs
155155
}
156156
}
157+
158+
extension ImportedFunc {
159+
var javaGetterName: String {
160+
let returnsBoolean = self.functionSignature.result.type.asNominalTypeDeclaration?.knownTypeKind == .bool
161+
162+
if !returnsBoolean {
163+
return "get\(self.name.toCamelCase)"
164+
} else if !self.name.hasJavaBooleanNamingConvention {
165+
return "is\(self.name.toCamelCase)"
166+
} else {
167+
return self.name.toCamelCase
168+
}
169+
}
170+
171+
var javaSetterName: String {
172+
"set\(self.name.toCamelCase)"
173+
}
174+
}

Sources/JExtractSwiftLib/JNI/JNISwift2JavaGenerator+JavaBindingsPrinting.swift

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,11 @@ extension JNISwift2JavaGenerator {
7979
printFunctionBinding(&printer, decl)
8080
printer.println()
8181
}
82+
83+
for decl in analysis.importedGlobalVariables {
84+
printFunctionBinding(&printer, decl)
85+
printer.println()
86+
}
8287
}
8388
}
8489

@@ -113,10 +118,17 @@ extension JNISwift2JavaGenerator {
113118

114119
for initializer in decl.initializers {
115120
printInitializerBindings(&printer, initializer, type: decl)
121+
printer.println()
116122
}
117123

118124
for method in decl.methods {
119125
printFunctionBinding(&printer, method)
126+
printer.println()
127+
}
128+
129+
for variable in decl.variables {
130+
printFunctionBinding(&printer, variable)
131+
printer.println()
120132
}
121133

122134
printDestroyFunction(&printer, decl)

0 commit comments

Comments
 (0)