Skip to content

Commit

Permalink
Merge pull request #30 from skiptools/dynamicconfig
Browse files Browse the repository at this point in the history
Tweaks to dynamic object support
  • Loading branch information
aabewhite authored Nov 30, 2024
2 parents 2b29e39 + 6599bbb commit 668340a
Show file tree
Hide file tree
Showing 5 changed files with 44 additions and 24 deletions.
31 changes: 18 additions & 13 deletions Sources/SkipBridge/AnyDynamicObject.swift
Original file line number Diff line number Diff line change
Expand Up @@ -11,26 +11,31 @@ open class AnyDynamicObject: JObjectProtocol, JConvertible {
private var object: JObject!

/// Supply the class name of the object and arguments to pass to the constructor.
public init(reflectingClassName: String, arguments: [Any?]) throws {
public convenience init(className: String, _ arguments: Any?...) throws {
try self.init(className: className, arguments: arguments)
}

/// Supply the class name of the object and arguments to pass to the constructor.
public init(className: String, arguments: [Any?]) throws {
try jniContext {
let arguments: [Any?]? = arguments.isEmpty ? nil : arguments
let ptr = try Java_reflectorClass.create(ctor: Java_reflectorClassNameConstructor, args: [reflectingClassName.toJavaParameter(options: []), arguments.toJavaParameter(options: .kotlincompat)])
let ptr = try Java_reflectorClass.create(ctor: Java_reflectorClassNameConstructor, args: [className.toJavaParameter(options: []), arguments.toJavaParameter(options: .kotlincompat)])
self.object = JObject(ptr)
}
}

/// Supply the class name of the statics to access.
public init(reflectingStaticsOfClassName: String) throws {
public init(forStaticsOfClassName className: String) throws {
try jniContext {
let ptr = try Java_reflectorClass.create(ctor: Java_reflectorStaticsOfClassNameConstructor, args: [reflectingStaticsOfClassName.toJavaParameter(options: [])])
let ptr = try Java_reflectorClass.create(ctor: Java_reflectorStaticsOfClassNameConstructor, args: [className.toJavaParameter(options: [])])
self.object = JObject(ptr)
}
}

/// Interact wih the given Kotlin object in Swift.
public required init(reflecting: JavaObjectPointer) throws {
public required init(for object: JavaObjectPointer) throws {
try jniContext {
let reflectorPtr = try Java_reflectorClass.create(ctor: Java_reflectorConstructor, args: [reflecting.toJavaParameter(options: [])])
let reflectorPtr = try Java_reflectorClass.create(ctor: Java_reflectorConstructor, args: [object.toJavaParameter(options: [])])
self.object = JObject(reflectorPtr)
}
}
Expand Down Expand Up @@ -286,7 +291,7 @@ open class AnyDynamicObject: JObjectProtocol, JConvertible {
get {
jniContext {
let ptr: JavaObjectPointer? = try! object.call(method: Java_reflectorObjectProperty, options: [], args: [member.toJavaParameter(options: [])])
return try! T.init(reflecting: ptr!)
return try! T.init(for: ptr!)
}
}
set {
Expand All @@ -302,7 +307,7 @@ open class AnyDynamicObject: JObjectProtocol, JConvertible {
guard let ptr = try! object.call(method: Java_reflectorObjectProperty, options: [], args: [member.toJavaParameter(options: [])]) as JavaObjectPointer? else {
return nil
}
return try! T.init(reflecting: ptr)
return try! T.init(for: ptr)
}
}
set {
Expand Down Expand Up @@ -363,7 +368,7 @@ open class AnyDynamicObject: JObjectProtocol, JConvertible {
// JConvertible

public static func fromJavaObject(_ obj: JavaObjectPointer?, options: JConvertibleOptions) -> Self {
return try! .init(reflecting: obj!)
return try! .init(for: obj!)
}

public func toJavaObject(options: JConvertibleOptions) -> JavaObjectPointer? {
Expand Down Expand Up @@ -684,15 +689,15 @@ public struct AnyDynamicObjectFunction {
try jniContext {
let arguments: [Any?]? = withArguments.isEmpty ? nil : withArguments
let ptr: JavaObjectPointer? = try object.call(method: Java_reflectorObjectFunction, options: [], args: [name.toJavaParameter(options: []), arguments.toJavaParameter(options: .kotlincompat)])
return try T.init(reflecting: ptr!)
return try T.init(for: ptr!)
}
}

public func dynamicallyCall<T: AnyDynamicObject>(withKeywordArguments: [String: Any?]) throws -> T {
try jniContext {
let arguments: [String: Any?]? = withKeywordArguments.isEmpty ? nil : withKeywordArguments
let ptr: JavaObjectPointer? = try object.call(method: Java_reflectorObjectKeywordFunction, options: [], args: [name.toJavaParameter(options: []), arguments.toJavaParameter(options: .kotlincompat)])
return try T.init(reflecting: ptr!)
return try T.init(for: ptr!)
}
}

Expand All @@ -702,7 +707,7 @@ public struct AnyDynamicObjectFunction {
guard let ptr = try object.call(method: Java_reflectorObjectFunction, options: [], args: [name.toJavaParameter(options: []), arguments.toJavaParameter(options: .kotlincompat)]) as JavaObjectPointer? else {
return nil
}
return try T.init(reflecting: ptr)
return try T.init(for: ptr)
}
}

Expand All @@ -712,7 +717,7 @@ public struct AnyDynamicObjectFunction {
guard let ptr = try object.call(method: Java_reflectorObjectKeywordFunction, options: [], args: [name.toJavaParameter(options: []), arguments.toJavaParameter(options: .kotlincompat)]) as JavaObjectPointer? else {
return nil
}
return try T.init(reflecting: ptr)
return try T.init(for: ptr)
}
}

Expand Down
6 changes: 3 additions & 3 deletions Sources/SkipBridgeKt/Skip/Reflector.kt
Original file line number Diff line number Diff line change
Expand Up @@ -26,11 +26,11 @@ class Reflector {
this.cls = javaCls.kotlin
}

constructor(className: String, arguments: List<Any?>?) {
val cls = Class.forName(className).kotlin
constructor(reflectingClassName: String, arguments: List<Any?>?) {
val cls = Class.forName(reflectingClassName).kotlin
val match = matchConstructor(cls, arguments ?: listOf<Any?>())
if (match == null) {
throw NoSuchMethodError("${className}.<init>(${argumentsString(arguments)})")
throw NoSuchMethodError("${reflectingClassName}.<init>(${argumentsString(arguments)})")
}
val (matchConstructor, matchArguments) = match
this.obj = matchConstructor.callBy(matchArguments)!!
Expand Down
2 changes: 1 addition & 1 deletion Sources/SkipBridgeToKotlinSamples/Skip/skip.yml
Original file line number Diff line number Diff line change
Expand Up @@ -2,4 +2,4 @@
skip:
mode: 'native'
bridging: true

dynamicroot: 'K'
24 changes: 17 additions & 7 deletions Sources/SkipBridgeToKotlinSamples/TestsSupport.swift
Original file line number Diff line number Diff line change
Expand Up @@ -46,7 +46,7 @@ public func testSupport_swiftKotlinClassConstant_stringVar() -> String {
}

public func testSupport_dynamicJavaObjectProperties() throws -> Bool {
let date = try AnyDynamicObject(reflectingClassName: "java.util.Date", arguments: [999])
let date = try AnyDynamicObject(className: "java.util.Date", 999)
guard date.time == 999 else {
return false
}
Expand All @@ -59,13 +59,13 @@ public func testSupport_dynamicJavaObjectProperties() throws -> Bool {
}

public func testSupport_dynamicJavaObjectTraversal() throws -> Bool {
let date = try AnyDynamicObject(reflectingClassName: "java.util.Date", arguments: [])
let date = try AnyDynamicObject(className: "java.util.Date")
let string: String = try date.toInstant().toString()
return !string.isEmpty
}

public func testSupport_dynamicJavaObjectFunctions() throws -> Bool {
let date = try AnyDynamicObject(reflectingClassName: "java.util.Date", arguments: [999])
let date = try AnyDynamicObject(className: "java.util.Date", 999)
guard try date.getTime() == 999 else {
return false
}
Expand All @@ -78,7 +78,7 @@ public func testSupport_dynamicJavaObjectFunctions() throws -> Bool {
}

public func testSupport_dynamicKotlinObjects() throws -> Bool {
let dict = try AnyDynamicObject(reflectingClassName: "skip.lib.Dictionary", arguments: [])
let dict = try AnyDynamicObject(className: "skip.lib.Dictionary")
try dict.put(key: "a", value: 1) as Void
try dict.put(key: "b", value: 2) as Void
try dict.put(key: "c", value: 3) as Void
Expand All @@ -99,7 +99,7 @@ public func testSupport_dynamicKotlinObjects() throws -> Bool {

public func testSupport_dynamicConverting() throws -> Bool {
// Test that we can retrieve our bridged types from their Kotlin equivalents
let arr = try AnyDynamicObject(reflectingClassName: "skip.lib.Array", arguments: [])
let arr = try AnyDynamicObject(className: "skip.lib.Array")
try arr.append(1) as Void
try arr.append(2) as Void
try arr.append(3) as Void
Expand All @@ -113,7 +113,7 @@ public func testSupport_dynamicConverting() throws -> Bool {
return false
}

let url = try AnyDynamicObject(reflectingClassName: "java.net.URL", arguments: ["https://skip.tools"])
let url = try AnyDynamicObject(className: "java.net.URL", "https://skip.tools")
let uri: URL = try url.toURI() // java.net.URI converts
guard uri.absoluteString == "https://skip.tools" else {
return false
Expand All @@ -123,7 +123,7 @@ public func testSupport_dynamicConverting() throws -> Bool {
}

public func testSupport_dynamicStatics() throws -> Bool {
let math = try AnyDynamicObject(reflectingStaticsOfClassName: "java.lang.Math")
let math = try AnyDynamicObject(forStaticsOfClassName: "java.lang.Math")
let abs: Double = try math.abs(-1.0)
guard abs == 1.0 else {
return false
Expand All @@ -135,3 +135,13 @@ public func testSupport_dynamicStatics() throws -> Bool {
}
return true
}

#if os(Android) || ROBOLECTRIC
public func testSupport_dynamicCodeGenJavaDateTime() throws -> Int64 {
return try K.java.util.Date().time
}

public func testSupport_dynamicCodeGenSkipDateTime() -> Double {
return K.skip.foundation.Date.Companion.now.timeIntervalSince1970
}
#endif
Original file line number Diff line number Diff line change
Expand Up @@ -482,5 +482,10 @@ final class BridgeToKotlinTests: XCTestCase {
func testDynamicStatics() throws {
XCTAssertTrue(try testSupport_dynamicStatics())
}

func testDynamicCodeGen() throws {
XCTAssertNotEqual(try testSupport_dynamicCodeGenJavaDateTime(), Int64(0))
XCTAssertNotEqual(try testSupport_dynamicCodeGenSkipDateTime(), 0.0)
}
#endif
}

0 comments on commit 668340a

Please sign in to comment.