Skip to content

#line macro cannot access original location inside of body macro #3253

Description

@fthdgn

Description

#line value is wrong inside of body macro, even after using #sourceLocation to fix it.

Steps to Reproduce

I will use this macro implementation from #2757. It is only online example I can found which uses sourceLocation.

@attached(body)
public macro SourceLocationMacro(_ properties: String...) =
    #externalMacro(module: "MyMacros", type: "SourceLocationMacro")
public struct SourceLocationMacro: BodyMacro {
    public static var formatMode: FormatMode { .disabled }
    public static func expansion(of node: AttributeSyntax, providingBodyFor declaration: some DeclSyntaxProtocol & WithOptionalCodeBlockSyntax, in context: some MacroExpansionContext) throws -> [CodeBlockItemSyntax] {
        
        if let statements = declaration.body?.statements {
            var body: [CodeBlockItemSyntax] = []
            statements.forEach { statement in
                if let location = context.location(of: statement, at: .afterLeadingTrivia, filePathMode: .filePath) {
                    let transformed = CodeBlockItemListSyntax {
                        "\n#sourceLocation(file: \(location.file), line: \(location.line))"
                        statement
                        "\n#sourceLocation()"
                    }
                    body.append(contentsOf: transformed)
                }
            }
            return body
        } else {
            return []
        }
    }
}
    // this line is 237 on original source code
    @SourceLocationMacro
    func demo() {
        let x: Int = 1
        print("demo line", #line)
    }

Expanded macro

{

#sourceLocation(file: "/***/AppDelegate.swift", line: 240)
        let x: Int = 1
#sourceLocation()
#sourceLocation(file: "/***/AppDelegate.swift", line: 241)
        print("demo line", #line)
#sourceLocation()
}

On this example sourceLocation does something, it makes Xcode to jump correct line on from the build warning about unused variable. This is the original purpose of the issue #2757. If the macro does not insert sourceLocation lines, the Xcode jumps to a generated code snippet.

My problem is that, sourceLocation does not fix #line value. It prints 239 instead of 241.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions