13
13
// https://github.com/apple/swift-package-manager/blob/main/Sources/PackagePlugin/Plugin.swift
14
14
15
15
import SwiftSyntaxMacros
16
+ @_implementationOnly import SwiftCompilerPluginMessageHandling
16
17
17
18
@_implementationOnly import Foundation
18
19
#if os(Windows)
@@ -61,6 +62,37 @@ public protocol CompilerPlugin {
61
62
var providingMacros : [ Macro . Type ] { get }
62
63
}
63
64
65
+ extension CompilerPlugin {
66
+ func resolveMacro( moduleName: String , typeName: String ) -> Macro . Type ? {
67
+ let qualifedName = " \( moduleName) . \( typeName) "
68
+
69
+ for type in providingMacros {
70
+ // FIXME: Is `String(reflecting:)` stable?
71
+ // Getting the module name and type name should be more robust.
72
+ let name = String ( reflecting: type)
73
+ if name == qualifedName {
74
+ return type
75
+ }
76
+ }
77
+ return nil
78
+ }
79
+
80
+ // @testable
81
+ public func _resolveMacro( moduleName: String , typeName: String ) -> Macro . Type ? {
82
+ resolveMacro ( moduleName: moduleName, typeName: typeName)
83
+ }
84
+ }
85
+
86
+ struct MacroProviderAdapter < Plugin: CompilerPlugin > : PluginProvider {
87
+ let plugin : Plugin
88
+ init ( plugin: Plugin ) {
89
+ self . plugin = plugin
90
+ }
91
+ func resolveMacro( moduleName: String , typeName: String ) -> Macro . Type ? {
92
+ plugin. resolveMacro ( moduleName: moduleName, typeName: typeName)
93
+ }
94
+ }
95
+
64
96
extension CompilerPlugin {
65
97
66
98
/// Main entry point of the plugin — sets up a communication channel with
@@ -105,18 +137,17 @@ extension CompilerPlugin {
105
137
#endif
106
138
107
139
// Open a message channel for communicating with the plugin host.
108
- pluginHostConnection = PluginHostConnection (
140
+ let connection = PluginHostConnection (
109
141
inputStream: FileHandle ( fileDescriptor: inputFD) ,
110
142
outputStream: FileHandle ( fileDescriptor: outputFD)
111
143
)
112
144
113
145
// Handle messages from the host until the input stream is closed,
114
146
// indicating that we're done.
115
- let instance = Self ( )
147
+ let provider = MacroProviderAdapter ( plugin: Self ( ) )
148
+ let impl = CompilerPluginMessageHandler ( connection: connection, provider: provider)
116
149
do {
117
- while let message = try pluginHostConnection. waitForNextMessage ( ) {
118
- try instance. handleMessage ( message)
119
- }
150
+ try impl. main ( )
120
151
} catch {
121
152
// Emit a diagnostic and indicate failure to the plugin host,
122
153
// and exit with an error code.
@@ -135,46 +166,13 @@ extension CompilerPlugin {
135
166
if let cStr = strerror ( errno) { return String ( cString: cStr) }
136
167
return String ( describing: errno)
137
168
}
138
-
139
- /// Handles a single message received from the plugin host.
140
- fileprivate func handleMessage( _ message: HostToPluginMessage ) throws {
141
- switch message {
142
- case . getCapability:
143
- try pluginHostConnection. sendMessage (
144
- . getCapabilityResult( capability: PluginMessage . capability)
145
- )
146
- break
147
-
148
- case . expandFreestandingMacro( let macro, let discriminator, let expandingSyntax) :
149
- try expandFreestandingMacro (
150
- macro: macro,
151
- discriminator: discriminator,
152
- expandingSyntax: expandingSyntax
153
- )
154
-
155
- case . expandAttachedMacro( let macro, let macroRole, let discriminator, let attributeSyntax, let declSyntax, let parentDeclSyntax) :
156
- try expandAttachedMacro (
157
- macro: macro,
158
- macroRole: macroRole,
159
- discriminator: discriminator,
160
- attributeSyntax: attributeSyntax,
161
- declSyntax: declSyntax,
162
- parentDeclSyntax: parentDeclSyntax
163
- )
164
- }
165
- }
166
169
}
167
170
168
- /// Message channel for bidirectional communication with the plugin host.
169
- internal fileprivate( set) var pluginHostConnection : PluginHostConnection !
170
-
171
- typealias PluginHostConnection = MessageConnection < PluginToHostMessage , HostToPluginMessage >
172
-
173
- internal struct MessageConnection < TX, RX> where TX: Encodable , RX: Decodable {
171
+ internal struct PluginHostConnection : MessageConnection {
174
172
let inputStream : FileHandle
175
173
let outputStream : FileHandle
176
174
177
- func sendMessage( _ message: TX ) throws {
175
+ func sendMessage< TX : Encodable > ( _ message: TX ) throws {
178
176
// Encode the message as JSON.
179
177
let payload = try JSONEncoder ( ) . encode ( message)
180
178
@@ -188,7 +186,7 @@ internal struct MessageConnection<TX, RX> where TX: Encodable, RX: Decodable {
188
186
try outputStream. _write ( contentsOf: payload)
189
187
}
190
188
191
- func waitForNextMessage( ) throws -> RX ? {
189
+ func waitForNextMessage< RX : Decodable > ( _ ty : RX . Type ) throws -> RX ? {
192
190
// Read the header (a 64-bit length field in little endian byte order).
193
191
guard
194
192
let header = try inputStream. _read ( upToCount: 8 ) ,
0 commit comments