@@ -201,7 +201,7 @@ struct JavaToSwift: ParsableCommand {
201
201
// Add the configuration for this module.
202
202
translator. addConfiguration ( config, forSwiftModule: moduleName)
203
203
204
- // Load all of the requested classes.
204
+ // Load all of the explicitly- requested classes.
205
205
let classLoader = try JavaClass < ClassLoader > ( environment: environment)
206
206
. getSystemClassLoader ( ) !
207
207
var javaClasses : [ JavaClass < JavaObject > ] = [ ]
@@ -211,29 +211,50 @@ struct JavaToSwift: ParsableCommand {
211
211
continue
212
212
}
213
213
214
+ // Add this class to the list of classes we'll translate.
214
215
javaClasses. append ( javaClass)
216
+ }
217
+
218
+ // Find all of the nested classes for each class, adding them to the list
219
+ // of classes to be translated if they were already specified.
220
+ var allClassesToVisit = javaClasses
221
+ var currentClassIndex : Int = 0
222
+ while currentClassIndex < allClassesToVisit. count {
223
+ defer {
224
+ currentClassIndex += 1
225
+ }
226
+
227
+ // Find all of the nested classes that weren't explicitly translated
228
+ // already.
229
+ let currentClass = allClassesToVisit [ currentClassIndex]
230
+ let nestedClasses : [ JavaClass < JavaObject > ] = currentClass. getClasses ( ) . compactMap { nestedClass in
231
+ guard let nestedClass else { return nil }
232
+
233
+ // If this is a local class, we're done.
234
+ let javaClassName = nestedClass. getName ( )
235
+ if javaClassName. isLocalJavaClass {
236
+ return nil
237
+ }
215
238
216
- // Replace any $'s within the Java class name (which separate nested
217
- // classes) with .'s (which represent nesting in Swift).
218
- let translatedSwiftName = swiftName. replacing ( " $ " , with: " . " )
219
-
220
- // Note that we will be translating this Java class, so it is a known class.
221
- translator. translatedClasses [ javaClassName] = ( translatedSwiftName, nil , true )
222
-
223
- var classes : [ JavaClass < JavaObject > ? ] = javaClass. getClasses ( )
224
-
225
- // Go through all subclasses to find all of the classes to translate
226
- while let internalClass = classes. popLast ( ) {
227
- if let internalClass {
228
- let ( javaName, swiftName) = names ( from: internalClass. getName ( ) )
229
- // If we have already been through this class, don't go through it again
230
- guard translator. translatedClasses [ javaName] == nil else { continue }
231
- let currentClassName = swiftName
232
- let currentSanitizedClassName = currentClassName. replacing ( " $ " , with: " . " )
233
- classes. append ( contentsOf: internalClass. getClasses ( ) )
234
- translator. translatedClasses [ javaName] = ( currentSanitizedClassName, nil , true )
239
+ // If this class has been explicitly mentioned, we're done.
240
+ if translator. translatedClasses [ javaClassName] != nil {
241
+ return nil
235
242
}
243
+
244
+ // Record this as a translated class.
245
+ let swiftName = javaClassName. defaultSwiftNameForJavaClass
246
+ translator. translatedClasses [ javaClassName] = ( swiftName, nil , true )
247
+ return nestedClass
236
248
}
249
+
250
+ // If there were no new nested classes, there's nothing to do.
251
+ if nestedClasses. isEmpty {
252
+ continue
253
+ }
254
+
255
+ // Record all of the nested classes that we will visit.
256
+ translator. nestedClasses [ currentClass. getName ( ) ] = nestedClasses
257
+ allClassesToVisit. append ( contentsOf: nestedClasses)
237
258
}
238
259
239
260
// Translate all of the Java classes into Swift classes.
@@ -276,7 +297,7 @@ struct JavaToSwift: ParsableCommand {
276
297
javaClassName = javaClassNameOpt
277
298
}
278
299
279
- return ( javaClassName, swiftName)
300
+ return ( javaClassName, swiftName. javaClassNameToCanonicalName )
280
301
}
281
302
282
303
mutating func writeContents( _ contents: String , to filename: String , description: String ) throws {
@@ -317,12 +338,9 @@ struct JavaToSwift: ParsableCommand {
317
338
continue
318
339
}
319
340
320
- // If any of the segments of the Java name start with a number, it's a
321
- // local class that cannot be mapped into Swift.
322
- for segment in entry. getName ( ) . split ( separator: " $ " ) {
323
- if let firstChar = segment. first, firstChar. isNumber {
324
- continue
325
- }
341
+ // If this is a local class, it cannot be mapped into Swift.
342
+ if entry. getName ( ) . isLocalJavaClass {
343
+ continue
326
344
}
327
345
328
346
let javaCanonicalName = String ( entry. getName ( ) . replacing ( " / " , with: " . " )
@@ -365,10 +383,10 @@ extension String {
365
383
fileprivate var defaultSwiftNameForJavaClass : String {
366
384
if let dotLoc = lastIndex ( of: " . " ) {
367
385
let afterDot = index ( after: dotLoc)
368
- return String ( self [ afterDot... ] )
386
+ return String ( self [ afterDot... ] ) . javaClassNameToCanonicalName
369
387
}
370
388
371
- return self
389
+ return javaClassNameToCanonicalName
372
390
}
373
391
}
374
392
@@ -382,3 +400,22 @@ extension JavaClass<ClassLoader> {
382
400
@JavaStaticMethod
383
401
public func getSystemClassLoader( ) -> ClassLoader ?
384
402
}
403
+
404
+ extension String {
405
+ /// Replace all of the $'s for nested names with "." to turn a Java class
406
+ /// name into a Java canonical class name,
407
+ fileprivate var javaClassNameToCanonicalName : String {
408
+ return replacing ( " $ " , with: " . " )
409
+ }
410
+
411
+ /// Whether this is the name of an anonymous class.
412
+ fileprivate var isLocalJavaClass : Bool {
413
+ for segment in split ( separator: " $ " ) {
414
+ if let firstChar = segment. first, firstChar. isNumber {
415
+ return true
416
+ }
417
+ }
418
+
419
+ return false
420
+ }
421
+ }
0 commit comments