I don't think "not realistically usably by third-parties" is a fair characterization. SwiftLint is actively migrating over to SwiftSyntax, and a number of folks here in this thread have managed to build nontrivial macros with it despite the limitations of the prototype. Yes, we can improve tutorials (some of which ha happened during this review), and as more examples and docs are written over time it'll get easier to get started.
There's several kinds of "stepped through in a debugger" that apply for macros. The first is stepping through the syntactic transformation as it occurs, to debug the workings of the macro itself. The macro being a normal Swift program means this is the just the normal debugger. Since we're doing syntactic transforms, stepping through the transform involves putting the Swift code you want to start with in a string literal that initializes a SourceFileSyntax
:
let sf: SourceFileSyntax =
"""
my code that uses macros
"
and then calling sf.expand(macros: [MyMacroType.self], in: testContext)
and checking whether you get the source code out. The simple test in the example repository is all it takes, and you can single-step through the transformation.
If you want to do it "online", as part of the compiler running, you can break at the start of the macro program. Debuggers can do that (by following the process launch), and one could make it a little easier with extra tooling.
This is actually a huge benefit to this "macros are normal Swift programs" approach, because all the existing tools apply. In contrast, if we had some kind of macro interpreter in the compiler---say, a more declaration macro scheme, or interpreted sublanguage---then you would need special debugging tools.
A second thing "debugging macros" can mean is understanding what's failing to type check in the code that resulted from the expansion. Perhaps the expansion is correct, but your inputs were wrong in some way, and you need to make sure you see the result of the expansion to understand the diagnostics. This is less "step through in a debugger", yet still important. I gave a long-winded answer about how the system is designed to track all of the information needed to see through the layers of macro expansion.
Finally, "debugging macros" could mean debugging the code produced by macro expansion. This means ensuring that the results of macro expansion persist in some form that can be used for debugging, and that one can (say) step into a macro expansion to walk into the expanded code. This is absolutely achievable in the implementation.
I vehemently disagree with this statement. The model has been designed to be debuggable. But Xiaodi is correct in drawing the line between "can be implemented well" and "is guaranteed to be implemented well". The former is relevant to the design, the latter is not.
Doug