Skip to content

Allow crate-level program(name/address) to override the primary program - #131

Merged
lorisleiva merged 1 commit into
mainfrom
feat/crate-scope-program-name-override
Aug 18, 2026
Merged

Allow crate-level program(name/address) to override the primary program#131
lorisleiva merged 1 commit into
mainfrom
feat/crate-scope-program-name-override

Conversation

@lorisleiva

Copy link
Copy Markdown
Member

This PR lets a crate-level #![codama(program(name = ..., address = ...))] directive override the primary program's identity, with either argument optional so omitted fields fall back to the crate defaults (the Cargo.toml package name and the declare_id! / package.metadata.solana.program-id address).

Scope-aware program(...) directive

The directive's required arguments now depend on where it is attached:

Scope name address
Crate root (#![codama(program(...))] in lib.rs) optional optional
File-module (#![...] in foo.rs) required required
Module block (#[codama(program(...))] mod { .. }) required required
Item (instruction / account / event / …) required required

Only the crate root overrides an existing default program, so it may omit either field. Every other scope declares a distinct program that has no defaults to fall back on, so both remain required.

To tell the crate root apart from a file-module (both previously mapped to AttributeContext::File), this adds a new AttributeContext::Crate variant, built explicitly by CrateKorok::parse.

Behaviour

  • ProgramDirective's name/address become Option; update_or_wrap_program_node only overrides the fields the directive actually set.
  • SetProgramMetadataVisitor applies the crate-level directive before the Cargo.toml / declare_id! fallbacks, so an explicit value wins while unset fields still resolve from the manifest.
  • The additional-program separation for item / module / file-module scopes is unchanged.

Tests

  • Scope-aware parsing: crate scope accepts program(name = ..), program(address = ..) and program(); item scope still errors when either is missing.
  • Visitor-level overrides: name-only, name-over-manifest, and address override.

Follow-up

Enables renaming a program without touching the crate name, e.g. #![cfg_attr(feature = "codama", codama(program(name = "associatedTokenAccount")))] in the associated-token-account interface crate, which will be done once a version carrying this change is released.

Let a crate-level #![codama(program(name = ..., address = ...))] directive
override the primary program's identity, with either argument optional so
omitted fields fall back to the crate defaults (Cargo.toml package name and
declare_id! / package.metadata.solana.program-id).

The program(...) directive is now scope-aware:
- a new AttributeContext::Crate distinguishes a crate root from a file-module
  (both previously mapped to File);
- at the crate root, name and address are optional (override semantics);
- at every other scope (item, module block, file-module) both remain required,
  since those declare a distinct program with no defaults.

SetProgramMetadataVisitor applies the crate-level directive before the Cargo /
declare_id! fallbacks, so an explicit value wins while unset fields still
resolve from the manifest. ProgramDirective's name/address become Option, and
update_or_wrap_program_node only overrides the fields the directive actually
set.
@lorisleiva
lorisleiva merged commit d3c6800 into main Aug 18, 2026
3 checks passed
@lorisleiva
lorisleiva deleted the feat/crate-scope-program-name-override branch August 27, 2026 15:41
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant