Skip to content

Commit

Permalink
feat: macro recompile trigger (#1061)
Browse files Browse the repository at this point in the history
`abigen!` and `setup_program_test!` should now rerun if any changes to the abi files are detected.
  • Loading branch information
segfault-magnet authored Jul 26, 2023
1 parent a182d63 commit ff74fc7
Show file tree
Hide file tree
Showing 28 changed files with 107 additions and 78 deletions.
7 changes: 3 additions & 4 deletions examples/cookbook/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -87,10 +87,8 @@ mod tests {

#[tokio::test]
async fn custom_chain() -> Result<()> {
use fuels::prelude::*;
// ANCHOR: custom_chain_import
use fuels::fuel_node::ChainConfig;
use fuels::tx::ConsensusParameters;
use fuels::{fuel_node::ChainConfig, prelude::*, tx::ConsensusParameters};
// ANCHOR_END: custom_chain_import

// ANCHOR: custom_chain_consensus
Expand Down Expand Up @@ -188,9 +186,10 @@ mod tests {
#[tokio::test]
#[cfg(any(not(feature = "fuel-core-lib"), feature = "rocksdb"))]
async fn create_or_use_rocksdb() -> Result<()> {
use fuels::prelude::*;
use std::path::PathBuf;

use fuels::prelude::*;

// ANCHOR: create_or_use_rocksdb
let provider_config = Config {
database_path: PathBuf::from("/tmp/.spider/db"),
Expand Down
2 changes: 1 addition & 1 deletion packages/fuels-accounts/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -318,9 +318,9 @@ pub trait Account: ViewOnlyAccount {

#[cfg(test)]
mod tests {
use fuel_core_client::client::FuelClient;
use std::str::FromStr;

use fuel_core_client::client::FuelClient;
use fuel_crypto::{Message, SecretKey};
use fuel_tx::{Address, ConsensusParameters, Output};
use fuels_core::types::transaction::Transaction;
Expand Down
31 changes: 25 additions & 6 deletions packages/fuels-code-gen/src/program_bindings/abigen.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use std::collections::HashSet;
use std::{collections::HashSet, path::PathBuf};

pub use abigen_target::{AbigenTarget, ProgramType};
use fuel_abi_types::abi::full_program::FullTypeDeclaration;
use inflector::Inflector;
use itertools::Itertools;
use proc_macro2::TokenStream;
Expand All @@ -17,8 +18,6 @@ use crate::{
utils::ident,
};

use fuel_abi_types::abi::full_program::FullTypeDeclaration;

mod abigen_target;
mod bindings;
mod configurables;
Expand Down Expand Up @@ -103,10 +102,30 @@ impl Abigen {
) -> Result<GeneratedCode> {
let mod_name = ident(&format!("{}_mod", &target.name.to_snake_case()));

let types = generate_types(&target.source.types, shared_types, no_std)?;
let recompile_trigger =
Self::generate_macro_recompile_trigger(target.source.path.as_ref(), no_std);
let types = generate_types(&target.source.abi.types, shared_types, no_std)?;
let bindings = generate_bindings(target, no_std)?;
Ok(recompile_trigger
.merge(types)
.merge(bindings)
.wrap_in_mod(mod_name))
}

Ok(types.merge(bindings).wrap_in_mod(mod_name))
/// Any changes to the file pointed to by `path` will cause the reevaluation of the current
/// procedural macro. This is a hack until https://github.com/rust-lang/rust/issues/99515
/// lands.
fn generate_macro_recompile_trigger(path: Option<&PathBuf>, no_std: bool) -> GeneratedCode {
let code = path
.as_ref()
.map(|path| {
let stringified_path = path.display().to_string();
quote! {
const _: &[u8] = include_bytes!(#stringified_path);
}
})
.unwrap_or_default();
GeneratedCode::new(code, Default::default(), no_std)
}

fn parse_targets(targets: Vec<AbigenTarget>) -> Result<Vec<ParsedAbigenTarget>> {
Expand Down Expand Up @@ -135,7 +154,7 @@ impl Abigen {
) -> impl Iterator<Item = &FullTypeDeclaration> {
all_types
.iter()
.flat_map(|target| &target.source.types)
.flat_map(|target| &target.source.abi.types)
.filter(|ttype| ttype.is_custom_type())
}

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::{convert::TryFrom, str::FromStr};
use std::{convert::TryFrom, path::PathBuf, str::FromStr};

use fuel_abi_types::abi::full_program::FullProgramABI;
use proc_macro2::Ident;

use crate::{
Expand All @@ -8,18 +9,21 @@ use crate::{
utils::Source,
};

use fuel_abi_types::abi::full_program::FullProgramABI;

#[derive(Debug, Clone)]
pub struct AbigenTarget {
pub name: String,
pub abi: String,
pub program_type: ProgramType,
}

pub(crate) struct Abi {
pub(crate) path: Option<PathBuf>,
pub(crate) abi: FullProgramABI,
}

pub(crate) struct ParsedAbigenTarget {
pub name: String,
pub source: FullProgramABI,
pub source: Abi,
pub program_type: ProgramType,
}

Expand All @@ -35,10 +39,13 @@ impl TryFrom<AbigenTarget> for ParsedAbigenTarget {
}
}

fn parse_program_abi(abi_source: &str) -> Result<FullProgramABI> {
fn parse_program_abi(abi_source: &str) -> Result<Abi> {
let source = Source::parse(abi_source).expect("failed to parse JSON ABI");

let json_abi_str = source.get().expect("failed to parse JSON ABI from string");
FullProgramABI::from_json_abi(&json_abi_str).map_err(|e| e.into())
let abi = FullProgramABI::from_json_abi(&json_abi_str)?;
let path = source.path();
Ok(Abi { path, abi })
}

#[derive(Debug, Clone, Copy, PartialEq, Eq)]
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,6 +27,6 @@ pub(crate) fn generate_bindings(target: ParsedAbigenTarget, no_std: bool) -> Res
};

let name = ident(&target.name);
let abi = target.source;
let abi = target.source.abi;
bindings_generator(&name, abi, no_std)
}
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use fuel_abi_types::abi::full_program::{FullABIFunction, FullProgramABI};
use itertools::Itertools;
use proc_macro2::{Ident, TokenStream};
use quote::{quote, TokenStreamExt};
Expand All @@ -15,8 +16,6 @@ use crate::{
utils::{ident, TypePath},
};

use fuel_abi_types::abi::full_program::{FullABIFunction, FullProgramABI};

pub(crate) fn contract_bindings(
name: &Ident,
abi: FullProgramABI,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use fuel_abi_types::abi::full_program::{FullABIFunction, FullTypeApplication};
use proc_macro2::TokenStream;
use quote::{quote, ToTokens};

Expand All @@ -10,8 +11,6 @@ use crate::{
utils::{safe_ident, TypePath},
};

use fuel_abi_types::abi::full_program::{FullABIFunction, FullTypeApplication};

#[derive(Debug)]
pub(crate) struct FunctionGenerator {
name: String,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use fuel_abi_types::abi::full_program::FullProgramABI;
use proc_macro2::{Ident, TokenStream};
use quote::quote;

Expand All @@ -13,8 +14,6 @@ use crate::{
utils::{ident, TypePath},
};

use fuel_abi_types::abi::full_program::FullProgramABI;

pub(crate) fn predicate_bindings(
name: &Ident,
abi: FullProgramABI,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use fuel_abi_types::abi::full_program::FullProgramABI;
use proc_macro2::{Ident, TokenStream};
use quote::quote;

Expand All @@ -14,8 +15,6 @@ use crate::{
utils::{ident, TypePath},
};

use fuel_abi_types::abi::full_program::FullProgramABI;

pub(crate) fn script_bindings(
name: &Ident,
abi: FullProgramABI,
Expand Down
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
use crate::error::{error, Result};

use fuel_abi_types::abi::full_program::FullABIFunction;

use crate::error::{error, Result};

pub(crate) fn extract_main_fn(abi: &[FullABIFunction]) -> Result<&FullABIFunction> {
let candidates = abi
.iter()
Expand All @@ -24,9 +24,10 @@ pub(crate) fn extract_main_fn(abi: &[FullABIFunction]) -> Result<&FullABIFunctio

#[cfg(test)]
mod tests {
use super::*;
use fuel_abi_types::abi::full_program::{FullTypeApplication, FullTypeDeclaration};

use super::*;

#[test]
fn correctly_extracts_the_main_fn() {
let functions = ["fn_1", "main", "fn_2"].map(given_a_fun_named);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
use fuel_abi_types::abi::full_program::FullConfigurable;
use proc_macro2::{Ident, TokenStream};
use quote::quote;

Expand All @@ -7,8 +8,6 @@ use crate::{
utils::safe_ident,
};

use fuel_abi_types::abi::full_program::FullConfigurable;

#[derive(Debug)]
pub(crate) struct ResolvedConfigurable {
pub name: Ident,
Expand Down
3 changes: 1 addition & 2 deletions packages/fuels-code-gen/src/program_bindings/abigen/logs.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,9 @@
use fuel_abi_types::abi::full_program::FullLoggedType;
use proc_macro2::TokenStream;
use quote::quote;

use crate::program_bindings::resolved_type::TypeResolver;

use fuel_abi_types::abi::full_program::FullLoggedType;

pub(crate) fn log_formatters_instantiation_code(
contract_id: TokenStream,
logged_types: &[FullLoggedType],
Expand Down
3 changes: 1 addition & 2 deletions packages/fuels-code-gen/src/program_bindings/custom_types.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::collections::HashSet;

use fuel_abi_types::abi::full_program::FullTypeDeclaration;
use itertools::Itertools;
use quote::quote;

Expand All @@ -13,8 +14,6 @@ use crate::{
utils::TypePath,
};

use fuel_abi_types::abi::full_program::FullTypeDeclaration;

mod enums;
mod structs;
mod utils;
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::collections::HashSet;

use fuel_abi_types::abi::full_program::FullTypeDeclaration;
use proc_macro2::{Ident, TokenStream};
use quote::quote;

Expand All @@ -12,8 +13,6 @@ use crate::{
},
};

use fuel_abi_types::abi::full_program::FullTypeDeclaration;

/// Returns a TokenStream containing the declaration, `Parameterize`,
/// `Tokenizable` and `TryFrom` implementations for the enum described by the
/// given TypeDeclaration.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::collections::HashSet;

use fuel_abi_types::abi::full_program::FullTypeDeclaration;
use proc_macro2::{Ident, TokenStream};
use quote::quote;

Expand All @@ -12,8 +13,6 @@ use crate::{
},
};

use fuel_abi_types::abi::full_program::FullTypeDeclaration;

/// Returns a TokenStream containing the declaration, `Parameterize`,
/// `Tokenizable` and `TryFrom` implementations for the struct described by the
/// given TypeDeclaration.
Expand Down
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
use fuel_abi_types::utils::extract_generic_name;
use fuel_abi_types::{
abi::full_program::FullTypeDeclaration,
utils::{extract_generic_name, ident, TypePath},
};
use proc_macro2::TokenStream;
use quote::quote;

use crate::{error::Result, program_bindings::utils::Component};

use fuel_abi_types::{
abi::full_program::FullTypeDeclaration,
utils::{ident, TypePath},
};

/// Transforms components from inside the given `FullTypeDeclaration` into a vector
/// of `Components`. Will fail if there are no components.
pub(crate) fn extract_components(
Expand Down
6 changes: 3 additions & 3 deletions packages/fuels-code-gen/src/program_bindings/utils.rs
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
use std::collections::HashMap;

use fuel_abi_types::abi::full_program::FullTypeApplication;
use inflector::Inflector;
use proc_macro2::{Ident, TokenStream};
use quote::{quote, ToTokens};
Expand All @@ -10,8 +11,6 @@ use crate::{
utils::{safe_ident, TypePath},
};

use fuel_abi_types::abi::full_program::FullTypeApplication;

// Represents a component of either a struct(field name) or an enum(variant
// name).
#[derive(Debug)]
Expand Down Expand Up @@ -69,9 +68,10 @@ pub(crate) fn single_param_type_call(field_type: &ResolvedType) -> TokenStream {

#[cfg(test)]
mod tests {
use super::*;
use fuel_abi_types::abi::full_program::FullTypeDeclaration;

use super::*;

#[test]
fn respects_snake_case_flag() -> Result<()> {
let type_application = type_application_named("WasNotSnakeCased");
Expand Down
9 changes: 8 additions & 1 deletion packages/fuels-code-gen/src/utils/source.rs
Original file line number Diff line number Diff line change
Expand Up @@ -64,13 +64,20 @@ impl Source {

/// Retrieves the source JSON of the artifact this will either read the JSON
/// from the file system or retrieve a contract ABI from the network
/// dependending on the source type.
/// depending on the source type.
pub fn get(&self) -> Result<String> {
match self {
Source::Local(path) => get_local_contract(path),
Source::String(abi) => Ok(abi.clone()),
}
}

pub fn path(&self) -> Option<PathBuf> {
match self {
Source::Local(path) => Some(path.clone()),
_ => None,
}
}
}

fn get_local_contract(path: &Path) -> Result<String> {
Expand Down
4 changes: 1 addition & 3 deletions packages/fuels-core/src/types.rs
Original file line number Diff line number Diff line change
@@ -1,10 +1,8 @@
use std::fmt;

pub use fuel_tx::{Address, AssetId, ContractId, TxPointer, UtxoId};
pub use fuel_types::Nonce;

use fuel_types::bytes::padded_len;
pub use fuel_types::MessageId;
pub use fuel_types::{MessageId, Nonce};

pub use crate::types::{core::*, wrappers::*};
use crate::types::{
Expand Down
6 changes: 4 additions & 2 deletions packages/fuels-core/src/types/wrappers/block.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
#![cfg(feature = "std")]

use chrono::{DateTime, NaiveDateTime, Utc};
use fuel_core_client::client::types::block::{Block as ClientBlock, Header as ClientHeader};
use fuel_core_client::client::types::primitives::Bytes32;
use fuel_core_client::client::types::{
block::{Block as ClientBlock, Header as ClientHeader},
primitives::Bytes32,
};

#[derive(Debug)]
pub struct Header {
Expand Down
Loading

0 comments on commit ff74fc7

Please sign in to comment.