@@ -312,7 +312,7 @@ extension JavaClassTranslator {
312312 // Render all of the instance methods in Swift.
313313 let instanceMethods = methods. methods. compactMap { method in
314314 do {
315- return try renderMethod ( method, implementedInSwift: false )
315+ return try renderMethod ( method, implementedInSwift: false , renderFailureAsBestEffortUnavailableDecl : true )
316316 } catch {
317317 translator. logUntranslated ( " Unable to translate ' \( javaClass. getName ( ) ) ' method ' \( method. getName ( ) ) ': \( error) " )
318318 return nil
@@ -461,7 +461,8 @@ extension JavaClassTranslator {
461461 do {
462462 return try renderMethod (
463463 method,
464- implementedInSwift: true
464+ implementedInSwift: true ,
465+
465466 )
466467 } catch {
467468 translator. logUntranslated ( " Unable to translate ' \( javaClass. getName ( ) ) ' method ' \( method. getName ( ) ) ': \( error) " )
@@ -517,14 +518,20 @@ extension JavaClassTranslator {
517518 package func renderConstructor(
518519 _ javaConstructor: Constructor < some AnyJavaObject >
519520 ) throws -> DeclSyntax {
520- let parameters = try translateParameters ( javaConstructor. getParameters ( ) ) + [ " environment: JNIEnvironment? = nil " ]
521+ var errors = TranslationErrorCollector ( bestEffortRecover: false )
522+
523+ let parameters = try translateParameters ( javaConstructor. getParameters ( ) , translationErrors: & errors) + [ " environment: JNIEnvironment? = nil " ]
521524 let parametersStr = parameters. map { $0. description } . joined ( separator: " , " )
522525 let throwsStr = javaConstructor. throwsCheckedException ? " throws " : " "
523526 let accessModifier = javaConstructor. isPublic ? " public " : " "
524527 let convenienceModifier = translateAsClass ? " convenience " : " "
525528 let nonoverrideAttribute = translateAsClass ? " @_nonoverride " : " "
526529 return """
530+ /**
531+ \(raw: errors.doccCommentsText)
532+ */
527533 @JavaMethod
534+ \( raw: errors. unavailableDueToImportErrorsText)
528535 \( raw: nonoverrideAttribute) \( raw: accessModifier) \( raw: convenienceModifier) init( \( raw: parametersStr) ) \( raw: throwsStr)
529536 """
530537 }
@@ -534,10 +541,13 @@ extension JavaClassTranslator {
534541 _ javaMethod: Method ,
535542 implementedInSwift: Bool ,
536543 genericParameterClause: String = " " ,
537- whereClause: String = " "
544+ whereClause: String = " " ,
545+ renderFailureAsBestEffortUnavailableDecl: Bool = false
538546 ) throws -> DeclSyntax {
547+ var errors = TranslationErrorCollector ( bestEffortRecover: renderFailureAsBestEffortUnavailableDecl)
548+
539549 // Map the parameters.
540- let parameters = try translateParameters ( javaMethod. getParameters ( ) )
550+ let parameters = try translateParameters ( javaMethod. getParameters ( ) , translationErrors : & errors )
541551
542552 let parametersStr = parameters. map { $0. description } . joined ( separator: " , " )
543553
@@ -589,6 +599,8 @@ extension JavaClassTranslator {
589599
590600
591601 return """
602+ \( raw: errors. doccCommentsText)
603+ \( raw: errors. unavailableDueToImportErrorsText)
592604 \( methodAttribute) \( raw: accessModifier) \( raw: overrideOpt) func \( raw: swiftMethodName) \( raw: genericParameterClause) ( \( raw: parametersStr) ) \( raw: throwsStr) \( raw: resultTypeStr) \( raw: whereClause)
593605
594606 \( raw: accessModifier) \( raw: overrideOpt) func \( raw: swiftMethodName) Optional \( raw: genericParameterClause) ( \( raw: parameters. map ( \. clause. description) . joined ( separator: " , " ) ) ) \( raw: throwsStr) -> \( raw: resultOptional) \( raw: whereClause) {
@@ -597,6 +609,8 @@ extension JavaClassTranslator {
597609 """
598610 } else {
599611 return """
612+ \( raw: errors. doccCommentsText)
613+ \( raw: errors. unavailableDueToImportErrorsText)
600614 \( methodAttribute) \( raw: accessModifier) \( raw: overrideOpt) func \( raw: swiftMethodName) \( raw: genericParameterClause) ( \( raw: parametersStr) ) \( raw: throwsStr) \( raw: resultTypeStr) \( raw: whereClause)
601615 """
602616 }
@@ -700,21 +714,63 @@ extension JavaClassTranslator {
700714 }
701715
702716 // Translate a Java parameter list into Swift parameters.
703- private func translateParameters( _ parameters: [ Parameter ? ] ) throws -> [ FunctionParameterSyntax ] {
704- return try parameters. compactMap { javaParameter in
717+ private func translateParameters( _ parameters: [ Parameter ? ] , translationErrors : inout TranslationErrorCollector ) throws -> [ FunctionParameterSyntax ] {
718+ return try parameters. compactMap { ( javaParameter) -> ( FunctionParameterSyntax ? ) in
705719 guard let javaParameter else { return nil }
706720
707- let typeName = try translator. getSwiftTypeNameAsString (
708- javaParameter. getParameterizedType ( ) !,
709- preferValueTypes: true ,
710- outerOptional: . optional
711- )
721+ let typeName : String
722+ do {
723+ typeName = try translator. getSwiftTypeNameAsString (
724+ javaParameter. getParameterizedType ( ) !,
725+ preferValueTypes: true ,
726+ outerOptional: . optional
727+ )
728+ } catch {
729+ translationErrors. record ( " Failed to convert parameter ' \( javaParameter. getName ( ) ) ' type ' \( javaParameter. getParameterizedType ( ) !) to Swift' " )
730+ typeName = " SwiftJavaFailedImportType " // best-effort placeholder
731+ }
712732 let paramName = javaParameter. getName ( )
713733 return " _ \( raw: paramName) : \( raw: typeName) "
714734 }
715735 }
716736}
717737
738+ package struct TranslationErrorCollector {
739+ package let bestEffortRecover : Bool
740+ private var errors : [ String ] = [ ]
741+
742+ package var doccCommentsText : String {
743+ guard errors. count > 0 else {
744+ return " "
745+ }
746+
747+ return """
748+ ///
749+ /// ### Swift-Java import errors
750+ ///
751+ /// * \( errors. joined ( separator: " \n /// * " ) )
752+ """
753+ }
754+
755+ package var unavailableDueToImportErrorsText : String {
756+ guard errors. count > 0 else {
757+ return " "
758+ }
759+
760+ return """
761+ @available(*, unavailable, message: " swift-java was unable to import this method. See doc comments for import error details. " )
762+ """
763+ }
764+
765+ mutating func record( _ errorMessage: String ) {
766+ errors. append ( errorMessage)
767+ }
768+
769+ package init ( bestEffortRecover: Bool ) {
770+ self . bestEffortRecover = bestEffortRecover
771+ }
772+ }
773+
718774/// Helper struct that collects methods, removing any that have been overridden
719775/// by a covariant method.
720776struct MethodCollector {
0 commit comments