-
-
Notifications
You must be signed in to change notification settings - Fork 18
Expand file tree
/
Copy pathAddBlockerMacro.swift
More file actions
63 lines (55 loc) · 2.22 KB
/
AddBlockerMacro.swift
File metadata and controls
63 lines (55 loc) · 2.22 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
import MacroToolkit
import SwiftDiagnostics
import SwiftOperators
import SwiftSyntax
import SwiftSyntaxMacros
// Modified from: https://github.com/DougGregor/swift-macro-examples/blob/f61ac7cdca8dc3557e53f86e7e03df1353908d3e/MacroExamplesPlugin/AddBlocker.swift
/// Implementation of the `addBlocker` macro, which demonstrates how to
/// produce detailed diagnostics from a macro implementation for an utterly
/// silly task: warning about every "add" (binary +) in the argument, with a
/// Fix-It that changes it to a "-".
public struct AddBlockerMacro: ExpressionMacro {
class AddVisitor: SyntaxRewriter {
var diagnostics: [Diagnostic] = []
override func visit(
_ node: BinaryOperatorExprSyntax
) -> ExprSyntax {
if node.operator.text == "+" {
let messageID = MessageID(domain: "ExampleMacros", id: "addBlocker")
diagnostics.append(
DiagnosticBuilder(for: node.operator)
.message("blocked an add; did you mean to subtract?")
.messageID(messageID)
.severity(.warning)
.suggestReplacement(
"use '-'",
old: node.operator,
new: node.operator.with(\.tokenKind, .binaryOperator("-"))
)
.build()
)
return ExprSyntax(
node.with(
\.operator,
node.operator.with(\.tokenKind, .binaryOperator("-"))
)
)
}
return ExprSyntax(node)
}
}
public static func expansion(
of node: some FreestandingMacroExpansionSyntax,
in context: some MacroExpansionContext
) throws -> ExprSyntax {
guard let (argument) = destructureSingle(node.argumentList) else {
throw MacroError("#addBlocker only expects one argument")
}
let visitor = AddVisitor()
let result = visitor.visit(argument.expression)
for diag in visitor.diagnostics {
context.diagnose(diag)
}
return ExprSyntax(result)
}
}