Why Macros
- Lots of build in code expansion like Codable and property wrappers
- Used to allow your own language features, to eliminate tedium and boiler plate.
Design Philosophy
- Different from C Macros
- Distinctive use sites
- All start with either # or @ depending on type of macros
- Complete, type-checked, validated – macros must be all of this
- Inserted in a predictable additive ways. It can not delete anything
- Should not be Magic – you can expand the macro in line or step into it in the debugger. Even if it is a closed source library.
Translation Model
- Basic concept, extract the usage from code and sends to compiler plugin, in separate process and sandbox, and returns an expansion of code – which is added to your program – which is then compiled with your code.
- All macros have to be declared so that the compiler can do the prior step – this is pacifically the API for the macro. You can either import it via library/framework or write it inline in your code.
- It must define it’s role
Macro Roles
- Role is a set of rules for the macro
- Where it can be used
- What types of code it expands into
- Where the expansions are inserted
- They are responsible for achieving the goals.
- There are two that create free standing macros and 5 that are attached macros
- An expression is a piece of code that executes and presents a result.
- Detailed examples for each of these types of macros are gone thru in the session
- If two different macros are attached to the same code it doesn’t matter about ordering, since they all are based on the original code.
Macro Implementation
- Comes after an = sign, and it is always another macro
- Usually an external macro implemented by a compiler plugin
- #externalMacro specifies the plugin to call and use to expand the code.
- You need to import SwiftSyntax – in your macro code to understand the Swift code syntax. Check out the Write Swift Macros session or the SwiftSyntax developer documentation.
- Import SwiftSyntaxMacros – protocols and types
- Import SwiftSyntaxBuilder – provides convince tools
- You should include comprehensive error codes for when someone tries to use it incorrectly
- You can provide Fix buttons, highlights and other information in your error message when the macro is used incorrectly
Writing correct macros
- Name collision – you can use the makeUniqueName() method on the macro expansion context.
- ● Swift needs to use names outside of the macro, so you need to use makeUniqueName() to solve this.
- Macros can only use the information that the compiler provides to them, so you can’t create a macro that inserts the current date and time (as an example)
- Testing – it’s an ordinary swift module so you should write normal swift unit test for it