Swift Macros : Le Guide Complet de la Métaprogrammation

Publié le · Mis à jour le · 22 min

Wlad
Wlad
Fondateur & Tech Lead Swift

Qu'est-ce qu'une macro Swift ?

Une macro est une transformation de code source qui s'exécute au moment de la compilation. Contrairement aux macros C qui effectuent de simples remplacements de texte, les macros Swift travaillent sur l'arbre syntaxique abstrait (AST) et sont entièrement type-safe.

Les caractéristiques principales :

  • Génération de code à la compilation, pas à l'exécution

  • Vérification de types complète sur le code généré

  • Exécution dans un environnement sandbox sécurisé

  • Possibilité d'inspecter le code généré dans Xcode

  • Intégration native avec SwiftPM

Les macros résolvent des problèmes que ni les génériques, ni les protocoles, ni les property wrappers ne pouvaient résoudre élégamment.

Avant les macros

Avant Swift 5.9, les développeurs utilisaient plusieurs approches pour réduire le boilerplate :

ApprocheAvantagesInconvénients

Property Wrappers

Intégrés au langage

Limités aux propriétés

Sourcery

Très puissant

Outil externe, maintenance

Protocoles + Extensions

Standard Swift

Pas de génération de code

Code generation scripts

Flexible

Hors du compilateur

Les macros combinent le meilleur : puissance de Sourcery, intégration native, et sécurité du compilateur.

Timeline des macros

Swift 5.9 — Septembre 2023

Introduction des macros avec trois proposals fondatrices :

  • SE-0382 : Expression Macros

  • SE-0389 : Attached Macros

  • SE-0397 : Freestanding Declaration Macros

Swift 6.0 — Septembre 2024

Stabilisation et adoption massive. Apple introduit @Observable et @Model.

Swift 6.1+ — 2025

Améliorations continues de SwiftSyntax et nouvelles proposals en discussion (Body Macros SE-0415).

Les deux familles de macros

Swift distingue deux types de macros selon leur syntaxe d'utilisation :

Freestanding Macros

Utilisent le préfixe # et peuvent apparaître comme expressions ou déclarations :

Attached Macros

Utilisent le préfixe @ et s'attachent à une déclaration existante :

Tableau des rôles de macros

RôleSyntaxeDescription

@freestanding(expression)

#macro()

Retourne une valeur

@freestanding(declaration)

#macro()

Génère des déclarations

@attached(peer)

@Macro

Ajoute des déclarations à côté

@attached(accessor)

@Macro

Ajoute get/set/willSet/didSet

@attached(memberAttribute)

@Macro

Ajoute des attributs aux membres

@attached(member)

@Macro

Ajoute de nouveaux membres

@attached(extension)

@Macro

Ajoute des conformances

Une macro peut combiner plusieurs rôles.

Freestanding Expression Macros

Les expression macros (@freestanding(expression)) retournent une valeur utilisable dans le code :

Exemple : #stringify

La macro #stringify retourne un tuple avec la valeur et sa représentation textuelle :

Exemple : #URL avec validation

Exemple : #Predicate

Freestanding Declaration Macros

Les declaration macros (@freestanding(declaration)) génèrent de nouvelles déclarations :

Attached Peer Macros

Les peer macros ajoutent des déclarations "à côté" de la déclaration annotée :

Attached Accessor Macros

Les accessor macros ajoutent des accesseurs (get, set, willSet, didSet) :

Attached Member Macros

Les member macros ajoutent de nouveaux membres à un type :

Attached Extension Macros

Les extension macros ajoutent des conformances de protocoles :

Attached MemberAttribute Macros

Les memberAttribute macros appliquent des attributs à tous les membres :

Macros d'Apple dans la stdlib

Apple utilise massivement les macros dans ses propres frameworks :

@Observable (Observation framework)

@Model (SwiftData)

#expect et #require (Swift Testing)

#Predicate (Foundation)

Créer sa première macro — Pas à pas

Créons une macro @AutoDescription qui génère une description lisible.

Structure du package

Package.swift

Déclaration de la macro

Implémentation de la macro

Utilisation

SwiftSyntax — Le coeur des macros

SwiftSyntax est la bibliothèque qui permet de manipuler l'AST Swift.

Les protocoles principaux

Naviguer dans l'AST

SwiftSyntaxBuilder — Générer du code

SwiftSyntaxBuilder permet de construire du code avec une syntaxe expressive :

MacroExpansionContext

Le contexte fournit des informations utiles :

Debugging et tests

Expand Macro dans Xcode

Clic droit sur une macro → "Expand Macro" pour voir le code généré :

Tests unitaires de macros

SwiftSyntax fournit des utilitaires de test :

Diagnostics custom

Créez des messages d'erreur informatifs :

Macros populaires de l'écosystème

swift-dependencies (@Dependency)

swift-composable-architecture (@Reducer)

Autres macros populaires

La communauté a créé de nombreuses macros open source :

  • @CodableKey : Personnalisation des clés JSON

  • @Builder : Pattern builder automatique

  • @EnumSubset : Sous-ensembles d'enum type-safe

  • @Copyable : Méthode copy(with:) automatique

  • @DefaultValue : Valeurs par défaut pour Codable

Bonnes pratiques

Quand utiliser les macros

Les macros sont appropriées pour :

  • Éliminer du boilerplate répétitif

  • Générer du code basé sur la structure existante

  • Ajouter des conformances automatiques

  • Valider des données à la compilation

Quand éviter les macros

Les macros ne sont pas idéales pour :

  • Logique métier complexe (préférer des fonctions)

  • Cas simples couverts par les protocoles

  • Transformations qui changent fréquemment

Performance de compilation

Les macros s'exécutent à chaque compilation. Gardez-les légères :

Versioning SwiftSyntax

SwiftSyntax évolue avec chaque version de Swift. Spécifiez une version compatible :

Limites et sécurité

Sandbox d'exécution

Les macros s'exécutent dans un environnement isolé :

  • Pas d'accès au système de fichiers

  • Pas de réseau

  • Pas d'exécution de code arbitraire

  • Mémoire et temps limités

Ce que les macros ne peuvent pas faire

Vérification à la compilation

Le code généré est entièrement vérifié :

Ressources officielles

Documentation Apple

Swift Evolution Proposals

ProposalTitreStatus

SE-0382

Expression Macros

Implémenté (Swift 5.9)

SE-0389

Attached Macros

Implémenté (Swift 5.9)

SE-0394

Package Manager Support for Custom Macros

Implémenté (Swift 5.9)

SE-0397

Freestanding Declaration Macros

Implémenté (Swift 5.9)

SE-0415

Function Body Macros

En discussion

Communauté

Les Swift Macros représentent un outil puissant pour tout développeur Swift sérieux. Maîtrisées correctement, elles permettent d'écrire du code plus propre, plus sûr et plus maintenable.