Skip to content

Commit

Permalink
refactor(cli): use bpaf instead clap
Browse files Browse the repository at this point in the history
  • Loading branch information
Boshen committed Aug 18, 2023
1 parent 3110490 commit 1ae2bcc
Show file tree
Hide file tree
Showing 11 changed files with 262 additions and 401 deletions.
87 changes: 23 additions & 64 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 @@ -39,9 +39,9 @@ oxc_query = { path = "crates/oxc_query" }
oxc_tasks_common = { path = "tasks/common" }
oxc_vscode = { path = "editor/vscode/server" }

bpaf = { version = "0.9.4" }
bitflags = { version = "2.4.0" }
bumpalo = { version = "3.13.0" }
clap = { version = "4.3.19" }
compact_str = { version = "0.7.1" }
convert_case = { version = "0.6.0" }
criterion = { version = "0.5.1", default-features = false }
Expand Down
2 changes: 1 addition & 1 deletion crates/oxc_cli/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -35,10 +35,10 @@ oxc_type_synthesis = { workspace = true }
# TODO temp, for type check output, replace with Miette
codespan-reporting = "0.11.1"

clap = { workspace = true }
dashmap = { workspace = true }
ignore = { workspace = true, features = ["simd-accel"] }
miette = { workspace = true, features = ["fancy-no-backtrace"] }
rayon = { workspace = true }
rustc-hash = { workspace = true }
bpaf = { workspace = true, features = ["derive", "autocomplete", "bright-color"] }
# git2 = { version = "0.16.1", default_features = false }
170 changes: 170 additions & 0 deletions crates/oxc_cli/src/command.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,170 @@
use bpaf::{any, Bpaf, Parser};
use std::path::PathBuf;

#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub enum CliCommand {
/// Lint this repository
#[bpaf(command)]
Lint(#[bpaf(external(lint_options))] LintOptions),

/// Use Ezno to type check source code (experimental and work in progress)
#[bpaf(command)]
Check(#[bpaf(external(check_options))] CheckOptions),
}

impl CliCommand {
pub fn cli_options(&self) -> &CliOptions {
match self {
Self::Lint(options) => &options.cli,
Self::Check(options) => &options.cli,
}
}

pub fn handle_threads(&self) {
Self::set_rayon_threads(self.cli_options().threads);
}

fn set_rayon_threads(threads: Option<usize>) {
if let Some(threads) = threads {
rayon::ThreadPoolBuilder::new().num_threads(threads).build_global().unwrap();
}
}
}

/// Linter for the JavaScript Oxidation Compiler
#[derive(Debug, Clone, Bpaf)]
#[bpaf(options)]
pub struct LintCommand {
#[bpaf(external(lint_options))]
pub lint_options: LintOptions,
}

impl LintCommand {
pub fn handle_threads(&self) {
CliCommand::set_rayon_threads(self.lint_options.cli.threads);
}
}

#[derive(Debug, Clone, Bpaf)]
pub struct CliOptions {
/// Disable reporting on warnings, only errors are reported
#[bpaf(switch, hide_usage)]
pub quiet: bool,

/// Specify a warning threshold,
/// which can be used to force exit with an error status if there are too many warning-level rule violations in your project
#[bpaf(argument("NUMBER"), hide_usage)]
pub max_warnings: Option<usize>,

/// Number of threads to use. Set to 1 for using only 1 CPU core.
#[bpaf(argument("NUMBER"), hide_usage)]
pub threads: Option<usize>,
}

#[derive(Debug, Clone, Bpaf)]
pub struct IgnoreOptions {
/// Disables excluding of files from .eslintignore files
#[bpaf(switch)]
pub no_ignore: bool,

/// Specify the file to use as your .eslintignore
#[bpaf(argument("PATH"), optional)]
pub ignore_path: Option<PathBuf>,

/// Specify patterns of files to ignore (in addition to those in .eslintignore)
#[bpaf(argument("PATTERN"), many)]
pub ignore_pattern: Vec<String>,
}

static FILTER_HELP: &str = r#"
To allow or deny a rule, use multiple -A <NAME> or -D <NAME>.
For example "-D correctness -A no-debugger" or "-A all -D no-debugger".
The categories are:
* correctness - code that is outright wrong or useless
* suspicious - code that is most likely wrong or useless
* pedantic - lints which are rather strict or have occasional false positives
* style - code that should be written in a more idiomatic way
* nursery - new lints that are still under development
* restriction - lints which prevent the use of language and library features
* all - all the categories listed above
The default category is "-D correctness".
"#;

#[derive(Debug, Clone, Bpaf)]
pub struct LintOptions {
/// Fix as many issues as possible. Only unfixed issues are reported in the output
#[bpaf(switch)]
pub fix: bool,

#[bpaf(external(ignore_options), hide_usage)]
pub ignore: IgnoreOptions,

/// Display the execution time of each lint rule
#[bpaf(switch, env("TIMING"), hide_usage)]
pub timing: bool,

/// list all the rules that are currently registered
#[bpaf(switch, hide_usage)]
pub rules: bool,

#[bpaf(external(cli_options), hide_usage)]
pub cli: CliOptions,

/// Single file, single path or list of paths
#[bpaf(positional("PATH"), many)]
pub paths: Vec<PathBuf>,

#[bpaf(external(filter_value), many, group_help(FILTER_HELP))]
pub filter: Vec<FilterValue>,
}

#[derive(Debug, Clone, Bpaf)]
pub struct FilterValue {
#[bpaf(external(filter_type))]
pub ty: FilterType,

#[bpaf(any("NAME", identity), help("Rule or Category"))]
pub value: String,
}

#[derive(Debug, Clone, Copy)]
pub enum FilterType {
Allow,
Deny,
}

fn filter_type() -> impl Parser<FilterType> {
any("TOGGLE", |s: String| match s.as_str() {
"-A" | "--allow" => Some(FilterType::Allow),
"-D" | "--deny" => Some(FilterType::Deny),
_ => None,
})
.help("-A | --allow | -D | --deny")
}

#[allow(clippy::unnecessary_wraps)]
fn identity(s: String) -> Option<String> {
Some(s)
}

#[derive(Debug, Clone, Bpaf)]
pub struct CheckOptions {
#[bpaf(external(cli_options), hide_usage)]
pub cli: CliOptions,

/// Print called functions
#[bpaf(switch, hide_usage)]
pub print_called_functions: bool,

/// Print types of expressions
#[bpaf(switch, hide_usage)]
pub print_expression_mappings: bool,

/// File to type check
#[bpaf(positional("PATH"))]
pub path: PathBuf,
}
22 changes: 2 additions & 20 deletions crates/oxc_cli/src/lib.rs
Original file line number Diff line number Diff line change
@@ -1,32 +1,14 @@
// mod git;
mod command;
mod lint;
mod runner;
mod type_check;
mod walk;

use clap::{Arg, Command};

pub use crate::{
command::*,
lint::LintRunner,
runner::{CliRunResult, Runner},
type_check::TypeCheckRunner,
walk::Walk,
};

pub fn command() -> Command {
Command::new("oxc")
.bin_name("oxc")
.version("alpha")
.author("Boshen")
.about("The JavaScript Oxidation Compiler")
.subcommand_required(true)
.arg_required_else_help(true)
.subcommand(LintRunner::command())
.subcommand(TypeCheckRunner::command())
.arg(
Arg::new("threads")
.long("threads")
.value_parser(clap::value_parser!(usize))
.help("Number of threads to use. Set to 1 for using only 1 CPU core."),
)
}
Loading

0 comments on commit 1ae2bcc

Please sign in to comment.