Add resolvable directive system for extensible type and value directives#84
Merged
lorisleiva merged 1 commit intomainfrom Mar 18, 2026
Merged
Add resolvable directive system for extensible type and value directives#84lorisleiva merged 1 commit intomainfrom
lorisleiva merged 1 commit intomainfrom
Conversation
This PR introduces a system that allows Codama plugins to contribute custom type and value directives inside `#[codama(...)]` attributes using a namespaced `prefix::name(...)` syntax. Today, all type and value directives inside `#[codama(...)]` are hardcoded. If someone wants a shorthand like `ata(...)` for Associated Token Account PDAs, it must be added to the core `codama-attributes` crate. This PR makes these directive slots extensible so that plugins can provide their own. Any directive with exactly two path segments (e.g., `token::ata(...)`) is treated as a resolvable directive. Single-segment paths (e.g., `payer`, `number(u8)`) continue to be parsed as built-in directives with hard errors on unrecognized names. ```rust // Built-in (parsed eagerly as before): // Resolvable (deferred to a plugin for resolution): // Composable (multiple plugins in one attribute): ``` Directive structs now store `Resolvable<T>` instead of bare node types in their type/value slots. `Resolvable<T>` is either `Resolved(T)` (a concrete node) or `Unresolved(ResolvableDirective)` (namespace + name + raw meta, waiting for a plugin to resolve it). Before any lifecycle hooks fire, the framework runs a `ResolveDirectivesVisitor` that walks the korok tree and delegates each `Unresolved` entry to the `DirectiveResolver` (built from all installed plugins). Plugins implement `resolve_type_directive` and/or `resolve_value_directive` on the `KorokPlugin` trait to claim directives matching their namespace. Nested resolution across plugins is supported — a plugin can call the resolver for directives belonging to other plugins while parsing its own arguments. - **`codama-syn-helpers`**: `Meta`, `PathValue`, `PathList` now implement `Clone` and `PartialEq`. - **`codama-errors`**: New `CodamaError::UnresolvedDirective` variant. - **`codama-attributes`**: New `Resolvable<T>` enum and `ResolvableDirective` struct. `TypeDirective`, `DefaultValueDirective`, `AccountDirective`, `FieldDirective`, `ArgumentDirective`, and `SeedDirective` now store `Resolvable<T>` in their type/value slots. `SeedDirectiveType::Defined` replaced by `Variable` and `Constant` variants. Directive structs that previously stored inline nodes (`AccountDirective`, `FieldDirective`, `ArgumentDirective`) now store individual fields with `to_*_node()` methods for constructing the node after resolution. - **`codama-korok-plugins`**: New `DirectiveResolver` trait, `CompositeDirectiveResolver` implementation, and `ResolveDirectivesVisitor`. `KorokPlugin` gains `resolve_type_directive` and `resolve_value_directive` methods. `resolve_plugins()` automatically runs directive resolution before `on_initialized`. - **`codama-korok-visitors`**: All visitors that consume directives now propagate `CodamaResult` errors from `try_resolved()` instead of silently skipping unresolved entries.
amilz
reviewed
Mar 18, 2026
4 tasks
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
This PR introduces a system that allows Codama plugins to contribute custom type and value directives inside
#[codama(...)]attributes using a namespacedprefix::name(...)syntax.Context
Today, all type and value directives inside
#[codama(...)]are hardcoded. If someone wants a shorthand likeata(...)for Associated Token Account PDAs, it must be added to the corecodama-attributescrate. This PR makes these directive slots extensible so that plugins can provide their own.Syntax
Any directive with exactly two path segments (e.g.,
token::ata(...)) is treated as a resolvable directive. Single-segment paths (e.g.,payer,number(u8)) continue to be parsed as built-in directives with hard errors on unrecognized names.How it works
Directive structs now store
Resolvable<T>instead of bare node types in their type/value slots.Resolvable<T>is eitherResolved(T)(a concrete node) orUnresolved(ResolvableDirective)(namespace + name + raw meta, waiting for a plugin to resolve it). Before any lifecycle hooks fire, the framework runs aResolveDirectivesVisitorthat walks the korok tree and delegates eachUnresolvedentry to theDirectiveResolver(built from all installed plugins). Plugins implementresolve_type_directiveand/orresolve_value_directiveon theKorokPlugintrait to claim directives matching their namespace. Nested resolution across plugins is supported — a plugin can call the resolver for directives belonging to other plugins while parsing its own arguments.Changes
codama-syn-helpers:Meta,PathValue,PathListnow implementCloneandPartialEq.codama-errors: NewCodamaError::UnresolvedDirectivevariant.codama-attributes: NewResolvable<T>enum andResolvableDirectivestruct.TypeDirective,DefaultValueDirective,AccountDirective,FieldDirective,ArgumentDirective, andSeedDirectivenow storeResolvable<T>in their type/value slots.SeedDirectiveType::Definedreplaced byVariableandConstantvariants. Directive structs that previously stored inline nodes (AccountDirective,FieldDirective,ArgumentDirective) now store individual fields withto_*_node()methods for constructing the node after resolution.codama-korok-plugins: NewDirectiveResolvertrait,CompositeDirectiveResolverimplementation, andResolveDirectivesVisitor.KorokPlugingainsresolve_type_directiveandresolve_value_directivemethods.resolve_plugins()automatically runs directive resolution beforeon_initialized.codama-korok-visitors: All visitors that consume directives now propagateCodamaResulterrors fromtry_resolved()instead of silently skipping unresolved entries.