Thanks so much for your feedback!
As for the proposed example, I'm afraid it's not going to work as expected. Using a macro on an extension of a protocol in totally different file rather than the protocol declaration itself might seem like an elegant solution at first, but it's important to understand how macros actually work.
During compilation, Swift expands any macros in code before building code as usual. Macros operate on the Abstract Syntax Tree (AST), which is a tree representation of the syntactic structure of the code. Macros themselves do not have any knowledge about the types, classes, or interfaces - they only have access to this plain textual structure.
Therefore, attaching a macro to an extension won't have the effect you're hoping for, because the macro won't know anything about the extended protocol. The protocol and the extension are separate entities in the AST and the macro wouldn't be able to connect them.
As @mlienert mentioned:
We could indeed utilize compiler directives, specifically the #if directive, to check whether the DEBUG flag is enabled or not. This way, we can include the spy code only when the app is built in debug mode for testing. When the app is compiled for a release, the spy code would be ignored and wouldn't be a part of the final executable.
Here's an example of how this might look:
@Spyable
protocol Foo {
func bar()
}
// expends to:
#if DEBUG
class FooSpy: Foo { ... }
#endif
This strategy should help us keep our production codebase clean while still maintaining the convenience of having test spies during our development process. Please let me know if you have any thoughts or further questions on this approach!