Accessing source code after macro expansion

When building a tool that walks Swift source code with SwiftSyntax, is there a straightforward way to walk the source post macro expansion? Does this need to be manually done by trying to expand every source file?

In a tool I am building, I am copying source files and operating on them, but that is straight from the file system and pre-expansion. Specifically, the tool walks valid .swift files and captures all types that conform to a given protocol. In my case, I am using macros to add conformances to that protocol, but my build plugin doesn't have insight to that eventual conformance simply by reading the non-expanded source code. I am using the Target.directory to determine where source files are for a given target, but is there a better way to access a build directory where the expanded source lives?

Hi there!

If you're curious about how macro expansion works, you can read up on it in this documentation.

TL;DR: Macro expansion in Swift is based on an in-memory representation of the syntax, meaning you can't retrieve the expanded code directly from a source file without manually performing the expansion.

You might consider trying to expand all your macros using this method: SyntaxProtocol.expand(macros:in:).

Hope this helps!

1 Like

Thanks for the quick reply!

Does this mean that because a build tool plugin does not have insight into what potential macros are in use in a given targets source files, this makes it impossible to view a targets expanded source?

This would be unfortunate and mean that adopting macros to replace boilerplate that is then expected by plugin tools would potentially break source code or produce unexpected results.

1 Like

I'm not an expert in the field, but best to my understanding that's pretty much the crux of it. Swift's macros expand in-memory during compilation, and this process doesn't leave behind an expanded source file that can be inspected. This is different from some other languages where macro expansion results in a new source file. For build tool plugins that are designed to work with the source code, this can indeed pose a challenge.

So yes, if your build tool plugin is expecting certain code patterns or elements to be present in the source, and you're using macros to generate these elements, then the plugin might not work as expected.

Thanks for your input @Matejkob!

I'd be curious if there is anyone that can weigh in here on if there is a way that this can be worked around or if there is potential for this to be accounted for within the plugin system somehow, though it seems it would be difficult to do so.

1 Like