swiftlang / swiftlang/swift-syntax

MacroSystem expansion detached nodes lose diagnostic context

Open
#2,054 4 comments 0 reactions 0 assignees View on GitHub
Dominant language
Swift
Stars
3.7k
Forks
553
Avg merge
5d 13h
Merged PRs (30d)
16

Description

### Description

Macro expansions create diagnostics that are not relative to the given context (because they're `detached`), which means that there's no way to collocate diagnostics with the original source.

### Steps to Reproduce

You can take the `AddBlocker` macro demo from [swift-macro-examples](/DougGregor/swift-macro-examples) and expand the given macro:

```swift
let x = 1
let y = 2
let z = 3
#addBlocker(x * y + z)
```

If you expand as is, the context's diagnostic for the "+" will be relative to the `#addBlocker` expression macro node, not the entire source (starting at `let x = 1`), so formatting the diagnostics against the original source will render the diagnostic in the wrong place:

```swift
let x = 1
let y = 2
// ╰─ warning: blocked an add; did you mean to subtract?
let z = 3
#addBlocker(x * y + z)
```

It can be rendered correctly by _not_ detaching the context during expansion [here](https://github.com/apple/swift-syntax/blob/f6953015ba2d8c97df61760b614c59c084b72c7d/Sources/SwiftSyntaxMacroExpansion/MacroSystem.swift#L83):

```diff
-node: node.detach(in: context),
+node: node, //.detach(in: context),
```
```swift
let x = 1
let y = 2
let z = 3
#addBlocker(x * y + z)
// ╰─ warning: blocked an add; did you mean to subtract?
```

Diagnostics added during expansion should ideally be adjusted from where they were detached.

Contributor guide

Open the contributing guide

Assessment

This issue has not been assessed yet.

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.