@@ -28,11 +28,20 @@ package class JavaTranslator {
2828 let environment : JNIEnvironment
2929 let format : BasicFormat
3030
31- /// A mapping from the canonical name of Java classes to the corresponding
32- /// Swift type name, its Swift module, and whether we need to be working
33- /// with optionals.
34- package var translatedClasses : [ String : ( swiftType: String , swiftModule: String ? , isOptional: Bool ) ] =
35- defaultTranslatedClasses
31+ /// A mapping from the name of each known Java class to the corresponding
32+ /// Swift type name and its Swift module.
33+ package var translatedClasses : [ String : ( swiftType: String , swiftModule: String ? ) ] = [ : ]
34+
35+ /// A mapping from the name of each known Java class with the Swift value type
36+ /// (and its module) to which it is mapped.
37+ ///
38+ /// The Java classes here can also be part of `translatedClasses`. The entry in
39+ /// `translatedClasses` should map to a representation of the Java class (i.e.,
40+ /// an AnyJavaObject-conforming type) whereas the entry here should map to
41+ /// a value type.
42+ package let translatedToValueTypes : [ String : ( swiftType: String , swiftModule: String ) ] = [
43+ " java.lang.String " : ( " String " , " JavaKit " ) ,
44+ ]
3645
3746 /// The set of Swift modules that need to be imported to make the generated
3847 /// code compile. Use `getImportDecls()` to format this into a list of
@@ -80,13 +89,6 @@ extension JavaTranslator {
8089 " JavaKit " ,
8190 " JavaRuntime " ,
8291 ]
83-
84- /// The default set of translated classes that do not come from JavaKit
85- /// itself. This should only be used to refer to types that are built-in to
86- /// JavaKit and therefore aren't captured in any configuration file.
87- package static let defaultTranslatedClasses : [ String : ( swiftType: String , swiftModule: String ? , isOptional: Bool ) ] = [
88- " java.lang.String " : ( " String " , " JavaKit " , false ) ,
89- ]
9092}
9193
9294// MARK: Import translation
@@ -104,13 +106,21 @@ extension JavaTranslator {
104106// MARK: Type translation
105107extension JavaTranslator {
106108 /// Turn a Java type into a string.
107- func getSwiftTypeNameAsString( _ javaType: Type , outerOptional: OptionalKind ) throws -> String {
109+ func getSwiftTypeNameAsString(
110+ _ javaType: Type ,
111+ preferValueTypes: Bool ,
112+ outerOptional: OptionalKind
113+ ) throws -> String {
108114 // Replace type variables with their bounds.
109115 if let typeVariable = javaType. as ( TypeVariable< GenericDeclaration> . self ) ,
110116 typeVariable. getBounds ( ) . count == 1 ,
111117 let bound = typeVariable. getBounds ( ) [ 0 ]
112118 {
113- return try getSwiftTypeNameAsString ( bound, outerOptional: outerOptional)
119+ return try getSwiftTypeNameAsString (
120+ bound,
121+ preferValueTypes: preferValueTypes,
122+ outerOptional: outerOptional
123+ )
114124 }
115125
116126 // Replace wildcards with their upper bound.
@@ -119,21 +129,42 @@ extension JavaTranslator {
119129 let bound = wildcardType. getUpperBounds ( ) [ 0 ]
120130 {
121131 // Replace a wildcard type with its first bound.
122- return try getSwiftTypeNameAsString ( bound, outerOptional: outerOptional)
132+ return try getSwiftTypeNameAsString (
133+ bound,
134+ preferValueTypes: preferValueTypes,
135+ outerOptional: outerOptional
136+ )
123137 }
124138
125139 // Handle array types by recursing into the component type.
126140 if let arrayType = javaType. as ( GenericArrayType . self) {
127- let elementType = try getSwiftTypeNameAsString ( arrayType. getGenericComponentType ( ) !, outerOptional: . optional)
128- return " [ \( elementType) ] "
141+ if preferValueTypes {
142+ let elementType = try getSwiftTypeNameAsString (
143+ arrayType. getGenericComponentType ( ) !,
144+ preferValueTypes: preferValueTypes,
145+ outerOptional: . optional
146+ )
147+ return " [ \( elementType) ] "
148+ }
149+
150+ let ( swiftName, _) = try getSwiftTypeName (
151+ JavaClass < JavaArray > ( ) . as ( JavaClass< JavaObject> . self ) !,
152+ preferValueTypes: false
153+ )
154+
155+ return outerOptional. adjustTypeName ( swiftName)
129156 }
130157
131158 // Handle parameterized types by recursing on the raw type and the type
132159 // arguments.
133160 if let parameterizedType = javaType. as ( ParameterizedType . self) ,
134161 let rawJavaType = parameterizedType. getRawType ( )
135162 {
136- var rawSwiftType = try getSwiftTypeNameAsString ( rawJavaType, outerOptional: outerOptional)
163+ var rawSwiftType = try getSwiftTypeNameAsString (
164+ rawJavaType,
165+ preferValueTypes: false ,
166+ outerOptional: outerOptional
167+ )
137168
138169 let optionalSuffix : String
139170 if let lastChar = rawSwiftType. last, lastChar == " ? " || lastChar == " ! " {
@@ -145,7 +176,7 @@ extension JavaTranslator {
145176
146177 let typeArguments = try parameterizedType. getActualTypeArguments ( ) . compactMap { typeArg in
147178 try typeArg. map { typeArg in
148- try getSwiftTypeNameAsString ( typeArg, outerOptional: . nonoptional)
179+ try getSwiftTypeNameAsString ( typeArg, preferValueTypes : false , outerOptional: . nonoptional)
149180 }
150181 }
151182
@@ -157,38 +188,50 @@ extension JavaTranslator {
157188 throw TranslationError . unhandledJavaType ( javaType)
158189 }
159190
160- let ( swiftName, isOptional) = try getSwiftTypeName ( javaClass)
191+ let ( swiftName, isOptional) = try getSwiftTypeName ( javaClass, preferValueTypes : preferValueTypes )
161192 var resultString = swiftName
162193 if isOptional {
163- switch outerOptional {
164- case . implicitlyUnwrappedOptional:
165- resultString += " ! "
166- case . optional:
167- resultString += " ? "
168- case . nonoptional:
169- break
170- }
194+ resultString = outerOptional. adjustTypeName ( resultString)
171195 }
172196 return resultString
173197 }
174198
175199 /// Translate a Java class into its corresponding Swift type name.
176- package func getSwiftTypeName( _ javaClass: JavaClass < JavaObject > ) throws -> ( swiftName: String , isOptional: Bool ) {
200+ package func getSwiftTypeName(
201+ _ javaClass: JavaClass < JavaObject > ,
202+ preferValueTypes: Bool
203+ ) throws -> ( swiftName: String , isOptional: Bool ) {
177204 let javaType = try JavaType ( javaTypeName: javaClass. getName ( ) )
178- let isSwiftOptional = javaType. isSwiftOptional
179- return (
180- try javaType. swiftTypeName { javaClassName in
181- try self . getSwiftTypeNameFromJavaClassName ( javaClassName)
182- } ,
183- isSwiftOptional
184- )
205+ let isSwiftOptional = javaType. isSwiftOptional ( stringIsValueType: preferValueTypes)
206+
207+ let swiftTypeName : String
208+ if !preferValueTypes, case . array( _) = javaType {
209+ swiftTypeName = try self . getSwiftTypeNameFromJavaClassName ( " java.lang.reflect.Array " , preferValueTypes: false )
210+ } else {
211+ swiftTypeName = try javaType. swiftTypeName { javaClassName in
212+ try self . getSwiftTypeNameFromJavaClassName ( javaClassName, preferValueTypes: preferValueTypes)
213+ }
214+ }
215+
216+ return ( swiftTypeName, isSwiftOptional)
185217 }
186218
187219 /// Map a Java class name to its corresponding Swift type.
188220 func getSwiftTypeNameFromJavaClassName(
189221 _ name: String ,
222+ preferValueTypes: Bool ,
190223 escapeMemberNames: Bool = true
191224 ) throws -> String {
225+ // If we want a value type, look for one.
226+ if preferValueTypes, let translatedValueType = translatedToValueTypes [ name] {
227+ // Note that we need to import this Swift module.
228+ if translatedValueType. swiftModule != swiftModuleName {
229+ importedSwiftModules. insert ( translatedValueType. swiftModule)
230+ }
231+
232+ return translatedValueType. swiftType
233+ }
234+
192235 if let translated = translatedClasses [ name] {
193236 // Note that we need to import this Swift module.
194237 if let swiftModule = translated. swiftModule, swiftModule != swiftModuleName {
0 commit comments