diff --git a/Cargo.lock b/Cargo.lock index dbd7a746eb..e4468ae018 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1921,6 +1921,24 @@ version = "0.1.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "06069a848f95fceae3e5e03c0ddc8cb78452b56654ee0c8e68f938cf790fb9e3" +[[package]] +name = "xflags" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1a6292b9528efc06cb25a41b8a0814dd3a9590c0fe2cd95341fe41bbe034fafb" +dependencies = [ + "xflags-macros", +] + +[[package]] +name = "xflags-macros" +version = "0.1.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba2108d40e49a0653f2ee4eda59f51447e0cab5cc2cc197a5abd96525c6bd89e" +dependencies = [ + "proc-macro2", +] + [[package]] name = "xshell" version = "0.1.8" @@ -1942,11 +1960,11 @@ version = "0.1.0" dependencies = [ "anyhow", "flate2", - "pico-args", "proc-macro2", "quote", "ungrammar", "walkdir", "write-json", + "xflags", "xshell", ] diff --git a/xtask/Cargo.toml b/xtask/Cargo.toml index 0455dd2eb3..b17dde598b 100644 --- a/xtask/Cargo.toml +++ b/xtask/Cargo.toml @@ -9,11 +9,11 @@ license = "MIT OR Apache-2.0" [dependencies] anyhow = "1.0.26" flate2 = "1.0" -pico-args = "0.4.0" proc-macro2 = "1.0.8" quote = "1.0.2" ungrammar = "=1.11" walkdir = "2.3.1" write-json = "0.1.0" xshell = "0.1" +xflags = "0.1.2" # Avoid adding more dependencies to this crate diff --git a/xtask/src/codegen.rs b/xtask/src/codegen.rs index 743e83e766..2f56c5ad0c 100644 --- a/xtask/src/codegen.rs +++ b/xtask/src/codegen.rs @@ -18,7 +18,7 @@ use std::{ }; use xshell::{cmd, pushenv, read_file, write_file}; -use crate::{ensure_rustfmt, project_root, Result}; +use crate::{ensure_rustfmt, flags, project_root, Result}; pub(crate) use self::{ gen_assists_docs::{generate_assists_docs, generate_assists_tests}, @@ -35,11 +35,7 @@ pub(crate) enum Mode { Verify, } -pub(crate) struct CodegenCmd { - pub(crate) features: bool, -} - -impl CodegenCmd { +impl flags::Codegen { pub(crate) fn run(self) -> Result<()> { if self.features { generate_lint_completions(Mode::Overwrite)?; diff --git a/xtask/src/flags.rs b/xtask/src/flags.rs new file mode 100644 index 0000000000..ce72879a12 --- /dev/null +++ b/xtask/src/flags.rs @@ -0,0 +1,139 @@ +#![allow(unreachable_pub)] + +xflags::args_parser! { + /// Run custom build command. + cmd xtask { + default cmd help { + /// Print help information. + optional -h, --help + } + + /// Install rust-analyzer server or editor plugin. + cmd install { + /// Install only VS Code plugin. + optional --client + /// One of 'code', 'code-exploration', 'code-insiders', 'codium', or 'code-oss'. + optional --code-bin name: String + + /// Install only the language server. + optional --server + /// Use mimalloc allocator for server + optional --mimalloc + /// Use jemalloc allocator for server + optional --jemalloc + } + + cmd codegen { + optional --features + } + + cmd lint {} + cmd fuzz-tests {} + cmd pre-cache {} + + cmd release { + optional --dry-run + } + cmd promote { + optional --dry-run + } + cmd dist { + optional --nightly + optional --client version: String + } + cmd metrics { + optional --dry-run + } + /// Builds a benchmark version of rust-analyzer and puts it into `./target`. + cmd bb + required suffix : String + {} + } +} + +// generated start +// The following code is generated by `xflags` macro. +// Run `env XFLAGS_DUMP= cargo build` to regenerate. +#[derive(Debug)] +pub struct Xtask { + pub subcommand: XtaskCmd, +} + +#[derive(Debug)] +pub enum XtaskCmd { + Help(Help), + Install(Install), + Codegen(Codegen), + Lint(Lint), + FuzzTests(FuzzTests), + PreCache(PreCache), + Release(Release), + Promote(Promote), + Dist(Dist), + Metrics(Metrics), + Bb(Bb), +} + +#[derive(Debug)] +pub struct Help { + pub help: bool, +} + +#[derive(Debug)] +pub struct Install { + pub client: bool, + pub code_bin: Option, + pub server: bool, + pub mimalloc: bool, + pub jemalloc: bool, +} + +#[derive(Debug)] +pub struct Codegen { + pub features: bool, +} + +#[derive(Debug)] +pub struct Lint {} + +#[derive(Debug)] +pub struct FuzzTests {} + +#[derive(Debug)] +pub struct PreCache {} + +#[derive(Debug)] +pub struct Release { + pub dry_run: bool, +} + +#[derive(Debug)] +pub struct Promote { + pub dry_run: bool, +} + +#[derive(Debug)] +pub struct Dist { + pub nightly: bool, + pub client: Option, +} + +#[derive(Debug)] +pub struct Metrics { + pub dry_run: bool, +} + +#[derive(Debug)] +pub struct Bb { + pub suffix: String, +} + +impl Xtask { + pub const HELP: &'static str = Self::_HELP; + + pub fn from_env() -> xflags::Result { + let mut p = xflags::rt::Parser::new_from_env(); + Self::_parse(&mut p) + } +} +// generated end diff --git a/xtask/src/main.rs b/xtask/src/main.rs index 84b17ce230..e419db7a71 100644 --- a/xtask/src/main.rs +++ b/xtask/src/main.rs @@ -7,6 +7,8 @@ //! //! This binary is integrated into the `cargo` command line by using an alias in //! `.cargo/config`. +mod flags; + mod codegen; mod ast_src; #[cfg(test)] @@ -19,8 +21,6 @@ mod metrics; mod pre_cache; use anyhow::{bail, Result}; -use codegen::CodegenCmd; -use pico_args::Arguments; use std::{ env, path::{Path, PathBuf}, @@ -32,42 +32,19 @@ use crate::{ codegen::Mode, dist::DistCmd, install::{InstallCmd, Malloc, ServerOpt}, - metrics::MetricsCmd, - pre_cache::PreCacheCmd, - release::{PromoteCmd, ReleaseCmd}, }; fn main() -> Result<()> { let _d = pushd(project_root())?; - let mut args = Arguments::from_env(); - let subcommand = args.subcommand()?.unwrap_or_default(); - - match subcommand.as_str() { - "install" => { - if args.contains(["-h", "--help"]) { - eprintln!( - "\ -cargo xtask install -Install rust-analyzer server or editor plugin. - -USAGE: - cargo xtask install [FLAGS] - -FLAGS: - --client[=CLIENT] Install only VS Code plugin. - CLIENT is one of 'code', 'code-exploration', 'code-insiders', 'codium', or 'code-oss' - --server Install only the language server - --mimalloc Use mimalloc allocator for server - --jemalloc Use jemalloc allocator for server - -h, --help Prints help information - " - ); - return Ok(()); - } - let server = args.contains("--server"); - let client_code = args.contains("--client"); - if server && client_code { + let flags = flags::Xtask::from_env()?; + match flags.subcommand { + flags::XtaskCmd::Help(_) => { + println!("{}", flags::Xtask::HELP); + return Ok(()); + } + flags::XtaskCmd::Install(flags) => { + if flags.server && flags.client { eprintln!( "error: The argument `--server` cannot be used with `--client`\n\n\ For more information try --help" @@ -75,102 +52,43 @@ FLAGS: return Ok(()); } - let malloc = if args.contains("--mimalloc") { + let malloc = if flags.mimalloc { Malloc::Mimalloc - } else if args.contains("--jemalloc") { + } else if flags.jemalloc { Malloc::Jemalloc } else { Malloc::System }; - let client_opt = args.opt_value_from_str("--client")?; - - finish_args(args)?; + let client_bin = flags.code_bin.map(|it| it.parse()).transpose()?; InstallCmd { - client: if server { None } else { Some(client_opt.unwrap_or_default()) }, - server: if client_code { None } else { Some(ServerOpt { malloc }) }, + client: if flags.server { None } else { client_bin }, + server: if flags.client { None } else { Some(ServerOpt { malloc }) }, } .run() } - "codegen" => { - let features = args.contains("--features"); - finish_args(args)?; - CodegenCmd { features }.run() + flags::XtaskCmd::Codegen(cmd) => cmd.run(), + flags::XtaskCmd::Lint(_) => run_clippy(), + flags::XtaskCmd::FuzzTests(_) => run_fuzzer(), + flags::XtaskCmd::PreCache(cmd) => cmd.run(), + flags::XtaskCmd::Release(cmd) => cmd.run(), + flags::XtaskCmd::Promote(cmd) => cmd.run(), + flags::XtaskCmd::Dist(flags) => { + DistCmd { nightly: flags.nightly, client_version: flags.client }.run() } - "lint" => { - finish_args(args)?; - run_clippy() - } - "fuzz-tests" => { - finish_args(args)?; - run_fuzzer() - } - "pre-cache" => { - finish_args(args)?; - PreCacheCmd.run() - } - "release" => { - let dry_run = args.contains("--dry-run"); - finish_args(args)?; - ReleaseCmd { dry_run }.run() - } - "promote" => { - let dry_run = args.contains("--dry-run"); - finish_args(args)?; - PromoteCmd { dry_run }.run() - } - "dist" => { - let nightly = args.contains("--nightly"); - let client_version: Option = args.opt_value_from_str("--client")?; - finish_args(args)?; - DistCmd { nightly, client_version }.run() - } - "metrics" => { - let dry_run = args.contains("--dry-run"); - finish_args(args)?; - MetricsCmd { dry_run }.run() - } - "bb" => { - let suffix: String = args.free_from_str()?; - finish_args(args)?; + flags::XtaskCmd::Metrics(cmd) => cmd.run(), + flags::XtaskCmd::Bb(cmd) => { { let _d = pushd("./crates/rust-analyzer")?; cmd!("cargo build --release --features jemalloc").run()?; } - cp("./target/release/rust-analyzer", format!("./target/rust-analyzer-{}", suffix))?; - Ok(()) - } - _ => { - eprintln!( - "\ -cargo xtask -Run custom build command. - -USAGE: - cargo xtask - -SUBCOMMANDS: - fuzz-tests - codegen - install - lint - dist - promote - bb" - ); + cp("./target/release/rust-analyzer", format!("./target/rust-analyzer-{}", cmd.suffix))?; Ok(()) } } } -fn finish_args(args: Arguments) -> Result<()> { - if !args.finish().is_empty() { - bail!("Unused arguments."); - } - Ok(()) -} - fn project_root() -> PathBuf { Path::new( &env::var("CARGO_MANIFEST_DIR").unwrap_or_else(|_| env!("CARGO_MANIFEST_DIR").to_owned()), diff --git a/xtask/src/metrics.rs b/xtask/src/metrics.rs index babc2a6d4c..eb58b32745 100644 --- a/xtask/src/metrics.rs +++ b/xtask/src/metrics.rs @@ -9,13 +9,11 @@ use std::{ use anyhow::{bail, format_err, Result}; use xshell::{cmd, mkdir_p, pushd, pushenv, read_file, rm_rf}; +use crate::flags; + type Unit = String; -pub(crate) struct MetricsCmd { - pub(crate) dry_run: bool, -} - -impl MetricsCmd { +impl flags::Metrics { pub(crate) fn run(self) -> Result<()> { let mut metrics = Metrics::new()?; if !self.dry_run { diff --git a/xtask/src/pre_cache.rs b/xtask/src/pre_cache.rs index 54f4a95a99..b456224fd6 100644 --- a/xtask/src/pre_cache.rs +++ b/xtask/src/pre_cache.rs @@ -6,9 +6,9 @@ use std::{ use anyhow::Result; use xshell::rm_rf; -pub(crate) struct PreCacheCmd; +use crate::flags; -impl PreCacheCmd { +impl flags::PreCache { /// Cleans the `./target` dir after the build such that only /// dependencies are cached on CI. pub(crate) fn run(self) -> Result<()> { diff --git a/xtask/src/release.rs b/xtask/src/release.rs index 5008881e48..d8d86fd63e 100644 --- a/xtask/src/release.rs +++ b/xtask/src/release.rs @@ -2,13 +2,9 @@ use std::fmt::Write; use xshell::{cmd, cp, pushd, read_dir, write_file}; -use crate::{codegen, date_iso, is_release_tag, project_root, Mode, Result}; +use crate::{codegen, date_iso, flags, is_release_tag, project_root, Mode, Result}; -pub(crate) struct ReleaseCmd { - pub(crate) dry_run: bool, -} - -impl ReleaseCmd { +impl flags::Release { pub(crate) fn run(self) -> Result<()> { if !self.dry_run { cmd!("git switch release").run()?; @@ -86,11 +82,7 @@ https://github.com/sponsors/rust-analyzer[GitHub Sponsors]. } } -pub(crate) struct PromoteCmd { - pub(crate) dry_run: bool, -} - -impl PromoteCmd { +impl flags::Promote { pub(crate) fn run(self) -> Result<()> { let _dir = pushd("../rust-rust-analyzer")?; cmd!("git switch master").run()?;