Crates.io | pendzl_lang_codegen |
lib.rs | pendzl_lang_codegen |
version | 1.0.2 |
source | src |
created_at | 2024-01-21 13:43:58.650942 |
updated_at | 2024-11-05 12:14:31.370977 |
description | pendzl codegeneration for macros in `pendzl_lang_macro`. |
homepage | |
repository | |
max_upload_size | |
id | 1107625 |
size | 110,805 |
This module contains the implementations of macros used for code generation in the library.
Contains:
codegen::implementation
macro:
implementation
macro, which injects default fn implementations (& overrides) of standard traits.codegen::storage_item
macro:
storage_item
macro, handling storage-related code generation.codegen::storage_field_getter_derive
macro:
StorageFieldGetter
trait for storage structures.generate
FunctionThe generate
function serves as the core entry point for the procedural macro, processing an ink! module, injecting default implementations for specified traits & handling overridden methods.
The function begins by parsing the attributes provided to the macro to determine which traits require default implementations. The attributes are expected to be a list of trait names, such as #[implementation(PSP22, PSP34)]
. These are parsed using the syn::parse2::<AttributeArgs>
function, which results in a vector of trait names (to_inject_default_impls_vec
).
The storage struct is the central data structure for an ink! contract, representing the contract's state. The extract_storage_struct_name
function iterates over the module's items to find the struct annotated with #[ink(storage)]
. Once found, it extracts the struct's identifier (name) for later use in implementing traits.
Users can provide custom implementations for specific trait methods by annotating functions with #[overrider(TraitName)]
. The consume_overriders
function searches for these annotated functions, extracts them, and removes them from the module's items to prevent duplication. It collects these overrides into an OverridenFnMap
, mapping trait names to the corresponding overridden functions.
For each trait specified in the attributes (eg. for pendzl::implementation(PSP22, Pausable) would be PSP22 and Pausable), it calls the corresponding implementation function (e.g., impl_psp22
, impl_pausable
), passing impl_args
as the context. These implementation functions generate the default implementations of the traits, modify the module's items, and handle any necessary imports.
Note that all of the impl_XYZ functions follow the same pattern - injecting default implementations for internal and public traits & potentially injecting required imports. Such boilerplate is necessary for simplicity and further DX down the line.
Pendzl's codegen removes unnecessary base trait imports when extended traits are present to avoiding potential conflicts or redundancy. This optimization ensures that the generated code includes only the necessary imports.
It also auto injects StorageFieldGetter
trait and any overridden trait implementations collected earlier.
following section talks about the contents of implenentation.rs
file
The Pendzl codegen provides several functions to generate default implementations for specific traits, such as impl_psp22
, impl_pausable
, impl_psp22_vault
, impl_psp34
, impl_psp34_burnable
, impl_ownable
, impl_vesting
, impl_set_code_hash
... and more.
. Each of these functions follows a similar pattern:
impl_args
.override_functions
to apply any user-provided overrides to the trait implementations.impl_args.imports
, ensuring all required types and traits are available in the generated code.impl_args.items
.The impl_psp22
function injects the default implementation of the PSP22
trait into the module. It constructs the internal default implementation (PSP22InternalDefaultImpl
), the internal trait implementation (PSP22Internal
), the public default implementation (PSP22DefaultImpl
), and the public trait implementation (PSP22
). Each of these implementations defines methods that provide default behaviors or delegate to internal methods.
The function then calls override_functions
to handle any overrides provided by the user for both PSP22Internal
and PSP22
. It manages necessary imports, such as pendzl::contracts::psp22::*
, and appends the implementations to the module items.
The storage_item
function implements the #[pendzl::storage_item]
macro, preparing structs or enums to be part of the contract's storage. It allows the use of the #[lazy]
attribute to mark fields that should be lazily loaded and wrapped in ::ink::storage::Lazy
. The macro also generates constant storage keys for every mapping or lazy field, following recommendations from ink!'s storage layout documentation.