Skip to content

Commit b383905

Browse files
committed
[Macros] Ensure plugin process is alive before sending a message
1 parent d07e8ce commit b383905

File tree

2 files changed

+105
-3
lines changed

2 files changed

+105
-3
lines changed

lib/ASTGen/Sources/ASTGen/PluginHost.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -138,15 +138,15 @@ struct CompilerPlugin {
138138
}
139139

140140
func sendMessageAndWaitWithoutLock(_ message: HostToPluginMessage) throws -> PluginToHostMessage {
141+
guard !Plugin_spawnIfNeeded(opaqueHandle) else {
142+
throw PluginError.stalePlugin
143+
}
141144
try sendMessage(message)
142145
return try waitForNextMessage()
143146
}
144147

145148
func sendMessageAndWait(_ message: HostToPluginMessage) throws -> PluginToHostMessage {
146149
try self.withLock {
147-
guard !Plugin_spawnIfNeeded(opaqueHandle) else {
148-
throw PluginError.stalePlugin
149-
}
150150
return try sendMessageAndWaitWithoutLock(message);
151151
}
152152
}
Lines changed: 102 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,102 @@
1+
// REQUIRES: swift_swift_parser
2+
3+
// RUN: %empty-directory(%t)
4+
// RUN: %empty-directory(%t/plugins)
5+
// RUN: split-file %s %t
6+
7+
//== Build the plugin library
8+
// RUN: %host-build-swift \
9+
// RUN: -swift-version 5 \
10+
// RUN: -emit-library \
11+
// RUN: -o %t/plugins/%target-library-name(MacroDefinition) \
12+
// RUN: -module-name=MacroDefinition \
13+
// RUN: %t/MacroDefinition.swift \
14+
// RUN: -g -no-toolchain-stdlib-rpath
15+
16+
// RUN: %host-build-swift \
17+
// RUN: -swift-version 5 \
18+
// RUN: -emit-library \
19+
// RUN: -o %t/plugins/%target-library-name(EvilMacros) \
20+
// RUN: -module-name=EvilMacros \
21+
// RUN: %t/EvilMacros.swift \
22+
// RUN: -g -no-toolchain-stdlib-rpath
23+
24+
// RUN: %target-swift-frontend \
25+
// RUN: -swift-version 5 \
26+
// RUN: -emit-module -o \
27+
// RUN: %t/MacroLibrary.swiftmodule \
28+
// RUN: %t/MacroLibrary.swift \
29+
// RUN: -module-name MacroLibrary \
30+
// RUN: -external-plugin-path %t/plugins#%swift-plugin-server
31+
32+
// RUN: env SWIFT_DUMP_PLUGIN_MESSAGING=1 %target-swift-frontend \
33+
// RUN: -typecheck -verify \
34+
// RUN: -I %t \
35+
// RUN: -swift-version 5 \
36+
// RUN: -external-plugin-path %t/plugins#%swift-plugin-server \
37+
// RUN: -module-name MyApp \
38+
// RUN: %t/app.swift \
39+
// RUN: 2>&1 | tee %t/macro-expansions.txt
40+
41+
// RUN: %FileCheck -strict-whitespace %s < %t/macro-expansions.txt
42+
43+
// CHECK: ->(plugin:[[#PID1:]]) {"getCapability":{"capability":{"protocolVersion":[[#PROTOCOL_VERSION:]]}}}
44+
// CHECK-NEXT: <-(plugin:[[#PID1]]) {"getCapabilityResult":{"capability":{"features":["load-plugin-library"],"protocolVersion":7}}}
45+
// CHECK-NEXT: ->(plugin:[[#PID1]]) {"loadPluginLibrary":{"libraryPath":"{{.*}}EvilMacros{{.*}},"moduleName":"EvilMacros"}}
46+
// CHECK-NEXT: <-(plugin:[[#PID1]]) {"loadPluginLibraryResult":{"diagnostics":[],"loaded":true}}
47+
// CHECK-NEXT: ->(plugin:[[#PID1]]) {"expandFreestandingMacro":{"discriminator":"{{.*}}","lexicalContext":{{.*}},"macro":{"moduleName":"EvilMacros","name":"evil","typeName":"CrashingMacro"}{{.*}}
48+
49+
// CHECK-NEXT: ->(plugin:[[#PID2:]]) {"getCapability":{"capability":{"protocolVersion":7}}}
50+
// CHECK-NEXT: <-(plugin:[[#PID2]]) {"getCapabilityResult":{"capability":{"features":["load-plugin-library"],"protocolVersion":[[#PROTOCOL_VERSION]]}}}
51+
// CHECK-NEXT: ->(plugin:[[#PID2]]) {"loadPluginLibrary":{"libraryPath":"{{.*}}EvilMacros{{.*}}","moduleName":"EvilMacros"}}
52+
// CHECK-NEXT: <-(plugin:[[#PID2]]) {"loadPluginLibraryResult":{"diagnostics":[],"loaded":true}}
53+
// CHECK-NEXT: ->(plugin:[[#PID2]]) {"loadPluginLibrary":{"libraryPath":"{{.*}}MacroDefinition{{.*}}","moduleName":"MacroDefinition"}}
54+
// CHECK-NEXT: <-(plugin:[[#PID2]]) {"loadPluginLibraryResult":{"diagnostics":[],"loaded":true}}
55+
// CHECK-NEXT: ->(plugin:[[#PID2]]) {"expandFreestandingMacro":{"discriminator":"{{.*}}","lexicalContext":{{.*}},"macro":{"moduleName":"MacroDefinition","name":"stringify","typeName":"StringifyMacro"}{{.*}}
56+
// CHECK-NEXT: <-(plugin:[[#PID2]]) {"expandMacroResult":{"diagnostics":[],"expandedSource":"(1, \"1\")"}}
57+
58+
//--- MacroDefinition.swift
59+
import SwiftSyntax
60+
import SwiftSyntaxBuilder
61+
import SwiftSyntaxMacros
62+
63+
public struct StringifyMacro: ExpressionMacro {
64+
public static func expansion(
65+
of macro: some FreestandingMacroExpansionSyntax,
66+
in context: some MacroExpansionContext
67+
) -> ExprSyntax {
68+
guard let argument = macro.arguments.first?.expression else {
69+
fatalError("boom")
70+
}
71+
72+
return "(\(argument), \(StringLiteralExprSyntax(content: argument.description)))"
73+
}
74+
}
75+
76+
//--- EvilMacros.swift
77+
import SwiftSyntax
78+
import SwiftSyntaxBuilder
79+
import SwiftSyntaxMacros
80+
81+
public struct CrashingMacro: ExpressionMacro {
82+
public static func expansion(
83+
of macro: some FreestandingMacroExpansionSyntax,
84+
in context: some MacroExpansionContext
85+
) -> ExprSyntax {
86+
let arg: UInt = UInt(macro.argumentList.first!.expression.description)!
87+
let zero: UInt = 0
88+
return "\(raw: zero - arg).description"
89+
}
90+
}
91+
92+
//--- MacroLibrary.swift
93+
@freestanding(expression) public macro stringify<T>(_ value: T) -> (T, String) = #externalMacro(module: "MacroDefinition", type: "StringifyMacro")
94+
@freestanding(expression) public macro evil(_ value: Int) -> String = #externalMacro(module: "EvilMacros", type: "CrashingMacro")
95+
96+
//--- app.swift
97+
import MacroLibrary
98+
99+
func test() {
100+
_ = #evil(1) // expected-error {{failed to receive result from plugin (from macro 'evil')}}
101+
_ = #stringify(1)
102+
}

0 commit comments

Comments
 (0)