Skip to content

Commit 68d4f24

Browse files
authored
Merge pull request #62598 from DougGregor/macro-diagnostics-fixes
Macro diagnostics fixes
2 parents 9eb3adb + cb3a24e commit 68d4f24

File tree

9 files changed

+56
-43
lines changed

9 files changed

+56
-43
lines changed

lib/ASTGen/Sources/ASTGen/Diagnostics.swift

Lines changed: 4 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import SwiftSyntax
55
fileprivate func emitDiagnosticParts(
66
diagEnginePtr: UnsafeMutablePointer<UInt8>,
77
sourceFileBuffer: UnsafeMutableBufferPointer<UInt8>,
8-
nodeStartOffset: Int?,
98
message: String,
109
severity: DiagnosticSeverity,
1110
position: AbsolutePosition,
@@ -22,18 +21,8 @@ fileprivate func emitDiagnosticParts(
2221

2322
// Form a source location for the given absolute position
2423
func sourceLoc(
25-
at origPosition: AbsolutePosition
24+
at position: AbsolutePosition
2625
) -> UnsafeMutablePointer<UInt8>? {
27-
// FIXME: Our tree is very confused about absolute offsets. Work around
28-
// the issue in a very hacky way.
29-
let position: AbsolutePosition
30-
if let nodeStartOffset = nodeStartOffset,
31-
origPosition.utf8Offset < nodeStartOffset {
32-
position = origPosition + SourceLength(utf8Length: nodeStartOffset)
33-
} else {
34-
position = origPosition
35-
}
36-
3726
if let sourceFileBase = sourceFileBuffer.baseAddress,
3827
position.utf8Offset >= 0 &&
3928
position.utf8Offset < sourceFileBuffer.count {
@@ -99,8 +88,8 @@ fileprivate func emitDiagnosticParts(
9988
func emitDiagnostic(
10089
diagEnginePtr: UnsafeMutablePointer<UInt8>,
10190
sourceFileBuffer: UnsafeMutableBufferPointer<UInt8>,
102-
nodeStartOffset: Int? = nil,
103-
diagnostic: Diagnostic
91+
diagnostic: Diagnostic,
92+
messageSuffix: String? = nil
10493
) {
10594
// Collect all of the Fix-It changes based on their Fix-It ID.
10695
var fixItChangesByID: [MessageID : [FixIt.Change]] = [:]
@@ -113,8 +102,7 @@ func emitDiagnostic(
113102
emitDiagnosticParts(
114103
diagEnginePtr: diagEnginePtr,
115104
sourceFileBuffer: sourceFileBuffer,
116-
nodeStartOffset: nodeStartOffset,
117-
message: diagnostic.diagMessage.message,
105+
message: diagnostic.diagMessage.message + (messageSuffix ?? ""),
118106
severity: diagnostic.diagMessage.severity,
119107
position: diagnostic.position,
120108
highlights: diagnostic.highlights,
@@ -126,7 +114,6 @@ func emitDiagnostic(
126114
emitDiagnosticParts(
127115
diagEnginePtr: diagEnginePtr,
128116
sourceFileBuffer: sourceFileBuffer,
129-
nodeStartOffset: nodeStartOffset,
130117
message: note.message,
131118
severity: .note, position: note.position,
132119
fixItChanges: fixItChangesByID[note.noteMessage.fixItID] ?? []

lib/ASTGen/Sources/ASTGen/Macros.swift

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -176,14 +176,13 @@ func evaluateMacro(
176176
}
177177

178178
// Emit diagnostics accumulated in the context.
179+
let macroName = parentExpansion.macro.withoutTrivia().description
179180
for diag in context.diagnostics {
180-
// FIXME: Consider tacking on a note that says that this diagnostic
181-
// came from a macro expansion.
182181
emitDiagnostic(
183182
diagEnginePtr: diagEnginePtr,
184183
sourceFileBuffer: .init(mutating: sourceFile.pointee.buffer),
185-
nodeStartOffset: parentSyntax.position.utf8Offset,
186-
diagnostic: diag
184+
diagnostic: diag,
185+
messageSuffix: " (from macro '\(macroName)')"
187186
)
188187
}
189188

test/Index/index_macros.swift

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -3,9 +3,9 @@
33
// REQUIRES: OS=macosx
44

55

6-
macro myLine: Int = _SwiftSyntaxMacros.LineMacro
7-
macro myFilename<T: ExpressibleByStringLiteral>: T = _SwiftSyntaxMacros.FilePathMacro
8-
macro myStringify<T>(_: T) -> (T, String) = _SwiftSyntaxMacros.StringifyMacro
6+
macro myLine: Int = MacroDefinition.LineMacro
7+
macro myFilename<T: ExpressibleByStringLiteral>: T = MacroDefinition.FileMacro
8+
macro myStringify<T>(_: T) -> (T, String) = MacroDefinition.StringifyMacro
99

1010
func test(x: Int) {
1111
_ = #myLine

test/Macros/Inputs/syntax_macro_definitions.swift

Lines changed: 33 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -63,6 +63,10 @@ struct SimpleDiagnosticMessage: DiagnosticMessage {
6363
let severity: DiagnosticSeverity
6464
}
6565

66+
extension SimpleDiagnosticMessage: FixItMessage {
67+
var fixItID: MessageID { diagnosticID }
68+
}
69+
6670
public struct AddBlocker: ExpressionMacro {
6771
public static func expansion(
6872
of node: MacroExpansionExprSyntax, in context: inout MacroExpansionContext
@@ -77,12 +81,13 @@ public struct AddBlocker: ExpressionMacro {
7781
context.diagnose(error.asDiagnostic)
7882
}
7983

84+
// Link the folded argument back into the tree.
85+
var node = node.withArgumentList(node.argumentList.replacing(childAt: 0, with: node.argumentList.first!.withExpression(foldedArgument.as(ExprSyntax.self)!)))
86+
8087
class AddVisitor: SyntaxVisitor {
8188
var diagnostics: [Diagnostic] = []
82-
let startPosition: AbsolutePosition
8389

84-
init(startPosition: AbsolutePosition) {
85-
self.startPosition = startPosition
90+
init() {
8691
super.init(viewMode: .sourceAccurate)
8792
}
8893

@@ -91,18 +96,38 @@ public struct AddBlocker: ExpressionMacro {
9196
) -> SyntaxVisitorContinueKind {
9297
if let binOp = node.operatorOperand.as(BinaryOperatorExprSyntax.self) {
9398
if binOp.operatorToken.text == "+" {
99+
let messageID = MessageID(domain: "silly", id: "addblock")
94100
diagnostics.append(
95101
Diagnostic(
96102
node: Syntax(node.operatorOperand),
97-
position: startPosition + SourceLength(utf8Length: binOp.operatorToken.position.utf8Offset),
98103
message: SimpleDiagnosticMessage(
99-
message: "blocked an add",
100-
diagnosticID: MessageID(domain: "silly", id: "addblock"),
104+
message: "blocked an add; did you mean to subtract?",
105+
diagnosticID: messageID,
101106
severity: .error
102107
),
103108
highlights: [
104109
Syntax(node.leftOperand.withoutTrivia()),
105110
Syntax(node.rightOperand.withoutTrivia())
111+
],
112+
fixIts: [
113+
FixIt(
114+
message: SimpleDiagnosticMessage(
115+
message: "use '-'",
116+
diagnosticID: messageID,
117+
severity: .error
118+
),
119+
changes: [
120+
FixIt.Change.replace(
121+
oldNode: Syntax(binOp.operatorToken.withoutTrivia()),
122+
newNode: Syntax(
123+
TokenSyntax(
124+
.spacedBinaryOperator("-"),
125+
presence: .present
126+
)
127+
)
128+
)
129+
]
130+
),
106131
]
107132
)
108133
)
@@ -113,8 +138,8 @@ public struct AddBlocker: ExpressionMacro {
113138
}
114139
}
115140

116-
let visitor = AddVisitor(startPosition: argument.position)
117-
visitor.walk(Syntax(foldedArgument))
141+
let visitor = AddVisitor()
142+
visitor.walk(Syntax(node))
118143

119144
for diag in visitor.diagnostics {
120145
context.diagnose(diag)

test/Macros/macro_expand.swift

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -53,7 +53,6 @@ macro addBlocker<T>(_ value: T) -> T = MacroDefinition.AddBlocker
5353
func testAddBlocker(a: Int, b: Int, c: Int) {
5454
_ = #addBlocker(a * b * c)
5555
#if TEST_DIAGNOSTICS
56-
// FIXME: Highlight locations are wrong.
57-
_ = #addBlocker(a + b * c) // expected-error{{blocked an add}}
56+
_ = #addBlocker(a + b * c) // expected-error{{blocked an add; did you mean to subtract? (from macro 'addBlocker')}}{{21-22=-}}
5857
#endif
5958
}

test/Macros/macros_diagnostics.swift

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
1-
// RUN: %target-typecheck-verify-swift -enable-experimental-feature Macros -module-name MacrosTest
1+
// RUN: %empty-directory(%t)
2+
// RUN: %target-build-swift -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
3+
// RUN: %target-typecheck-verify-swift -enable-experimental-feature Macros -module-name MacrosTest -load-plugin-library %t/%target-library-name(MacroDefinition) -I %swift-host-lib-dir
24
// REQUIRES: OS=macosx
35

4-
macro stringify<T>(_ value: T) -> (T, String) = _SwiftSyntaxMacros.StringifyMacro
6+
macro stringify<T>(_ value: T) -> (T, String) = MacroDefinition.StringifyMacro
57
macro missingMacro1(_: Any) = MissingModule.MissingType // expected-note{{'missingMacro1' declared here}}
68
macro missingMacro2(_: Any) = MissingModule.MissingType
79

test/ModuleInterface/macros.swift

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -7,14 +7,14 @@
77
// RUN: %target-swift-frontend -compile-module-from-interface %t/Macros.swiftinterface -o %t/Macros.swiftmodule
88

99
// CHECK: #if compiler(>=5.3) && $Macros
10-
// CHECK-NEXT: public macro publicStringify<T>(_ value: T) -> (T, Swift.String) = _SwiftSyntaxMacros.StringifyMacro
10+
// CHECK-NEXT: public macro publicStringify<T>(_ value: T) -> (T, Swift.String) = SomeModule.StringifyMacro
1111
// CHECK-NEXT: #endif
12-
public macro publicStringify<T>(_ value: T) -> (T, String) = _SwiftSyntaxMacros.StringifyMacro
12+
public macro publicStringify<T>(_ value: T) -> (T, String) = SomeModule.StringifyMacro
1313

1414
// CHECK: #if compiler(>=5.3) && $Macros
15-
// CHECK: public macro publicLine<T>: T = _SwiftSyntaxMacros.Line where T : Swift.ExpressibleByIntegerLiteral
15+
// CHECK: public macro publicLine<T>: T = SomeModule.Line where T : Swift.ExpressibleByIntegerLiteral
1616
// CHECK-NEXT: #endif
17-
public macro publicLine<T: ExpressibleByIntegerLiteral>: T = _SwiftSyntaxMacros.Line
17+
public macro publicLine<T: ExpressibleByIntegerLiteral>: T = SomeModule.Line
1818

1919
// CHECK-NOT: internalStringify
20-
macro internalStringify<T>(_ value: T) -> (T, String) = _SwiftSyntaxMacros.StringifyMacro
20+
macro internalStringify<T>(_ value: T) -> (T, String) = SomeModule.StringifyMacro
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
public macro publicStringify<T>(_ value: T) -> (T, String) = _SwiftSyntaxMacros.StringifyMacro
1+
public macro publicStringify<T>(_ value: T) -> (T, String) = SomeModule.StringifyMacro
22

3-
macro internalStringify<T>(_ value: T) -> (T, String) = _SwiftSyntaxMacros.StringifyMacro
3+
macro internalStringify<T>(_ value: T) -> (T, String) = SomeModule.StringifyMacro

test/Serialization/macros.swift

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@ import def_macros
1010

1111
func test(a: Int, b: Int) {
1212
_ = #publicStringify(a + b)
13+
// expected-error@-1{{external macro implementation type 'SomeModule.StringifyMacro' could not be found for macro 'publicStringify'; the type must be public and provided via '-load-plugin-library'}}
1314

1415
_ = #internalStringify(a + b)
1516
// expected-error@-1{{macro 'internalStringify' is undefined}}

0 commit comments

Comments
 (0)