Skip to content

Commit 64c7c13

Browse files
committed
[Macros] Unpack DiagnosticsError into separate diagnostics
Fixes rdar://107289985.
1 parent fd2f878 commit 64c7c13

File tree

3 files changed

+76
-1
lines changed

3 files changed

+76
-1
lines changed

lib/ASTGen/Sources/ASTGen/Macros.swift

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -373,6 +373,14 @@ func expandFreestandingMacroInProcess(
373373
print("not an expression macro or a declaration macro")
374374
return nil
375375
}
376+
} catch let diagsError as DiagnosticsError {
377+
for diag in diagsError.diagnostics {
378+
sourceManager.diagnose(
379+
diagnostic: diag,
380+
messageSuffix: " (from macro '\(macroName)')"
381+
)
382+
}
383+
return nil
376384
} catch {
377385
// Record the error
378386
sourceManager.diagnose(
@@ -805,6 +813,15 @@ func expandAttachedMacroInProcess(
805813
print("\(macroPtr) does not conform to any known attached macro protocol")
806814
return nil
807815
}
816+
} catch let diagsError as DiagnosticsError {
817+
for diag in diagsError.diagnostics {
818+
sourceManager.diagnose(
819+
diagnostic: diag,
820+
messageSuffix: " (from macro '\(macroName)')"
821+
)
822+
}
823+
824+
return nil
808825
} catch {
809826
// Record the error
810827
// FIXME: Need to decide where to diagnose the error:

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -316,6 +316,51 @@ public struct WarningMacro: ExpressionMacro {
316316
}
317317
}
318318

319+
public struct ErrorMacro: ExpressionMacro {
320+
public static func expansion(
321+
of macro: some FreestandingMacroExpansionSyntax,
322+
in context: some MacroExpansionContext
323+
) throws -> ExprSyntax {
324+
guard let firstElement = macro.argumentList.first,
325+
let stringLiteral = firstElement.expression.as(StringLiteralExprSyntax.self),
326+
stringLiteral.segments.count == 1,
327+
case let .stringSegment(messageString)? = stringLiteral.segments.first
328+
else {
329+
let errorNode: Syntax
330+
if let firstElement = macro.argumentList.first {
331+
errorNode = Syntax(firstElement)
332+
} else {
333+
errorNode = Syntax(macro)
334+
}
335+
336+
let messageID = MessageID(domain: "silly", id: "error")
337+
let diag = Diagnostic(
338+
node: errorNode,
339+
message: SimpleDiagnosticMessage(
340+
message: "#myError macro requires a string literal",
341+
diagnosticID: messageID,
342+
severity: .error
343+
)
344+
)
345+
346+
throw DiagnosticsError(diagnostics: [diag])
347+
}
348+
349+
context.diagnose(
350+
Diagnostic(
351+
node: Syntax(macro),
352+
message: SimpleDiagnosticMessage(
353+
message: messageString.content.description,
354+
diagnosticID: MessageID(domain: "test", id: "error"),
355+
severity: .error
356+
)
357+
)
358+
)
359+
360+
return "()"
361+
}
362+
}
363+
319364
public struct PropertyWrapperMacro {}
320365

321366
extension PropertyWrapperMacro: AccessorMacro, Macro {

test/Macros/macro_expand_throwing.swift

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
// RUN: %target-build-swift -swift-version 5 -I %swift-host-lib-dir -L %swift-host-lib-dir -emit-library -o %t/%target-library-name(MacroDefinition) -module-name=MacroDefinition %S/Inputs/syntax_macro_definitions.swift -g -no-toolchain-stdlib-rpath -swift-version 5
33

44
// Make sure the diagnostic comes through...
5-
// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -module-name MacroUser
5+
// RUN: %target-typecheck-verify-swift -swift-version 5 -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir -module-name MacroUser -DTEST_DIAGNOSTICS
66

77
// Make sure the diagnostic doesn't crash in SILGen
88
// RUN: not %target-swift-frontend -swift-version 5 -emit-sil -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir %s -module-name MacroUser -o - -g
@@ -12,9 +12,22 @@
1212

1313
@freestanding(expression) macro myWarning(_ message: String) = #externalMacro(module: "MacroDefinition", type: "WarningMacro")
1414

15+
@freestanding(expression) macro myError(_ message: String) = #externalMacro(module: "MacroDefinition", type: "ErrorMacro")
16+
1517
func testThrownError() {
1618
let name = "hello"
1719
#myWarning (name) // expected-error{{#myWarning macro requires a string literal (from macro 'myWarning')}}
1820

1921
#myWarning("experimental features ahead") // expected-warning{{experimental features ahead}}
2022
}
23+
24+
#if TEST_DIAGNOSTICS
25+
func testThrownErrors() {
26+
let name = "hello"
27+
#myError(
28+
name
29+
) // expected-error@-1{{macro requires a string literal (from macro 'myError')}}
30+
31+
#myError("experimental features ahead") // expected-error{{experimental features ahead}}
32+
}
33+
#endif

0 commit comments

Comments
 (0)