Skip to content

Commit 5e288d6

Browse files
authored
Merge pull request #2643 from rintaro/6.0-macros-library-provider
[6.0] Macro plugin related changes
2 parents 115a651 + 0d993d5 commit 5e288d6

File tree

8 files changed

+282
-42
lines changed

8 files changed

+282
-42
lines changed

Package.swift

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,14 @@ let package = Package(
139139
dependencies: ["_SwiftSyntaxTestSupport", "SwiftIDEUtils", "SwiftParser", "SwiftSyntax"]
140140
),
141141

142+
// MARK: SwiftLibraryPluginProvider
143+
144+
.target(
145+
name: "SwiftLibraryPluginProvider",
146+
dependencies: ["SwiftSyntaxMacros", "SwiftCompilerPluginMessageHandling"],
147+
exclude: ["CMakeLists.txt"]
148+
),
149+
142150
// MARK: SwiftSyntax
143151

144152
.target(

Sources/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ add_subdirectory(_SwiftSyntaxCShims)
1010
add_subdirectory(SwiftBasicFormat)
1111
add_subdirectory(SwiftSyntax)
1212
add_subdirectory(SwiftDiagnostics)
13+
add_subdirectory(SwiftLibraryPluginProvider)
1314
add_subdirectory(SwiftParser)
1415
add_subdirectory(SwiftParserDiagnostics)
1516
add_subdirectory(SwiftRefactor)

Sources/SwiftCompilerPlugin/CompilerPlugin.swift

Lines changed: 2 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,7 @@ extension CompilerPlugin {
111111
public static func main() throws {
112112
let connection = try StandardIOMessageConnection()
113113
let provider = MacroProviderAdapter(plugin: Self())
114-
let impl = CompilerPluginMessageHandler(connection: connection, provider: provider)
115-
do {
116-
try impl.main()
117-
} catch {
118-
// Emit a diagnostic and indicate failure to the plugin host,
119-
// and exit with an error code.
120-
fatalError("Internal Error: \(error)")
121-
}
114+
let impl = CompilerPluginMessageListener(connection: connection, provider: provider)
115+
impl.main()
122116
}
123117
}

Sources/SwiftCompilerPluginMessageHandling/CompilerPluginMessageHandler.swift

Lines changed: 44 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,10 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
#if swift(>=6)
14+
private import _SwiftSyntaxCShims
1415
public import SwiftSyntaxMacros
1516
#else
17+
@_implementationOnly import _SwiftSyntaxCShims
1618
import SwiftSyntaxMacros
1719
#endif
1820

@@ -23,6 +25,8 @@ public enum PluginFeature: String {
2325
}
2426

2527
/// A type that provides the actual plugin functions.
28+
///
29+
/// Note that it's an implementation's responsibility to cache the API results as needed.
2630
@_spi(PluginMessage)
2731
public protocol PluginProvider {
2832
/// Resolve macro type by the module name and the type name.
@@ -64,50 +68,60 @@ struct HostCapability {
6468
var hasExpandMacroResult: Bool { protocolVersion >= 5 }
6569
}
6670

67-
/// 'CompilerPluginMessageHandler' is a type that listens to the message
68-
/// connection and dispatches them to the actual plugin provider, then send back
71+
/// 'CompilerPluginMessageListener' is a type that listens to the message
72+
/// connection, delegate them to the message handler, then send back
6973
/// the response.
7074
///
7175
/// The low level connection and the provider is injected by the client.
7276
@_spi(PluginMessage)
73-
public class CompilerPluginMessageHandler<Connection: MessageConnection, Provider: PluginProvider> {
77+
public class CompilerPluginMessageListener<Connection: MessageConnection, Provider: PluginProvider> {
7478
/// Message channel for bidirectional communication with the plugin host.
7579
let connection: Connection
7680

77-
/// Object to provide actual plugin functions.
78-
let provider: Provider
79-
80-
/// Plugin host capability
81-
var hostCapability: HostCapability
81+
let handler: CompilerPluginMessageHandler<Provider>
8282

8383
public init(connection: Connection, provider: Provider) {
8484
self.connection = connection
85-
self.provider = provider
86-
self.hostCapability = HostCapability()
87-
}
88-
}
89-
90-
extension CompilerPluginMessageHandler {
91-
func sendMessage(_ message: PluginToHostMessage) throws {
92-
try connection.sendMessage(message)
93-
}
94-
95-
func waitForNextMessage() throws -> HostToPluginMessage? {
96-
try connection.waitForNextMessage(HostToPluginMessage.self)
85+
self.handler = CompilerPluginMessageHandler(provider: provider)
9786
}
9887

9988
/// Run the main message listener loop.
10089
/// Returns when the message connection was closed.
101-
/// Throws an error when it failed to send/receive the message, or failed
102-
/// to serialize/deserialize the message.
103-
public func main() throws {
104-
while let message = try self.waitForNextMessage() {
105-
try handleMessage(message)
90+
///
91+
/// On internal errors, such as I/O errors or JSON serialization errors, print
92+
/// an error message and `exit(1)`
93+
public func main() {
94+
do {
95+
while let message = try connection.waitForNextMessage(HostToPluginMessage.self) {
96+
let result = handler.handleMessage(message)
97+
try connection.sendMessage(result)
98+
}
99+
} catch {
100+
// Emit a diagnostic and indicate failure to the plugin host,
101+
// and exit with an error code.
102+
fputs("Internal Error: \(error)\n", _stderr)
103+
exit(1)
106104
}
107105
}
106+
}
107+
108+
/// 'CompilerPluginMessageHandler' is a type that handle a message and do the
109+
/// corresponding operation.
110+
@_spi(PluginMessage)
111+
public class CompilerPluginMessageHandler<Provider: PluginProvider> {
112+
/// Object to provide actual plugin functions.
113+
let provider: Provider
114+
115+
/// Plugin host capability
116+
var hostCapability: HostCapability
117+
118+
public init(provider: Provider) {
119+
self.provider = provider
120+
self.hostCapability = HostCapability()
121+
}
108122

109123
/// Handles a single message received from the plugin host.
110-
fileprivate func handleMessage(_ message: HostToPluginMessage) throws {
124+
public func handleMessage(_ message: HostToPluginMessage) -> PluginToHostMessage {
111125
switch message {
112126
case .getCapability(let hostCapability):
113127
// Remember the peer capability if provided.
@@ -120,7 +134,7 @@ extension CompilerPluginMessageHandler {
120134
protocolVersion: PluginMessage.PROTOCOL_VERSION_NUMBER,
121135
features: provider.features.map({ $0.rawValue })
122136
)
123-
try self.sendMessage(.getCapabilityResult(capability: capability))
137+
return .getCapabilityResult(capability: capability)
124138

125139
case .expandFreestandingMacro(
126140
let macro,
@@ -129,7 +143,7 @@ extension CompilerPluginMessageHandler {
129143
let expandingSyntax,
130144
let lexicalContext
131145
):
132-
try expandFreestandingMacro(
146+
return expandFreestandingMacro(
133147
macro: macro,
134148
macroRole: macroRole,
135149
discriminator: discriminator,
@@ -148,7 +162,7 @@ extension CompilerPluginMessageHandler {
148162
let conformanceListSyntax,
149163
let lexicalContext
150164
):
151-
try expandAttachedMacro(
165+
return expandAttachedMacro(
152166
macro: macro,
153167
macroRole: macroRole,
154168
discriminator: discriminator,
@@ -176,7 +190,7 @@ extension CompilerPluginMessageHandler {
176190
)
177191
)
178192
}
179-
try self.sendMessage(.loadPluginLibraryResult(loaded: diags.isEmpty, diagnostics: diags));
193+
return .loadPluginLibraryResult(loaded: diags.isEmpty, diagnostics: diags)
180194
}
181195
}
182196
}

Sources/SwiftCompilerPluginMessageHandling/Macros.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -55,7 +55,7 @@ extension CompilerPluginMessageHandler {
5555
discriminator: String,
5656
expandingSyntax: PluginMessage.Syntax,
5757
lexicalContext: [PluginMessage.Syntax]?
58-
) throws {
58+
) -> PluginToHostMessage {
5959
let sourceManager = SourceManager()
6060
let syntax = sourceManager.add(expandingSyntax, foldingWith: .standardOperators)
6161

@@ -105,7 +105,7 @@ extension CompilerPluginMessageHandler {
105105
// TODO: Remove this when all compilers have 'hasExpandMacroResult'.
106106
response = .expandFreestandingMacroResult(expandedSource: expandedSource, diagnostics: diagnostics)
107107
}
108-
try self.sendMessage(response)
108+
return response
109109
}
110110

111111
/// Expand `@attached(XXX)` macros.
@@ -119,7 +119,7 @@ extension CompilerPluginMessageHandler {
119119
extendedTypeSyntax: PluginMessage.Syntax?,
120120
conformanceListSyntax: PluginMessage.Syntax?,
121121
lexicalContext: [PluginMessage.Syntax]?
122-
) throws {
122+
) -> PluginToHostMessage {
123123
let sourceManager = SourceManager()
124124
let attributeNode = sourceManager.add(
125125
attributeSyntax,
@@ -189,7 +189,7 @@ extension CompilerPluginMessageHandler {
189189
} else {
190190
response = .expandAttachedMacroResult(expandedSources: expandedSources, diagnostics: diagnostics)
191191
}
192-
try self.sendMessage(response)
192+
return response
193193
}
194194
}
195195

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
# This source file is part of the Swift.org open source project
2+
#
3+
# Copyright (c) 2024 Apple Inc. and the Swift project authors
4+
# Licensed under Apache License v2.0 with Runtime Library Exception
5+
#
6+
# See http://swift.org/LICENSE.txt for license information
7+
# See http://swift.org/CONTRIBUTORS.txt for Swift project authors
8+
9+
add_swift_syntax_library(SwiftLibraryPluginProvider
10+
LibraryPluginProvider.swift
11+
)
12+
13+
target_link_swift_syntax_libraries(SwiftLibraryPluginProvider PUBLIC
14+
SwiftSyntaxMacros
15+
SwiftCompilerPluginMessageHandling
16+
)

0 commit comments

Comments
 (0)