Skip to content

Commit 19b43d5

Browse files
committed
[Plugin] Add 'loadPluginLibrary' message
This message is to load a dynamic link library from the specified path. Later on, the loaded macro should be usable just like the normal macro expansion. Also, add 'features' to the capability message. Plugin implementations can declare the optional features they implement. 'CompilerPlugin' doesn't implement any optional features at this point.
1 parent b6adf00 commit 19b43d5

File tree

5 files changed

+99
-7
lines changed

5 files changed

+99
-7
lines changed

Sources/CMakeLists.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,4 +39,5 @@ add_subdirectory(SwiftParserDiagnostics)
3939
add_subdirectory(SwiftOperators)
4040
add_subdirectory(SwiftSyntaxBuilder)
4141
add_subdirectory(SwiftSyntaxMacros)
42+
add_subdirectory(SwiftCompilerPluginMessageHandling)
4243
add_subdirectory(IDEUtils)

Sources/SwiftCompilerPlugin/CompilerPlugin.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -88,6 +88,7 @@ struct MacroProviderAdapter<Plugin: CompilerPlugin>: PluginProvider {
8888
init(plugin: Plugin) {
8989
self.plugin = plugin
9090
}
91+
9192
func resolveMacro(moduleName: String, typeName: String) -> Macro.Type? {
9293
plugin.resolveMacro(moduleName: moduleName, typeName: typeName)
9394
}
Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
# This source file is part of the Swift.org open source project
2+
#
3+
# Copyright (c) 2014 - 2023 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_host_library(SwiftCompilerPluginMessageHandling
10+
CompilerPluginMessageHandler.swift
11+
Diagnostics.swift
12+
Macros.swift
13+
PluginMacroExpansionContext.swift
14+
PluginMessages.swift
15+
)
16+
17+
target_link_libraries(SwiftCompilerPluginMessageHandling PUBLIC
18+
SwiftSyntax
19+
SwiftDiagnostics
20+
SwiftParser
21+
SwiftSyntaxMacros
22+
SwiftOperators)

Sources/SwiftCompilerPluginMessageHandling/CompilerPluginMessageHandler.swift

Lines changed: 52 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,22 @@
1212

1313
import SwiftSyntaxMacros
1414

15+
/// Optional features.
16+
public enum PluginFeature: String {
17+
case loadPluginLibrary
18+
}
19+
1520
/// A type that provides the actual plugin functions.
1621
public protocol PluginProvider {
22+
/// Resolve loaded macro type by the module name and the type name.
1723
func resolveMacro(moduleName: String, typeName: String) -> Macro.Type?
24+
25+
/// Load dynamic link library and resolve a macro type by the 'symbolName'.
26+
func loadPluginLibrary(libraryPath: String, moduleName: String) throws
27+
28+
/// Optional plugin features. This is sent to the host so the it can decide
29+
/// the behavior depending on these.
30+
var features: [PluginFeature] { get }
1831
}
1932

2033
/// Low level message connection to the plugin host.
@@ -67,9 +80,11 @@ extension CompilerPluginMessageHandler {
6780
fileprivate func handleMessage(_ message: HostToPluginMessage) throws {
6881
switch message {
6982
case .getCapability:
70-
try self.sendMessage(
71-
.getCapabilityResult(capability: PluginMessage.capability)
83+
let capability = PluginMessage.PluginCapability(
84+
protocolVersion: PluginMessage.PROTOCOL_VERSION_NUMBER,
85+
features: provider.features.map({ $0.rawValue })
7286
)
87+
try self.sendMessage(.getCapabilityResult(capability: capability))
7388

7489
case .expandFreestandingMacro(let macro, let discriminator, let expandingSyntax):
7590
try expandFreestandingMacro(
@@ -87,6 +102,41 @@ extension CompilerPluginMessageHandler {
87102
declSyntax: declSyntax,
88103
parentDeclSyntax: parentDeclSyntax
89104
)
105+
106+
case .loadPluginLibrary(let libraryPath, let moduleName):
107+
var diags: [PluginMessage.Diagnostic] = []
108+
do {
109+
try provider.loadPluginLibrary(libraryPath: libraryPath, moduleName: moduleName)
110+
} catch {
111+
diags.append(
112+
PluginMessage.Diagnostic(
113+
message: String(describing: error),
114+
severity: .error,
115+
position: .invalid,
116+
highlights: [],
117+
notes: [],
118+
fixIts: []
119+
)
120+
)
121+
}
122+
try self.sendMessage(.loadPluginLibraryResult(loaded: diags.isEmpty, diagnostics: diags));
90123
}
91124
}
92125
}
126+
127+
struct UnimplementedError: Error, CustomStringConvertible {
128+
var description: String { "unimplemented" }
129+
}
130+
131+
/// Default implementation of 'PluginProvider' requirements.
132+
public extension PluginProvider {
133+
public var features: [PluginFeature] {
134+
/// No optional features by default.
135+
return []
136+
}
137+
138+
/// Load dynamic link library and resolve a macro type by the 'symbolName'.
139+
public func loadPluginLibrary(libraryPath: String, moduleName: String) throws {
140+
throw UnimplementedError()
141+
}
142+
}

Sources/SwiftCompilerPluginMessageHandling/PluginMessages.swift

Lines changed: 23 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -14,14 +14,17 @@
1414
// NOTE: Types in this file should be self-contained and should not depend on any non-stdlib types.
1515

1616
internal enum HostToPluginMessage: Codable {
17+
/// Get capability of this plugin.
1718
case getCapability
1819

20+
/// Expand a '@freestanding' macro.
1921
case expandFreestandingMacro(
2022
macro: PluginMessage.MacroReference,
2123
discriminator: String,
2224
syntax: PluginMessage.Syntax
2325
)
2426

27+
/// Expand an '@attached' macro.
2528
case expandAttachedMacro(
2629
macro: PluginMessage.MacroReference,
2730
macroRole: PluginMessage.MacroRole,
@@ -30,9 +33,21 @@ internal enum HostToPluginMessage: Codable {
3033
declSyntax: PluginMessage.Syntax,
3134
parentDeclSyntax: PluginMessage.Syntax?
3235
)
36+
37+
/// Optionally implemented message to load a dynamic link library.
38+
/// 'moduleName' can be used as a hint indicating that the library
39+
/// provides the specified module.
40+
case loadPluginLibrary(
41+
libraryPath: String,
42+
moduleName: String
43+
)
3344
}
3445

3546
internal enum PluginToHostMessage: Codable {
47+
case getCapabilityResult(
48+
capability: PluginMessage.PluginCapability
49+
)
50+
3651
case expandFreestandingMacroResult(
3752
expandedSource: String?,
3853
diagnostics: [PluginMessage.Diagnostic]
@@ -43,18 +58,21 @@ internal enum PluginToHostMessage: Codable {
4358
diagnostics: [PluginMessage.Diagnostic]
4459
)
4560

46-
case getCapabilityResult(capability: PluginMessage.PluginCapability)
61+
case loadPluginLibraryResult(
62+
loaded: Bool,
63+
diagnostics: [PluginMessage.Diagnostic]
64+
)
4765
}
4866

4967
/*namespace*/ internal enum PluginMessage {
50-
static var PROTOCOL_VERSION_NUMBER: Int { 3 } // Renamed 'customAttributeSyntax' to 'attributeSyntax'.
68+
static var PROTOCOL_VERSION_NUMBER: Int { 4 } // Added 'loadPluginLibrary'.
5169

5270
struct PluginCapability: Codable {
5371
var protocolVersion: Int
54-
}
5572

56-
static var capability: PluginCapability {
57-
PluginCapability(protocolVersion: PluginMessage.PROTOCOL_VERSION_NUMBER)
73+
/// Optional features this plugin provides.
74+
/// * resolveLibraryMacro: 'resolveLibraryMacro' message is implemented.
75+
var features: [String]?
5876
}
5977

6078
struct MacroReference: Codable {

0 commit comments

Comments
 (0)