@@ -28,11 +28,20 @@ package class JavaTranslator {
28
28
let environment : JNIEnvironment
29
29
let format : BasicFormat
30
30
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
+ ]
36
45
37
46
/// The set of Swift modules that need to be imported to make the generated
38
47
/// code compile. Use `getImportDecls()` to format this into a list of
@@ -80,13 +89,6 @@ extension JavaTranslator {
80
89
" JavaKit " ,
81
90
" JavaRuntime " ,
82
91
]
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
- ]
90
92
}
91
93
92
94
// MARK: Import translation
@@ -104,13 +106,21 @@ extension JavaTranslator {
104
106
// MARK: Type translation
105
107
extension JavaTranslator {
106
108
/// 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 {
108
114
// Replace type variables with their bounds.
109
115
if let typeVariable = javaType. as ( TypeVariable< GenericDeclaration> . self ) ,
110
116
typeVariable. getBounds ( ) . count == 1 ,
111
117
let bound = typeVariable. getBounds ( ) [ 0 ]
112
118
{
113
- return try getSwiftTypeNameAsString ( bound, outerOptional: outerOptional)
119
+ return try getSwiftTypeNameAsString (
120
+ bound,
121
+ preferValueTypes: preferValueTypes,
122
+ outerOptional: outerOptional
123
+ )
114
124
}
115
125
116
126
// Replace wildcards with their upper bound.
@@ -119,21 +129,42 @@ extension JavaTranslator {
119
129
let bound = wildcardType. getUpperBounds ( ) [ 0 ]
120
130
{
121
131
// 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
+ )
123
137
}
124
138
125
139
// Handle array types by recursing into the component type.
126
140
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)
129
156
}
130
157
131
158
// Handle parameterized types by recursing on the raw type and the type
132
159
// arguments.
133
160
if let parameterizedType = javaType. as ( ParameterizedType . self) ,
134
161
let rawJavaType = parameterizedType. getRawType ( )
135
162
{
136
- var rawSwiftType = try getSwiftTypeNameAsString ( rawJavaType, outerOptional: outerOptional)
163
+ var rawSwiftType = try getSwiftTypeNameAsString (
164
+ rawJavaType,
165
+ preferValueTypes: false ,
166
+ outerOptional: outerOptional
167
+ )
137
168
138
169
let optionalSuffix : String
139
170
if let lastChar = rawSwiftType. last, lastChar == " ? " || lastChar == " ! " {
@@ -145,7 +176,7 @@ extension JavaTranslator {
145
176
146
177
let typeArguments = try parameterizedType. getActualTypeArguments ( ) . compactMap { typeArg in
147
178
try typeArg. map { typeArg in
148
- try getSwiftTypeNameAsString ( typeArg, outerOptional: . nonoptional)
179
+ try getSwiftTypeNameAsString ( typeArg, preferValueTypes : false , outerOptional: . nonoptional)
149
180
}
150
181
}
151
182
@@ -157,38 +188,50 @@ extension JavaTranslator {
157
188
throw TranslationError . unhandledJavaType ( javaType)
158
189
}
159
190
160
- let ( swiftName, isOptional) = try getSwiftTypeName ( javaClass)
191
+ let ( swiftName, isOptional) = try getSwiftTypeName ( javaClass, preferValueTypes : preferValueTypes )
161
192
var resultString = swiftName
162
193
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)
171
195
}
172
196
return resultString
173
197
}
174
198
175
199
/// 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 ) {
177
204
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)
185
217
}
186
218
187
219
/// Map a Java class name to its corresponding Swift type.
188
220
func getSwiftTypeNameFromJavaClassName(
189
221
_ name: String ,
222
+ preferValueTypes: Bool ,
190
223
escapeMemberNames: Bool = true
191
224
) 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
+
192
235
if let translated = translatedClasses [ name] {
193
236
// Note that we need to import this Swift module.
194
237
if let swiftModule = translated. swiftModule, swiftModule != swiftModuleName {
0 commit comments