Skip to content

Commit 5bc8a3c

Browse files
committed
[Macros] Eliminate MacroResult.
Per pitch feedback, eliminate MacroResult. Instead, macro implementations can produce diagnostics by calling `diagnose()` on the macro evaluation context.
1 parent 217af0e commit 5bc8a3c

File tree

10 files changed

+52
-100
lines changed

10 files changed

+52
-100
lines changed

Sources/_SwiftSyntaxMacros/CMakeLists.txt

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,6 @@ add_swift_host_library(_SwiftSyntaxMacros
1010
ExpressionMacro.swift
1111
Macro.swift
1212
MacroExpansionContext.swift
13-
MacroResult.swift
1413
MacroSystem+Builtin.swift
1514
MacroSystem+Examples.swift
1615
MacroSystem.swift

Sources/_SwiftSyntaxMacros/ExpressionMacro.swift

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,11 +19,12 @@ import _CompilerPluginSupport
1919

2020
/// Describes a macro that is explicitly expanded as an expression.
2121
public protocol ExpressionMacro: Macro {
22-
/// Evaluate a macro described by the given macro expansion expression
22+
/// Expansion a macro described by the given macro expansion expression
2323
/// within the given context to produce a replacement expression.
2424
static func apply(
25-
_ macro: MacroExpansionExprSyntax, in context: inout MacroExpansionContext
26-
) -> MacroResult<ExprSyntax>
25+
_ expansion: MacroExpansionExprSyntax,
26+
in context: inout MacroExpansionContext
27+
) -> ExprSyntax
2728
}
2829

2930
#if canImport(_CompilerPluginSupport)

Sources/_SwiftSyntaxMacros/MacroExpansionContext.swift

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@
1111
//===----------------------------------------------------------------------===//
1212

1313
import SwiftSyntax
14+
import SwiftDiagnostics
1415

1516
/// System-supplied structure that provides information about the context in
1617
/// which a given macro is being expanded.
@@ -28,6 +29,10 @@ public struct MacroExpansionContext {
2829
/// Counter used to generate names local to the macro.
2930
var localNameCounter = 0
3031

32+
/// The set of diagnostics that were emitted as part of expanding the
33+
/// macro.
34+
public private(set) var diagnostics: [Diagnostic] = []
35+
3136
/// Create a new macro evaluation context.
3237
public init(moduleName: String, fileName: String) {
3338
self.moduleName = moduleName
@@ -54,4 +59,9 @@ public struct MacroExpansionContext {
5459

5560
self.init(moduleName: moduleName, fileName: fileName)
5661
}
62+
63+
/// Produce a diagnostic while expanding the macro.
64+
public mutating func diagnose(_ diagnostic: Diagnostic) {
65+
diagnostics.append(diagnostic)
66+
}
5767
}

Sources/_SwiftSyntaxMacros/MacroResult.swift

Lines changed: 0 additions & 26 deletions
This file was deleted.

Sources/_SwiftSyntaxMacros/MacroSystem+Builtin.swift

Lines changed: 12 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -29,59 +29,59 @@ private func replaceFirstLabel(
2929
public struct ColorLiteralMacro: ExpressionMacro {
3030
public static func apply(
3131
_ macro: MacroExpansionExprSyntax, in context: inout MacroExpansionContext
32-
) -> MacroResult<ExprSyntax> {
32+
) -> ExprSyntax {
3333
let argList = replaceFirstLabel(
3434
of: macro.argumentList, with: "_colorLiteralRed"
3535
)
3636
let initSyntax: ExprSyntax = ".init(\(argList))"
3737
if let leadingTrivia = macro.leadingTrivia {
38-
return MacroResult(initSyntax.withLeadingTrivia(leadingTrivia))
38+
return initSyntax.withLeadingTrivia(leadingTrivia)
3939
}
40-
return MacroResult(initSyntax)
40+
return initSyntax
4141
}
4242
}
4343

4444
public struct FileLiteralMacro: ExpressionMacro {
4545
public static func apply(
4646
_ macro: MacroExpansionExprSyntax, in context: inout MacroExpansionContext
47-
) -> MacroResult<ExprSyntax> {
47+
) -> ExprSyntax {
4848
let argList = replaceFirstLabel(
4949
of: macro.argumentList, with: "fileReferenceLiteralResourceName"
5050
)
5151
let initSyntax: ExprSyntax = ".init(\(argList))"
5252
if let leadingTrivia = macro.leadingTrivia {
53-
return MacroResult(initSyntax.withLeadingTrivia(leadingTrivia))
53+
return initSyntax.withLeadingTrivia(leadingTrivia)
5454
}
55-
return MacroResult(initSyntax)
55+
return initSyntax
5656
}
5757
}
5858

5959
public struct ImageLiteralMacro: ExpressionMacro {
6060
public static func apply(
6161
_ macro: MacroExpansionExprSyntax, in context: inout MacroExpansionContext
62-
) -> MacroResult<ExprSyntax> {
62+
) -> ExprSyntax {
6363
let argList = replaceFirstLabel(
6464
of: macro.argumentList, with: "imageLiteralResourceName"
6565
)
6666
let initSyntax: ExprSyntax = ".init(\(argList))"
6767
if let leadingTrivia = macro.leadingTrivia {
68-
return MacroResult(initSyntax.withLeadingTrivia(leadingTrivia))
68+
return initSyntax.withLeadingTrivia(leadingTrivia)
6969
}
70-
return MacroResult(initSyntax)
70+
return initSyntax
7171
}
7272
}
7373

7474
public struct FileIDMacro: ExpressionMacro {
7575
public static func apply(
7676
_ macro: MacroExpansionExprSyntax, in context: inout MacroExpansionContext
77-
) -> MacroResult<ExprSyntax> {
77+
) -> ExprSyntax {
7878
// FIXME: Compiler has more sophisticated file ID computation
7979
let fileID = "\(context.moduleName)/\(context.fileName)"
8080
let fileLiteral: ExprSyntax = "\(literal: fileID)"
8181
if let leadingTrivia = macro.leadingTrivia {
82-
return MacroResult(fileLiteral.withLeadingTrivia(leadingTrivia))
82+
return fileLiteral.withLeadingTrivia(leadingTrivia)
8383
}
84-
return MacroResult(fileLiteral)
84+
return fileLiteral
8585
}
8686
}
8787

Sources/_SwiftSyntaxMacros/MacroSystem+Examples.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -17,13 +17,13 @@ import SwiftSyntaxBuilder
1717
public struct StringifyMacro: ExpressionMacro {
1818
public static func apply(
1919
_ macro: MacroExpansionExprSyntax, in context: inout MacroExpansionContext
20-
) -> MacroResult<ExprSyntax> {
20+
) -> ExprSyntax {
2121
guard let argument = macro.argumentList.first?.expression else {
2222
// FIXME: Create a diagnostic for the missing argument?
23-
return MacroResult(ExprSyntax(macro))
23+
return ExprSyntax(macro)
2424
}
2525

26-
return MacroResult("(\(argument), \(StringLiteralExprSyntax(content: argument.description)))")
26+
return "(\(argument), \(StringLiteralExprSyntax(content: argument.description)))"
2727
}
2828
}
2929

Sources/_SwiftSyntaxMacros/MacroSystem.swift

Lines changed: 7 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -63,16 +63,13 @@ public struct MacroSystem {
6363
class MacroApplication : SyntaxRewriter {
6464
let macroSystem: MacroSystem
6565
var context: MacroExpansionContext
66-
let errorHandler: (MacroSystemError) -> Void
6766

6867
init(
6968
macroSystem: MacroSystem,
70-
context: MacroExpansionContext,
71-
errorHandler: @escaping (MacroSystemError) -> Void
69+
context: MacroExpansionContext
7270
) {
7371
self.macroSystem = macroSystem
7472
self.context = context
75-
self.errorHandler = errorHandler
7673
}
7774

7875
override func visitAny(_ node: Syntax) -> Syntax? {
@@ -81,7 +78,7 @@ class MacroApplication : SyntaxRewriter {
8178
}
8279

8380
return node.evaluateMacro(
84-
with: macroSystem, context: &context, errorHandler: errorHandler
81+
with: macroSystem, context: &context
8582
)
8683
}
8784

@@ -108,19 +105,14 @@ extension MacroSystem {
108105
///
109106
/// - Parameter node: The syntax node in which macros will be evaluated.
110107
/// - Parameter context: The context in which macros are evaluated.
111-
/// - Parameter errorHandler: Errors encountered during traversal will
112-
/// be passed to the error handler.
113108
/// - Returns: the syntax tree with all macros evaluated.
114109
public func evaluateMacros<Node: SyntaxProtocol>(
115110
node: Node,
116-
in context: inout MacroExpansionContext,
117-
errorHandler: (MacroSystemError) -> Void
111+
in context: inout MacroExpansionContext
118112
) -> Syntax {
119-
return withoutActuallyEscaping(errorHandler) { errorHandler in
120-
let applier = MacroApplication(
121-
macroSystem: self, context: context, errorHandler: errorHandler
122-
)
123-
return applier.visit(Syntax(node))
124-
}
113+
let applier = MacroApplication(
114+
macroSystem: self, context: context
115+
)
116+
return applier.visit(Syntax(node))
125117
}
126118
}

Sources/_SwiftSyntaxMacros/Syntax+MacroEvaluation.swift

Lines changed: 7 additions & 29 deletions
Original file line numberDiff line numberDiff line change
@@ -34,27 +34,14 @@ extension MacroExpansionExprSyntax {
3434
/// result and (possibly) some diagnostics.
3535
func evaluateMacro(
3636
_ macro: Macro.Type,
37-
in context: inout MacroExpansionContext,
38-
errorHandler: (MacroSystemError) -> Void
37+
in context: inout MacroExpansionContext
3938
) -> ExprSyntax {
4039
guard let exprMacro = macro as? ExpressionMacro.Type else {
41-
errorHandler(.requiresExpressionMacro(macro: macro, node: Syntax(self)))
4240
return ExprSyntax(self)
4341
}
4442

4543
// Handle the rewrite.
46-
let result = exprMacro.apply(disconnectedCopy(), in: &context)
47-
48-
// Report diagnostics, if there were any.
49-
if !result.diagnostics.isEmpty {
50-
errorHandler(
51-
.evaluationDiagnostics(
52-
node: Syntax(self), diagnostics: result.diagnostics
53-
)
54-
)
55-
}
56-
57-
return result.rewritten
44+
return exprMacro.apply(disconnectedCopy(), in: &context)
5845
}
5946
}
6047

@@ -81,16 +68,13 @@ extension MacroExpansionDeclSyntax {
8168
/// result and (possibly) some diagnostics.
8269
func evaluateMacro(
8370
_ macro: Macro.Type,
84-
in context: inout MacroExpansionContext,
85-
errorHandler: (MacroSystemError) -> Void
71+
in context: inout MacroExpansionContext
8672
) -> Syntax {
8773
// TODO: declaration/statement macros
8874

8975
// Fall back to evaluating as an expression macro.
9076
return Syntax(
91-
asMacroExpansionExpr().evaluateMacro(
92-
macro, in: &context, errorHandler: errorHandler
93-
)
77+
asMacroExpansionExpr().evaluateMacro(macro, in: &context)
9478
)
9579
}
9680
}
@@ -120,8 +104,7 @@ extension Syntax {
120104
/// some kind.
121105
public func evaluateMacro(
122106
with macroSystem: MacroSystem,
123-
context: inout MacroExpansionContext,
124-
errorHandler: (MacroSystemError) -> Void
107+
context: inout MacroExpansionContext
125108
) -> Syntax {
126109
// If this isn't a macro evaluation node, do nothing.
127110
guard let macroName = evaluatedMacroName else {
@@ -130,21 +113,16 @@ extension Syntax {
130113

131114
// Look for a macro with the given name. Otherwise, fail.
132115
guard let macro = macroSystem.macros[macroName] else {
133-
errorHandler(.unknownMacro(name: macroName, node: self))
134116
return self
135117
}
136118

137119
switch self.as(SyntaxEnum.self) {
138120
case .macroExpansionDecl(let expansion):
139-
return expansion.evaluateMacro(
140-
macro, in: &context, errorHandler: errorHandler
141-
)
121+
return expansion.evaluateMacro(macro, in: &context)
142122

143123
case .macroExpansionExpr(let expansion):
144124
return Syntax(
145-
expansion.evaluateMacro(
146-
macro, in: &context, errorHandler: errorHandler
147-
)
125+
expansion.evaluateMacro(macro, in: &context)
148126
)
149127

150128
default:

Sources/swift-parser-cli/swift-parser-cli.swift

Lines changed: 3 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -248,11 +248,9 @@ class ExpandMacros: ParsableCommand {
248248
var diags = ParseDiagnosticsGenerator.diagnostics(for: tree)
249249
let transformedTree = MacroSystem.exampleSystem.evaluateMacros(
250250
node: resultTree, in: &context
251-
) { error in
252-
if case let .evaluationDiagnostics(_, diagnostics) = error {
253-
diags.append(contentsOf: diagnostics)
254-
}
255-
}
251+
)
252+
253+
diags.append(contentsOf: context.diagnostics)
256254

257255
print(transformedTree)
258256
print(DiagnosticsFormatter.annotatedSource(tree: tree, diags: diags))

Tests/SwiftSyntaxMacrosTest/MacroSystemTests.swift

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -21,15 +21,15 @@ import _SwiftSyntaxTestSupport
2121
struct CheckContextIndependenceMacro: ExpressionMacro {
2222
static func apply(
2323
_ macro: MacroExpansionExprSyntax,
24-
in context: inout MacroExpansionContext) -> MacroResult<ExprSyntax> {
24+
in context: inout MacroExpansionContext) -> ExprSyntax {
2525

2626
// Should not have a parent.
2727
XCTAssertNil(macro.parent)
2828

2929
// Absolute starting position should be zero.
3030
XCTAssertEqual(macro.position.utf8Offset, 0)
3131

32-
return .init(ExprSyntax(macro))
32+
return ExprSyntax(macro)
3333
}
3434
}
3535

@@ -44,7 +44,7 @@ final class MacroSystemTests: XCTestCase {
4444
moduleName: "MyModule", fileName: "test.swift"
4545
)
4646
let transformedSF = MacroSystem.exampleSystem.evaluateMacros(
47-
node: sf, in: &context, errorHandler: { error in }
47+
node: sf, in: &context
4848
)
4949
AssertStringsEqualWithDiff(
5050
transformedSF.description,
@@ -67,7 +67,7 @@ final class MacroSystemTests: XCTestCase {
6767
moduleName: "MyModule", fileName: "test.swift"
6868
)
6969
let transformedSF = MacroSystem.exampleSystem.evaluateMacros(
70-
node: sf, in: &context, errorHandler: { error in }
70+
node: sf, in: &context
7171
)
7272
AssertStringsEqualWithDiff(
7373
transformedSF.description,
@@ -89,7 +89,7 @@ final class MacroSystemTests: XCTestCase {
8989
moduleName: "MyModule", fileName: "taylor.swift"
9090
)
9191
let transformedSF = MacroSystem.exampleSystem.evaluateMacros(
92-
node: sf, in: &context, errorHandler: { error in }
92+
node: sf, in: &context
9393
)
9494
AssertStringsEqualWithDiff(
9595
transformedSF.description,
@@ -122,7 +122,7 @@ final class MacroSystemTests: XCTestCase {
122122
moduleName: "MyModule", fileName: "taylor.swift"
123123
)
124124
let transformedSF = system.evaluateMacros(
125-
node: sf, in: &context, errorHandler: { error in }
125+
node: sf, in: &context
126126
)
127127
AssertStringsEqualWithDiff(
128128
transformedSF.description,

0 commit comments

Comments
 (0)