diff --git a/Package.swift b/Package.swift index cba5115c3..14bd36aea 100644 --- a/Package.swift +++ b/Package.swift @@ -384,7 +384,6 @@ let package = Package( .product(name: "SwiftParser", package: "swift-syntax"), .product(name: "SwiftSyntax", package: "swift-syntax"), .product(name: "SwiftSyntaxBuilder", package: "swift-syntax"), - .product(name: "Logging", package: "swift-log"), "SwiftExtractConfigurationShared", ], path: "Sources/SwiftExtract", diff --git a/Sources/JExtractSwiftLib/Configuration+SwiftExtract.swift b/Sources/JExtractSwiftLib/Configuration+SwiftExtract.swift index 1435a62ab..9de57f21a 100644 --- a/Sources/JExtractSwiftLib/Configuration+SwiftExtract.swift +++ b/Sources/JExtractSwiftLib/Configuration+SwiftExtract.swift @@ -22,4 +22,8 @@ import SwiftJavaConfigurationShared /// protocol extension on `SwiftExtractConfiguration` defaults /// `availableImportModules` and `allowUnresolvedTypeReferences`, so this /// conformance is empty. -extension Configuration: SwiftExtractConfiguration {} +extension Configuration: SwiftExtractConfiguration { + public var unresolvedTypeHint: String? { + "If the unresolved type lives in another Swift module, declare it as a SwiftPM target dependency with its own swift-java.config (the JExtractSwiftPlugin wires --depends-on automatically), or pass --depends-on = explicitly." + } +} diff --git a/Sources/JExtractSwiftLib/Convenience/String+JavaNaming.swift b/Sources/JExtractSwiftLib/Convenience/String+JavaNaming.swift index d069a8c4a..6363dbf19 100644 --- a/Sources/JExtractSwiftLib/Convenience/String+JavaNaming.swift +++ b/Sources/JExtractSwiftLib/Convenience/String+JavaNaming.swift @@ -14,6 +14,11 @@ import SwiftExtract +extension SwiftQualifiedTypeName { + /// Dollar-separated for JNI C symbol parent names, e.g. "Logger$Message" + package var jniEscapedName: String { components.joined(separator: "$") } +} + extension String { /// Returns whether the string is of the format `isX` (Java Beans boolean /// property naming convention) diff --git a/Sources/SwiftExtract/SwiftAnalysisVisitor.swift b/Sources/SwiftExtract/SwiftAnalysisVisitor.swift index 773ba9662..571dbe6ee 100644 --- a/Sources/SwiftExtract/SwiftAnalysisVisitor.swift +++ b/Sources/SwiftExtract/SwiftAnalysisVisitor.swift @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// import Foundation -import Logging import SwiftIfConfig import SwiftParser import SwiftSyntax @@ -207,7 +206,7 @@ final class SwiftAnalysisVisitor { ) } catch { self.log.warning( - Self.makeMissingTypeMessage( + self.makeMissingTypeMessage( "Failed to import: '\(node.qualifiedNameForDebug)' in module '\(analyzer.swiftModuleName)'; \(error)" ) ) @@ -281,7 +280,7 @@ final class SwiftAnalysisVisitor { } } catch { self.log.warning( - Self.makeMissingTypeMessage( + self.makeMissingTypeMessage( "Failed to import: \(node.qualifiedNameForDebug) in module '\(analyzer.swiftModuleName)'; \(error)" ) ) @@ -328,7 +327,7 @@ final class SwiftAnalysisVisitor { } } catch { self.log.warning( - Self.makeMissingTypeMessage( + self.makeMissingTypeMessage( "Failed to import: \(node.qualifiedNameForDebug) in module '\(analyzer.swiftModuleName)'; \(error)" ) ) @@ -358,7 +357,7 @@ final class SwiftAnalysisVisitor { ) } catch { self.log.warning( - Self.makeMissingTypeMessage( + self.makeMissingTypeMessage( "Failed to import: \(node.qualifiedNameForDebug) in module '\(analyzer.swiftModuleName)'; \(error)" ) ) @@ -409,7 +408,7 @@ final class SwiftAnalysisVisitor { } } catch { self.log.warning( - Self.makeMissingTypeMessage( + self.makeMissingTypeMessage( "Failed to import: \(node.qualifiedNameForDebug) in module '\(analyzer.swiftModuleName)'; \(error)" ) ) @@ -720,8 +719,11 @@ final class SwiftAnalysisVisitor { return true } - static func makeMissingTypeMessage(_ message: String) -> String { - "\(message). If the unresolved type lives in another Swift module, declare it as a SwiftPM target dependency with its own swift-java.config (the JExtractSwiftPlugin wires --depends-on automatically), or pass --depends-on = explicitly." + func makeMissingTypeMessage(_ message: String) -> String { + guard let hint = config.unresolvedTypeHint else { + return message + } + return "\(message). \(hint)" } } diff --git a/Sources/SwiftExtract/SwiftAnalyzer.swift b/Sources/SwiftExtract/SwiftAnalyzer.swift index c50e9401d..f43d3d4e8 100644 --- a/Sources/SwiftExtract/SwiftAnalyzer.swift +++ b/Sources/SwiftExtract/SwiftAnalyzer.swift @@ -13,7 +13,6 @@ //===----------------------------------------------------------------------===// import Foundation -import Logging import SwiftIfConfig import SwiftParser import SwiftSyntax diff --git a/Sources/SwiftExtract/SwiftExtractConfiguration.swift b/Sources/SwiftExtract/SwiftExtractConfiguration.swift index 6ff68c9d6..fa82c43c5 100644 --- a/Sources/SwiftExtract/SwiftExtractConfiguration.swift +++ b/Sources/SwiftExtract/SwiftExtractConfiguration.swift @@ -59,6 +59,11 @@ public protocol SwiftExtractConfiguration { /// generator can declare its runtime module importable here). Default: empty. var availableImportModules: Set { get } + /// Consumer-specific guidance appended to "unresolved type" log messages, + /// e.g. pointing the user at the consumer's mechanism for declaring + /// cross-module dependencies. `nil` appends nothing. + var unresolvedTypeHint: String? { get } + /// Whether type lookups that can't resolve a name should fall back to a /// synthetic, unresolved nominal reference instead of throwing /// `TypeTranslationError.unknown`. @@ -88,6 +93,8 @@ extension SwiftExtractConfiguration { public var allowUnresolvedTypeReferences: Bool { false } + public var unresolvedTypeHint: String? { nil } + public func hasImportedModuleStub(moduleOfNominal moduleName: String) -> Bool { importedModuleStubs?.keys.contains(moduleName) ?? false } diff --git a/Sources/SwiftExtract/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift b/Sources/SwiftExtract/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift index 0887cea90..08bc4e146 100644 --- a/Sources/SwiftExtract/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift +++ b/Sources/SwiftExtract/SwiftTypes/SwiftParsedModuleSymbolTableBuilder.swift @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// -import Logging import SwiftIfConfig import SwiftSyntax diff --git a/Sources/SwiftExtract/SwiftTypes/SwiftQualifiedTypeName.swift b/Sources/SwiftExtract/SwiftTypes/SwiftQualifiedTypeName.swift index 71cf956ca..81a5c4419 100644 --- a/Sources/SwiftExtract/SwiftTypes/SwiftQualifiedTypeName.swift +++ b/Sources/SwiftExtract/SwiftTypes/SwiftQualifiedTypeName.swift @@ -40,9 +40,6 @@ public struct SwiftQualifiedTypeName: Hashable, Sendable, CustomStringConvertibl /// Underscore-separated for C symbols and Java identifiers, e.g. "Logger_Message" public var fullFlatName: String { components.joined(separator: "_") } - /// Dollar-separated for JNI C symbol parent names, e.g. "Logger$Message" - public var jniEscapedName: String { components.joined(separator: "$") } - /// CustomStringConvertible - uses fullName public var description: String { fullName } diff --git a/Sources/SwiftExtract/SwiftTypes/SwiftSymbolTable.swift b/Sources/SwiftExtract/SwiftTypes/SwiftSymbolTable.swift index 45557b7ac..d29271b69 100644 --- a/Sources/SwiftExtract/SwiftTypes/SwiftSymbolTable.swift +++ b/Sources/SwiftExtract/SwiftTypes/SwiftSymbolTable.swift @@ -12,7 +12,6 @@ // //===----------------------------------------------------------------------===// -import Logging import SwiftIfConfig import SwiftParser import SwiftSyntax