swiftlang/swift-syntax

Fix-it Application Failure in `assertMacroExpansion` Function

Closed this issue · 1 comments

Description

The fix-it provided by a peer macro is correctly applied by the compiler, yet the assertMacroExpansion function fails to apply it appropriately.

Steps to Reproduce

  1. Reference the example Macro from SwiftSyntax repository: https://github.com/apple/swift-syntax/blob/098b177830c0d2e614b3757241b2572d758f9143/Examples/Sources/MacroExamples/Implementation/Peer/AddCompletionHandlerMacro.swift#L18-L164
  2. Utilize the macro in the code as shown:
    struct Test {
      @AddCompletionHandler
      func fetchData() -> String {
        return "Hello, World!"
      }
    }
    The macro generates a diagnostic with a fix-it add 'async'.
  3. When the fix-it is applied using the compiler, the async keyword is correctly inserted before -> String.
  4. Construct a unit test to validate this scenario:
    func testExpansionOnNonAsyncFunctionAppliesFixIt() {
      assertMacroExpansion(
        """
        struct Test {
          @AddCompletionHandler
          func fetchData() -> String {
            return "Hello, World!"
          }
        }
        """,
        expandedSource: """
          struct Test {
            func fetchData() -> String {
              return "Hello, World!"
            }
          }
          """,
        diagnostics: [
          DiagnosticSpec(
            message: "can only add a completion-handler variant to an 'async' function",
            line: 3,
            column: 3,
            severity: .error,
            fixIts: [FixItSpec(message: "add 'async'")]
          )
        ],
        macros: macros,
        applyFixIts: ["add 'async'"],
        fixedSource: """
        struct Test {
          @AddCompletionHandler
          func fetchData() async -> String {
            return "Hello, World!"
          }
        }
        """,
        indentationWidth: .spaces(2)
      )
    }
    The expectation is for the test to pass, but it fails. The fixedSource string produced by the assertMacroExpansion function erroneously manifests as:
    struct Test {
      @AddCompletionHandler
      f() async -> String () -> String {
        return "Hello, World!"
      }
    }
    Notice the incorrect placement and duplication of the function signature, suggesting that the fix-it application is not handling the source code transformation as intended.

Tracked in Apple’s issue tracker as rdar://118012820