Skip to content

Commit 0e6ec19

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 0e6ec19

File tree

4 files changed

+99
-7
lines changed

4 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)
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: 53 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -12,9 +12,23 @@
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 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 at `libraryPath`. Implementations can use
26+
/// `moduleName` to associate the loaded library with it.
27+
func loadPluginLibrary(libraryPath: String, moduleName: String) throws
28+
29+
/// Optional plugin features. This is sent to the host so the it can decide
30+
/// the behavior depending on these.
31+
var features: [PluginFeature] { get }
1832
}
1933

2034
/// Low level message connection to the plugin host.
@@ -67,9 +81,11 @@ extension CompilerPluginMessageHandler {
6781
fileprivate func handleMessage(_ message: HostToPluginMessage) throws {
6882
switch message {
6983
case .getCapability:
70-
try self.sendMessage(
71-
.getCapabilityResult(capability: PluginMessage.capability)
84+
let capability = PluginMessage.PluginCapability(
85+
protocolVersion: PluginMessage.PROTOCOL_VERSION_NUMBER,
86+
features: provider.features.map({ $0.rawValue })
7287
)
88+
try self.sendMessage(.getCapabilityResult(capability: capability))
7389

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

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+
/// * loadPluginLibrary: 'loadPluginLibrary' message is implemented.
75+
var features: [String]?
5876
}
5977

6078
struct MacroReference: Codable {

0 commit comments

Comments
 (0)