diff --git a/packages/cli/binding/src/cli/help.rs b/packages/cli/binding/src/cli/help.rs index 07f3c48cac..9aa19bfbe1 100644 --- a/packages/cli/binding/src/cli/help.rs +++ b/packages/cli/binding/src/cli/help.rs @@ -56,6 +56,12 @@ fn has_flag_before_terminator(args: &[String], flag: &str) -> bool { false } +pub(super) fn has_help_flag_before_terminator(args: &[String]) -> bool { + args.iter() + .take_while(|arg| arg.as_str() != "--") + .any(|arg| matches!(arg.as_str(), "-h" | "--help")) +} + pub(super) fn should_suppress_subcommand_stdout(subcommand: &SynthesizableSubcommand) -> bool { match subcommand { SynthesizableSubcommand::Lint { args } => has_flag_before_terminator(args, "--init"), @@ -67,6 +73,15 @@ pub(super) fn should_suppress_subcommand_stdout(subcommand: &SynthesizableSubcom } } +pub(super) fn should_capture_help_stdout(subcommand: &SynthesizableSubcommand) -> bool { + let args = match subcommand { + SynthesizableSubcommand::Lint { args } | SynthesizableSubcommand::Fmt { args } => args, + _ => return false, + }; + + has_help_flag_before_terminator(args) +} + pub(super) fn should_prepend_vitest_run(args: &[String]) -> bool { let Some(first_arg) = args.first().map(String::as_str) else { return true; @@ -295,6 +310,25 @@ mod tests { assert!(!should_suppress_subcommand_stdout(&subcommand)); } + #[test] + fn lint_help_captures_stdout() { + let subcommand = SynthesizableSubcommand::Lint { args: vec!["--help".to_string()] }; + assert!(should_capture_help_stdout(&subcommand)); + } + + #[test] + fn fmt_short_help_captures_stdout() { + let subcommand = SynthesizableSubcommand::Fmt { args: vec!["-h".to_string()] }; + assert!(should_capture_help_stdout(&subcommand)); + } + + #[test] + fn help_after_terminator_is_not_captured() { + let subcommand = + SynthesizableSubcommand::Lint { args: vec!["--".to_string(), "--help".to_string()] }; + assert!(!should_capture_help_stdout(&subcommand)); + } + #[test] fn global_subcommands_produce_invalid_subcommand_error() { use clap::error::ErrorKind; diff --git a/packages/cli/binding/src/cli/mod.rs b/packages/cli/binding/src/cli/mod.rs index f94443964b..4b7da3efb2 100644 --- a/packages/cli/binding/src/cli/mod.rs +++ b/packages/cli/binding/src/cli/mod.rs @@ -33,8 +33,8 @@ use self::{ execution::{FilterStream, resolve_and_execute, resolve_and_execute_with_filter}, handler::{VitePlusCommandHandler, VitePlusConfigLoader}, help::{ - handle_cli_parse_error, normalize_help_args, print_help, should_print_help, - should_suppress_subcommand_stdout, + handle_cli_parse_error, normalize_help_args, print_help, should_capture_help_stdout, + should_print_help, should_suppress_subcommand_stdout, }, types::CLIArgs, }; @@ -96,6 +96,18 @@ async fn execute_direct_subcommand( |_| Cow::Borrowed(""), ) .await? + } else if should_capture_help_stdout(&other) { + resolve_and_execute_with_filter( + &resolver, + other, + None, + &envs, + cwd, + &cwd_arc, + FilterStream::Stdout, + |s| Cow::Borrowed(s), + ) + .await? } else if matches!(&other, SynthesizableSubcommand::Fmt { .. }) { resolve_and_execute_with_filter( &resolver, diff --git a/packages/cli/binding/src/cli/resolver.rs b/packages/cli/binding/src/cli/resolver.rs index db5dd3727b..4a4e840284 100644 --- a/packages/cli/binding/src/cli/resolver.rs +++ b/packages/cli/binding/src/cli/resolver.rs @@ -8,7 +8,7 @@ use vite_task::config::user::{ }; use super::{ - help::should_prepend_vitest_run, + help::{has_help_flag_before_terminator, should_prepend_vitest_run}, types::{CliOptions, ResolvedSubcommand, ResolvedUniversalViteConfig, SynthesizableSubcommand}, }; @@ -94,15 +94,18 @@ impl SubcommandResolver { .to_str() .ok_or_else(|| anyhow::anyhow!("lint JS path is not valid UTF-8"))?; let owned_resolved_vite_config; - let resolved_vite_config = if let Some(config) = resolved_vite_config { - config + let resolved_vite_config = if has_help_flag_before_terminator(&args) { + None + } else if let Some(config) = resolved_vite_config { + Some(config) } else { owned_resolved_vite_config = self.resolve_universal_vite_config().await?; - &owned_resolved_vite_config + Some(&owned_resolved_vite_config) }; - if let (Some(_), Some(config_file)) = - (&resolved_vite_config.lint, &resolved_vite_config.config_file) + if let Some(resolved_vite_config) = resolved_vite_config + && let (Some(_), Some(config_file)) = + (&resolved_vite_config.lint, &resolved_vite_config.config_file) { args.insert(0, "-c".to_string()); args.insert(1, config_file.clone()); @@ -130,15 +133,18 @@ impl SubcommandResolver { .to_str() .ok_or_else(|| anyhow::anyhow!("fmt JS path is not valid UTF-8"))?; let owned_resolved_vite_config; - let resolved_vite_config = if let Some(config) = resolved_vite_config { - config + let resolved_vite_config = if has_help_flag_before_terminator(&args) { + None + } else if let Some(config) = resolved_vite_config { + Some(config) } else { owned_resolved_vite_config = self.resolve_universal_vite_config().await?; - &owned_resolved_vite_config + Some(&owned_resolved_vite_config) }; - if let (Some(_), Some(config_file)) = - (&resolved_vite_config.fmt, &resolved_vite_config.config_file) + if let Some(resolved_vite_config) = resolved_vite_config + && let (Some(_), Some(config_file)) = + (&resolved_vite_config.fmt, &resolved_vite_config.config_file) { args.insert(0, "-c".to_string()); args.insert(1, config_file.clone()); diff --git a/packages/cli/snap-tests-todo/test-panicked-fix/snap.txt b/packages/cli/snap-tests-todo/test-panicked-fix/snap.txt deleted file mode 100644 index 8ea62f190a..0000000000 --- a/packages/cli/snap-tests-todo/test-panicked-fix/snap.txt +++ /dev/null @@ -1,27 +0,0 @@ -> vp lint --help | head -n 20 # print help message and no panicked -Usage: [-c=<./.oxlintrc.json>] [PATH]... - -Basic Configuration - -c, --config=<./.oxlintrc.json> Oxlint configuration file (experimental) - * only `.json` extension is supported - * you can use comments in configuration files. - * tries to be compatible with the ESLint v8's format - --tsconfig=<./tsconfig.json> TypeScript `tsconfig.json` path for reading path alias and - project references for import plugin - --init Initialize oxlint configuration with default values - -Allowing / Denying Multiple Lints - Accumulate rules and categories from left to right on the command-line. - For example `-D correctness -A no-debugger` or `-A all -D no-debugger`. - The categories are: - * `correctness` - code that is outright wrong or useless (default). - * `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. - - -thread 'tokio-runtime-worker' panicked at library/std/src/io/stdio.rs:1165:9: -failed printing to stdout: Broken pipe (os error 32) -note: run with `RUST_BACKTRACE=1` environment variable to display a backtrace -[Vite+] run error: [Error: Panic in async function] { code: 'GenericFailure' } diff --git a/packages/cli/snap-tests-todo/test-panicked-fix/package.json b/packages/cli/snap-tests/test-panicked-fix/package.json similarity index 100% rename from packages/cli/snap-tests-todo/test-panicked-fix/package.json rename to packages/cli/snap-tests/test-panicked-fix/package.json diff --git a/packages/cli/snap-tests/test-panicked-fix/snap.txt b/packages/cli/snap-tests/test-panicked-fix/snap.txt new file mode 100644 index 0000000000..a512fc9601 --- /dev/null +++ b/packages/cli/snap-tests/test-panicked-fix/snap.txt @@ -0,0 +1,21 @@ +> vp lint --help | head -n 20 # print help message and no panicked +Usage: [-c=<./.oxlintrc.json>] [PATH]... + +Basic Configuration + -c, --config=<./.oxlintrc.json> Oxlint configuration file + * `.json` and `.jsonc` config files are supported in all runtimes + * JavaScript/TypeScript config files are experimental and require + running via Node.js + * you can use comments in configuration files. + * tries to be compatible with ESLint v8's format + --tsconfig=<./tsconfig.json> Override the TypeScript config used for import resolution. + Oxlint automatically discovers the relevant `tsconfig.json` for each + file. Use this only when your project uses a non-standard tsconfig + name or location. + --init Initialize oxlint configuration with default values + +Allowing / Denying Multiple Lints + Accumulate rules and categories from left to right on the command-line. + For example `-D correctness -A no-debugger` or `-A all -D no-debugger`. + The categories are: + * `correctness` - Code that is outright wrong or useless (default) diff --git a/packages/cli/snap-tests-todo/test-panicked-fix/steps.json b/packages/cli/snap-tests/test-panicked-fix/steps.json similarity index 100% rename from packages/cli/snap-tests-todo/test-panicked-fix/steps.json rename to packages/cli/snap-tests/test-panicked-fix/steps.json