Skip to content

Commit

Permalink
config section
Browse files Browse the repository at this point in the history
  • Loading branch information
klkvr committed Jul 10, 2024
1 parent e48776e commit bc2b4fd
Show file tree
Hide file tree
Showing 5 changed files with 71 additions and 7 deletions.
29 changes: 29 additions & 0 deletions crates/config/src/bind_json.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
use crate::from_vec_glob;
use serde::{Deserialize, Serialize};
use std::path::PathBuf;

/// Contains the config for `forge bind-json`
#[derive(Clone, Debug, PartialEq, Eq, Serialize, Deserialize)]
pub struct BindJsonConfig {
/// Path for the generated bindings file.
pub out: PathBuf,
/// Globs to include.
///
/// If provided, only the files matching the globs will be included. Otherwise, defaults to
/// including all project files.
#[serde(with = "from_vec_glob")]
pub include: Vec<globset::Glob>,
/// Globs to ignore
#[serde(with = "from_vec_glob")]
pub exclude: Vec<globset::Glob>,
}

impl Default for BindJsonConfig {
fn default() -> Self {
Self {
out: PathBuf::from("utils/JsonBindings.sol"),
exclude: Vec::new(),
include: Vec::new(),
}
}
}
7 changes: 7 additions & 0 deletions crates/config/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -110,6 +110,9 @@ use soldeer::SoldeerConfig;
mod vyper;
use vyper::VyperConfig;

mod bind_json;
use bind_json::BindJsonConfig;

/// Foundry configuration
///
/// # Defaults
Expand Down Expand Up @@ -383,6 +386,8 @@ pub struct Config {
pub fmt: FormatterConfig,
/// Configuration for `forge doc`
pub doc: DocConfig,
/// Configuration for `forge bind-json`
pub bind_json: BindJsonConfig,
/// Configures the permissions of cheat codes that touch the file system.
///
/// This includes what operations can be executed (read, write)
Expand Down Expand Up @@ -478,6 +483,7 @@ impl Config {
"labels",
"dependencies",
"vyper",
"bind_json",
];

/// File name of config toml file
Expand Down Expand Up @@ -2130,6 +2136,7 @@ impl Default for Config {
build_info_path: None,
fmt: Default::default(),
doc: Default::default(),
bind_json: Default::default(),
labels: Default::default(),
unchecked_cheatcode_artifacts: false,
create2_library_salt: Self::DEFAULT_CREATE2_LIBRARY_SALT,
Expand Down
40 changes: 33 additions & 7 deletions crates/forge/bin/cmd/bind_json.rs
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ use foundry_compilers::{
solc::SolcLanguage,
CompilerSettings, Graph, Project,
};
use foundry_config::{filter::GlobMatcher, Config};
use itertools::Itertools;
use rayon::prelude::*;
use solang_parser::pt as solang_ast;
Expand Down Expand Up @@ -57,7 +58,7 @@ impl BindJsonArgs {
let config = self.try_load_config_emit_warnings()?;
let project = config.create_project(false, true)?;

let target_path = config.root.0.join("utils/JsonBindings.sol");
let target_path = config.root.0.join(&config.bind_json.out);

let sources = project.paths.read_input_files()?;
let graph = Graph::<MultiCompilerParsedSource>::resolve_sources(&project.paths, sources)?;
Expand Down Expand Up @@ -156,7 +157,7 @@ impl BindJsonArgs {
.collect::<Result<BTreeMap<_, _>>>()?,
);

Ok(PreprocessedState { sources, target_path, project })
Ok(PreprocessedState { sources, target_path, project, config })
}
}

Expand Down Expand Up @@ -215,11 +216,12 @@ struct PreprocessedState {
sources: Sources,
target_path: PathBuf,
project: Project,
config: Config,
}

impl PreprocessedState {
fn compile(self) -> Result<CompiledState> {
let Self { sources, target_path, mut project } = self;
let Self { sources, target_path, mut project, config } = self;

project.settings.update_output_selection(|selection| {
*selection = OutputSelection::ast_output_selection();
Expand Down Expand Up @@ -248,19 +250,21 @@ impl PreprocessedState {
})
.collect::<Result<BTreeMap<_, _>>>()?;

Ok(CompiledState { asts, target_path })
Ok(CompiledState { asts, target_path, config, project })
}
}

#[derive(Debug, Clone, Default)]
#[derive(Debug, Clone)]
struct CompiledState {
asts: BTreeMap<PathBuf, SourceUnit>,
target_path: PathBuf,
config: Config,
project: Project,
}

impl CompiledState {
fn find_structs(self) -> Result<StructsState> {
let Self { asts, target_path } = self;
let Self { asts, target_path, config, project } = self;

// construct mapping (file, id) -> (struct definition, optional parent contract name)
let structs = asts
Expand Down Expand Up @@ -293,6 +297,11 @@ impl CompiledState {

let mut structs_to_write = Vec::new();

let include =
config.bind_json.include.into_iter().map(GlobMatcher::new).collect::<Vec<_>>();
let exclude =
config.bind_json.exclude.into_iter().map(GlobMatcher::new).collect::<Vec<_>>();

for ((path, id), (def, contract_name)) in structs {
// For some structs there's no schema (e.g. if they contain a mapping), so we just skip
// those.
Expand All @@ -301,6 +310,21 @@ impl CompiledState {
continue
};

if !include.is_empty() {
if !include.iter().any(|matcher| matcher.is_match(path)) {
continue;
}
} else {
// Exclude library files by default
if project.paths.has_library_ancestor(path) {
continue;
}
}

if exclude.iter().any(|matcher| matcher.is_match(path)) {
continue;
}

structs_to_write.push(StructToWrite {
name: def.name.clone(),
contract_name,
Expand Down Expand Up @@ -412,6 +436,8 @@ impl ResolvedState {
fs::create_dir_all(self.target_path.parent().unwrap())?;
fs::write(&self.target_path, &result)?;

println!("Bindings written to {}", self.target_path.display());

Ok(result)
}

Expand All @@ -426,7 +452,7 @@ impl ResolvedState {
.insert(item);
}

result.push_str("pragma solidity >=0.6.2 <0.9.0;\npragma experimental ABIEncoderV2;\n\n");
result.push_str("// Automatically generated by forge bind-json.\n\npragma solidity >=0.6.2 <0.9.0;\npragma experimental ABIEncoderV2;\n\n");

for (path, names) in grouped_imports {
result.push_str(&format!(
Expand Down
1 change: 1 addition & 0 deletions crates/forge/bin/opts.rs
Original file line number Diff line number Diff line change
Expand Up @@ -168,6 +168,7 @@ pub enum ForgeSubcommand {
/// Generate EIP-712 struct encodings for structs from a given file.
Eip712(eip712::Eip712Args),

/// Generate bindings for serialization/deserialization of project structs via JSON cheatcodes.
BindJson(bind_json::BindJsonArgs),
}

Expand Down
1 change: 1 addition & 0 deletions crates/forge/tests/cli/config.rs
Original file line number Diff line number Diff line change
Expand Up @@ -130,6 +130,7 @@ forgetest!(can_extract_config_values, |prj, cmd| {
build_info_path: None,
fmt: Default::default(),
doc: Default::default(),
bind_json: Default::default(),
fs_permissions: Default::default(),
labels: Default::default(),
prague: true,
Expand Down

0 comments on commit bc2b4fd

Please sign in to comment.