Skip to content

Skip and rename for Shank types and account fields#73

Merged
blockiosaurus merged 4 commits into
masterfrom
feat/skip-and-rename
Jul 15, 2025
Merged

Skip and rename for Shank types and account fields#73
blockiosaurus merged 4 commits into
masterfrom
feat/skip-and-rename

Conversation

@blockiosaurus
Copy link
Copy Markdown
Contributor

This PR adds #[skip] and #[idl_name("name")] field attributes for ShankAccount and ShankType structs for more IDL output customization.

e.g.

#[derive(ShankAccount)]
pub struct FieldAttributesExample {
    pub normal_field: u64,
    
    #[idl_name("customName")]
    pub renamed_field: String,
    
    #[skip]
    pub skipped_field: bool,
    
    #[idl_name("renamedAndPadded")]
    #[padding]
    pub renamed_padding_field: [u8; 32],
    
    #[idl_type("u32")]
    #[idl_name("customTypedField")]
    pub custom_typed_field: SomeWrapper<u32>,
}

@blockiosaurus blockiosaurus requested review from danenbm and pileks July 13, 2025 20:38
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Jul 13, 2025

Summary by CodeRabbit

  • New Features

    • Added support for new field attributes: idl_name (to override field names in the generated IDL) and skip (to exclude fields from the IDL) in struct macros.
  • Documentation

    • Updated documentation and examples to describe the new idl_name and skip attributes.
    • Added a new guide for Claude Code users and expanded macro documentation.
  • Bug Fixes

    • Ensured fields marked as skipped are excluded from IDL generation.
  • Tests

    • Added tests and fixtures to verify correct handling of field attributes in IDL output.
  • Refactor

    • Changed internal attribute handling from sets to vectors for improved flexibility and ordering.

Summary by CodeRabbit

  • New Features

    • Added support for idl_name and skip field attributes in IDL generation macros, allowing custom field names and exclusion of fields from the generated IDL.
    • Updated macro documentation to describe and provide examples for these new attributes.
  • Bug Fixes

    • Fields marked with skip are now correctly excluded from the generated IDL.
  • Tests

    • Introduced new tests and fixtures to validate correct handling of idl_name and skip attributes.
  • Documentation

    • Added a comprehensive guide for AI code assistants and updated macro documentation to cover new field attributes.

Walkthrough

This update introduces support for two new field attributes, idl_name and skip, in the Shank Rust macros for Solana program IDL generation. The changes enable custom field naming and exclusion from IDL output, update macro documentation, parsing logic, and add tests and fixtures to verify the new attribute behaviors.

Changes

File(s) Change Summary
CLAUDE.md Added new documentation detailing project overview, architecture, workflow, commands, macros, attributes, and development notes.
shank-macro/src/lib.rs Updated macro documentation and attribute lists for ShankAccount and ShankType to include idl_name and skip.
shank-macro-impl/src/parsed_struct/struct_field_attr.rs Added IdlName(String) and Skip variants to StructFieldAttr; implemented parsing for idl_name and skip attributes.
shank-macro-impl/src/parsed_struct/parsed_struct.rs Added name_override and is_skipped methods to StructField for attribute access.
shank-idl/src/idl_field.rs Modified field-to-IDL conversion to use name_override if present for field naming.
shank-idl/src/idl_type_definition.rs Updated struct-to-IDL conversion to filter out fields marked as skipped.
shank-idl/tests/accounts.rs Added test account_from_single_file_field_attributes to verify new attribute behaviors.
shank-idl/tests/fixtures/accounts/single_file/field_attributes.rs,
field_attributes.json
Added Rust fixture and expected JSON for struct using idl_name and skip attributes.
shank-macro-impl/src/account/extract_accounts.rs Replaced attribute presence checks from .get() to .contains() for padding attribute due to attribute container type change.
shank-macro-impl/src/parsed_struct/parsed_struct_test.rs Updated tests to reflect change from HashSet to Vec for StructFieldAttr storage and assertions.

Sequence Diagram(s)

sequenceDiagram
    participant User
    participant RustMacro
    participant StructField
    participant IDLGenerator

    User->>RustMacro: Annotate struct fields with #[idl_name] or #[skip]
    RustMacro->>StructField: Parse attributes
    StructField->>IDLGenerator: Provide name_override and is_skipped info
    IDLGenerator->>IDLGenerator: Use override for field name if present
    IDLGenerator->>IDLGenerator: Exclude fields marked as skipped
    IDLGenerator->>User: Output customized IDL JSON
Loading

Possibly related PRs

  • metaplex-foundation/shank#71: Introduces the idl_type attribute for overriding field types in the IDL, related to this PR's focus on attribute-driven IDL customization.

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 Clippy (1.86.0)
Updating crates.io index

warning: failed to write cache, path: /usr/local/registry/index/index.crates.io-1949cf8c6b5b557f/.cache/pr/oc/proc-macro2, error: Permission denied (os error 13)
Locking 76 packages to latest compatible versions
Adding cargo_toml v0.17.2 (available: v0.22.1)
Adding clap v3.2.25 (available: v4.5.41)
Adding fern v0.6.2 (available: v0.7.1)
Adding heck v0.3.3 (available: v0.5.0)
Adding prettyplease v0.1.25 (available: v0.2.35)
Adding shellexpand v2.1.2 (available: v3.1.1)
Adding syn v1.0.109 (available: v2.0.104)
Downloading crates ...
Downloaded atty v0.2.14
error: failed to create directory /usr/local/registry/cache/index.crates.io-1949cf8c6b5b557f

Caused by:
Permission denied (os error 13)


📜 Recent review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between ca22e03 and 0698449.

📒 Files selected for processing (5)
  • shank-idl/tests/fixtures/accounts/single_file/field_attributes.json (1 hunks)
  • shank-macro-impl/src/account/extract_accounts.rs (2 hunks)
  • shank-macro-impl/src/parsed_struct/parsed_struct.rs (2 hunks)
  • shank-macro-impl/src/parsed_struct/parsed_struct_test.rs (3 hunks)
  • shank-macro-impl/src/parsed_struct/struct_field_attr.rs (2 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
shank-macro-impl/src/parsed_struct/struct_field_attr.rs (3)
shank-macro-impl/src/types/resolve_rust_ty.rs (3)
  • from (54-57)
  • try_from (38-40)
  • try_from (46-49)
shank-macro-impl/src/parsed_struct/parsed_struct.rs (2)
  • try_from (67-90)
  • try_from (111-132)
shank-idl/src/idl_field.rs (1)
  • try_from (21-43)
⏰ Context from checks skipped due to timeout of 90000ms. You can increase the timeout in your CodeRabbit configuration to a maximum of 15 minutes (900000ms). (1)
  • GitHub Check: build_and_test (windows-latest, stable)
🔇 Additional comments (13)
shank-macro-impl/src/account/extract_accounts.rs (2)

51-51: LGTM! Correct adaptation to Vec container.

The change from .get().is_some() to .contains() correctly adapts to the new Vec<StructFieldAttr> container type while maintaining the same functionality.


208-208: LGTM! Test assertion correctly updated.

The test assertion properly adapts to the new Vec-based attribute storage while preserving the intended verification logic.

shank-idl/tests/fixtures/accounts/single_file/field_attributes.json (1)

1-50: LGTM! Well-structured test fixture for new field attributes.

This fixture properly demonstrates the new idl_name functionality and attribute combinations:

  • Line 12-14: Normal field without attributes
  • Line 16-21: Field renamed via idl-name attribute
  • Line 23-34: Field with both idl-name and padding attributes
  • Line 36-42: Field with both idl-type and idl-name attributes

The JSON structure correctly follows the expected IDL format and provides comprehensive test coverage for the new attribute functionality.

shank-macro-impl/src/parsed_struct/parsed_struct.rs (3)

20-20: LGTM! Container type change supports attribute ordering.

Changing from HashSet<StructFieldAttr> to Vec<StructFieldAttr> is appropriate as it:

  • Preserves attribute order which may be important for processing
  • Allows multiple attributes of the same type if needed in the future
  • Aligns with the parsing logic that builds attributes sequentially

47-56: LGTM! Well-implemented name override method.

The name_override method correctly uses find_map to locate the first IdlName attribute and extract its value. The approach is efficient and handles the case where no override is present by returning None.


58-61: LGTM! Efficient skip check implementation.

The is_skipped method uses any() with pattern matching to efficiently check for the presence of the Skip attribute, returning a boolean as expected.

shank-macro-impl/src/parsed_struct/parsed_struct_test.rs (1)

20-20: LGTM! Test code correctly updated for Vec container.

All test changes properly adapt to the new Vec<StructFieldAttr> container type:

  • Assertions updated to compare with Vec::new() instead of HashSet::new()
  • Helper function padding_attrs() correctly returns Vec and uses push()
  • Parameter types updated consistently
  • Test logic and coverage remain intact

These mechanical changes ensure tests continue to work with the new container type.

Also applies to: 55-55, 231-235, 208-208

shank-macro-impl/src/parsed_struct/struct_field_attr.rs (6)

9-9: LGTM! Added derives support Vec operations.

Adding PartialEq, Eq derives is appropriate for the transition to Vec<StructFieldAttr> as these traits are commonly needed for vector operations and comparisons.


13-14: LGTM! Well-designed new attribute variants.

The new enum variants are well-designed:

  • IdlName(String): Stores the custom field name for IDL generation
  • Skip: Simple marker to exclude fields from IDL

Both variants follow the existing enum pattern and support the intended functionality.


22-23: LGTM! Correct string representations for new variants.

The string representations properly map to the expected attribute names in the IDL output format.


28-28: LGTM! Consistent container type change.

The change from HashSet to Vec is implemented consistently:

  • Struct definition updated
  • Initialization changed to Vec::new()
  • Operations changed from insert to push

This preserves attribute order and supports the new functionality requirements.

Also applies to: 34-34, 115-115


38-41: LGTM! Simple and correct skip attribute parsing.

The parsing for the skip attribute is straightforward and correct - it simply adds a Skip marker when the attribute is encountered.


42-72: LGTM! Robust idl_name attribute parsing with comprehensive error handling.

The idl_name parsing logic is well-implemented with thorough error handling:

  • Validation: Correctly checks for exactly one argument (lines 44-49)
  • Type checking: Validates the argument is a string literal (lines 51-58)
  • Error messages: Provides clear, actionable error messages for different failure cases
  • Edge cases: Handles malformed attributes, wrong argument counts, and parsing failures

The error messages guide users toward the correct syntax: #[idl_name("fieldName")].

✨ Finishing Touches
  • 📝 Generate Docstrings

🪧 Tips

Chat

There are 3 ways to chat with CodeRabbit:

  • Review comments: Directly reply to a review comment made by CodeRabbit. Example:
    • I pushed a fix in commit <commit_id>, please review it.
    • Explain this complex logic.
    • Open a follow-up GitHub issue for this discussion.
  • Files and specific lines of code (under the "Files changed" tab): Tag @coderabbitai in a new review comment at the desired location with your query. Examples:
    • @coderabbitai explain this code block.
    • @coderabbitai modularize this function.
  • PR comments: Tag @coderabbitai in a new PR comment to ask questions about the PR branch. For the best results, please provide a very specific query, as very limited context is provided in this mode. Examples:
    • @coderabbitai gather interesting stats about this repository and render them as a table. Additionally, render a pie chart showing the language distribution in the codebase.
    • @coderabbitai read src/utils.ts and explain its main purpose.
    • @coderabbitai read the files in the src/scheduler package and generate a class diagram using mermaid and a README in the markdown format.
    • @coderabbitai help me debug CodeRabbit configuration file.

Support

Need help? Create a ticket on our support page for assistance with any issues or questions.

Note: Be mindful of the bot's finite context window. It's strongly recommended to break down tasks such as reading entire modules into smaller chunks. For a focused discussion, use review comments to chat about specific files and their changes, instead of using the PR comments.

CodeRabbit Commands (Invoked using PR comments)

  • @coderabbitai pause to pause the reviews on a PR.
  • @coderabbitai resume to resume the paused reviews.
  • @coderabbitai review to trigger an incremental review. This is useful when automatic reviews are disabled for the repository.
  • @coderabbitai full review to do a full review from scratch and review all the files again.
  • @coderabbitai summary to regenerate the summary of the PR.
  • @coderabbitai generate docstrings to generate docstrings for this PR.
  • @coderabbitai generate sequence diagram to generate a sequence diagram of the changes in this PR.
  • @coderabbitai resolve resolve all the CodeRabbit review comments.
  • @coderabbitai configuration to show the current CodeRabbit configuration for the repository.
  • @coderabbitai help to get help.

Other keywords and placeholders

  • Add @coderabbitai ignore anywhere in the PR description to prevent this PR from being reviewed.
  • Add @coderabbitai summary to generate the high-level summary at a specific location in the PR description.
  • Add @coderabbitai anywhere in the PR title to generate the title automatically.

CodeRabbit Configuration File (.coderabbit.yaml)

  • You can programmatically configure CodeRabbit by adding a .coderabbit.yaml file to the root of your repository.
  • Please see the configuration documentation for more information.
  • If your editor has YAML language server enabled, you can add the path at the top of this file to enable auto-completion and validation: # yaml-language-server: $schema=https://coderabbit.ai/integrations/schema.v2.json

Documentation and Community

  • Visit our Documentation for detailed information on how to use CodeRabbit.
  • Join our Discord Community to get help, request features, and share feedback.
  • Follow us on X/Twitter for updates and announcements.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 46cbde9 and 4116929.

📒 Files selected for processing (9)
  • CLAUDE.md (1 hunks)
  • shank-idl/src/idl_field.rs (2 hunks)
  • shank-idl/src/idl_type_definition.rs (1 hunks)
  • shank-idl/tests/accounts.rs (1 hunks)
  • shank-idl/tests/fixtures/accounts/single_file/field_attributes.json (1 hunks)
  • shank-idl/tests/fixtures/accounts/single_file/field_attributes.rs (1 hunks)
  • shank-macro-impl/src/parsed_struct/parsed_struct.rs (1 hunks)
  • shank-macro-impl/src/parsed_struct/struct_field_attr.rs (2 hunks)
  • shank-macro/src/lib.rs (3 hunks)
🧰 Additional context used
🧬 Code Graph Analysis (1)
shank-idl/src/idl_type_definition.rs (1)
shank-idl/src/idl_field.rs (1)
  • field (35-39)
🪛 LanguageTool
CLAUDE.md

[grammar] ~1-~1: Use correct spacing
Context: # CLAUDE.md This file provides guidance to Claude C...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~3-~3: Use correct spacing
Context: ...ai/code) when working with code in this repository. ## Project Overview Shank is a collection...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~5-~5: Use correct spacing
Context: ...th code in this repository. ## Project Overview Shank is a collection of Rust crates th...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~7-~7: There might be a problem here.
Context: ... to generate TypeScript SDKs for Solana programs. ## Architecture This is a Rust workspace containing 6 m...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~11-~11: Use correct spacing
Context: ...s is a Rust workspace containing 6 main crates: - shank - Top-level crate that exports ...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~18-~18: Use correct spacing
Context: ...Command-line tool that orchestrates IDL extraction The workflow: Users annotate their Sola...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~20-~20: Use correct spacing
Context: ... → produces JSON IDL → consumed by code generators. ## Common Commands ### Building and Testi...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~22-~22: Use correct spacing
Context: ...consumed by code generators. ## Common Commands ### Building and Testing ```bash cargo test...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~24-~24: Use correct spacing
Context: .... ## Common Commands ### Building and Testing bash cargo test # Run all tests across workspace cargo build # Build all crates cargo build --release # Release build ### CLI Usage ```bash cargo install shank-c...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~31-~31: Use correct spacing
Context: ...se # Release build ### CLI Usagebash cargo install shank-cli # Install CLI globally shank idl # Extract IDL to ./idl/ directory shank idl -o

# Extract IDL to custom directory shank idl -r # Specify program crate root ### Release Processbash cargo test && c...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~39-~39: Use correct spacing
Context: ...ify program crate root ### Release Processbash cargo test && cargo release <major|minor|patch> # Dry run cargo release <major|minor|patch> --execute # Execute release ``` ## Key Macro Annotations - `#[derive(Shan...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~45-~45: There might be a problem here.
Context: ... # Execute release ``` ## Key Macro Annotations - #[derive(ShankAccount)] - Marks account structs with optional `#[...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~47-~47:
Context: ...tructs with optional #[seeds] for PDA generation - #[derive(ShankInstruction)] - Marks instruction enums with `#[account...

(QB_NEW_EN_OTHER_ERROR_IDS_)


[grammar] ~48-~48:
Context: ...rks instruction enums with #[account] attributes - #[derive(ShankType)] - Marks custom types for IDL inclusion - ...

(QB_NEW_EN_OTHER_ERROR_IDS_)


[grammar] ~49-~49:
Context: ...ankType)]- Marks custom types for IDL inclusion -#[derive(ShankBuilder)]- Generates instruction builders -#[de...

(QB_NEW_EN_OTHER_ERROR_IDS_)


[grammar] ~50-~50:
Context: ...ShankBuilder)]- Generates instruction builders -#[derive(ShankContext)]` - Generates account context structs ### ...

(QB_NEW_EN_OTHER_ERROR_IDS_)


[grammar] ~51-~51: Use correct spacing
Context: ...kContext)]- Generates account context structs ### Field Attributes -#[padding]` - Mark...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~53-~53: There might be a problem here.
Context: ...ates account context structs ### Field Attributes - #[padding] - Marks field as padding in IDL - `#[idl_...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~55-~55:
Context: ...#[padding]- Marks field as padding in IDL -#[idl_type("TypeName")]- Overrides field type in IDL -#[idl_na...

(QB_NEW_EN_OTHER_ERROR_IDS_)


[grammar] ~56-~56:
Context: ..."TypeName")]- Overrides field type in IDL -#[idl_name("name")]` - Renames field in IDL while keeping Rust...

(QB_NEW_EN_OTHER_ERROR_IDS_)


[grammar] ~57-~57:
Context: ...s field in IDL while keeping Rust field name - #[skip] - Excludes field from IDL entirely ## Te...

(QB_NEW_EN_OTHER_ERROR_IDS_)


[grammar] ~58-~58: There might be a problem here.
Context: ...e - #[skip] - Excludes field from IDL entirely ## Testing Test files are organized in each crate'...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~62-~62: Use correct spacing
Context: ...both macro expansion and IDL generation accuracy. ## Development Notes - Uses Rust 2018 edi...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~64-~64: Use correct spacing
Context: ...DL generation accuracy. ## Development Notes - Uses Rust 2018 edition - Release config...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~66-~66: There might be a mistake here.
Context: ... ## Development Notes - Uses Rust 2018 edition - Release configuration in `release.tom...

(QB_NEW_EN_OTHER)


[grammar] ~68-~68: Use articles correctly
Context: ...tion in release.toml - Only releases from master branch - Uses rustfmt.toml f...

(QB_NEW_EN_OTHER_ERROR_IDS_11)


[grammar] ~68-~68: There might be a mistake here.
Context: ...se.toml - Only releases frommasterbranch - Usesrustfmt.toml` for consistent fo...

(QB_NEW_EN_OTHER)


[grammar] ~69-~69: There might be a mistake here.
Context: ...ch - Uses rustfmt.toml for consistent formatting - Heavy use of syn and quote for ma...

(QB_NEW_EN_OTHER)


[grammar] ~70-~70: Use a period to end declarative sentences
Context: ...eavy use of syn and quote for macro implementation

(QB_NEW_EN_OTHER_ERROR_IDS_25)

🪛 markdownlint-cli2 (0.17.2)
CLAUDE.md

24-24: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


25-25: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


31-31: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


32-32: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


39-39: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)


40-40: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)


50-50: Trailing spaces
Expected: 0 or 2; Actual: 1

(MD009, no-trailing-spaces)


67-67: Trailing spaces
Expected: 0 or 2; Actual: 1

(MD009, no-trailing-spaces)


70-70: Files should end with a single newline character

(MD047, single-trailing-newline)

🔇 Additional comments (12)
shank-idl/src/idl_type_definition.rs (1)

30-30: LGTM! Clean implementation of skip attribute filtering.

The filter correctly excludes fields marked with the skip attribute before converting them to IDL fields. This is the right place in the conversion pipeline to implement this functionality.

shank-idl/tests/accounts.rs (1)

79-87: LGTM! Test follows established patterns and provides good coverage.

The new test function correctly follows the existing test pattern in the file and provides essential coverage for the field attributes functionality.

shank-idl/src/idl_field.rs (1)

22-27: LGTM! Clear implementation of idl_name attribute support.

The name override logic is well-implemented with a clear fallback strategy. The comment explains the behavior and the code maintains backward compatibility.

shank-idl/tests/fixtures/accounts/single_file/field_attributes.json (1)

1-50: LGTM! Comprehensive test fixture covering all field attribute combinations.

The JSON fixture effectively demonstrates the various field attribute combinations:

  • Normal field without attributes
  • idl-name attribute for field renaming
  • Combined idl-name + padding attributes
  • Combined idl-type + idl-name attributes

This provides thorough test coverage for the new functionality.

shank-macro-impl/src/parsed_struct/parsed_struct.rs (1)

48-62: LGTM! Well-implemented accessor methods for field attributes.

Both methods are correctly implemented:

  • name_override() efficiently extracts the custom name from the IdlName attribute
  • is_skipped() uses idiomatic Rust pattern matching to check for the Skip attribute

These methods provide clean APIs for the IDL conversion logic to use.

shank-macro/src/lib.rs (3)

55-79: Excellent documentation for the new field attributes.

The documentation clearly explains both new attributes with practical examples. The #[idl_name("name")] attribute documentation shows how to rename fields in IDL while preserving Rust field names, and the # attribute documentation demonstrates excluding fields from IDL output.


138-141: Correctly updated ShankAccount derive macro attributes.

The macro properly declares support for the new idl_name and skip attributes alongside existing ones.


385-385: Appropriately updated ShankType derive macro attributes.

The ShankType macro now correctly supports all three field attributes: idl_name, idl_type, and skip.

shank-macro-impl/src/parsed_struct/struct_field_attr.rs (3)

14-15: Well-designed enum variants for the new attributes.

The IdlName(String) and Skip variants properly capture the semantic meaning of each attribute type.


23-24: Appropriate string representations for new attributes.

The string identifiers "idl-name" and "skip" follow the established pattern and provide clear identification.


40-73: Robust parsing implementation with excellent error handling.

The parsing logic correctly handles both new attributes:

  • skip attribute is simple and requires no arguments
  • idl_name attribute validates exactly one string literal argument with comprehensive error messages

The error messages are descriptive and provide helpful guidance to users about the expected format.

shank-idl/tests/fixtures/accounts/single_file/field_attributes.rs (1)

1-22: Comprehensive test fixture covering all new attribute scenarios.

This fixture excellently demonstrates:

  • Basic #[idl_name("customName")] usage for field renaming
  • Simple # usage for field exclusion
  • Combining #[idl_name("renamedAndPadded")] with #[padding]
  • Combining #[idl_type("u32")] with #[idl_name("customTypedField")]

The examples show practical use cases and validate that the new attributes work both independently and in combination with existing ones.

Comment thread CLAUDE.md
Comment on lines +1 to +70
# CLAUDE.md

This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.

## Project Overview

Shank is a collection of Rust crates that extract Interface Definition Language (IDL) files from Solana programs using macro annotations. The generated IDL is consumed by tools like [solita](https://github.com/metaplex-foundation/solita) to generate TypeScript SDKs for Solana programs.

## Architecture

This is a Rust workspace containing 6 main crates:

- **shank** - Top-level crate that exports all macros, entry point for users
- **shank-macro** - Provides derive macros (`ShankAccount`, `ShankInstruction`, `ShankType`, etc.)
- **shank-macro-impl** - Core implementation of the derive macros and parsing logic
- **shank-idl** - Processes Rust source files to extract IDL from shank annotations
- **shank-render** - Generates Rust code (like PDA functions) from annotations
- **shank-cli** - Command-line tool that orchestrates IDL extraction

The workflow: Users annotate their Solana program structs/enums with shank macros → shank-cli analyzes the source code → produces JSON IDL → consumed by code generators.

## Common Commands

### Building and Testing
```bash
cargo test # Run all tests across workspace
cargo build # Build all crates
cargo build --release # Release build
```

### CLI Usage
```bash
cargo install shank-cli # Install CLI globally
shank idl # Extract IDL to ./idl/ directory
shank idl -o <dir> # Extract IDL to custom directory
shank idl -r <crate-root> # Specify program crate root
```

### Release Process
```bash
cargo test && cargo release <major|minor|patch> # Dry run
cargo release <major|minor|patch> --execute # Execute release
```

## Key Macro Annotations

- `#[derive(ShankAccount)]` - Marks account structs with optional `#[seeds]` for PDA generation
- `#[derive(ShankInstruction)]` - Marks instruction enums with `#[account]` attributes
- `#[derive(ShankType)]` - Marks custom types for IDL inclusion
- `#[derive(ShankBuilder)]` - Generates instruction builders
- `#[derive(ShankContext)]` - Generates account context structs

### Field Attributes

- `#[padding]` - Marks field as padding in IDL
- `#[idl_type("TypeName")]` - Overrides field type in IDL
- `#[idl_name("name")]` - Renames field in IDL while keeping Rust field name
- `#[skip]` - Excludes field from IDL entirely

## Testing

Test files are organized in each crate's `tests/` directory with fixture files demonstrating expected behavior. Tests verify both macro expansion and IDL generation accuracy.

## Development Notes

- Uses Rust 2018 edition
- Release configuration in `release.toml`
- Only releases from `master` branch
- Uses `rustfmt.toml` for consistent formatting
- Heavy use of `syn` and `quote` for macro implementation No newline at end of file
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Valuable documentation addition with minor formatting issues to address.

This documentation file provides excellent guidance for AI assistance with the Shank codebase. The content accurately describes the architecture, workflow, and key concepts.

Please address the formatting issues identified by static analysis:

-Shank is a collection of Rust crates that extract Interface Definition Language (IDL) files from Solana programs using macro annotations. The generated IDL is consumed by tools like [solita](https://github.com/metaplex-foundation/solita) to generate TypeScript SDKs for Solana programs.
+Shank is a collection of Rust crates that extract Interface Definition Language (IDL) files from Solana programs using macro annotations. The generated IDL is consumed by tools like [solita](https://github.com/metaplex-foundation/solita) to generate TypeScript SDKs for Solana programs.

### Building and Testing
+
 ```bash
 cargo test                    # Run all tests across workspace
 cargo build                   # Build all crates
 cargo build --release         # Release build

CLI Usage

cargo install shank-cli       # Install CLI globally
shank idl                     # Extract IDL to ./idl/ directory
shank idl -o <dir>            # Extract IDL to custom directory
shank idl -r <crate-root>     # Specify program crate root

Release Process

cargo test && cargo release <major|minor|patch>     # Dry run
cargo release <major|minor|patch> --execute         # Execute release

-- #[derive(ShankBuilder)] - Generates instruction builders
-- #[derive(ShankContext)] - Generates account context structs
+- #[derive(ShankBuilder)] - Generates instruction builders
+- #[derive(ShankContext)] - Generates account context structs

-- Only releases from master branch
-- Uses rustfmt.toml for consistent formatting
-- Heavy use of syn and quote for macro implementation
+- Only releases from the master branch
+- Uses rustfmt.toml for consistent formatting
+- Heavy use of syn and quote for macro implementation


<details>
<summary>🧰 Tools</summary>

<details>
<summary>🪛 LanguageTool</summary>

[grammar] ~1-~1: Use correct spacing
Context: # CLAUDE.md  This file provides guidance to Claude C...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

---

[grammar] ~3-~3: Use correct spacing
Context: ...ai/code) when working with code in this repository.  ## Project Overview  Shank is a collection...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

---

[grammar] ~5-~5: Use correct spacing
Context: ...th code in this repository.  ## Project Overview  Shank is a collection of Rust crates th...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

---

[grammar] ~7-~7: There might be a problem here.
Context: ... to generate TypeScript SDKs for Solana programs.  ## Architecture  This is a Rust workspace containing 6 m...

(QB_NEW_EN_MERGED_MATCH)

---

[grammar] ~11-~11: Use correct spacing
Context: ...s is a Rust workspace containing 6 main crates:  - **shank** - Top-level crate that exports ...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

---

[grammar] ~18-~18: Use correct spacing
Context: ...Command-line tool that orchestrates IDL extraction  The workflow: Users annotate their Sola...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

---

[grammar] ~20-~20: Use correct spacing
Context: ... → produces JSON IDL → consumed by code generators.  ## Common Commands  ### Building and Testi...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

---

[grammar] ~22-~22: Use correct spacing
Context: ...consumed by code generators.  ## Common Commands  ### Building and Testing ```bash cargo test...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

---

[grammar] ~24-~24: Use correct spacing
Context: ....  ## Common Commands  ### Building and Testing ```bash cargo test                    # Run all tests across workspace cargo build                   # Build all crates cargo build --release         # Release build ```  ### CLI Usage ```bash cargo install shank-c...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

---

[grammar] ~31-~31: Use correct spacing
Context: ...se         # Release build ```  ### CLI Usage ```bash cargo install shank-cli       # Install CLI globally shank idl                     # Extract IDL to ./idl/ directory shank idl -o <dir>            # Extract IDL to custom directory shank idl -r <crate-root>     # Specify program crate root ```  ### Release Process ```bash cargo test && c...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

---

[grammar] ~39-~39: Use correct spacing
Context: ...ify program crate root ```  ### Release Process ```bash cargo test && cargo release <major|minor|patch>     # Dry run cargo release <major|minor|patch> --execute         # Execute release ```  ## Key Macro Annotations  - `#[derive(Shan...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

---

[grammar] ~45-~45: There might be a problem here.
Context: ...    # Execute release ```  ## Key Macro Annotations  - `#[derive(ShankAccount)]` - Marks account structs with optional `#[...

(QB_NEW_EN_MERGED_MATCH)

---

[grammar] ~47-~47: 
Context: ...tructs with optional `#[seeds]` for PDA generation - `#[derive(ShankInstruction)]` - Marks instruction enums with `#[account...

(QB_NEW_EN_OTHER_ERROR_IDS_)

---

[grammar] ~48-~48: 
Context: ...rks instruction enums with `#[account]` attributes - `#[derive(ShankType)]` - Marks custom types for IDL inclusion - ...

(QB_NEW_EN_OTHER_ERROR_IDS_)

---

[grammar] ~49-~49: 
Context: ...ankType)]` - Marks custom types for IDL inclusion - `#[derive(ShankBuilder)]` - Generates instruction builders  - `#[de...

(QB_NEW_EN_OTHER_ERROR_IDS_)

---

[grammar] ~50-~50: 
Context: ...ShankBuilder)]` - Generates instruction builders  - `#[derive(ShankContext)]` - Generates account context structs  ### ...

(QB_NEW_EN_OTHER_ERROR_IDS_)

---

[grammar] ~51-~51: Use correct spacing
Context: ...kContext)]` - Generates account context structs  ### Field Attributes  - `#[padding]` - Mark...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

---

[grammar] ~53-~53: There might be a problem here.
Context: ...ates account context structs  ### Field Attributes  - `#[padding]` - Marks field as padding in IDL - `#[idl_...

(QB_NEW_EN_MERGED_MATCH)

---

[grammar] ~55-~55: 
Context: ...#[padding]` - Marks field as padding in IDL - `#[idl_type("TypeName")]` - Overrides field type in IDL - `#[idl_na...

(QB_NEW_EN_OTHER_ERROR_IDS_)

---

[grammar] ~56-~56: 
Context: ..."TypeName")]` - Overrides field type in IDL - `#[idl_name("name")]` - Renames field in IDL while keeping Rust...

(QB_NEW_EN_OTHER_ERROR_IDS_)

---

[grammar] ~57-~57: 
Context: ...s field in IDL while keeping Rust field name - `#[skip]` - Excludes field from IDL entirely  ## Te...

(QB_NEW_EN_OTHER_ERROR_IDS_)

---

[grammar] ~58-~58: There might be a problem here.
Context: ...e - `#[skip]` - Excludes field from IDL entirely  ## Testing  Test files are organized in each crate'...

(QB_NEW_EN_MERGED_MATCH)

---

[grammar] ~62-~62: Use correct spacing
Context: ...both macro expansion and IDL generation accuracy.  ## Development Notes  - Uses Rust 2018 edi...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

---

[grammar] ~64-~64: Use correct spacing
Context: ...DL generation accuracy.  ## Development Notes  - Uses Rust 2018 edition - Release config...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

---

[grammar] ~66-~66: There might be a mistake here.
Context: ... ## Development Notes  - Uses Rust 2018 edition - Release configuration in `release.tom...

(QB_NEW_EN_OTHER)

---

[grammar] ~68-~68: Use articles correctly
Context: ...tion in `release.toml`  - Only releases from `master` branch - Uses `rustfmt.toml` f...

(QB_NEW_EN_OTHER_ERROR_IDS_11)

---

[grammar] ~68-~68: There might be a mistake here.
Context: ...se.toml`  - Only releases from `master` branch - Uses `rustfmt.toml` for consistent fo...

(QB_NEW_EN_OTHER)

---

[grammar] ~69-~69: There might be a mistake here.
Context: ...ch - Uses `rustfmt.toml` for consistent formatting - Heavy use of `syn` and `quote` for ma...

(QB_NEW_EN_OTHER)

---

[grammar] ~70-~70: Use a period to end declarative sentences
Context: ...eavy use of `syn` and `quote` for macro implementation

(QB_NEW_EN_OTHER_ERROR_IDS_25)

</details>
<details>
<summary>🪛 markdownlint-cli2 (0.17.2)</summary>

24-24: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

---

25-25: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

---

31-31: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

---

32-32: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

---

39-39: Headings should be surrounded by blank lines
Expected: 1; Actual: 0; Below

(MD022, blanks-around-headings)

---

40-40: Fenced code blocks should be surrounded by blank lines

(MD031, blanks-around-fences)

---

50-50: Trailing spaces
Expected: 0 or 2; Actual: 1

(MD009, no-trailing-spaces)

---

67-67: Trailing spaces
Expected: 0 or 2; Actual: 1

(MD009, no-trailing-spaces)

---

70-70: Files should end with a single newline character

(MD047, single-trailing-newline)

</details>

</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

In CLAUDE.md from lines 1 to 70, fix the markdown formatting issues by ensuring
consistent spacing and proper code block delimiters around bash commands, remove
extra blank lines before and after code blocks, and adjust list item indentation
and spacing for bullet points to align with markdown standards. Also, correct
minor wording in the last bullet point by adding "the" before "master branch"
for clarity.


</details>

<!-- fingerprinting:phantom:poseidon:panther -->

<!-- This is an auto-generated comment by CodeRabbit -->

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

📜 Review details

Configuration used: CodeRabbit UI
Review profile: ASSERTIVE
Plan: Pro

📥 Commits

Reviewing files that changed from the base of the PR and between 4116929 and ee61e59.

📒 Files selected for processing (1)
  • shank-macro/README.md (1 hunks)
🧰 Additional context used
🪛 LanguageTool
shank-macro/README.md

[grammar] ~75-~75: There might be a problem here.
Context: ...etween your Rust code and the generated IDL. rs use shank::ShankAccount; use borsh::{BorshDeserialize, BorshSerialize}; #[derive(Clone, BorshSerialize, BorshDeserialize, ShankAccount)] pub struct MyAccount { // This field will appear as "displayName" in the IDL #[idl_name("displayName")] pub internal_name: String, // This field will appear as "userCount" in the IDL #[idl_name("userCount")] pub total_users: u32, } #### #[skip] attribute Excludes the field from the IDL entire...

(QB_NEW_EN_MERGED_MATCH)


[grammar] ~95-~95: Use correct spacing
Context: ...t shouldn't be exposed in the interface definition. rs use shank::ShankAccount; use borsh::{BorshDeserialize, BorshSerialize}; #[derive(Clone, BorshSerialize, BorshDeserialize, ShankAccount)] pub struct MyAccount { // This field will appear in the IDL pub public_field: u64, // This field will be excluded from the IDL #[skip] pub internal_only_field: String, // This field will also be excluded from the IDL #[skip] pub debug_info: Vec<u8>, } #### Combining Attributes You can combine m...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~116-~116: Use correct spacing
Context: ...ug_info: Vec, } ``` #### Combining Attributes You can combine multiple field attribut...

(QB_NEW_EN_OTHER_ERROR_IDS_5)


[grammar] ~118-~118: Use correct spacing
Context: ...e multiple field attributes on the same field: rs use shank::ShankAccount; use borsh::{BorshDeserialize, BorshSerialize}; #[derive(Clone, BorshSerialize, BorshDeserialize, ShankAccount)] pub struct MyAccount { // Rename the field and override its type #[idl_name("customField")] #[idl_type("CustomType")] pub internal_field: SomeWrapper<CustomType>, // Mark as padding and rename #[padding] #[idl_name("alignmentPadding")] pub _padding: [u8; 8], } ### Note The fields of a _ShankAccount_ struct can reference other types as long as they are annotated with `BorshSerialize`, `BorshDeserialize`, or `ShankType`. ## ShankInstruction Annotates the program _Instruction_ `Enum` in order to include `#[account]` attributes. The `#[account]` attributes indicate for each instruction _variant_ which accounts it expects and how they should be configured. ### `#[account]` attribute This attribute allows you to configure each account that is provided to the particular instruction. These annotations need to follow the order in which the accounts are provided. They take the following general form: rs #[account(index?, (writable|signer)?, name="<account_name>", desc?="optional description")] ``` - index: optionally provides the account index...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

Comment thread shank-macro/README.md
Comment on lines +93 to +97
#### `#[skip]` attribute

Excludes the field from the IDL entirely. The field will not appear in the generated IDL. This is useful for internal-only fields that shouldn't be exposed in the interface definition.

```rs
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Tweak wording to avoid repetition

The sentence repeats “IDL”; the second occurrence can be dropped:

-Excludes the field from the IDL entirely. The field will not appear in the generated IDL.
+Excludes the field entirely so it does not appear in the generated IDL.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#### `#[skip]` attribute
Excludes the field from the IDL entirely. The field will not appear in the generated IDL. This is useful for internal-only fields that shouldn't be exposed in the interface definition.
```rs
#### `#[skip]` attribute
Excludes the field entirely so it does not appear in the generated IDL. This is useful for internal-only fields that shouldn't be exposed in the interface definition.
🧰 Tools
🪛 LanguageTool

[grammar] ~95-~95: Use correct spacing
Context: ...t shouldn't be exposed in the interface definition. rs use shank::ShankAccount; use borsh::{BorshDeserialize, BorshSerialize}; #[derive(Clone, BorshSerialize, BorshDeserialize, ShankAccount)] pub struct MyAccount { // This field will appear in the IDL pub public_field: u64, // This field will be excluded from the IDL #[skip] pub internal_only_field: String, // This field will also be excluded from the IDL #[skip] pub debug_info: Vec<u8>, } #### Combining Attributes You can combine m...

(QB_NEW_EN_OTHER_ERROR_IDS_5)

🤖 Prompt for AI Agents
In shank-macro/README.md around lines 93 to 97, the description of the #[skip]
attribute repeats the term "IDL" unnecessarily. Edit the sentence to remove the
second occurrence of "IDL" to improve readability and avoid redundancy, keeping
the meaning clear and concise.

Comment thread shank-macro/README.md
Comment on lines +73 to +77
#### `#[idl_name("name")]` attribute

Allows you to override the field name that appears in the IDL while keeping the original Rust field name. This is useful when you need different naming conventions between your Rust code and the generated IDL.

```rs
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🧹 Nitpick (assertive)

Minor grammar-style polish for the new section

Consider inserting a comma to improve the flow and changing “while” → “but” for clarity:

-Allows you to override the field name that appears in the IDL while keeping the original Rust field name.
+Allows you to override the field name that appears in the IDL, but keeps the original Rust field name.
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
#### `#[idl_name("name")]` attribute
Allows you to override the field name that appears in the IDL while keeping the original Rust field name. This is useful when you need different naming conventions between your Rust code and the generated IDL.
```rs
#### `#[idl_name("name")]` attribute
Allows you to override the field name that appears in the IDL, but keeps the original Rust field name. This is useful when you need different naming conventions between your Rust code and the generated IDL.
🧰 Tools
🪛 LanguageTool

[grammar] ~75-~75: There might be a problem here.
Context: ...etween your Rust code and the generated IDL. rs use shank::ShankAccount; use borsh::{BorshDeserialize, BorshSerialize}; #[derive(Clone, BorshSerialize, BorshDeserialize, ShankAccount)] pub struct MyAccount { // This field will appear as "displayName" in the IDL #[idl_name("displayName")] pub internal_name: String, // This field will appear as "userCount" in the IDL #[idl_name("userCount")] pub total_users: u32, } #### #[skip] attribute Excludes the field from the IDL entire...

(QB_NEW_EN_MERGED_MATCH)

🤖 Prompt for AI Agents
In shank-macro/README.md around lines 73 to 77, improve the grammar and clarity
of the sentence describing the #[idl_name("name")] attribute by inserting a
comma after "IDL" and replacing "while" with "but" to better convey the contrast
between Rust field names and generated IDL names.

@blockiosaurus blockiosaurus merged commit e25b118 into master Jul 15, 2025
6 checks passed
@blockiosaurus blockiosaurus deleted the feat/skip-and-rename branch July 15, 2025 19:30
@coderabbitai coderabbitai Bot mentioned this pull request Aug 21, 2025
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.

2 participants