From 4285cb339d4ddfe564a98b030bcba6c621584e81 Mon Sep 17 00:00:00 2001 From: Yazan AbdAl-Rahman Date: Mon, 19 Aug 2024 23:42:13 +0300 Subject: [PATCH] fix(lint): support linting tsx/jsx from stdin (#24955) Co-authored-by: David Sherret --- cli/args/flags.rs | 26 +++++++++++++++++++++++++- cli/tools/lint/mod.rs | 5 ++++- tests/integration/lint_tests.rs | 30 ++++++++++++++++++++++++++++++ 3 files changed, 59 insertions(+), 2 deletions(-) diff --git a/cli/args/flags.rs b/cli/args/flags.rs index 2fc97c8a49..c3edd8d3f6 100644 --- a/cli/args/flags.rs +++ b/cli/args/flags.rs @@ -296,6 +296,7 @@ pub struct LintFlags { pub json: bool, pub compact: bool, pub watch: Option, + pub ext: Option, } impl LintFlags { @@ -2610,6 +2611,16 @@ Ignore linting a file by adding an ignore comment at the top of the file: .help_heading(LINT_HEADING), ) .arg( + Arg::new("ext") + .long("ext") + .require_equals(true) + .value_name("EXT") + .help("Specify the file extension to lint when reading from stdin.\ + For example, use `jsx` to lint JSX files or `tsx` for TSX files.\ + This argument is necessary because stdin input does not automatically infer the file type.\ + Example usage: `cat file.jsx | deno lint - --ext=jsx`."), + ) + .arg( Arg::new("rules") .long("rules") .help("List available rules") @@ -4570,6 +4581,8 @@ fn lint_parse(flags: &mut Flags, matches: &mut ArgMatches) { let json = matches.get_flag("json"); let compact = matches.get_flag("compact"); + let ext = matches.remove_one::("ext"); + flags.subcommand = DenoSubcommand::Lint(LintFlags { files: FileFlags { include: files, @@ -4583,6 +4596,7 @@ fn lint_parse(flags: &mut Flags, matches: &mut ArgMatches) { json, compact, watch: watch_arg_parse(matches), + ext, }); } @@ -6568,6 +6582,7 @@ mod tests { json: false, compact: false, watch: Default::default(), + ext: None, }), ..Flags::default() } @@ -6596,6 +6611,7 @@ mod tests { json: false, compact: false, watch: Some(Default::default()), + ext: None, }), ..Flags::default() } @@ -6628,7 +6644,8 @@ mod tests { hmr: false, no_clear_screen: true, exclude: vec![], - }) + }), + ext: None, }), ..Flags::default() } @@ -6656,6 +6673,7 @@ mod tests { json: false, compact: false, watch: Default::default(), + ext: None, }), ..Flags::default() } @@ -6678,6 +6696,7 @@ mod tests { json: false, compact: false, watch: Default::default(), + ext: None, }), ..Flags::default() } @@ -6705,6 +6724,7 @@ mod tests { json: false, compact: false, watch: Default::default(), + ext: None, }), ..Flags::default() } @@ -6733,6 +6753,7 @@ mod tests { json: false, compact: false, watch: Default::default(), + ext: None, }), ..Flags::default() } @@ -6755,6 +6776,7 @@ mod tests { json: true, compact: false, watch: Default::default(), + ext: None, }), ..Flags::default() } @@ -6784,6 +6806,7 @@ mod tests { json: true, compact: false, watch: Default::default(), + ext: None, }), config_flag: ConfigFlag::Path("Deno.jsonc".to_string()), ..Flags::default() @@ -6814,6 +6837,7 @@ mod tests { json: false, compact: true, watch: Default::default(), + ext: None, }), config_flag: ConfigFlag::Path("Deno.jsonc".to_string()), ..Flags::default() diff --git a/cli/tools/lint/mod.rs b/cli/tools/lint/mod.rs index efa11f03c8..5b51b2b40c 100644 --- a/cli/tools/lint/mod.rs +++ b/cli/tools/lint/mod.rs @@ -151,7 +151,10 @@ pub async fn lint( lint_options.rules, start_dir.maybe_deno_json().map(|c| c.as_ref()), )?; - let file_path = cli_options.initial_cwd().join(STDIN_FILE_NAME); + let mut file_path = cli_options.initial_cwd().join(STDIN_FILE_NAME); + if let Some(ext) = &lint_flags.ext { + file_path.set_extension(ext); + } let r = lint_stdin(&file_path, lint_rules, deno_lint_config); let success = handle_lint_result( &file_path.to_string_lossy(), diff --git a/tests/integration/lint_tests.rs b/tests/integration/lint_tests.rs index c0b1b4286e..b47a98da4d 100644 --- a/tests/integration/lint_tests.rs +++ b/tests/integration/lint_tests.rs @@ -4,6 +4,7 @@ use deno_core::serde_json::json; use test_util::assert_contains; use test_util::assert_not_contains; use test_util::itest; +use test_util::TestContext; use test_util::TestContextBuilder; itest!(ignore_unexplicit_files { @@ -235,3 +236,32 @@ fn opt_out_top_level_exclude_via_lint_unexclude() { assert_contains!(output, "excluded.ts"); assert_not_contains!(output, "actually_excluded.ts"); } + +#[test] +fn lint_stdin_jsx() { + TestContext::default() + .new_command() + .args("lint --ext=jsx -") + .stdin_text( + r#" +const data =
hello
; +"#, + ) + .run() + .assert_matches_text( + r#"error[no-unused-vars]: `data` is never used + --> [WILDLINE]$deno$stdin.jsx:2:7 + | +2 | const data =
hello
; + | ^^^^ + = hint: If this is intentional, prefix it with an underscore like `_data` + + docs: https://lint.deno.land/rules/no-unused-vars + + +Found 1 problem +Checked 1 file +"#, + ) + .assert_exit_code(1); +}