Skip to content

Commit 55349f8

Browse files
authored
Merge pull request #1411 from rintaro/plugin-dylibmacro
[Plugin] Add 'loadPluginLibrary' message
2 parents 07c08da + 6b677f7 commit 55349f8

File tree

4 files changed

+100
-7
lines changed

4 files changed

+100
-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: 54 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 = "load-plugin-library"
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,42 @@ 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+
func loadPluginLibrary(libraryPath: String, moduleName: String) throws {
140+
// This should be unreachable. The host should not call 'loadPluginLibrary'
141+
// unless the feature is not declared.
142+
throw UnimplementedError()
143+
}
144+
}

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

6078
struct MacroReference: Codable {

0 commit comments

Comments
 (0)