diff --git a/.changelog/remove-deprecated-forge-generate.md b/.changelog/remove-deprecated-forge-generate.md new file mode 100644 index 0000000000000..c2f3978de47f3 --- /dev/null +++ b/.changelog/remove-deprecated-forge-generate.md @@ -0,0 +1,5 @@ +--- +forge: major +--- + +Removed the deprecated `forge generate` command. diff --git a/crates/forge/assets/generated/TestTemplate.t.sol b/crates/forge/assets/generated/TestTemplate.t.sol deleted file mode 100644 index 816a8c68fd0a9..0000000000000 --- a/crates/forge/assets/generated/TestTemplate.t.sol +++ /dev/null @@ -1,13 +0,0 @@ -// SPDX-License-Identifier: UNLICENSED -pragma solidity ^0.8.13; - -import {Test, console} from "forge-std/Test.sol"; -import {{contract_name}} from "../src/{contract_name}.sol"; - -contract {contract_name}Test is Test { - {contract_name} public {instance_name}; - - function setUp() public { - {instance_name} = new {contract_name}(); - } -} diff --git a/crates/forge/src/args.rs b/crates/forge/src/args.rs index fe19063b5aa8f..6f6d1105f61d0 100644 --- a/crates/forge/src/args.rs +++ b/crates/forge/src/args.rs @@ -1,5 +1,5 @@ use crate::{ - cmd::{cache::CacheSubcommands, generate::GenerateSubcommands, watch}, + cmd::{cache::CacheSubcommands, watch}, opts::{Forge, ForgeSubcommand}, }; use clap::{CommandFactory, Parser}; @@ -139,9 +139,6 @@ pub fn run_command(args: Forge) -> Result<()> { } } ForgeSubcommand::Selectors { command } => global.block_on(command.run()), - ForgeSubcommand::Generate(cmd) => match cmd.sub { - GenerateSubcommands::Test(cmd) => cmd.run(), - }, ForgeSubcommand::Compiler(cmd) => cmd.run(), ForgeSubcommand::Soldeer(cmd) => global.block_on(cmd.run()), ForgeSubcommand::Eip712(cmd) => cmd.run(), diff --git a/crates/forge/src/cmd/generate/mod.rs b/crates/forge/src/cmd/generate/mod.rs deleted file mode 100644 index 1ca967aae5891..0000000000000 --- a/crates/forge/src/cmd/generate/mod.rs +++ /dev/null @@ -1,72 +0,0 @@ -use clap::{Parser, Subcommand}; -use eyre::Result; -use foundry_common::fs; -use std::path::Path; -use yansi::Paint; - -/// CLI arguments for `forge generate`. -#[derive(Debug, Parser)] -pub struct GenerateArgs { - #[command(subcommand)] - pub sub: GenerateSubcommands, -} - -#[derive(Debug, Subcommand)] -pub enum GenerateSubcommands { - /// Scaffolds test file for given contract. - Test(GenerateTestArgs), -} - -#[derive(Debug, Parser)] -pub struct GenerateTestArgs { - /// Contract name for test generation. - #[arg(long, short, value_name = "CONTRACT_NAME")] - pub contract_name: String, -} - -impl GenerateTestArgs { - pub fn run(self) -> Result<()> { - sh_warn!("`forge generate` is deprecated and will be removed in a future version")?; - - let contract_name = format_identifier(&self.contract_name, true); - let instance_name = format_identifier(&self.contract_name, false); - - // Create the test file content. - let test_content = include_str!("../../../assets/generated/TestTemplate.t.sol"); - let test_content = test_content - .replace("{contract_name}", &contract_name) - .replace("{instance_name}", &instance_name); - - // Create the test directory if it doesn't exist. - fs::create_dir_all("test")?; - - // Define the test file path - let test_file_path = Path::new("test").join(format!("{contract_name}.t.sol")); - - // Write the test content to the test file. - fs::write(&test_file_path, test_content)?; - - sh_status!("{} test file: {}", "Generated".green(), test_file_path.to_str().unwrap())?; - Ok(()) - } -} - -/// Utility function to convert an identifier to pascal or camel case. -fn format_identifier(input: &str, is_pascal_case: bool) -> String { - let mut result = String::new(); - let mut capitalize_next = is_pascal_case; - - for word in input.split_whitespace() { - if !word.is_empty() { - let (first, rest) = word.split_at(1); - let formatted_word = if capitalize_next { - format!("{}{}", first.to_uppercase(), rest) - } else { - format!("{}{}", first.to_lowercase(), rest) - }; - capitalize_next = true; - result.push_str(&formatted_word); - } - } - result -} diff --git a/crates/forge/src/cmd/mod.rs b/crates/forge/src/cmd/mod.rs index 082fd6f35ca8e..028fa45b6cbb3 100644 --- a/crates/forge/src/cmd/mod.rs +++ b/crates/forge/src/cmd/mod.rs @@ -20,7 +20,6 @@ pub mod flatten; pub mod fmt; pub mod fuzz; pub mod geiger; -pub mod generate; pub mod init; pub mod inspect; pub mod install; diff --git a/crates/forge/src/opts.rs b/crates/forge/src/opts.rs index 3b2135f4cc679..8608d0fbc6a02 100644 --- a/crates/forge/src/opts.rs +++ b/crates/forge/src/opts.rs @@ -1,7 +1,7 @@ use crate::cmd::{ bind::BindArgs, bind_json, build::BuildArgs, cache::CacheArgs, clone::CloneArgs, compiler::CompilerArgs, config, coverage, create::CreateArgs, doc::DocArgs, eip712, flatten, - fmt::FmtArgs, fuzz::FuzzArgs, geiger, generate, init::InitArgs, inspect, install::InstallArgs, + fmt::FmtArgs, fuzz::FuzzArgs, geiger, init::InitArgs, inspect, install::InstallArgs, lint::LintArgs, remappings::RemappingArgs, remove::RemoveArgs, selectors::SelectorsSubcommands, snapshot, soldeer, test, tree, update, }; @@ -220,10 +220,6 @@ pub enum ForgeSubcommand { command: SelectorsSubcommands, }, - /// Generate scaffold files. - #[command(hide = true)] - Generate(generate::GenerateArgs), - /// Compiler utilities. Compiler(CompilerArgs), diff --git a/crates/forge/tests/cli/cmd.rs b/crates/forge/tests/cli/cmd.rs index 5aa12207e8dbc..376ebd542e4eb 100644 --- a/crates/forge/tests/cli/cmd.rs +++ b/crates/forge/tests/cli/cmd.rs @@ -4764,21 +4764,6 @@ Flattened file written at [..]flat.sol assert!(out.exists(), "flattened file should have been written"); }); -// `forge generate test` writes the scaffolded file and emits its status string to stderr, -// keeping stdout empty so agents can pipe the command without diagnostics. -forgetest!(generate_test_writes_status_to_stderr, |prj, cmd| { - cmd.args(["generate", "test", "--contract-name", "Counter"]) - .assert_success() - .stdout_eq(str![""]) - .stderr_eq(str![[r#" -Warning: `forge generate` is deprecated and will be removed in a future version -Generated test file: test/Counter.t.sol - -"#]]); - - assert!(prj.root().join("test/Counter.t.sol").exists(), "scaffolded test file should exist"); -}); - // `forge init` writes its status prose to stderr and keeps stdout empty so agents // can pipe the command without diagnostics. Uses `--offline` + `--no-git` to skip // network and git side-effects that would otherwise add prose to stdout. diff --git a/docs/dev/output-channels.md b/docs/dev/output-channels.md index a777bfe092385..ac47d3127def7 100644 --- a/docs/dev/output-channels.md +++ b/docs/dev/output-channels.md @@ -150,7 +150,6 @@ Each row's status is one of: | `forge clean` | (empty) | n/a | migrated | | `forge completions` | Generated shell completion script | n/a | migrated | | `forge doc` | (empty) | n/a | migrated | -| `forge generate` | (empty) or generated path | n/a | migrated | | `forge soldeer` | Passthrough to `soldeer` crate; foundry adds no wrapper prose | n/a | migrated | | `forge remappings` | One remapping per line | n/a | migrated | | `forge compiler` | Compiler info | JSON | migrated |