Skip to content

Commit ff74fc7

Browse files
feat: macro recompile trigger (#1061)
`abigen!` and `setup_program_test!` should now rerun if any changes to the abi files are detected.
1 parent a182d63 commit ff74fc7

File tree

28 files changed

+107
-78
lines changed

28 files changed

+107
-78
lines changed

examples/cookbook/src/lib.rs

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -87,10 +87,8 @@ mod tests {
8787

8888
#[tokio::test]
8989
async fn custom_chain() -> Result<()> {
90-
use fuels::prelude::*;
9190
// ANCHOR: custom_chain_import
92-
use fuels::fuel_node::ChainConfig;
93-
use fuels::tx::ConsensusParameters;
91+
use fuels::{fuel_node::ChainConfig, prelude::*, tx::ConsensusParameters};
9492
// ANCHOR_END: custom_chain_import
9593

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

191+
use fuels::prelude::*;
192+
194193
// ANCHOR: create_or_use_rocksdb
195194
let provider_config = Config {
196195
database_path: PathBuf::from("/tmp/.spider/db"),

packages/fuels-accounts/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -318,9 +318,9 @@ pub trait Account: ViewOnlyAccount {
318318

319319
#[cfg(test)]
320320
mod tests {
321-
use fuel_core_client::client::FuelClient;
322321
use std::str::FromStr;
323322

323+
use fuel_core_client::client::FuelClient;
324324
use fuel_crypto::{Message, SecretKey};
325325
use fuel_tx::{Address, ConsensusParameters, Output};
326326
use fuels_core::types::transaction::Transaction;

packages/fuels-code-gen/src/program_bindings/abigen.rs

Lines changed: 25 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
use std::collections::HashSet;
1+
use std::{collections::HashSet, path::PathBuf};
22

33
pub use abigen_target::{AbigenTarget, ProgramType};
4+
use fuel_abi_types::abi::full_program::FullTypeDeclaration;
45
use inflector::Inflector;
56
use itertools::Itertools;
67
use proc_macro2::TokenStream;
@@ -17,8 +18,6 @@ use crate::{
1718
utils::ident,
1819
};
1920

20-
use fuel_abi_types::abi::full_program::FullTypeDeclaration;
21-
2221
mod abigen_target;
2322
mod bindings;
2423
mod configurables;
@@ -103,10 +102,30 @@ impl Abigen {
103102
) -> Result<GeneratedCode> {
104103
let mod_name = ident(&format!("{}_mod", &target.name.to_snake_case()));
105104

106-
let types = generate_types(&target.source.types, shared_types, no_std)?;
105+
let recompile_trigger =
106+
Self::generate_macro_recompile_trigger(target.source.path.as_ref(), no_std);
107+
let types = generate_types(&target.source.abi.types, shared_types, no_std)?;
107108
let bindings = generate_bindings(target, no_std)?;
109+
Ok(recompile_trigger
110+
.merge(types)
111+
.merge(bindings)
112+
.wrap_in_mod(mod_name))
113+
}
108114

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

112131
fn parse_targets(targets: Vec<AbigenTarget>) -> Result<Vec<ParsedAbigenTarget>> {
@@ -135,7 +154,7 @@ impl Abigen {
135154
) -> impl Iterator<Item = &FullTypeDeclaration> {
136155
all_types
137156
.iter()
138-
.flat_map(|target| &target.source.types)
157+
.flat_map(|target| &target.source.abi.types)
139158
.filter(|ttype| ttype.is_custom_type())
140159
}
141160

packages/fuels-code-gen/src/program_bindings/abigen/abigen_target.rs

Lines changed: 13 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
1-
use std::{convert::TryFrom, str::FromStr};
1+
use std::{convert::TryFrom, path::PathBuf, str::FromStr};
22

3+
use fuel_abi_types::abi::full_program::FullProgramABI;
34
use proc_macro2::Ident;
45

56
use crate::{
@@ -8,18 +9,21 @@ use crate::{
89
utils::Source,
910
};
1011

11-
use fuel_abi_types::abi::full_program::FullProgramABI;
12-
1312
#[derive(Debug, Clone)]
1413
pub struct AbigenTarget {
1514
pub name: String,
1615
pub abi: String,
1716
pub program_type: ProgramType,
1817
}
1918

19+
pub(crate) struct Abi {
20+
pub(crate) path: Option<PathBuf>,
21+
pub(crate) abi: FullProgramABI,
22+
}
23+
2024
pub(crate) struct ParsedAbigenTarget {
2125
pub name: String,
22-
pub source: FullProgramABI,
26+
pub source: Abi,
2327
pub program_type: ProgramType,
2428
}
2529

@@ -35,10 +39,13 @@ impl TryFrom<AbigenTarget> for ParsedAbigenTarget {
3539
}
3640
}
3741

38-
fn parse_program_abi(abi_source: &str) -> Result<FullProgramABI> {
42+
fn parse_program_abi(abi_source: &str) -> Result<Abi> {
3943
let source = Source::parse(abi_source).expect("failed to parse JSON ABI");
44+
4045
let json_abi_str = source.get().expect("failed to parse JSON ABI from string");
41-
FullProgramABI::from_json_abi(&json_abi_str).map_err(|e| e.into())
46+
let abi = FullProgramABI::from_json_abi(&json_abi_str)?;
47+
let path = source.path();
48+
Ok(Abi { path, abi })
4249
}
4350

4451
#[derive(Debug, Clone, Copy, PartialEq, Eq)]

packages/fuels-code-gen/src/program_bindings/abigen/bindings.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,6 @@ pub(crate) fn generate_bindings(target: ParsedAbigenTarget, no_std: bool) -> Res
2727
};
2828

2929
let name = ident(&target.name);
30-
let abi = target.source;
30+
let abi = target.source.abi;
3131
bindings_generator(&name, abi, no_std)
3232
}

packages/fuels-code-gen/src/program_bindings/abigen/bindings/contract.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use fuel_abi_types::abi::full_program::{FullABIFunction, FullProgramABI};
12
use itertools::Itertools;
23
use proc_macro2::{Ident, TokenStream};
34
use quote::{quote, TokenStreamExt};
@@ -15,8 +16,6 @@ use crate::{
1516
utils::{ident, TypePath},
1617
};
1718

18-
use fuel_abi_types::abi::full_program::{FullABIFunction, FullProgramABI};
19-
2019
pub(crate) fn contract_bindings(
2120
name: &Ident,
2221
abi: FullProgramABI,

packages/fuels-code-gen/src/program_bindings/abigen/bindings/function_generator.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use fuel_abi_types::abi::full_program::{FullABIFunction, FullTypeApplication};
12
use proc_macro2::TokenStream;
23
use quote::{quote, ToTokens};
34

@@ -10,8 +11,6 @@ use crate::{
1011
utils::{safe_ident, TypePath},
1112
};
1213

13-
use fuel_abi_types::abi::full_program::{FullABIFunction, FullTypeApplication};
14-
1514
#[derive(Debug)]
1615
pub(crate) struct FunctionGenerator {
1716
name: String,

packages/fuels-code-gen/src/program_bindings/abigen/bindings/predicate.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use fuel_abi_types::abi::full_program::FullProgramABI;
12
use proc_macro2::{Ident, TokenStream};
23
use quote::quote;
34

@@ -13,8 +14,6 @@ use crate::{
1314
utils::{ident, TypePath},
1415
};
1516

16-
use fuel_abi_types::abi::full_program::FullProgramABI;
17-
1817
pub(crate) fn predicate_bindings(
1918
name: &Ident,
2019
abi: FullProgramABI,

packages/fuels-code-gen/src/program_bindings/abigen/bindings/script.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use fuel_abi_types::abi::full_program::FullProgramABI;
12
use proc_macro2::{Ident, TokenStream};
23
use quote::quote;
34

@@ -14,8 +15,6 @@ use crate::{
1415
utils::{ident, TypePath},
1516
};
1617

17-
use fuel_abi_types::abi::full_program::FullProgramABI;
18-
1918
pub(crate) fn script_bindings(
2019
name: &Ident,
2120
abi: FullProgramABI,

packages/fuels-code-gen/src/program_bindings/abigen/bindings/utils.rs

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
1-
use crate::error::{error, Result};
2-
31
use fuel_abi_types::abi::full_program::FullABIFunction;
42

3+
use crate::error::{error, Result};
4+
55
pub(crate) fn extract_main_fn(abi: &[FullABIFunction]) -> Result<&FullABIFunction> {
66
let candidates = abi
77
.iter()
@@ -24,9 +24,10 @@ pub(crate) fn extract_main_fn(abi: &[FullABIFunction]) -> Result<&FullABIFunctio
2424

2525
#[cfg(test)]
2626
mod tests {
27-
use super::*;
2827
use fuel_abi_types::abi::full_program::{FullTypeApplication, FullTypeDeclaration};
2928

29+
use super::*;
30+
3031
#[test]
3132
fn correctly_extracts_the_main_fn() {
3233
let functions = ["fn_1", "main", "fn_2"].map(given_a_fun_named);

packages/fuels-code-gen/src/program_bindings/abigen/configurables.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
use fuel_abi_types::abi::full_program::FullConfigurable;
12
use proc_macro2::{Ident, TokenStream};
23
use quote::quote;
34

@@ -7,8 +8,6 @@ use crate::{
78
utils::safe_ident,
89
};
910

10-
use fuel_abi_types::abi::full_program::FullConfigurable;
11-
1211
#[derive(Debug)]
1312
pub(crate) struct ResolvedConfigurable {
1413
pub name: Ident,

packages/fuels-code-gen/src/program_bindings/abigen/logs.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1+
use fuel_abi_types::abi::full_program::FullLoggedType;
12
use proc_macro2::TokenStream;
23
use quote::quote;
34

45
use crate::program_bindings::resolved_type::TypeResolver;
56

6-
use fuel_abi_types::abi::full_program::FullLoggedType;
7-
87
pub(crate) fn log_formatters_instantiation_code(
98
contract_id: TokenStream,
109
logged_types: &[FullLoggedType],

packages/fuels-code-gen/src/program_bindings/custom_types.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::HashSet;
22

3+
use fuel_abi_types::abi::full_program::FullTypeDeclaration;
34
use itertools::Itertools;
45
use quote::quote;
56

@@ -13,8 +14,6 @@ use crate::{
1314
utils::TypePath,
1415
};
1516

16-
use fuel_abi_types::abi::full_program::FullTypeDeclaration;
17-
1817
mod enums;
1918
mod structs;
2019
mod utils;

packages/fuels-code-gen/src/program_bindings/custom_types/enums.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::HashSet;
22

3+
use fuel_abi_types::abi::full_program::FullTypeDeclaration;
34
use proc_macro2::{Ident, TokenStream};
45
use quote::quote;
56

@@ -12,8 +13,6 @@ use crate::{
1213
},
1314
};
1415

15-
use fuel_abi_types::abi::full_program::FullTypeDeclaration;
16-
1716
/// Returns a TokenStream containing the declaration, `Parameterize`,
1817
/// `Tokenizable` and `TryFrom` implementations for the enum described by the
1918
/// given TypeDeclaration.

packages/fuels-code-gen/src/program_bindings/custom_types/structs.rs

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::HashSet;
22

3+
use fuel_abi_types::abi::full_program::FullTypeDeclaration;
34
use proc_macro2::{Ident, TokenStream};
45
use quote::quote;
56

@@ -12,8 +13,6 @@ use crate::{
1213
},
1314
};
1415

15-
use fuel_abi_types::abi::full_program::FullTypeDeclaration;
16-
1716
/// Returns a TokenStream containing the declaration, `Parameterize`,
1817
/// `Tokenizable` and `TryFrom` implementations for the struct described by the
1918
/// given TypeDeclaration.

packages/fuels-code-gen/src/program_bindings/custom_types/utils.rs

Lines changed: 4 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,12 @@
1-
use fuel_abi_types::utils::extract_generic_name;
1+
use fuel_abi_types::{
2+
abi::full_program::FullTypeDeclaration,
3+
utils::{extract_generic_name, ident, TypePath},
4+
};
25
use proc_macro2::TokenStream;
36
use quote::quote;
47

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

7-
use fuel_abi_types::{
8-
abi::full_program::FullTypeDeclaration,
9-
utils::{ident, TypePath},
10-
};
11-
1210
/// Transforms components from inside the given `FullTypeDeclaration` into a vector
1311
/// of `Components`. Will fail if there are no components.
1412
pub(crate) fn extract_components(

packages/fuels-code-gen/src/program_bindings/utils.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
use std::collections::HashMap;
22

3+
use fuel_abi_types::abi::full_program::FullTypeApplication;
34
use inflector::Inflector;
45
use proc_macro2::{Ident, TokenStream};
56
use quote::{quote, ToTokens};
@@ -10,8 +11,6 @@ use crate::{
1011
utils::{safe_ident, TypePath},
1112
};
1213

13-
use fuel_abi_types::abi::full_program::FullTypeApplication;
14-
1514
// Represents a component of either a struct(field name) or an enum(variant
1615
// name).
1716
#[derive(Debug)]
@@ -69,9 +68,10 @@ pub(crate) fn single_param_type_call(field_type: &ResolvedType) -> TokenStream {
6968

7069
#[cfg(test)]
7170
mod tests {
72-
use super::*;
7371
use fuel_abi_types::abi::full_program::FullTypeDeclaration;
7472

73+
use super::*;
74+
7575
#[test]
7676
fn respects_snake_case_flag() -> Result<()> {
7777
let type_application = type_application_named("WasNotSnakeCased");

packages/fuels-code-gen/src/utils/source.rs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,13 +64,20 @@ impl Source {
6464

6565
/// Retrieves the source JSON of the artifact this will either read the JSON
6666
/// from the file system or retrieve a contract ABI from the network
67-
/// dependending on the source type.
67+
/// depending on the source type.
6868
pub fn get(&self) -> Result<String> {
6969
match self {
7070
Source::Local(path) => get_local_contract(path),
7171
Source::String(abi) => Ok(abi.clone()),
7272
}
7373
}
74+
75+
pub fn path(&self) -> Option<PathBuf> {
76+
match self {
77+
Source::Local(path) => Some(path.clone()),
78+
_ => None,
79+
}
80+
}
7481
}
7582

7683
fn get_local_contract(path: &Path) -> Result<String> {

packages/fuels-core/src/types.rs

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,8 @@
11
use std::fmt;
22

33
pub use fuel_tx::{Address, AssetId, ContractId, TxPointer, UtxoId};
4-
pub use fuel_types::Nonce;
5-
64
use fuel_types::bytes::padded_len;
7-
pub use fuel_types::MessageId;
5+
pub use fuel_types::{MessageId, Nonce};
86

97
pub use crate::types::{core::*, wrappers::*};
108
use crate::types::{

packages/fuels-core/src/types/wrappers/block.rs

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,10 @@
11
#![cfg(feature = "std")]
22

33
use chrono::{DateTime, NaiveDateTime, Utc};
4-
use fuel_core_client::client::types::block::{Block as ClientBlock, Header as ClientHeader};
5-
use fuel_core_client::client::types::primitives::Bytes32;
4+
use fuel_core_client::client::types::{
5+
block::{Block as ClientBlock, Header as ClientHeader},
6+
primitives::Bytes32,
7+
};
68

79
#[derive(Debug)]
810
pub struct Header {

0 commit comments

Comments
 (0)