Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

feat(forge): add compiler subcommand #7909

Merged
merged 20 commits into from
Oct 16, 2024
Merged
Show file tree
Hide file tree
Changes from 16 commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/nextest.yml
Original file line number Diff line number Diff line change
Expand Up @@ -67,12 +67,12 @@ jobs:
with:
bun-version: latest
- name: Setup Python
if: contains(matrix.name, 'external')
if: contains(matrix.name, 'external') || contains(matrix.name, 'integration')
uses: actions/setup-python@v4
with:
python-version: 3.11
- name: Install Vyper
if: contains(matrix.name, 'external')
if: contains(matrix.name, 'external') || contains(matrix.name, 'integration')
zerosnacks marked this conversation as resolved.
Show resolved Hide resolved
run: pip install vyper~=0.4.0

- name: Forge RPC cache
Expand Down
20 changes: 10 additions & 10 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -169,7 +169,7 @@ foundry-linking = { path = "crates/linking" }

# solc & compilation utilities
foundry-block-explorers = { version = "0.7.3", default-features = false }
foundry-compilers = { version = "0.11.4", default-features = false }
foundry-compilers = { version = "0.11.5", default-features = false }
foundry-fork-db = "0.4.0"
solang-parser = "=0.3.3"

Expand Down
145 changes: 145 additions & 0 deletions crates/forge/bin/cmd/compiler.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,145 @@
use clap::{ArgAction, Parser, Subcommand, ValueHint};
use eyre::Result;
use foundry_compilers::Graph;
use foundry_config::Config;
use semver::Version;
use std::{collections::BTreeMap, path::PathBuf};

/// CLI arguments for `forge compiler`.
#[derive(Debug, Parser)]
pub struct CompilerArgs {
#[command(subcommand)]
pub sub: CompilerSubcommands,
}

impl CompilerArgs {
pub async fn run(self) -> Result<()> {
match self.sub {
CompilerSubcommands::Resolve(args) => args.run().await,
}
}
}

#[derive(Debug, Subcommand)]
pub enum CompilerSubcommands {
#[command(visible_alias = "r")]
/// Retrieves the resolved version(s) of the compiler within the project.
zerosnacks marked this conversation as resolved.
Show resolved Hide resolved
Resolve(ResolveArgs),
}

/// CLI arguments for `forge compiler resolve`.
#[derive(Debug, Parser)]
pub struct ResolveArgs {
/// The root directory
#[arg(long, short, value_hint = ValueHint::DirPath, value_name = "PATH")]
root: Option<PathBuf>,

/// Skip files that match the given regex pattern.
#[arg(long, short, value_name = "REGEX")]
skip: Option<regex::Regex>,

/// Verbosity of the output.
///
/// Pass multiple times to increase the verbosity (e.g. -v, -vv, -vvv).
///
/// Verbosity levels:
/// - 2: Print source paths.
#[arg(long, short, verbatim_doc_comment, action = ArgAction::Count, help_heading = "Display options")]
pub verbosity: u8,

/// Print as JSON.
#[arg(long, short, help_heading = "Display options")]
json: bool,
}

impl ResolveArgs {
pub async fn run(self) -> Result<()> {
zerosnacks marked this conversation as resolved.
Show resolved Hide resolved
let Self { root, skip, verbosity, json } = self;

let root = root.unwrap_or_else(|| PathBuf::from("."));
let config = Config::load_with_root(&root);
let project = config.project()?;

let graph = Graph::resolve(&project.paths)?;
let (sources, _) = graph.into_sources_by_version(
project.offline,
&project.locked_versions,
&project.compiler,
)?;

let mut output: BTreeMap<String, Vec<(Version, Vec<String>)>> = BTreeMap::new();

for (language, sources) in sources {
let mut versions_with_paths: Vec<(Version, Vec<String>)> = sources
.iter()
.map(|(version, sources)| {
let paths: Vec<String> = sources
.iter()
.filter_map(|(path_file, _)| {
let path_str = path_file
.strip_prefix(&project.paths.root)
.unwrap_or(path_file)
.to_path_buf()
.display()
.to_string();

// Skip files that match the given regex pattern.
if let Some(ref regex) = skip {
if regex.is_match(&path_str) {
return None;
}
}

Some(path_str)
})
.collect();

(version.clone(), paths)
})
.filter(|(_, paths)| !paths.is_empty())
.collect();

// Sort by SemVer version.
versions_with_paths.sort_by(|(v1, _), (v2, _)| Version::cmp(v1, v2));

// Skip language if no paths are found after filtering.
if !versions_with_paths.is_empty() {
output.insert(language.to_string(), versions_with_paths);
}
}

if json {
println!("{}", serde_json::to_string(&output)?);
return Ok(());
}

for (language, versions) in &output {
if verbosity < 1 {
println!("{language}:");
} else {
println!("{language}:\n");
}

for (version, paths) in versions {
if verbosity >= 1 {
println!("{version}:");
for (idx, path) in paths.iter().enumerate() {
if idx == paths.len() - 1 {
println!("└── {path}\n");
} else {
println!("├── {path}");
}
}
} else {
println!("- {version}");
}
}

if verbosity < 1 {
println!();
}
}

Ok(())
}
}
1 change: 1 addition & 0 deletions crates/forge/bin/cmd/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ pub mod bind_json;
pub mod build;
pub mod cache;
pub mod clone;
pub mod compiler;
pub mod config;
pub mod coverage;
pub mod create;
Expand Down
1 change: 1 addition & 0 deletions crates/forge/bin/main.rs
Original file line number Diff line number Diff line change
Expand Up @@ -118,6 +118,7 @@ fn main() -> Result<()> {
ForgeSubcommand::Generate(cmd) => match cmd.sub {
GenerateSubcommands::Test(cmd) => cmd.run(),
},
ForgeSubcommand::Compiler(cmd) => utils::block_on(cmd.run()),
ForgeSubcommand::Soldeer(cmd) => utils::block_on(cmd.run()),
ForgeSubcommand::Eip712(cmd) => cmd.run(),
ForgeSubcommand::BindJson(cmd) => cmd.run(),
Expand Down
14 changes: 9 additions & 5 deletions crates/forge/bin/opts.rs
Original file line number Diff line number Diff line change
@@ -1,8 +1,9 @@
use crate::cmd::{
bind::BindArgs, bind_json, build::BuildArgs, cache::CacheArgs, clone::CloneArgs, config,
coverage, create::CreateArgs, debug::DebugArgs, doc::DocArgs, eip712, flatten, fmt::FmtArgs,
geiger, generate, init::InitArgs, inspect, install::InstallArgs, remappings::RemappingArgs,
remove::RemoveArgs, selectors::SelectorsSubcommands, snapshot, soldeer, test, tree, update,
bind::BindArgs, bind_json, build::BuildArgs, cache::CacheArgs, clone::CloneArgs,
compiler::CompilerArgs, config, coverage, create::CreateArgs, debug::DebugArgs, doc::DocArgs,
eip712, flatten, fmt::FmtArgs, geiger, generate, init::InitArgs, inspect, install::InstallArgs,
remappings::RemappingArgs, remove::RemoveArgs, selectors::SelectorsSubcommands, snapshot,
soldeer, test, tree, update,
};
use clap::{Parser, Subcommand, ValueHint};
use forge_script::ScriptArgs;
Expand Down Expand Up @@ -152,7 +153,7 @@ pub enum ForgeSubcommand {
/// Generate documentation for the project.
Doc(DocArgs),

/// Function selector utilities
/// Function selector utilities.
#[command(visible_alias = "se")]
Selectors {
#[command(subcommand)]
Expand All @@ -162,6 +163,9 @@ pub enum ForgeSubcommand {
/// Generate scaffold files.
Generate(generate::GenerateArgs),

/// Compiler utilities.
Compiler(CompilerArgs),

/// Soldeer dependency manager.
Soldeer(soldeer::SoldeerArgs),

Expand Down
Loading
Loading