diff --git a/Sources/SwiftCompilerPlugin/CompilerPlugin.swift b/Sources/SwiftCompilerPlugin/CompilerPlugin.swift index 23a2b22cdb2..69766b44c73 100644 --- a/Sources/SwiftCompilerPlugin/CompilerPlugin.swift +++ b/Sources/SwiftCompilerPlugin/CompilerPlugin.swift @@ -63,7 +63,8 @@ public protocol CompilerPlugin { } extension CompilerPlugin { - func resolveMacro(moduleName: String, typeName: String) -> Macro.Type? { + @_spi(Testing) + public func resolveMacro(moduleName: String, typeName: String) throws -> Macro.Type { let qualifedName = "\(moduleName).\(typeName)" for type in providingMacros { @@ -74,12 +75,9 @@ extension CompilerPlugin { return type } } - return nil - } - // @testable - public func _resolveMacro(moduleName: String, typeName: String) -> Macro.Type? { - resolveMacro(moduleName: moduleName, typeName: typeName) + let pluginPath = CommandLine.arguments.first ?? Bundle.main.executablePath ?? ProcessInfo.processInfo.processName + throw CompilerPluginError(message: "macro implementation type '\(moduleName).\(typeName)' could not be found in executable plugin '\(pluginPath)'") } } @@ -88,8 +86,8 @@ struct MacroProviderAdapter: PluginProvider { init(plugin: Plugin) { self.plugin = plugin } - func resolveMacro(moduleName: String, typeName: String) -> Macro.Type? { - plugin.resolveMacro(moduleName: moduleName, typeName: typeName) + func resolveMacro(moduleName: String, typeName: String) throws -> Macro.Type { + try plugin.resolveMacro(moduleName: moduleName, typeName: typeName) } } @@ -242,3 +240,10 @@ private extension FileHandle { } } } + +struct CompilerPluginError: Error, CustomStringConvertible { + var description: String + init(message: String) { + self.description = message + } +} diff --git a/Sources/SwiftCompilerPluginMessageHandling/CompilerPluginMessageHandler.swift b/Sources/SwiftCompilerPluginMessageHandling/CompilerPluginMessageHandler.swift index a7bca3ebf53..dd836a2f73c 100644 --- a/Sources/SwiftCompilerPluginMessageHandling/CompilerPluginMessageHandler.swift +++ b/Sources/SwiftCompilerPluginMessageHandling/CompilerPluginMessageHandler.swift @@ -20,7 +20,7 @@ public enum PluginFeature: String { /// A type that provides the actual plugin functions. public protocol PluginProvider { /// Resolve macro type by the module name and the type name. - func resolveMacro(moduleName: String, typeName: String) -> Macro.Type? + func resolveMacro(moduleName: String, typeName: String) throws -> Macro.Type /// Load dynamic link library at `libraryPath`. Implementations can use /// `moduleName` to associate the loaded library with it. diff --git a/Sources/SwiftCompilerPluginMessageHandling/Macros.swift b/Sources/SwiftCompilerPluginMessageHandling/Macros.swift index 5d65f8899df..1f9b13b5153 100644 --- a/Sources/SwiftCompilerPluginMessageHandling/Macros.swift +++ b/Sources/SwiftCompilerPluginMessageHandling/Macros.swift @@ -19,8 +19,8 @@ import SwiftSyntaxMacros extension CompilerPluginMessageHandler { /// Get concrete macro type from a pair of module name and type name. - private func resolveMacro(_ ref: PluginMessage.MacroReference) -> Macro.Type? { - provider.resolveMacro(moduleName: ref.moduleName, typeName: ref.typeName) + private func resolveMacro(_ ref: PluginMessage.MacroReference) throws -> Macro.Type { + try provider.resolveMacro(moduleName: ref.moduleName, typeName: ref.typeName) } /// Expand `@freestainding(XXX)` macros. @@ -43,10 +43,7 @@ extension CompilerPluginMessageHandler { guard let macroSyntax = syntax.asProtocol(FreestandingMacroExpansionSyntax.self) else { throw MacroExpansionError.freestandingMacroSyntaxIsNotMacro } - guard let macroDefinition = resolveMacro(macro) else { - throw MacroExpansionError.macroTypeNotFound(macro) - } - + let macroDefinition = try resolveMacro(macro) let macroRole: MacroRole if let pluginMacroRole { macroRole = MacroRole(messageMacroRole: pluginMacroRole) @@ -113,9 +110,7 @@ extension CompilerPluginMessageHandler { // TODO: Make this a 'String?' and remove non-'hasExpandMacroResult' branches. let expandedSources: [String]? do { - guard let macroDefinition = resolveMacro(macro) else { - throw MacroExpansionError.macroTypeNotFound(macro) - } + let macroDefinition = try resolveMacro(macro) let role = MacroRole(messageMacroRole: macroRole) let expansions = SwiftSyntaxMacroExpansion.expandAttachedMacroWithoutCollapsing( diff --git a/Tests/SwiftCompilerPluginTest/CompilerPluginTests.swift b/Tests/SwiftCompilerPluginTest/CompilerPluginTests.swift index 1ccab7946c6..5a981224992 100644 --- a/Tests/SwiftCompilerPluginTest/CompilerPluginTests.swift +++ b/Tests/SwiftCompilerPluginTest/CompilerPluginTests.swift @@ -10,7 +10,7 @@ // //===----------------------------------------------------------------------===// -import SwiftCompilerPlugin +@_spi(Testing) import SwiftCompilerPlugin import SwiftSyntax import SwiftSyntaxMacros import XCTest @@ -51,7 +51,7 @@ public class CompilerPluginTests: XCTestCase { func testResolveMacro() { let plugin = MyPlugin() - let registeredMacro = plugin._resolveMacro( + let registeredMacro = try? plugin.resolveMacro( moduleName: "SwiftCompilerPluginTest", typeName: "RegisteredMacro" ) @@ -59,12 +59,12 @@ public class CompilerPluginTests: XCTestCase { XCTAssertTrue(registeredMacro == RegisteredMacro.self) /// Test the plugin doesn't provide unregistered macros. - let dummyMacro = plugin._resolveMacro( - moduleName: "SwiftCompilerPluginTest", - typeName: "DummyMacro" + XCTAssertThrowsError( + try plugin.resolveMacro( + moduleName: "SwiftCompilerPluginTest", + typeName: "DummyMacro" + ) ) - XCTAssertNil(dummyMacro) - XCTAssertFalse(dummyMacro == DummyMacro.self) } }