diff --git a/crates/anvil/src/anvil.rs b/crates/anvil/src/anvil.rs index c969c09420c1..5ff9394821d8 100644 --- a/crates/anvil/src/anvil.rs +++ b/crates/anvil/src/anvil.rs @@ -3,18 +3,18 @@ use anvil::cmd::NodeArgs; use clap::{CommandFactory, Parser, Subcommand}; /// A fast local Ethereum development node. -#[derive(Debug, Parser)] +#[derive(Parser)] #[clap(name = "anvil", version = anvil::VERSION_MESSAGE, next_display_order = None)] -pub struct App { +pub struct Anvil { #[clap(flatten)] pub node: NodeArgs, #[clap(subcommand)] - pub cmd: Option, + pub cmd: Option, } -#[derive(Clone, Debug, PartialEq, Eq, Subcommand)] -pub enum Commands { +#[derive(Subcommand)] +pub enum AnvilSubcommand { /// Generate shell completions script. #[clap(visible_alias = "com")] Completions { @@ -29,22 +29,22 @@ pub enum Commands { #[tokio::main] async fn main() -> Result<(), Box> { - let mut app = App::parse(); + let mut app = Anvil::parse(); app.node.evm_opts.resolve_rpc_alias(); if let Some(ref cmd) = app.cmd { match cmd { - Commands::Completions { shell } => { + AnvilSubcommand::Completions { shell } => { clap_complete::generate( *shell, - &mut App::command(), + &mut Anvil::command(), "anvil", &mut std::io::stdout(), ); } - Commands::GenerateFigSpec => clap_complete::generate( + AnvilSubcommand::GenerateFigSpec => clap_complete::generate( clap_complete_fig::Fig, - &mut App::command(), + &mut Anvil::command(), "anvil", &mut std::io::stdout(), ), @@ -62,14 +62,22 @@ async fn main() -> Result<(), Box> { mod tests { use super::*; + #[test] + fn verify_cli() { + Anvil::command().debug_assert(); + } + #[test] fn can_parse_help() { - let _: App = App::parse_from(["anvil", "--help"]); + let _: Anvil = Anvil::parse_from(["anvil", "--help"]); } #[test] fn can_parse_completions() { - let args: App = App::parse_from(["anvil", "completions", "bash"]); - assert_eq!(args.cmd, Some(Commands::Completions { shell: clap_complete::Shell::Bash })); + let args: Anvil = Anvil::parse_from(["anvil", "completions", "bash"]); + assert!(matches!( + args.cmd, + Some(AnvilSubcommand::Completions { shell: clap_complete::Shell::Bash }) + )); } } diff --git a/crates/cast/bin/main.rs b/crates/cast/bin/main.rs index 9c992e7667f2..c4ee0e56388e 100644 --- a/crates/cast/bin/main.rs +++ b/crates/cast/bin/main.rs @@ -27,7 +27,7 @@ use std::time::Instant; pub mod cmd; pub mod opts; -use opts::{Opts, Subcommands, ToBaseArgs}; +use opts::{Cast as Opts, CastSubcommand, ToBaseArgs}; #[tokio::main] async fn main() -> Result<()> { @@ -37,42 +37,42 @@ async fn main() -> Result<()> { utils::enable_paint(); let opts = Opts::parse(); - match opts.sub { + match opts.cmd { // Constants - Subcommands::MaxInt { r#type } => { + CastSubcommand::MaxInt { r#type } => { println!("{}", SimpleCast::max_int(&r#type)?); } - Subcommands::MinInt { r#type } => { + CastSubcommand::MinInt { r#type } => { println!("{}", SimpleCast::min_int(&r#type)?); } - Subcommands::MaxUint { r#type } => { + CastSubcommand::MaxUint { r#type } => { println!("{}", SimpleCast::max_int(&r#type)?); } - Subcommands::AddressZero => { + CastSubcommand::AddressZero => { println!("{:?}", Address::ZERO); } - Subcommands::HashZero => { + CastSubcommand::HashZero => { println!("{:?}", B256::ZERO); } // Conversions & transformations - Subcommands::FromUtf8 { text } => { + CastSubcommand::FromUtf8 { text } => { let value = stdin::unwrap(text, false)?; println!("{}", SimpleCast::from_utf8(&value)); } - Subcommands::ToAscii { hexdata } => { + CastSubcommand::ToAscii { hexdata } => { let value = stdin::unwrap(hexdata, false)?; println!("{}", SimpleCast::to_ascii(&value)?); } - Subcommands::FromFixedPoint { value, decimals } => { + CastSubcommand::FromFixedPoint { value, decimals } => { let (value, decimals) = stdin::unwrap2(value, decimals)?; println!("{}", SimpleCast::from_fixed_point(&value, &decimals)?); } - Subcommands::ToFixedPoint { value, decimals } => { + CastSubcommand::ToFixedPoint { value, decimals } => { let (value, decimals) = stdin::unwrap2(value, decimals)?; println!("{}", SimpleCast::to_fixed_point(&value, &decimals)?); } - Subcommands::ConcatHex { data } => { + CastSubcommand::ConcatHex { data } => { if data.is_empty() { let s = stdin::read(true)?; println!("{}", SimpleCast::concat_hex(s.split_whitespace())) @@ -80,11 +80,11 @@ async fn main() -> Result<()> { println!("{}", SimpleCast::concat_hex(data)) } } - Subcommands::FromBin => { + CastSubcommand::FromBin => { let hex = stdin::read_bytes(false)?; println!("{}", hex::encode_prefixed(hex)); } - Subcommands::ToHexdata { input } => { + CastSubcommand::ToHexdata { input } => { let value = stdin::unwrap_line(input)?; let output = match value { s if s.starts_with('@') => hex::encode(std::env::var(&s[1..])?), @@ -93,91 +93,91 @@ async fn main() -> Result<()> { }; println!("0x{output}"); } - Subcommands::ToCheckSumAddress { address } => { + CastSubcommand::ToCheckSumAddress { address } => { let value = stdin::unwrap_line(address)?; println!("{}", value.to_checksum(None)); } - Subcommands::ToUint256 { value } => { + CastSubcommand::ToUint256 { value } => { let value = stdin::unwrap_line(value)?; println!("{}", SimpleCast::to_uint256(&value)?); } - Subcommands::ToInt256 { value } => { + CastSubcommand::ToInt256 { value } => { let value = stdin::unwrap_line(value)?; println!("{}", SimpleCast::to_int256(&value)?); } - Subcommands::ToUnit { value, unit } => { + CastSubcommand::ToUnit { value, unit } => { let value = stdin::unwrap_line(value)?; println!("{}", SimpleCast::to_unit(&value, &unit)?); } - Subcommands::FromWei { value, unit } => { + CastSubcommand::FromWei { value, unit } => { let value = stdin::unwrap_line(value)?; println!("{}", SimpleCast::from_wei(&value, &unit)?); } - Subcommands::ToWei { value, unit } => { + CastSubcommand::ToWei { value, unit } => { let value = stdin::unwrap_line(value)?; println!("{}", SimpleCast::to_wei(&value, &unit)?); } - Subcommands::FromRlp { value } => { + CastSubcommand::FromRlp { value } => { let value = stdin::unwrap_line(value)?; println!("{}", SimpleCast::from_rlp(value)?); } - Subcommands::ToRlp { value } => { + CastSubcommand::ToRlp { value } => { let value = stdin::unwrap_line(value)?; println!("{}", SimpleCast::to_rlp(&value)?); } - Subcommands::ToHex(ToBaseArgs { value, base_in }) => { + CastSubcommand::ToHex(ToBaseArgs { value, base_in }) => { let value = stdin::unwrap_line(value)?; println!("{}", SimpleCast::to_base(&value, base_in.as_deref(), "hex")?); } - Subcommands::ToDec(ToBaseArgs { value, base_in }) => { + CastSubcommand::ToDec(ToBaseArgs { value, base_in }) => { let value = stdin::unwrap_line(value)?; println!("{}", SimpleCast::to_base(&value, base_in.as_deref(), "dec")?); } - Subcommands::ToBase { base: ToBaseArgs { value, base_in }, base_out } => { + CastSubcommand::ToBase { base: ToBaseArgs { value, base_in }, base_out } => { let (value, base_out) = stdin::unwrap2(value, base_out)?; println!("{}", SimpleCast::to_base(&value, base_in.as_deref(), &base_out)?); } - Subcommands::ToBytes32 { bytes } => { + CastSubcommand::ToBytes32 { bytes } => { let value = stdin::unwrap_line(bytes)?; println!("{}", SimpleCast::to_bytes32(&value)?); } - Subcommands::FormatBytes32String { string } => { + CastSubcommand::FormatBytes32String { string } => { let value = stdin::unwrap_line(string)?; println!("{}", SimpleCast::format_bytes32_string(&value)?); } - Subcommands::ParseBytes32String { bytes } => { + CastSubcommand::ParseBytes32String { bytes } => { let value = stdin::unwrap_line(bytes)?; println!("{}", SimpleCast::parse_bytes32_string(&value)?); } - Subcommands::ParseBytes32Address { bytes } => { + CastSubcommand::ParseBytes32Address { bytes } => { let value = stdin::unwrap_line(bytes)?; println!("{}", SimpleCast::parse_bytes32_address(&value)?); } // ABI encoding & decoding - Subcommands::AbiDecode { sig, calldata, input } => { + CastSubcommand::AbiDecode { sig, calldata, input } => { let tokens = SimpleCast::abi_decode(&sig, &calldata, input)?; let tokens = format_tokens(&tokens); tokens.for_each(|t| println!("{t}")); } - Subcommands::AbiEncode { sig, args } => { + CastSubcommand::AbiEncode { sig, args } => { println!("{}", SimpleCast::abi_encode(&sig, &args)?); } - Subcommands::CalldataDecode { sig, calldata } => { + CastSubcommand::CalldataDecode { sig, calldata } => { let tokens = SimpleCast::calldata_decode(&sig, &calldata, true)?; let tokens = format_tokens(&tokens); tokens.for_each(|t| println!("{t}")); } - Subcommands::CalldataEncode { sig, args } => { + CastSubcommand::CalldataEncode { sig, args } => { println!("{}", SimpleCast::calldata_encode(sig, &args)?); } - Subcommands::Interface(cmd) => cmd.run().await?, - Subcommands::Bind(cmd) => cmd.run().await?, - Subcommands::PrettyCalldata { calldata, offline } => { + CastSubcommand::Interface(cmd) => cmd.run().await?, + CastSubcommand::Bind(cmd) => cmd.run().await?, + CastSubcommand::PrettyCalldata { calldata, offline } => { let calldata = stdin::unwrap_line(calldata)?; println!("{}", pretty_calldata(&calldata, offline).await?); } - Subcommands::Sig { sig, optimize } => { + CastSubcommand::Sig { sig, optimize } => { let sig = stdin::unwrap_line(sig)?; match optimize { Some(opt) => { @@ -193,8 +193,8 @@ async fn main() -> Result<()> { } // Blockchain & RPC queries - Subcommands::AccessList(cmd) => cmd.run().await?, - Subcommands::Age { block, rpc } => { + CastSubcommand::AccessList(cmd) => cmd.run().await?, + CastSubcommand::Age { block, rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; println!( @@ -202,7 +202,7 @@ async fn main() -> Result<()> { Cast::new(provider).age(block.unwrap_or(BlockId::Number(Latest))).await? ); } - Subcommands::Balance { block, who, ether, rpc, erc20 } => { + CastSubcommand::Balance { block, who, ether, rpc, erc20 } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; @@ -242,7 +242,7 @@ async fn main() -> Result<()> { } } } - Subcommands::BaseFee { block, rpc } => { + CastSubcommand::BaseFee { block, rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; println!( @@ -250,7 +250,7 @@ async fn main() -> Result<()> { Cast::new(provider).base_fee(block.unwrap_or(BlockId::Number(Latest))).await? ); } - Subcommands::Block { block, full, field, json, rpc } => { + CastSubcommand::Block { block, full, field, json, rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; println!( @@ -260,37 +260,37 @@ async fn main() -> Result<()> { .await? ); } - Subcommands::BlockNumber { rpc } => { + CastSubcommand::BlockNumber { rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; println!("{}", Cast::new(provider).block_number().await?); } - Subcommands::Chain { rpc } => { + CastSubcommand::Chain { rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; println!("{}", Cast::new(provider).chain().await?); } - Subcommands::ChainId { rpc } => { + CastSubcommand::ChainId { rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; println!("{}", Cast::new(provider).chain_id().await?); } - Subcommands::Client { rpc } => { + CastSubcommand::Client { rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; println!("{}", provider.client_version().await?); } - Subcommands::Code { block, who, disassemble, rpc } => { + CastSubcommand::Code { block, who, disassemble, rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; println!("{}", Cast::new(provider).code(who, block, disassemble).await?); } - Subcommands::Codesize { block, who, rpc } => { + CastSubcommand::Codesize { block, who, rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; println!("{}", Cast::new(provider).codesize(who, block).await?); } - Subcommands::ComputeAddress { address, nonce, rpc } => { + CastSubcommand::ComputeAddress { address, nonce, rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; @@ -298,10 +298,10 @@ async fn main() -> Result<()> { let computed = Cast::new(&provider).compute_address(address, nonce).await?; println!("Computed Address: {}", computed.to_checksum(None)); } - Subcommands::Disassemble { bytecode } => { + CastSubcommand::Disassemble { bytecode } => { println!("{}", SimpleCast::disassemble(&bytecode)?); } - Subcommands::Selectors { bytecode, resolve } => { + CastSubcommand::Selectors { bytecode, resolve } => { let selectors_and_args = SimpleCast::extract_selectors(&bytecode)?; if resolve { let selectors_it = selectors_and_args.iter().map(|r| &r.0); @@ -324,31 +324,31 @@ async fn main() -> Result<()> { } } } - Subcommands::FindBlock(cmd) => cmd.run().await?, - Subcommands::GasPrice { rpc } => { + CastSubcommand::FindBlock(cmd) => cmd.run().await?, + CastSubcommand::GasPrice { rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; println!("{}", Cast::new(provider).gas_price().await?); } - Subcommands::Index { key_type, key, slot_number } => { + CastSubcommand::Index { key_type, key, slot_number } => { println!("{}", SimpleCast::index(&key_type, &key, &slot_number)?); } - Subcommands::Implementation { block, who, rpc } => { + CastSubcommand::Implementation { block, who, rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; println!("{}", Cast::new(provider).implementation(who, block).await?); } - Subcommands::Admin { block, who, rpc } => { + CastSubcommand::Admin { block, who, rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; println!("{}", Cast::new(provider).admin(who, block).await?); } - Subcommands::Nonce { block, who, rpc } => { + CastSubcommand::Nonce { block, who, rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; println!("{}", Cast::new(provider).nonce(who, block).await?); } - Subcommands::Proof { address, slots, rpc, block } => { + CastSubcommand::Proof { address, slots, rpc, block } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; let value = provider @@ -356,13 +356,13 @@ async fn main() -> Result<()> { .await?; println!("{}", serde_json::to_string(&value)?); } - Subcommands::Rpc(cmd) => cmd.run().await?, - Subcommands::Storage(cmd) => cmd.run().await?, + CastSubcommand::Rpc(cmd) => cmd.run().await?, + CastSubcommand::Storage(cmd) => cmd.run().await?, // Calls & transactions - Subcommands::Call(cmd) => cmd.run().await?, - Subcommands::Estimate(cmd) => cmd.run().await?, - Subcommands::PublishTx { raw_tx, cast_async, rpc } => { + CastSubcommand::Call(cmd) => cmd.run().await?, + CastSubcommand::Estimate(cmd) => cmd.run().await?, + CastSubcommand::PublishTx { raw_tx, cast_async, rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; let cast = Cast::new(&provider); @@ -377,7 +377,7 @@ async fn main() -> Result<()> { println!("{}", serde_json::json!(receipt)); } } - Subcommands::Receipt { tx_hash, field, json, cast_async, confirmations, rpc } => { + CastSubcommand::Receipt { tx_hash, field, json, cast_async, confirmations, rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; println!( @@ -387,9 +387,9 @@ async fn main() -> Result<()> { .await? ); } - Subcommands::Run(cmd) => cmd.run().await?, - Subcommands::SendTx(cmd) => cmd.run().await?, - Subcommands::Tx { tx_hash, field, raw, json, rpc } => { + CastSubcommand::Run(cmd) => cmd.run().await?, + CastSubcommand::SendTx(cmd) => cmd.run().await?, + CastSubcommand::Tx { tx_hash, field, raw, json, rpc } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; @@ -400,7 +400,7 @@ async fn main() -> Result<()> { } // 4Byte - Subcommands::FourByte { selector } => { + CastSubcommand::FourByte { selector } => { let selector = stdin::unwrap_line(selector)?; let sigs = decode_function_selector(&selector).await?; if sigs.is_empty() { @@ -410,7 +410,7 @@ async fn main() -> Result<()> { println!("{sig}"); } } - Subcommands::FourByteDecode { calldata } => { + CastSubcommand::FourByteDecode { calldata } => { let calldata = stdin::unwrap_line(calldata)?; let sigs = decode_calldata(&calldata).await?; sigs.iter().enumerate().for_each(|(i, sig)| println!("{}) \"{sig}\"", i + 1)); @@ -429,7 +429,7 @@ async fn main() -> Result<()> { println!("{token}"); } } - Subcommands::FourByteEvent { topic } => { + CastSubcommand::FourByteEvent { topic } => { let topic = stdin::unwrap_line(topic)?; let sigs = decode_event_topic(&topic).await?; if sigs.is_empty() { @@ -439,7 +439,7 @@ async fn main() -> Result<()> { println!("{sig}"); } } - Subcommands::UploadSignature { signatures } => { + CastSubcommand::UploadSignature { signatures } => { let signatures = stdin::unwrap_vec(signatures)?; let ParsedSignatures { signatures, abis } = parse_signatures(signatures); if !abis.is_empty() { @@ -451,11 +451,11 @@ async fn main() -> Result<()> { } // ENS - Subcommands::Namehash { name } => { + CastSubcommand::Namehash { name } => { let name = stdin::unwrap_line(name)?; println!("{}", SimpleCast::namehash(&name)?); } - Subcommands::LookupAddress { who, rpc, verify } => { + CastSubcommand::LookupAddress { who, rpc, verify } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; @@ -470,7 +470,7 @@ async fn main() -> Result<()> { } println!("{name}"); } - Subcommands::ResolveName { who, rpc, verify } => { + CastSubcommand::ResolveName { who, rpc, verify } => { let config = Config::from(&rpc); let provider = utils::get_provider(&config)?; @@ -487,7 +487,7 @@ async fn main() -> Result<()> { } // Misc - Subcommands::Keccak { data } => { + CastSubcommand::Keccak { data } => { let bytes = match data { Some(data) => data.into_bytes(), None => stdin::read_bytes(false)?, @@ -504,18 +504,18 @@ async fn main() -> Result<()> { } }; } - Subcommands::SigEvent { event_string } => { + CastSubcommand::SigEvent { event_string } => { let event_string = stdin::unwrap_line(event_string)?; let parsed_event = get_event(&event_string)?; println!("{:?}", parsed_event.selector()); } - Subcommands::LeftShift { value, bits, base_in, base_out } => { + CastSubcommand::LeftShift { value, bits, base_in, base_out } => { println!("{}", SimpleCast::left_shift(&value, &bits, base_in.as_deref(), &base_out)?); } - Subcommands::RightShift { value, bits, base_in, base_out } => { + CastSubcommand::RightShift { value, bits, base_in, base_out } => { println!("{}", SimpleCast::right_shift(&value, &bits, base_in.as_deref(), &base_out)?); } - Subcommands::EtherscanSource { address, directory, etherscan } => { + CastSubcommand::EtherscanSource { address, directory, etherscan } => { let config = Config::from(ðerscan); let chain = config.chain.unwrap_or_default(); let api_key = config.get_etherscan_api_key(Some(chain)).unwrap_or_default(); @@ -529,21 +529,21 @@ async fn main() -> Result<()> { } } } - Subcommands::Create2(cmd) => { + CastSubcommand::Create2(cmd) => { cmd.run()?; } - Subcommands::Wallet { command } => command.run().await?, - Subcommands::Completions { shell } => { + CastSubcommand::Wallet { command } => command.run().await?, + CastSubcommand::Completions { shell } => { generate(shell, &mut Opts::command(), "cast", &mut std::io::stdout()) } - Subcommands::GenerateFigSpec => clap_complete::generate( + CastSubcommand::GenerateFigSpec => clap_complete::generate( clap_complete_fig::Fig, &mut Opts::command(), "cast", &mut std::io::stdout(), ), - Subcommands::Logs(cmd) => cmd.run().await?, - Subcommands::DecodeTransaction { tx } => { + CastSubcommand::Logs(cmd) => cmd.run().await?, + CastSubcommand::DecodeTransaction { tx } => { let tx = stdin::unwrap_line(tx)?; let (tx, sig) = SimpleCast::decode_raw_transaction(&tx)?; diff --git a/crates/cast/bin/opts.rs b/crates/cast/bin/opts.rs index 89ef6f96744a..2f09c2534830 100644 --- a/crates/cast/bin/opts.rs +++ b/crates/cast/bin/opts.rs @@ -27,13 +27,13 @@ const VERSION_MESSAGE: &str = concat!( after_help = "Find more information in the book: http://book.getfoundry.sh/reference/cast/cast.html", next_display_order = None, )] -pub struct Opts { +pub struct Cast { #[clap(subcommand)] - pub sub: Subcommands, + pub cmd: CastSubcommand, } #[derive(Subcommand)] -pub enum Subcommands { +pub enum CastSubcommand { /// Prints the maximum value of the given integer type. #[clap(visible_aliases = &["--max-int", "maxi"])] MaxInt { @@ -898,11 +898,17 @@ pub fn parse_slot(s: &str) -> Result { mod tests { use super::*; use cast::SimpleCast; + use clap::CommandFactory; use ethers_core::types::BlockNumber; + #[test] + fn verify_cli() { + Cast::command().debug_assert(); + } + #[test] fn parse_proof_slot() { - let args: Opts = Opts::parse_from([ + let args: Cast = Cast::parse_from([ "foundry-cli", "proof", "0xC02aaA39b223FE8D0A0e5C4F27eAD9083C756Cc2", @@ -912,8 +918,8 @@ mod tests { "0x1", "0x01", ]); - match args.sub { - Subcommands::Proof { slots, .. } => { + match args.cmd { + CastSubcommand::Proof { slots, .. } => { assert_eq!( slots, vec![ @@ -931,15 +937,15 @@ mod tests { #[test] fn parse_call_data() { - let args: Opts = Opts::parse_from([ + let args: Cast = Cast::parse_from([ "foundry-cli", "calldata", "f()", "5c9d55b78febcc2061715ba4f57ecf8ea2711f2c", "2", ]); - match args.sub { - Subcommands::CalldataEncode { args, .. } => { + match args.cmd { + CastSubcommand::CalldataEncode { args, .. } => { assert_eq!( args, vec!["5c9d55b78febcc2061715ba4f57ecf8ea2711f2c".to_string(), "2".to_string()] @@ -952,13 +958,13 @@ mod tests { // #[test] fn parse_signature() { - let args: Opts = Opts::parse_from([ + let args: Cast = Cast::parse_from([ "foundry-cli", "sig", "__$_$__$$$$$__$$_$$$_$$__$$___$$(address,address,uint256)", ]); - match args.sub { - Subcommands::Sig { sig, .. } => { + match args.cmd { + CastSubcommand::Sig { sig, .. } => { let sig = sig.unwrap(); assert_eq!( sig, diff --git a/crates/chisel/bin/main.rs b/crates/chisel/bin/main.rs index d9028965a627..9da885860b62 100644 --- a/crates/chisel/bin/main.rs +++ b/crates/chisel/bin/main.rs @@ -7,7 +7,7 @@ use chisel::{ history::chisel_history_file, prelude::{ChiselCommand, ChiselDispatcher, DispatchResult, SolidityHelper}, }; -use clap::Parser; +use clap::{Parser, Subcommand}; use eyre::Context; use foundry_cli::{ handler, @@ -28,7 +28,7 @@ use tracing::debug; use yansi::Paint; // Loads project's figment and merges the build cli arguments into it -foundry_config::merge_impl_figment_convert!(ChiselParser, opts, evm_opts); +foundry_config::merge_impl_figment_convert!(Chisel, opts, evm_opts); const VERSION_MESSAGE: &str = concat!( env!("CARGO_PKG_VERSION"), @@ -42,9 +42,9 @@ const VERSION_MESSAGE: &str = concat!( /// Fast, utilitarian, and verbose Solidity REPL. #[derive(Debug, Parser)] #[clap(name = "chisel", version = VERSION_MESSAGE)] -pub struct ChiselParser { +pub struct Chisel { #[command(subcommand)] - pub sub: Option, + pub cmd: Option, /// Path to a directory containing Solidity files to import, or path to a single Solidity file. /// @@ -69,8 +69,8 @@ pub struct ChiselParser { } /// Chisel binary subcommands -#[derive(Debug, clap::Subcommand)] -pub enum ChiselParserSub { +#[derive(Debug, Subcommand)] +pub enum ChiselSubcommand { /// List all cached sessions List, @@ -102,7 +102,7 @@ async fn main() -> eyre::Result<()> { utils::load_dotenv(); // Parse command args - let args = ChiselParser::parse(); + let args = Chisel::parse(); // Keeps track of whether or not an interrupt was the last input let mut interrupt = false; @@ -125,8 +125,8 @@ async fn main() -> eyre::Result<()> { evaluate_prelude(&mut dispatcher, args.prelude).await?; // Check for chisel subcommands - match &args.sub { - Some(ChiselParserSub::List) => { + match &args.cmd { + Some(ChiselSubcommand::List) => { let sessions = dispatcher.dispatch_command(ChiselCommand::ListSessions, &[]).await; match sessions { DispatchResult::CommandSuccess(Some(session_list)) => { @@ -137,7 +137,7 @@ async fn main() -> eyre::Result<()> { } return Ok(()) } - Some(ChiselParserSub::Load { id }) | Some(ChiselParserSub::View { id }) => { + Some(ChiselSubcommand::Load { id }) | Some(ChiselSubcommand::View { id }) => { // For both of these subcommands, we need to attempt to load the session from cache match dispatcher.dispatch_command(ChiselCommand::Load, &[id]).await { DispatchResult::CommandSuccess(_) => { /* Continue */ } @@ -149,7 +149,7 @@ async fn main() -> eyre::Result<()> { } // If the subcommand was `view`, print the source and exit. - if matches!(args.sub, Some(ChiselParserSub::View { .. })) { + if matches!(args.cmd, Some(ChiselSubcommand::View { .. })) { match dispatcher.dispatch_command(ChiselCommand::Source, &[]).await { DispatchResult::CommandSuccess(Some(source)) => { println!("{source}"); @@ -159,7 +159,7 @@ async fn main() -> eyre::Result<()> { return Ok(()) } } - Some(ChiselParserSub::ClearCache) => { + Some(ChiselSubcommand::ClearCache) => { match dispatcher.dispatch_command(ChiselCommand::ClearCache, &[]).await { DispatchResult::CommandSuccess(Some(msg)) => println!("{}", Paint::green(msg)), DispatchResult::CommandFailed(e) => eprintln!("{e}"), @@ -229,7 +229,7 @@ async fn main() -> eyre::Result<()> { } /// [Provider] impl -impl Provider for ChiselParser { +impl Provider for Chisel { fn metadata(&self) -> Metadata { Metadata::named("Script Args Provider") } @@ -294,3 +294,14 @@ async fn load_prelude_file(dispatcher: &mut ChiselDispatcher, file: PathBuf) -> dispatch_repl_line(dispatcher, &prelude).await; Ok(()) } + +#[cfg(test)] +mod tests { + use super::*; + use clap::CommandFactory; + + #[test] + fn verify_cli() { + Chisel::command().debug_assert(); + } +} diff --git a/crates/forge/bin/main.rs b/crates/forge/bin/main.rs index 819c82f430ce..5fdc7c408a83 100644 --- a/crates/forge/bin/main.rs +++ b/crates/forge/bin/main.rs @@ -10,7 +10,7 @@ mod cmd; mod opts; use cmd::{cache::CacheSubcommands, generate::GenerateSubcommands, watch}; -use opts::{Opts, Subcommands}; +use opts::{Forge, ForgeSubcommand}; fn main() -> Result<()> { handler::install(); @@ -18,9 +18,9 @@ fn main() -> Result<()> { utils::subscriber(); utils::enable_paint(); - let opts = Opts::parse(); - match opts.sub { - Subcommands::Test(cmd) => { + let opts = Forge::parse(); + match opts.cmd { + ForgeSubcommand::Test(cmd) => { if cmd.is_watch() { utils::block_on(watch::watch_test(cmd)) } else { @@ -28,7 +28,7 @@ fn main() -> Result<()> { outcome.ensure_ok() } } - Subcommands::Script(cmd) => { + ForgeSubcommand::Script(cmd) => { // install the shell before executing the command foundry_common::shell::set_shell(foundry_common::shell::Shell::from_args( cmd.opts.args.silent, @@ -36,59 +36,59 @@ fn main() -> Result<()> { ))?; utils::block_on(cmd.run_script()) } - Subcommands::Coverage(cmd) => utils::block_on(cmd.run()), - Subcommands::Bind(cmd) => cmd.run(), - Subcommands::Build(cmd) => { + ForgeSubcommand::Coverage(cmd) => utils::block_on(cmd.run()), + ForgeSubcommand::Bind(cmd) => cmd.run(), + ForgeSubcommand::Build(cmd) => { if cmd.is_watch() { utils::block_on(watch::watch_build(cmd)) } else { cmd.run().map(|_| ()) } } - Subcommands::Debug(cmd) => utils::block_on(cmd.run()), - Subcommands::VerifyContract(args) => utils::block_on(args.run()), - Subcommands::VerifyCheck(args) => utils::block_on(args.run()), - Subcommands::Cache(cmd) => match cmd.sub { + ForgeSubcommand::Debug(cmd) => utils::block_on(cmd.run()), + ForgeSubcommand::VerifyContract(args) => utils::block_on(args.run()), + ForgeSubcommand::VerifyCheck(args) => utils::block_on(args.run()), + ForgeSubcommand::Cache(cmd) => match cmd.sub { CacheSubcommands::Clean(cmd) => cmd.run(), CacheSubcommands::Ls(cmd) => cmd.run(), }, - Subcommands::Create(cmd) => utils::block_on(cmd.run()), - Subcommands::Update(cmd) => cmd.run(), - Subcommands::Install(cmd) => cmd.run(), - Subcommands::Remove(cmd) => cmd.run(), - Subcommands::Remappings(cmd) => cmd.run(), - Subcommands::Init(cmd) => cmd.run(), - Subcommands::Completions { shell } => { - generate(shell, &mut Opts::command(), "forge", &mut std::io::stdout()); + ForgeSubcommand::Create(cmd) => utils::block_on(cmd.run()), + ForgeSubcommand::Update(cmd) => cmd.run(), + ForgeSubcommand::Install(cmd) => cmd.run(), + ForgeSubcommand::Remove(cmd) => cmd.run(), + ForgeSubcommand::Remappings(cmd) => cmd.run(), + ForgeSubcommand::Init(cmd) => cmd.run(), + ForgeSubcommand::Completions { shell } => { + generate(shell, &mut Forge::command(), "forge", &mut std::io::stdout()); Ok(()) } - Subcommands::GenerateFigSpec => { + ForgeSubcommand::GenerateFigSpec => { clap_complete::generate( clap_complete_fig::Fig, - &mut Opts::command(), + &mut Forge::command(), "forge", &mut std::io::stdout(), ); Ok(()) } - Subcommands::Clean { root } => { + ForgeSubcommand::Clean { root } => { let config = utils::load_config_with_root(root); config.project()?.cleanup()?; Ok(()) } - Subcommands::Snapshot(cmd) => { + ForgeSubcommand::Snapshot(cmd) => { if cmd.is_watch() { utils::block_on(watch::watch_snapshot(cmd)) } else { utils::block_on(cmd.run()) } } - Subcommands::Fmt(cmd) => cmd.run(), - Subcommands::Config(cmd) => cmd.run(), - Subcommands::Flatten(cmd) => cmd.run(), - Subcommands::Inspect(cmd) => cmd.run(), - Subcommands::Tree(cmd) => cmd.run(), - Subcommands::Geiger(cmd) => { + ForgeSubcommand::Fmt(cmd) => cmd.run(), + ForgeSubcommand::Config(cmd) => cmd.run(), + ForgeSubcommand::Flatten(cmd) => cmd.run(), + ForgeSubcommand::Inspect(cmd) => cmd.run(), + ForgeSubcommand::Tree(cmd) => cmd.run(), + ForgeSubcommand::Geiger(cmd) => { let check = cmd.check; let n = cmd.run()?; if check && n > 0 { @@ -96,9 +96,9 @@ fn main() -> Result<()> { } Ok(()) } - Subcommands::Doc(cmd) => cmd.run(), - Subcommands::Selectors { command } => utils::block_on(command.run()), - Subcommands::Generate(cmd) => match cmd.sub { + ForgeSubcommand::Doc(cmd) => cmd.run(), + ForgeSubcommand::Selectors { command } => utils::block_on(command.run()), + ForgeSubcommand::Generate(cmd) => match cmd.sub { GenerateSubcommands::Test(cmd) => cmd.run(), }, } diff --git a/crates/forge/bin/opts.rs b/crates/forge/bin/opts.rs index 3b9c48680e29..e62ac19083dc 100644 --- a/crates/forge/bin/opts.rs +++ b/crates/forge/bin/opts.rs @@ -39,14 +39,14 @@ const VERSION_MESSAGE: &str = concat!( after_help = "Find more information in the book: http://book.getfoundry.sh/reference/forge/forge.html", next_display_order = None, )] -pub struct Opts { +pub struct Forge { #[clap(subcommand)] - pub sub: Subcommands, + pub cmd: ForgeSubcommand, } #[derive(Subcommand)] #[allow(clippy::large_enum_variant)] -pub enum Subcommands { +pub enum ForgeSubcommand { /// Run the project's tests. #[clap(visible_alias = "t")] Test(test::TestArgs), @@ -168,3 +168,14 @@ pub enum Subcommands { /// Generate scaffold files. Generate(generate::GenerateArgs), } + +#[cfg(test)] +mod tests { + use super::*; + use clap::CommandFactory; + + #[test] + fn verify_cli() { + Forge::command().debug_assert(); + } +}