Skip to content

Commit

Permalink
feat!: unify CLI and Session options (#176)
Browse files Browse the repository at this point in the history
* chore: move opts to config crate

* feat: unify session and CLI options

* chore: unused build-dependency

* fix: long version

* fix: implement non_exhaustive manually

* chore: re-add feature gates

* chore: simplify build script

* fix

* chore: use get_or_insert_default

* fix

* fix: benches

* docs

* less noisy session
  • Loading branch information
DaniPopes authored Dec 23, 2024
1 parent bb81e5d commit 48ef4c1
Show file tree
Hide file tree
Showing 18 changed files with 394 additions and 315 deletions.
42 changes: 2 additions & 40 deletions Cargo.lock

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

11 changes: 9 additions & 2 deletions benches/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -97,15 +97,15 @@ impl Parser for Solar {
}

fn lex(&self, src: &str) {
let sess = Session::builder().with_stderr_emitter().build();
let sess = session();
for token in solar_parse::Lexer::new(&sess, src) {
black_box(token);
}
sess.dcx.has_errors().unwrap();
}

fn parse(&self, src: &str) {
let sess = Session::builder().with_stderr_emitter().build();
let sess = session();
sess.enter(|| -> solar_parse::interface::Result {
let arena = solar_parse::ast::Arena::new();
let filename = PathBuf::from("test.sol");
Expand All @@ -120,6 +120,13 @@ impl Parser for Solar {
}
}

fn session() -> Session {
Session::builder()
.with_stderr_emitter_and_color(solar_parse::interface::ColorChoice::Always)
.single_threaded()
.build()
}

pub struct Solang;
impl Parser for Solang {
fn name(&self) -> &'static str {
Expand Down
4 changes: 0 additions & 4 deletions crates/cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -15,9 +15,6 @@ categories.workspace = true
[lints]
workspace = true

[build-dependencies]
vergen = { workspace = true, features = ["build", "git", "gitcl", "cargo"] }

[dependencies]
solar-config = { workspace = true, features = ["clap"] }
solar-interface = { workspace = true, features = ["json"] }
Expand All @@ -26,7 +23,6 @@ solar-sema.workspace = true
alloy-primitives.workspace = true
cfg-if.workspace = true
clap = { workspace = true, features = ["derive"] }
const_format = { workspace = true, features = ["rust_1_64"] }
tracing.workspace = true
tracing-subscriber = { workspace = true, features = ["registry", "env-filter"] }

Expand Down
24 changes: 0 additions & 24 deletions crates/cli/build.rs

This file was deleted.

83 changes: 30 additions & 53 deletions crates/cli/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,16 +6,16 @@
#![cfg_attr(docsrs, feature(doc_cfg, doc_auto_cfg))]

use clap::Parser as _;
use cli::Args;
use solar_config::{ErrorFormat, ImportMap};
use solar_interface::{
diagnostics::{DiagCtxt, DynEmitter, HumanEmitter, JsonEmitter},
Result, Session, SourceMap,
};
use std::{collections::BTreeSet, num::NonZeroUsize, path::Path, sync::Arc};
use std::{path::Path, sync::Arc};

pub use solar_config::{self as config, version, Opts, UnstableOpts};

pub mod cli;
pub mod utils;
pub mod version;

#[cfg(all(unix, any(target_env = "gnu", target_os = "macos")))]
pub mod sigsegv_handler;
Expand All @@ -34,51 +34,50 @@ use alloy_primitives as _;

use tracing as _;

pub fn parse_args<I, T>(itr: I) -> Result<Args, clap::Error>
pub fn parse_args<I, T>(itr: I) -> Result<Opts, clap::Error>
where
I: IntoIterator<Item = T>,
T: Into<std::ffi::OsString> + Clone,
{
let mut args = Args::try_parse_from(itr)?;
args.finish()?;
Ok(args)
let mut opts = Opts::try_parse_from(itr)?;
opts.finish()?;
Ok(opts)
}

pub fn run_compiler_args(args: Args) -> Result<()> {
run_compiler_with(args, Compiler::run_default)
pub fn run_compiler_args(opts: Opts) -> Result<()> {
run_compiler_with(opts, Compiler::run_default)
}

pub struct Compiler {
pub sess: Session,
pub args: Args,
}

impl Compiler {
pub fn run_default(&self) -> Result<()> {
let Self { sess, args } = self;
let Self { sess } = self;

if sess.language.is_yul() && !args.unstable.parse_yul {
if sess.opts.language.is_yul() && !sess.opts.unstable.parse_yul {
return Err(sess.dcx.err("Yul is not supported yet").emit());
}

// Partition arguments into three categories:
// - `stdin`: `-`, occurrences after the first are ignored
// - remappings: `path=mapped`
// - paths: everything else
let stdin = args.input.iter().any(|arg| *arg == Path::new("-"));
let non_stdin_args = args.input.iter().filter(|arg| *arg != Path::new("-"));
let stdin = sess.opts.input.iter().any(|arg| *arg == Path::new("-"));
let non_stdin_args = sess.opts.input.iter().filter(|arg| *arg != Path::new("-"));
let arg_remappings = non_stdin_args
.clone()
.filter_map(|arg| arg.to_str().unwrap_or("").parse::<cli::ImportMap>().ok());
.filter_map(|arg| arg.to_str().unwrap_or("").parse::<ImportMap>().ok());
let paths =
non_stdin_args.filter(|arg| !arg.as_os_str().as_encoded_bytes().contains(&b'='));

let mut pcx = solar_sema::ParsingContext::new(sess);
let remappings = arg_remappings.chain(args.import_map.iter().cloned());
let remappings = arg_remappings.chain(sess.opts.import_map.iter().cloned());
for map in remappings {
pcx.file_resolver.add_import_map(map.map, map.path);
}
for path in &args.import_path {
for path in &sess.opts.import_path {
let new = pcx.file_resolver.add_import_path(path.clone());
if !new {
let msg = format!("import path {} already specified", path.display());
Expand All @@ -101,12 +100,12 @@ impl Compiler {
}
}

fn run_compiler_with(args: Args, f: impl FnOnce(&Compiler) -> Result + Send) -> Result {
let ui_testing = args.unstable.ui_testing;
fn run_compiler_with(opts: Opts, f: impl FnOnce(&Compiler) -> Result + Send) -> Result {
let ui_testing = opts.unstable.ui_testing;
let source_map = Arc::new(SourceMap::empty());
let emitter: Box<DynEmitter> = match args.error_format {
cli::ErrorFormat::Human => {
let color = match args.color {
let emitter: Box<DynEmitter> = match opts.error_format {
ErrorFormat::Human => {
let color = match opts.color {
clap::ColorChoice::Always => solar_interface::ColorChoice::Always,
clap::ColorChoice::Auto => solar_interface::ColorChoice::Auto,
clap::ColorChoice::Never => solar_interface::ColorChoice::Never,
Expand All @@ -116,49 +115,27 @@ fn run_compiler_with(args: Args, f: impl FnOnce(&Compiler) -> Result + Send) ->
.ui_testing(ui_testing);
Box::new(human)
}
cli::ErrorFormat::Json | cli::ErrorFormat::RustcJson => {
ErrorFormat::Json | ErrorFormat::RustcJson => {
// `io::Stderr` is not buffered.
let writer = Box::new(std::io::BufWriter::new(std::io::stderr()));
let json = JsonEmitter::new(writer, source_map.clone())
.pretty(args.pretty_json_err)
.rustc_like(matches!(args.error_format, cli::ErrorFormat::RustcJson))
.pretty(opts.pretty_json_err)
.rustc_like(matches!(opts.error_format, ErrorFormat::RustcJson))
.ui_testing(ui_testing);
Box::new(json)
}
};
let dcx = DiagCtxt::new(emitter).set_flags(|flags| {
flags.deduplicate_diagnostics &= !ui_testing;
flags.track_diagnostics &= !ui_testing;
flags.track_diagnostics |= args.unstable.track_diagnostics;
flags.track_diagnostics |= opts.unstable.track_diagnostics;
});

let mut sess = Session::new(dcx, source_map);
sess.evm_version = args.evm_version;
sess.language = args.language;
sess.stop_after = args.stop_after;
sess.dump = args.unstable.dump.clone();
sess.ast_stats = args.unstable.ast_stats;
sess.jobs = NonZeroUsize::new(args.threads)
.unwrap_or_else(|| std::thread::available_parallelism().unwrap_or(NonZeroUsize::MIN));
if !args.input.is_empty()
&& args.input.iter().all(|arg| arg.extension() == Some("yul".as_ref()))
{
sess.language = solar_config::Language::Yul;
}
sess.emit = {
let mut set = BTreeSet::default();
for &emit in &args.emit {
if !set.insert(emit) {
let msg = format!("cannot specify `--emit {emit}` twice");
return Err(sess.dcx.err(msg).emit());
}
}
set
};
sess.out_dir = args.out_dir.clone();
sess.pretty_json = args.pretty_json;
let mut sess = Session::builder().dcx(dcx).source_map(source_map).opts(opts).build();
sess.infer_language();
sess.validate()?;

let compiler = Compiler { sess, args };
let compiler = Compiler { sess };
compiler.sess.enter(|| {
let mut r = f(&compiler);
r = compiler.finish_diagnostics().and(r);
Expand Down
47 changes: 0 additions & 47 deletions crates/cli/src/version.rs

This file was deleted.

Loading

0 comments on commit 48ef4c1

Please sign in to comment.