Skip to content

Commit e181a4d

Browse files
committed
[Macros] Improve error handling for plugin errors
1 parent e93e4ba commit e181a4d

File tree

8 files changed

+51
-18
lines changed

8 files changed

+51
-18
lines changed

include/swift/AST/CASTBridging.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -313,6 +313,9 @@ void Plugin_setCapability(PluginHandle handle, PluginCapabilityPtr data);
313313
/// Get a capability data set by \c Plugin_setCapability .
314314
PluginCapabilityPtr _Nullable Plugin_getCapability(PluginHandle handle);
315315

316+
/// Get the executable file path of the plugin.
317+
const char *Plugin_getExecutableFilePath(PluginHandle handle);
318+
316319
/// Lock the plugin. Clients should lock it during sending and recving the
317320
/// response.
318321
void Plugin_lock(PluginHandle handle);

include/swift/AST/PluginRegistry.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
#ifndef SWIFT_PLUGIN_REGISTRY_H
1313
#define SWIFT_PLUGIN_REGISTRY_H
1414

15+
#include "swift/Basic/StringExtras.h"
1516
#include "llvm/ADT/ArrayRef.h"
1617
#include "llvm/ADT/StringMap.h"
1718
#include "llvm/ADT/StringRef.h"
@@ -139,6 +140,10 @@ class LoadedExecutablePlugin {
139140

140141
llvm::sys::procid_t getPid() { return Process->pid; }
141142

143+
NullTerminatedStringRef getExecutablePath() {
144+
return {ExecutablePath.c_str(), ExecutablePath.size()};
145+
}
146+
142147
const void *getCapability() { return capability; };
143148
void setCapability(const void *newValue) { capability = newValue; };
144149

lib/AST/CASTBridging.cpp

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -642,6 +642,11 @@ void Plugin_setCapability(PluginHandle handle, PluginCapabilityPtr data) {
642642
plugin->setCapability(data);
643643
}
644644

645+
const char *Plugin_getExecutableFilePath(PluginHandle handle) {
646+
auto *plugin = static_cast<LoadedExecutablePlugin *>(handle);
647+
return plugin->getExecutablePath().data();
648+
}
649+
645650
void Plugin_lock(PluginHandle handle) {
646651
auto *plugin = static_cast<LoadedExecutablePlugin *>(handle);
647652
plugin->lock();

lib/ASTGen/Sources/ASTGen/PluginHost.swift

Lines changed: 32 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -15,11 +15,13 @@ import CBasicBridging
1515
import SwiftSyntax
1616
import swiftLLVMJSON
1717

18-
enum PluginError: Error {
19-
case stalePlugin
20-
case failedToSendMessage
21-
case failedToReceiveMessage
22-
case invalidReponseKind
18+
enum PluginError: String, Error, CustomStringConvertible {
19+
case stalePlugin = "plugin is stale"
20+
case failedToSendMessage = "failed to send request to plugin"
21+
case failedToReceiveMessage = "failed to receive result from plugin"
22+
case invalidReponseKind = "plugin returned invalid result"
23+
24+
var description: String { rawValue }
2325
}
2426

2527
@_cdecl("swift_ASTGen_initializePlugin")
@@ -28,12 +30,15 @@ public func _initializePlugin(
2830
cxxDiagnosticEngine: UnsafeMutablePointer<UInt8>?
2931
) -> Bool {
3032
let plugin = CompilerPlugin(opaqueHandle: opaqueHandle)
33+
let diagEngine = PluginDiagnosticsEngine(cxxDiagnosticEngine: cxxDiagnosticEngine)
34+
3135
do {
3236
try plugin.initialize()
3337
return true
3438
} catch {
35-
// Diagnostics are emitted in the caller.
36-
// FIXME: Return what happened or emit diagnostics here.
39+
diagEngine?.diagnose(
40+
message: "compiler plugin not loaded: '\(plugin.executableFilePath); failed to initialize",
41+
severity: .warning)
3742
return false
3843
}
3944
}
@@ -56,12 +61,19 @@ func swift_ASTGen_pluginServerLoadLibraryPlugin(
5661
cxxDiagnosticEngine: UnsafeMutablePointer<UInt8>?
5762
) -> Bool {
5863
let plugin = CompilerPlugin(opaqueHandle: opaqueHandle)
64+
let diagEngine = PluginDiagnosticsEngine(cxxDiagnosticEngine: cxxDiagnosticEngine)
65+
66+
if plugin.capability?.features.contains(.loadPluginLibrary) != true {
67+
// This happens only if invalid plugin server was passed to `-external-plugin-path`.
68+
diagEngine?.diagnose(
69+
message: "compiler plugin not loaded: '\(libraryPath); invalid plugin server",
70+
severity: .warning)
71+
return false
72+
}
5973
assert(plugin.capability?.features.contains(.loadPluginLibrary) == true)
6074
let libraryPath = String(cString: libraryPath)
6175
let moduleName = String(cString: moduleName)
6276

63-
let diagEngine = PluginDiagnosticsEngine(cxxDiagnosticEngine: cxxDiagnosticEngine)
64-
6577
do {
6678
let result = try plugin.sendMessageAndWaitWithoutLock(
6779
.loadPluginLibrary(libraryPath: libraryPath, moduleName: moduleName)
@@ -72,7 +84,9 @@ func swift_ASTGen_pluginServerLoadLibraryPlugin(
7284
diagEngine?.emit(diagnostics);
7385
return loaded
7486
} catch {
75-
diagEngine?.diagnose(error: error)
87+
diagEngine?.diagnose(
88+
message: "compiler plugin not loaded: '\(libraryPath); \(error)",
89+
severity: .warning)
7690
return false
7791
}
7892
}
@@ -167,6 +181,10 @@ struct CompilerPlugin {
167181
}
168182
return nil
169183
}
184+
185+
var executableFilePath: String {
186+
return String(cString: Plugin_getExecutableFilePath(opaqueHandle))
187+
}
170188
}
171189

172190
class PluginDiagnosticsEngine {
@@ -288,6 +306,10 @@ class PluginDiagnosticsEngine {
288306
)
289307
}
290308

309+
func diagnose(message: String, severity: PluginMessage.Diagnostic.Severity) {
310+
self.emitSingle(message: message, severity: severity, position: .invalid)
311+
}
312+
291313
/// Produce the C++ source location for a given position based on a
292314
/// syntax node.
293315
private func cxxSourceLocation(

lib/Sema/TypeCheckMacros.cpp

Lines changed: 0 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -311,8 +311,6 @@ loadExecutablePluginByName(ASTContext &ctx, Identifier moduleName) {
311311
if (!executablePlugin->isInitialized()) {
312312
#if SWIFT_SWIFT_PARSER
313313
if (!swift_ASTGen_initializePlugin(executablePlugin, &ctx.Diags)) {
314-
ctx.Diags.diagnose(SourceLoc(), diag::compiler_plugin_not_loaded,
315-
executablePluginPath, "failed to initialize plugin");
316314
return nullptr;
317315
}
318316
executablePlugin->setCleanup([executablePlugin] {

test/Macros/macro_plugin_broken.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@
1919

2020
// RUN: c-index-test -read-diagnostics %t/macro_expand.dia 2>&1 | %FileCheck -check-prefix CHECK %s
2121

22-
// CHECK: (null):0:0: warning: compiler plugin not loaded: {{.+}}broken-plugin; loader error: failed to initialize plugin
22+
// CHECK: (null):0:0: warning: compiler plugin not loaded: {{.+}}broken-plugin; failed to initialize
2323
// CHECK: test.swift:1:33: warning: external macro implementation type 'TestPlugin.FooMacro' could not be found for macro 'fooMacro';
2424
// CHECK: test.swift:4:7: error: external macro implementation type 'TestPlugin.FooMacro' could not be found for macro 'fooMacro';
2525
// CHECK: +-{{.+}}test.swift:1:33: note: 'fooMacro' declared here

test/Macros/macro_plugin_error.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@
2323

2424
// CHECK: ->(plugin:[[#PID1:]]) {"getCapability":{}}
2525
// CHECK-NEXT: <-(plugin:[[#PID1]]) {"getCapabilityResult":{"capability":{"protocolVersion":1}}}
26-
// CHECK-NEXT: ->(plugin:[[#PID1]]) {"expandFreestandingMacro":{"discriminator":"$s{{.+}}","macro":{"moduleName":"TestPlugin","name":"fooMacro","typeName":"FooMacro"},"syntax":{"kind":"expression","location":{"column":19,"fileID":"MyApp/test.swift","fileName":"BUILD_DIR{{.+}}test.swift","line":6,"offset":200},"source":"#fooMacro(1)"}}}
26+
// CHECK-NEXT: ->(plugin:[[#PID1]]) {"expandFreestandingMacro":{"discriminator":"$s{{.+}}","macro":{"moduleName":"TestPlugin","name":"fooMacro","typeName":"FooMacro"},"syntax":{"kind":"expression","location":{"column":19,"fileID":"MyApp/test.swift","fileName":"BUILD_DIR{{.+}}test.swift","line":6,"offset":[[#]]},"source":"#fooMacro(1)"}}}
2727
// CHECK-NEXT: <-(plugin:[[#PID1]]) {"invalidResponse":{}}
28-
// CHECK-NEXT: ->(plugin:[[#PID1]]) {"expandFreestandingMacro":{"discriminator":"$s{{.+}}","macro":{"moduleName":"TestPlugin","name":"fooMacro","typeName":"FooMacro"},"syntax":{"kind":"expression","location":{"column":19,"fileID":"MyApp/test.swift","fileName":"BUILD_DIR{{.+}}test.swift","line":8,"offset":304},"source":"#fooMacro(2)"}}}
28+
// CHECK-NEXT: ->(plugin:[[#PID1]]) {"expandFreestandingMacro":{"discriminator":"$s{{.+}}","macro":{"moduleName":"TestPlugin","name":"fooMacro","typeName":"FooMacro"},"syntax":{"kind":"expression","location":{"column":19,"fileID":"MyApp/test.swift","fileName":"BUILD_DIR{{.+}}test.swift","line":8,"offset":[[#]]},"source":"#fooMacro(2)"}}}
2929
// ^ This messages causes the mock plugin exit because there's no matching expected message.
3030

31-
// CHECK: ->(plugin:[[#PID2:]]) {"expandFreestandingMacro":{"discriminator":"$s{{.+}}","macro":{"moduleName":"TestPlugin","name":"fooMacro","typeName":"FooMacro"},"syntax":{"kind":"expression","location":{"column":19,"fileID":"MyApp/test.swift","fileName":"BUILD_DIR{{.+}}test.swift","line":10,"offset":386},"source":"#fooMacro(3)"}}}
31+
// CHECK: ->(plugin:[[#PID2:]]) {"expandFreestandingMacro":{"discriminator":"$s{{.+}}","macro":{"moduleName":"TestPlugin","name":"fooMacro","typeName":"FooMacro"},"syntax":{"kind":"expression","location":{"column":19,"fileID":"MyApp/test.swift","fileName":"BUILD_DIR{{.+}}test.swift","line":10,"offset":[[#]]},"source":"#fooMacro(3)"}}}
3232
// CHECK-NEXT: <-(plugin:[[#PID2:]]) {"expandFreestandingMacroResult":{"diagnostics":[],"expandedSource":"3.description"}}
3333

3434
//--- test.swift
@@ -40,7 +40,7 @@ func test() {
4040
let _: String = #fooMacro(1)
4141
// expected-error @-1 {{typeMismatch(swiftASTGen.PluginToHostMessage}}
4242
let _: String = #fooMacro(2)
43-
// expected-error @-1 {{failedToReceiveMessage}}
43+
// expected-error @-1 {{failed to receive result from plugin (from macro 'fooMacro')}}
4444
let _: String = #fooMacro(3)
4545
// ^ This should succeed.
4646
}

test/Macros/macro_plugin_server.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ func testStringify(a: Int, b: Int) {
5656
let s1: String = #stringify(a + b).1
5757
print(s1)
5858

59-
// expected-error @+1 {{failedToReceiveMessage (from macro 'evil')}}
59+
// expected-error @+1 {{failed to receive result from plugin (from macro 'evil')}}
6060
let s2: String = #evil(42)
6161
print(s2)
6262

0 commit comments

Comments
 (0)