diff --git a/Sources/Java2Swift/JavaToSwift.swift b/Sources/Java2Swift/JavaToSwift.swift index 205c6a43..15e346ae 100644 --- a/Sources/Java2Swift/JavaToSwift.swift +++ b/Sources/Java2Swift/JavaToSwift.swift @@ -252,7 +252,7 @@ struct JavaToSwift: ParsableCommand { let swiftName = "\(currentSwiftName).\(swiftUnqualifiedName)" - translator.translatedClasses[javaClassName] = (swiftName, nil, true) + translator.translatedClasses[javaClassName] = (swiftName, nil) return nestedClass } @@ -279,7 +279,8 @@ struct JavaToSwift: ParsableCommand { """ - let swiftFileName = try! translator.getSwiftTypeName(javaClass).swiftName.replacing(".", with: "+") + ".swift" + let swiftFileName = try! translator.getSwiftTypeName(javaClass, preferValueTypes: false) + .swiftName.replacing(".", with: "+") + ".swift" try writeContents( swiftFileText, to: swiftFileName, diff --git a/Sources/Java2SwiftLib/JavaClassTranslator.swift b/Sources/Java2SwiftLib/JavaClassTranslator.swift index 232c9338..1df6d683 100644 --- a/Sources/Java2SwiftLib/JavaClassTranslator.swift +++ b/Sources/Java2SwiftLib/JavaClassTranslator.swift @@ -103,7 +103,11 @@ struct JavaClassTranslator { let fullName = javaClass.getName() self.javaClass = javaClass self.translator = translator - self.swiftTypeName = try translator.getSwiftTypeNameFromJavaClassName(fullName, escapeMemberNames: false) + self.swiftTypeName = try translator.getSwiftTypeNameFromJavaClassName( + fullName, + preferValueTypes: false, + escapeMemberNames: false + ) // Type parameters. self.javaTypeParameters = javaClass.getTypeParameters().compactMap { $0 } @@ -112,7 +116,7 @@ struct JavaClassTranslator { // Superclass. if !javaClass.isInterface(), let javaSuperclass = javaClass.getSuperclass() { do { - self.swiftSuperclass = try translator.getSwiftTypeName(javaSuperclass).swiftName + self.swiftSuperclass = try translator.getSwiftTypeName(javaSuperclass, preferValueTypes: false).swiftName } catch { translator.logUntranslated("Unable to translate '\(fullName)' superclass: \(error)") self.swiftSuperclass = nil @@ -128,7 +132,11 @@ struct JavaClassTranslator { } do { - let typeName = try translator.getSwiftTypeNameAsString(javaType, outerOptional: .nonoptional) + let typeName = try translator.getSwiftTypeNameAsString( + javaType, + preferValueTypes: false, + outerOptional: .nonoptional + ) return "\(typeName)" } catch { translator.logUntranslated("Unable to translate '\(fullName)' interface '\(javaType.getTypeName())': \(error)") @@ -314,7 +322,10 @@ extension JavaClassTranslator { /// Render any nested classes that will not be rendered separately. func renderNestedClasses() -> [DeclSyntax] { - return nestedClasses.compactMap { clazz in + return nestedClasses + .sorted { + $0.getName() < $1.getName() + }.compactMap { clazz in do { return try translator.translateClass(clazz) } catch { @@ -456,7 +467,11 @@ extension JavaClassTranslator { // Map the result type. let resultTypeStr: String - let resultType = try translator.getSwiftTypeNameAsString(javaMethod.getGenericReturnType()!, outerOptional: .implicitlyUnwrappedOptional) + let resultType = try translator.getSwiftTypeNameAsString( + javaMethod.getGenericReturnType()!, + preferValueTypes: true, + outerOptional: .implicitlyUnwrappedOptional + ) if resultType != "Void" { resultTypeStr = " -> \(resultType)" } else { @@ -477,7 +492,11 @@ extension JavaClassTranslator { /// Render a single Java field into the corresponding Swift property, or /// throw an error if that is not possible for any reason. package func renderField(_ javaField: Field) throws -> DeclSyntax { - let typeName = try translator.getSwiftTypeNameAsString(javaField.getGenericType()!, outerOptional: .implicitlyUnwrappedOptional) + let typeName = try translator.getSwiftTypeNameAsString( + javaField.getGenericType()!, + preferValueTypes: true, + outerOptional: .implicitlyUnwrappedOptional + ) let fieldAttribute: AttributeSyntax = javaField.isStatic ? "@JavaStaticField" : "@JavaField"; let swiftFieldName = javaField.getName().escapedSwiftName return """ @@ -544,7 +563,11 @@ extension JavaClassTranslator { return try parameters.compactMap { javaParameter in guard let javaParameter else { return nil } - let typeName = try translator.getSwiftTypeNameAsString(javaParameter.getParameterizedType()!, outerOptional: .optional) + let typeName = try translator.getSwiftTypeNameAsString( + javaParameter.getParameterizedType()!, + preferValueTypes: true, + outerOptional: .optional + ) let paramName = javaParameter.getName() return "_ \(raw: paramName): \(raw: typeName)" } diff --git a/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift b/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift index f13a8cce..b84d7a1e 100644 --- a/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift +++ b/Sources/Java2SwiftLib/JavaTranslator+Configuration.swift @@ -27,8 +27,7 @@ extension JavaTranslator { for (javaClassName, swiftName) in config.classes { translatedClasses[javaClassName] = ( swiftType: swiftName, - swiftModule: swiftModule, - isOptional: true + swiftModule: swiftModule ) } } diff --git a/Sources/Java2SwiftLib/JavaTranslator.swift b/Sources/Java2SwiftLib/JavaTranslator.swift index 9f5fa292..5889a193 100644 --- a/Sources/Java2SwiftLib/JavaTranslator.swift +++ b/Sources/Java2SwiftLib/JavaTranslator.swift @@ -28,11 +28,20 @@ package class JavaTranslator { let environment: JNIEnvironment let format: BasicFormat - /// A mapping from the canonical name of Java classes to the corresponding - /// Swift type name, its Swift module, and whether we need to be working - /// with optionals. - package var translatedClasses: [String: (swiftType: String, swiftModule: String?, isOptional: Bool)] = - defaultTranslatedClasses + /// A mapping from the name of each known Java class to the corresponding + /// Swift type name and its Swift module. + package var translatedClasses: [String: (swiftType: String, swiftModule: String?)] = [:] + + /// A mapping from the name of each known Java class with the Swift value type + /// (and its module) to which it is mapped. + /// + /// The Java classes here can also be part of `translatedClasses`. The entry in + /// `translatedClasses` should map to a representation of the Java class (i.e., + /// an AnyJavaObject-conforming type) whereas the entry here should map to + /// a value type. + package let translatedToValueTypes: [String: (swiftType: String, swiftModule: String) ] = [ + "java.lang.String": ("String", "JavaKit"), + ] /// The set of Swift modules that need to be imported to make the generated /// code compile. Use `getImportDecls()` to format this into a list of @@ -80,13 +89,6 @@ extension JavaTranslator { "JavaKit", "JavaRuntime", ] - - /// The default set of translated classes that do not come from JavaKit - /// itself. This should only be used to refer to types that are built-in to - /// JavaKit and therefore aren't captured in any configuration file. - package static let defaultTranslatedClasses: [String: (swiftType: String, swiftModule: String?, isOptional: Bool)] = [ - "java.lang.String": ("String", "JavaKit", false), - ] } // MARK: Import translation @@ -104,13 +106,21 @@ extension JavaTranslator { // MARK: Type translation extension JavaTranslator { /// Turn a Java type into a string. - func getSwiftTypeNameAsString(_ javaType: Type, outerOptional: OptionalKind) throws -> String { + func getSwiftTypeNameAsString( + _ javaType: Type, + preferValueTypes: Bool, + outerOptional: OptionalKind + ) throws -> String { // Replace type variables with their bounds. if let typeVariable = javaType.as(TypeVariable.self), typeVariable.getBounds().count == 1, let bound = typeVariable.getBounds()[0] { - return try getSwiftTypeNameAsString(bound, outerOptional: outerOptional) + return try getSwiftTypeNameAsString( + bound, + preferValueTypes: preferValueTypes, + outerOptional: outerOptional + ) } // Replace wildcards with their upper bound. @@ -119,13 +129,30 @@ extension JavaTranslator { let bound = wildcardType.getUpperBounds()[0] { // Replace a wildcard type with its first bound. - return try getSwiftTypeNameAsString(bound, outerOptional: outerOptional) + return try getSwiftTypeNameAsString( + bound, + preferValueTypes: preferValueTypes, + outerOptional: outerOptional + ) } // Handle array types by recursing into the component type. if let arrayType = javaType.as(GenericArrayType.self) { - let elementType = try getSwiftTypeNameAsString(arrayType.getGenericComponentType()!, outerOptional: .optional) - return "[\(elementType)]" + if preferValueTypes { + let elementType = try getSwiftTypeNameAsString( + arrayType.getGenericComponentType()!, + preferValueTypes: preferValueTypes, + outerOptional: .optional + ) + return "[\(elementType)]" + } + + let (swiftName, _) = try getSwiftTypeName( + JavaClass().as(JavaClass.self)!, + preferValueTypes: false + ) + + return outerOptional.adjustTypeName(swiftName) } // Handle parameterized types by recursing on the raw type and the type @@ -133,7 +160,11 @@ extension JavaTranslator { if let parameterizedType = javaType.as(ParameterizedType.self), let rawJavaType = parameterizedType.getRawType() { - var rawSwiftType = try getSwiftTypeNameAsString(rawJavaType, outerOptional: outerOptional) + var rawSwiftType = try getSwiftTypeNameAsString( + rawJavaType, + preferValueTypes: false, + outerOptional: outerOptional + ) let optionalSuffix: String if let lastChar = rawSwiftType.last, lastChar == "?" || lastChar == "!" { @@ -145,7 +176,7 @@ extension JavaTranslator { let typeArguments = try parameterizedType.getActualTypeArguments().compactMap { typeArg in try typeArg.map { typeArg in - try getSwiftTypeNameAsString(typeArg, outerOptional: .nonoptional) + try getSwiftTypeNameAsString(typeArg, preferValueTypes: false, outerOptional: .nonoptional) } } @@ -157,38 +188,50 @@ extension JavaTranslator { throw TranslationError.unhandledJavaType(javaType) } - let (swiftName, isOptional) = try getSwiftTypeName(javaClass) + let (swiftName, isOptional) = try getSwiftTypeName(javaClass, preferValueTypes: preferValueTypes) var resultString = swiftName if isOptional { - switch outerOptional { - case .implicitlyUnwrappedOptional: - resultString += "!" - case .optional: - resultString += "?" - case .nonoptional: - break - } + resultString = outerOptional.adjustTypeName(resultString) } return resultString } /// Translate a Java class into its corresponding Swift type name. - package func getSwiftTypeName(_ javaClass: JavaClass) throws -> (swiftName: String, isOptional: Bool) { + package func getSwiftTypeName( + _ javaClass: JavaClass, + preferValueTypes: Bool + ) throws -> (swiftName: String, isOptional: Bool) { let javaType = try JavaType(javaTypeName: javaClass.getName()) - let isSwiftOptional = javaType.isSwiftOptional - return ( - try javaType.swiftTypeName { javaClassName in - try self.getSwiftTypeNameFromJavaClassName(javaClassName) - }, - isSwiftOptional - ) + let isSwiftOptional = javaType.isSwiftOptional(stringIsValueType: preferValueTypes) + + let swiftTypeName: String + if !preferValueTypes, case .array(_) = javaType { + swiftTypeName = try self.getSwiftTypeNameFromJavaClassName("java.lang.reflect.Array", preferValueTypes: false) + } else { + swiftTypeName = try javaType.swiftTypeName { javaClassName in + try self.getSwiftTypeNameFromJavaClassName(javaClassName, preferValueTypes: preferValueTypes) + } + } + + return (swiftTypeName, isSwiftOptional) } /// Map a Java class name to its corresponding Swift type. func getSwiftTypeNameFromJavaClassName( _ name: String, + preferValueTypes: Bool, escapeMemberNames: Bool = true ) throws -> String { + // If we want a value type, look for one. + if preferValueTypes, let translatedValueType = translatedToValueTypes[name] { + // Note that we need to import this Swift module. + if translatedValueType.swiftModule != swiftModuleName { + importedSwiftModules.insert(translatedValueType.swiftModule) + } + + return translatedValueType.swiftType + } + if let translated = translatedClasses[name] { // Note that we need to import this Swift module. if let swiftModule = translated.swiftModule, swiftModule != swiftModuleName { diff --git a/Sources/Java2SwiftLib/OptionalKind.swift b/Sources/Java2SwiftLib/OptionalKind.swift index 57951fa4..c05bff18 100644 --- a/Sources/Java2SwiftLib/OptionalKind.swift +++ b/Sources/Java2SwiftLib/OptionalKind.swift @@ -22,4 +22,13 @@ enum OptionalKind { /// The value uses an implicitly-unwrapped optional. case implicitlyUnwrappedOptional + + /// Adjust the given type name string based on the optionality of this type. + func adjustTypeName(_ string: String) -> String { + switch self { + case .implicitlyUnwrappedOptional: return string + "!" + case .optional: return string + "?" + case .nonoptional: return string + } + } } diff --git a/Sources/JavaKit/Java2Swift.config b/Sources/JavaKit/Java2Swift.config index bace061f..ed284d31 100644 --- a/Sources/JavaKit/Java2Swift.config +++ b/Sources/JavaKit/Java2Swift.config @@ -1,5 +1,6 @@ { "classes" : { + "java.lang.reflect.Array" : "JavaArray", "java.lang.Boolean" : "JavaBoolean", "java.lang.Byte" : "JavaByte", "java.lang.Character" : "JavaCharacter", @@ -14,6 +15,7 @@ "java.lang.Object" : "JavaObject", "java.lang.RuntimeException" : "RuntimeException", "java.lang.Short" : "JavaShort", + "java.lang.String" : "JavaString", "java.lang.Throwable" : "Throwable", "java.lang.Void" : "JavaVoid" } diff --git a/Sources/JavaKit/generated/JavaArray.swift b/Sources/JavaKit/generated/JavaArray.swift new file mode 100644 index 00000000..805b3929 --- /dev/null +++ b/Sources/JavaKit/generated/JavaArray.swift @@ -0,0 +1,96 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.reflect.Array", extends: JavaObject.self) +public struct JavaArray { + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticMethod + public func get(_ arg0: JavaObject?, _ arg1: Int32) throws -> JavaObject! + + @JavaStaticMethod + public func getLength(_ arg0: JavaObject?) throws -> Int32 + + @JavaStaticMethod + public func getBoolean(_ arg0: JavaObject?, _ arg1: Int32) throws -> Bool + + @JavaStaticMethod + public func getByte(_ arg0: JavaObject?, _ arg1: Int32) throws -> Int8 + + @JavaStaticMethod + public func getShort(_ arg0: JavaObject?, _ arg1: Int32) throws -> Int16 + + @JavaStaticMethod + public func getChar(_ arg0: JavaObject?, _ arg1: Int32) throws -> UInt16 + + @JavaStaticMethod + public func getInt(_ arg0: JavaObject?, _ arg1: Int32) throws -> Int32 + + @JavaStaticMethod + public func getLong(_ arg0: JavaObject?, _ arg1: Int32) throws -> Int64 + + @JavaStaticMethod + public func getFloat(_ arg0: JavaObject?, _ arg1: Int32) throws -> Float + + @JavaStaticMethod + public func getDouble(_ arg0: JavaObject?, _ arg1: Int32) throws -> Double + + @JavaStaticMethod + public func newInstance(_ arg0: JavaClass?, _ arg1: Int32) throws -> JavaObject! + + @JavaStaticMethod + public func newInstance(_ arg0: JavaClass?, _ arg1: [Int32]) throws -> JavaObject! + + @JavaStaticMethod + public func set(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: JavaObject?) throws + + @JavaStaticMethod + public func setBoolean(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Bool) throws + + @JavaStaticMethod + public func setByte(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Int8) throws + + @JavaStaticMethod + public func setChar(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: UInt16) throws + + @JavaStaticMethod + public func setShort(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Int16) throws + + @JavaStaticMethod + public func setInt(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Int32) throws + + @JavaStaticMethod + public func setLong(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Int64) throws + + @JavaStaticMethod + public func setFloat(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Float) throws + + @JavaStaticMethod + public func setDouble(_ arg0: JavaObject?, _ arg1: Int32, _ arg2: Double) throws +} diff --git a/Sources/JavaKit/generated/JavaCharacter.swift b/Sources/JavaKit/generated/JavaCharacter.swift index 739cc260..1ebb7625 100644 --- a/Sources/JavaKit/generated/JavaCharacter.swift +++ b/Sources/JavaKit/generated/JavaCharacter.swift @@ -42,6 +42,37 @@ public struct JavaCharacter { @JavaMethod public func wait() throws } +extension JavaCharacter { + @JavaClass("java.lang.Character$Subset", extends: JavaObject.self) + public struct Subset { + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} extension JavaCharacter { @JavaClass("java.lang.Character$UnicodeBlock", extends: JavaCharacter.Subset.self) public struct UnicodeBlock { @@ -3146,37 +3177,6 @@ extension JavaClass { @JavaStaticMethod public func of(_ arg0: Int32) -> JavaCharacter.UnicodeScript! } -extension JavaCharacter { - @JavaClass("java.lang.Character$Subset", extends: JavaObject.self) - public struct Subset { - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - } -} extension JavaClass { @JavaStaticField(isFinal: true) public var MIN_RADIX: Int32 diff --git a/Sources/JavaKit/generated/JavaString.swift b/Sources/JavaKit/generated/JavaString.swift new file mode 100644 index 00000000..c062dc0d --- /dev/null +++ b/Sources/JavaKit/generated/JavaString.swift @@ -0,0 +1,264 @@ +// Auto-generated by Java-to-Swift wrapper generator. +import JavaRuntime + +@JavaClass("java.lang.String", extends: JavaObject.self) +public struct JavaString { + @JavaMethod + public init(_ arg0: [Int8], _ arg1: String, environment: JNIEnvironment? = nil) throws + + @JavaMethod + public init(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: [Int8], environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: [UInt16], environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: String, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32, _ arg3: String, environment: JNIEnvironment? = nil) throws + + @JavaMethod + public init(_ arg0: [Int8], _ arg1: Int32, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32, _ arg3: Int32, environment: JNIEnvironment? = nil) + + @JavaMethod + public init(_ arg0: [Int32], _ arg1: Int32, _ arg2: Int32, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func length() -> Int32 + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getChars(_ arg0: Int32, _ arg1: Int32, _ arg2: [UInt16], _ arg3: Int32) + + @JavaMethod + public func compareTo(_ arg0: JavaObject?) -> Int32 + + @JavaMethod + public func compareTo(_ arg0: String) -> Int32 + + @JavaMethod + public func indexOf(_ arg0: String, _ arg1: Int32, _ arg2: Int32) -> Int32 + + @JavaMethod + public func indexOf(_ arg0: String) -> Int32 + + @JavaMethod + public func indexOf(_ arg0: Int32) -> Int32 + + @JavaMethod + public func indexOf(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaMethod + public func indexOf(_ arg0: Int32, _ arg1: Int32, _ arg2: Int32) -> Int32 + + @JavaMethod + public func indexOf(_ arg0: String, _ arg1: Int32) -> Int32 + + @JavaMethod + public func charAt(_ arg0: Int32) -> UInt16 + + @JavaMethod + public func codePointAt(_ arg0: Int32) -> Int32 + + @JavaMethod + public func codePointBefore(_ arg0: Int32) -> Int32 + + @JavaMethod + public func codePointCount(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaMethod + public func offsetByCodePoints(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaMethod + public func getBytes() -> [Int8] + + @JavaMethod + public func getBytes(_ arg0: String) throws -> [Int8] + + @JavaMethod + public func getBytes(_ arg0: Int32, _ arg1: Int32, _ arg2: [Int8], _ arg3: Int32) + + @JavaMethod + public func regionMatches(_ arg0: Bool, _ arg1: Int32, _ arg2: String, _ arg3: Int32, _ arg4: Int32) -> Bool + + @JavaMethod + public func regionMatches(_ arg0: Int32, _ arg1: String, _ arg2: Int32, _ arg3: Int32) -> Bool + + @JavaMethod + public func startsWith(_ arg0: String) -> Bool + + @JavaMethod + public func startsWith(_ arg0: String, _ arg1: Int32) -> Bool + + @JavaMethod + public func lastIndexOf(_ arg0: String) -> Int32 + + @JavaMethod + public func lastIndexOf(_ arg0: Int32, _ arg1: Int32) -> Int32 + + @JavaMethod + public func lastIndexOf(_ arg0: String, _ arg1: Int32) -> Int32 + + @JavaMethod + public func lastIndexOf(_ arg0: Int32) -> Int32 + + @JavaMethod + public func substring(_ arg0: Int32) -> String + + @JavaMethod + public func substring(_ arg0: Int32, _ arg1: Int32) -> String + + @JavaMethod + public func isEmpty() -> Bool + + @JavaMethod + public func replace(_ arg0: UInt16, _ arg1: UInt16) -> String + + @JavaMethod + public func matches(_ arg0: String) -> Bool + + @JavaMethod + public func replaceFirst(_ arg0: String, _ arg1: String) -> String + + @JavaMethod + public func replaceAll(_ arg0: String, _ arg1: String) -> String + + @JavaMethod + public func split(_ arg0: String) -> [String] + + @JavaMethod + public func split(_ arg0: String, _ arg1: Int32) -> [String] + + @JavaMethod + public func splitWithDelimiters(_ arg0: String, _ arg1: Int32) -> [String] + + @JavaMethod + public func toLowerCase() -> String + + @JavaMethod + public func toUpperCase() -> String + + @JavaMethod + public func trim() -> String + + @JavaMethod + public func strip() -> String + + @JavaMethod + public func stripLeading() -> String + + @JavaMethod + public func stripTrailing() -> String + + @JavaMethod + public func `repeat`(_ arg0: Int32) -> String + + @JavaMethod + public func isBlank() -> Bool + + @JavaMethod + public func toCharArray() -> [UInt16] + + @JavaMethod + public func equalsIgnoreCase(_ arg0: String) -> Bool + + @JavaMethod + public func compareToIgnoreCase(_ arg0: String) -> Int32 + + @JavaMethod + public func endsWith(_ arg0: String) -> Bool + + @JavaMethod + public func concat(_ arg0: String) -> String + + @JavaMethod + public func indent(_ arg0: Int32) -> String + + @JavaMethod + public func stripIndent() -> String + + @JavaMethod + public func translateEscapes() -> String + + @JavaMethod + public func formatted(_ arg0: [JavaObject?]) -> String + + @JavaMethod + public func intern() -> String + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws +} +extension JavaClass { + @JavaStaticMethod + public func valueOf(_ arg0: Int64) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: [UInt16]) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: JavaObject?) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: Float) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: Double) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: UInt16) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: Bool) -> String + + @JavaStaticMethod + public func valueOf(_ arg0: Int32) -> String + + @JavaStaticMethod + public func format(_ arg0: String, _ arg1: [JavaObject?]) -> String + + @JavaStaticMethod + public func copyValueOf(_ arg0: [UInt16]) -> String + + @JavaStaticMethod + public func copyValueOf(_ arg0: [UInt16], _ arg1: Int32, _ arg2: Int32) -> String +} diff --git a/Sources/JavaKitCollection/generated/HashMap.swift b/Sources/JavaKitCollection/generated/HashMap.swift index 90e50295..287593f5 100644 --- a/Sources/JavaKitCollection/generated/HashMap.swift +++ b/Sources/JavaKitCollection/generated/HashMap.swift @@ -88,92 +88,6 @@ public struct HashMap { @JavaMethod public func wait() throws } -extension HashMap { - @JavaClass("java.util.AbstractMap$SimpleImmutableEntry", extends: JavaObject.self) - public struct SimpleImmutableEntry { - @JavaMethod - public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getValue() -> JavaObject! - - @JavaMethod - public func getKey() -> JavaObject! - - @JavaMethod - public func setValue(_ arg0: JavaObject?) -> JavaObject! - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - } -} -extension HashMap { - @JavaClass("java.util.AbstractMap$SimpleEntry", extends: JavaObject.self) - public struct SimpleEntry { - @JavaMethod - public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) - - @JavaMethod - public func equals(_ arg0: JavaObject?) -> Bool - - @JavaMethod - public func toString() -> String - - @JavaMethod - public func hashCode() -> Int32 - - @JavaMethod - public func getValue() -> JavaObject! - - @JavaMethod - public func getKey() -> JavaObject! - - @JavaMethod - public func setValue(_ arg0: JavaObject?) -> JavaObject! - - @JavaMethod - public func getClass() -> JavaClass! - - @JavaMethod - public func notify() - - @JavaMethod - public func notifyAll() - - @JavaMethod - public func wait(_ arg0: Int64) throws - - @JavaMethod - public func wait(_ arg0: Int64, _ arg1: Int32) throws - - @JavaMethod - public func wait() throws - } -} extension JavaClass { @JavaStaticMethod public func newHashMap(_ arg0: Int32) -> HashMap! where ObjectType == HashMap diff --git a/Sources/JavaKitCollection/generated/TreeMap.swift b/Sources/JavaKitCollection/generated/TreeMap.swift index 3c45b998..706d5339 100644 --- a/Sources/JavaKitCollection/generated/TreeMap.swift +++ b/Sources/JavaKitCollection/generated/TreeMap.swift @@ -106,3 +106,89 @@ public struct TreeMap { @JavaMethod public func getOrDefault(_ arg0: JavaObject?, _ arg1: JavaObject?) -> JavaObject! } +extension TreeMap { + @JavaClass("java.util.AbstractMap$SimpleEntry", extends: JavaObject.self) + public struct SimpleEntry { + @JavaMethod + public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getValue() -> JavaObject! + + @JavaMethod + public func getKey() -> JavaObject! + + @JavaMethod + public func setValue(_ arg0: JavaObject?) -> JavaObject! + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} +extension TreeMap { + @JavaClass("java.util.AbstractMap$SimpleImmutableEntry", extends: JavaObject.self) + public struct SimpleImmutableEntry { + @JavaMethod + public init(_ arg0: JavaObject?, _ arg1: JavaObject?, environment: JNIEnvironment? = nil) + + @JavaMethod + public func equals(_ arg0: JavaObject?) -> Bool + + @JavaMethod + public func toString() -> String + + @JavaMethod + public func hashCode() -> Int32 + + @JavaMethod + public func getValue() -> JavaObject! + + @JavaMethod + public func getKey() -> JavaObject! + + @JavaMethod + public func setValue(_ arg0: JavaObject?) -> JavaObject! + + @JavaMethod + public func getClass() -> JavaClass! + + @JavaMethod + public func notify() + + @JavaMethod + public func notifyAll() + + @JavaMethod + public func wait(_ arg0: Int64) throws + + @JavaMethod + public func wait(_ arg0: Int64, _ arg1: Int32) throws + + @JavaMethod + public func wait() throws + } +} diff --git a/Sources/JavaKitJar/generated/JarInputStream.swift b/Sources/JavaKitJar/generated/JarInputStream.swift index 580202e4..de063bb9 100644 --- a/Sources/JavaKitJar/generated/JarInputStream.swift +++ b/Sources/JavaKitJar/generated/JarInputStream.swift @@ -4,9 +4,6 @@ import JavaRuntime @JavaClass("java.util.jar.JarInputStream") public struct JarInputStream { - @JavaMethod - public func getNextJarEntry() throws -> JarEntry! - @JavaMethod public func read(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 @@ -14,7 +11,7 @@ public struct JarInputStream { public func getManifest() -> Manifest! @JavaMethod - public func closeEntry() throws + public func getNextJarEntry() throws -> JarEntry! @JavaMethod public func read() throws -> Int32 @@ -26,10 +23,10 @@ public struct JarInputStream { public func readAllBytes() throws -> [Int8] @JavaMethod - public func readNBytes(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 + public func readNBytes(_ arg0: Int32) throws -> [Int8] @JavaMethod - public func readNBytes(_ arg0: Int32) throws -> [Int8] + public func readNBytes(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws -> Int32 @JavaMethod public func skip(_ arg0: Int64) throws -> Int64 @@ -40,6 +37,9 @@ public struct JarInputStream { @JavaMethod public func skipNBytes(_ arg0: Int64) throws + @JavaMethod + public func closeEntry() throws + @JavaMethod public func reset() throws diff --git a/Sources/JavaKitJar/generated/JarOutputStream.swift b/Sources/JavaKitJar/generated/JarOutputStream.swift index 57a13841..542a784f 100644 --- a/Sources/JavaKitJar/generated/JarOutputStream.swift +++ b/Sources/JavaKitJar/generated/JarOutputStream.swift @@ -4,9 +4,6 @@ import JavaRuntime @JavaClass("java.util.jar.JarOutputStream") public struct JarOutputStream { - @JavaMethod - public func closeEntry() throws - @JavaMethod public func write(_ arg0: [Int8], _ arg1: Int32, _ arg2: Int32) throws @@ -25,6 +22,9 @@ public struct JarOutputStream { @JavaMethod public func setLevel(_ arg0: Int32) + @JavaMethod + public func closeEntry() throws + @JavaMethod public func flush() throws diff --git a/Sources/JavaTypes/JavaType+SwiftNames.swift b/Sources/JavaTypes/JavaType+SwiftNames.swift index 8577640e..e1604eaa 100644 --- a/Sources/JavaTypes/JavaType+SwiftNames.swift +++ b/Sources/JavaTypes/JavaType+SwiftNames.swift @@ -19,12 +19,15 @@ public typealias JavaToSwiftClassNameResolver = (String) throws -> String extension JavaType { /// Whether this Java type needs to be represented by a Swift optional. - public var isSwiftOptional: Bool { + public func isSwiftOptional(stringIsValueType: Bool) -> Bool { switch self { case .boolean, .byte, .char, .short, .int, .long, .float, .double, .void, - .array, .class(package: "java.lang", name: "String"): + .array: return false + case .class(package: "java.lang", name: "String"): + return !stringIsValueType + case .class: return true } @@ -56,7 +59,7 @@ extension JavaType { case .void: return "Void" case .array(let elementType): let elementTypeName = try elementType.swiftTypeName(resolver: resolver) - let elementIsOptional = elementType.isSwiftOptional + let elementIsOptional = elementType.isSwiftOptional(stringIsValueType: true) return "[\(elementTypeName)\(elementIsOptional ? "?" : "")]" case .class: return try resolver(description) diff --git a/Tests/Java2SwiftTests/Java2SwiftTests.swift b/Tests/Java2SwiftTests/Java2SwiftTests.swift index 85240305..80c86fc0 100644 --- a/Tests/Java2SwiftTests/Java2SwiftTests.swift +++ b/Tests/Java2SwiftTests/Java2SwiftTests.swift @@ -63,8 +63,7 @@ class Java2SwiftTests: XCTestCase { JavaClass.self, swiftTypeName: "MyJavaClass", translatedClasses: [ - "java.lang.Object": ("JavaObject", nil, true), - "java.lang.String": ("JavaString", nil, true), + "java.lang.Object": ("JavaObject", nil), ], expectedChunks: [ "import JavaKit", @@ -74,7 +73,7 @@ class Java2SwiftTests: XCTestCase { """, """ @JavaStaticMethod - public func forName(_ arg0: JavaString) throws -> MyJavaClass! where ObjectType == MyJavaClass + public func forName(_ arg0: String) throws -> MyJavaClass! where ObjectType == MyJavaClass """, ] ) @@ -115,13 +114,19 @@ class Java2SwiftTests: XCTestCase { MyArrayList.self, swiftTypeName: "JavaArrayList", translatedClasses: [ - "java.lang.Object": ("JavaObject", nil, true), - "java.util.List": ("JavaList", nil, true), + "java.lang.Object": ("JavaObject", nil), + "java.lang.reflect.Array": ("JavaArray", nil), + "java.util.List": ("JavaList", nil), + "java.util.function.IntFunction": ("MyJavaIntFunction", nil), ], expectedChunks: [ """ @JavaMethod public func subList(_ arg0: Int32, _ arg1: Int32) -> JavaList! + """, + """ + @JavaMethod + public func toArray(_ arg0: MyJavaIntFunction?) -> [JavaObject?] """ ] ) @@ -132,8 +137,8 @@ class Java2SwiftTests: XCTestCase { MyLinkedList.self, swiftTypeName: "JavaLinkedList", translatedClasses: [ - "java.lang.Object": ("JavaObject", nil, true), - "java.util.List": ("JavaList", nil, true), + "java.lang.Object": ("JavaObject", nil), + "java.util.List": ("JavaList", nil), ], expectedChunks: [ """ @@ -149,9 +154,9 @@ class Java2SwiftTests: XCTestCase { ProcessBuilder.self, swiftTypeName: "ProcessBuilder", translatedClasses: [ - "java.lang.ProcessBuilder": ("ProcessBuilder", nil, true), - "java.lang.ProcessBuilder$Redirect": ("ProcessBuilder.Redirect", nil, true), - "java.lang.ProcessBuilder$Redirect$Type": ("ProcessBuilder.Redirect.Type", nil, true), + "java.lang.ProcessBuilder": ("ProcessBuilder", nil), + "java.lang.ProcessBuilder$Redirect": ("ProcessBuilder.Redirect", nil), + "java.lang.ProcessBuilder$Redirect$Type": ("ProcessBuilder.Redirect.Type", nil), ], nestedClasses: [ "java.lang.ProcessBuilder": [JavaClass().as(JavaClass.self)!], @@ -189,9 +194,9 @@ class Java2SwiftTests: XCTestCase { ProcessBuilder.self, swiftTypeName: "ProcessBuilder", translatedClasses: [ - "java.lang.ProcessBuilder": ("ProcessBuilder", nil, true), - "java.lang.ProcessBuilder$Redirect": ("ProcessBuilder.PBRedirect", nil, true), - "java.lang.ProcessBuilder$Redirect$Type": ("ProcessBuilder.PBRedirect.JavaType", nil, true), + "java.lang.ProcessBuilder": ("ProcessBuilder", nil), + "java.lang.ProcessBuilder$Redirect": ("ProcessBuilder.PBRedirect", nil), + "java.lang.ProcessBuilder$Redirect$Type": ("ProcessBuilder.PBRedirect.JavaType", nil), ], nestedClasses: [ "java.lang.ProcessBuilder": [JavaClass().as(JavaClass.self)!], @@ -223,6 +228,44 @@ class Java2SwiftTests: XCTestCase { ] ) } + + func testJavaString() throws { + try assertTranslatedClass( + MyJavaString.self, + swiftTypeName: "JavaString", + expectedChunks: [ + """ + @JavaClass("java.lang.String") + public struct JavaString { + """ + ] + ) + } + + func testJavaObjects() throws { + try assertTranslatedClass( + MyObjects.self, + swiftTypeName: "MyJavaObjects", + translatedClasses: [ + "java.lang.Object" : ("JavaObject", "JavaKit"), + "java.util.function.Supplier" : ("MySupplier", "JavaKitFunction"), + "java.lang.String" : ("JavaString", "JavaKit"), + ], + expectedChunks: [ + """ + import JavaKitFunction + """, + """ + @JavaClass("java.util.Objects", extends: JavaObject.self) + public struct MyJavaObjects { + """, + """ + @JavaStaticMethod + public func requireNonNull(_ arg0: JavaObject?, _ arg1: MySupplier?) -> JavaObject! + """, + ] + ) + } } @JavaClass("java.util.ArrayList") @@ -233,14 +276,28 @@ public struct MyArrayList { public struct MyLinkedList { } +@JavaClass("java.lang.String") +public struct MyJavaString { +} + +@JavaClass("java.util.Objects") +public struct MyObjects { } + +@JavaInterface("java.util.function.Supplier") +public struct MySupplier { } + +@JavaInterface("java.util.function.IntFunction") +public struct MyJavaIntFunction { +} + /// Translate a Java class and assert that the translated output contains /// each of the expected "chunks" of text. func assertTranslatedClass( _ javaType: JavaClassType.Type, swiftTypeName: String, translatedClasses: [ - String: (swiftType: String, swiftModule: String?, isOptional: Bool) - ] = JavaTranslator.defaultTranslatedClasses, + String: (swiftType: String, swiftModule: String?) + ] = [:], nestedClasses: [String: [JavaClass]] = [:], expectedChunks: [String], file: StaticString = #filePath, @@ -253,7 +310,7 @@ func assertTranslatedClass( ) translator.translatedClasses = translatedClasses - translator.translatedClasses[javaType.fullJavaClassName] = (swiftTypeName, nil, true) + translator.translatedClasses[javaType.fullJavaClassName] = (swiftTypeName, nil) translator.nestedClasses = nestedClasses translator.startNewFile() let translatedDecls = try translator.translateClass(