From a0b687235907ce91358677353c00f575548313b4 Mon Sep 17 00:00:00 2001 From: nokazn <41154684+nokazn@users.noreply.github.com> Date: Thu, 4 Jan 2024 10:43:17 +0900 Subject: [PATCH] fix(cli): respect `exclude` option for `deno check` command (#21779) This PR fixes #21658. - `check` subcommand sees `exclude` option in `deno.json`. When some paths passed with `check` command listed in `exclude`, they are ignored. - When some files are listed in `exclude` and imported indirectly among module graph, they are checked. --- cli/args/mod.rs | 27 +++++++++++++++++ cli/module_loader.rs | 29 ++++++++++++++++--- cli/tests/integration/check_tests.rs | 28 ++++++++++++++++++ .../exclude_option/deno.exclude_dir.json | 5 ++++ .../exclude_option/deno.exclude_glob.json | 5 ++++ .../testdata/check/exclude_option/deno.json | 3 ++ .../exclude_option.ts.error.out | 4 +++ .../check/exclude_option/ignored/index.ts | 1 + .../testdata/check/exclude_option/index.ts | 5 ++++ 9 files changed, 103 insertions(+), 4 deletions(-) create mode 100644 cli/tests/testdata/check/exclude_option/deno.exclude_dir.json create mode 100644 cli/tests/testdata/check/exclude_option/deno.exclude_glob.json create mode 100644 cli/tests/testdata/check/exclude_option/deno.json create mode 100644 cli/tests/testdata/check/exclude_option/exclude_option.ts.error.out create mode 100644 cli/tests/testdata/check/exclude_option/ignored/index.ts create mode 100644 cli/tests/testdata/check/exclude_option/index.ts diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 6366ce26037b89..dd9ae36e3be72e 100644 --- a/cli/args/mod.rs +++ b/cli/args/mod.rs @@ -311,6 +311,23 @@ fn resolve_fmt_options( options } +#[derive(Clone, Debug, Default)] +pub struct CheckOptions { + pub exclude: Vec, +} + +impl CheckOptions { + pub fn resolve( + maybe_files_config: Option, + ) -> Result { + Ok(Self { + exclude: expand_globs( + maybe_files_config.map(|c| c.exclude).unwrap_or_default(), + )?, + }) + } +} + #[derive(Clone)] pub struct TestOptions { pub files: FilesConfig, @@ -1182,6 +1199,16 @@ impl CliOptions { LintOptions::resolve(maybe_lint_config, Some(lint_flags)) } + pub fn resolve_check_options(&self) -> Result { + let maybe_files_config = if let Some(config_file) = &self.maybe_config_file + { + config_file.to_files_config()? + } else { + None + }; + CheckOptions::resolve(maybe_files_config) + } + pub fn resolve_test_options( &self, test_flags: TestFlags, diff --git a/cli/module_loader.rs b/cli/module_loader.rs index 445cf4902d67a5..f7957610864409 100644 --- a/cli/module_loader.rs +++ b/cli/module_loader.rs @@ -224,10 +224,7 @@ impl ModuleLoadPreparer { ) -> Result<(), AnyError> { let lib = self.options.ts_type_lib_window(); - let specifiers = files - .iter() - .map(|file| resolve_url_or_path(file, self.options.initial_cwd())) - .collect::, _>>()?; + let specifiers = self.collect_specifiers(files); self .prepare_module_load( specifiers, @@ -237,6 +234,30 @@ impl ModuleLoadPreparer { ) .await } + + fn collect_specifiers(&self, files: &[String]) -> Vec { + let excludes = match self.options.resolve_check_options() { + Ok(o) => o.exclude, + Err(_) => vec![], + }; + files + .iter() + .filter_map(|file| { + let file_url = + resolve_url_or_path(file, self.options.initial_cwd()).ok()?; + if file_url.scheme() != "file" { + return Some(file_url); + } + // ignore local files that match any of files listed in `exclude` option + let file_path = file_url.to_file_path().ok()?; + if excludes.iter().any(|e| file_path.starts_with(e)) { + None + } else { + Some(file_url) + } + }) + .collect::>() + } } pub struct ModuleCodeSource { diff --git a/cli/tests/integration/check_tests.rs b/cli/tests/integration/check_tests.rs index fb699072e5182b..36b80149d4b15c 100644 --- a/cli/tests/integration/check_tests.rs +++ b/cli/tests/integration/check_tests.rs @@ -133,6 +133,34 @@ itest!(check_deno_unstable_from_config { output_str: Some(""), }); +itest!(check_with_exclude_option_by_dir { + args: + "check --quiet --config check/exclude_option/deno.exclude_dir.json check/exclude_option/ignored/index.ts", + output_str: Some(""), + exit_code: 0, +}); + +itest!(check_with_exclude_option_by_glob { + args: + "check --quiet --config check/exclude_option/deno.exclude_glob.json check/exclude_option/ignored/index.ts", + output_str: Some(""), + exit_code: 0, +}); + +itest!(check_without_exclude_option { + args: + "check --quiet --config check/exclude_option/deno.json check/exclude_option/ignored/index.ts", + output: "check/exclude_option/exclude_option.ts.error.out", + exit_code: 1, +}); + +itest!(check_imported_files_listed_in_exclude_option { + args: + "check --quiet --config check/exclude_option/deno.exclude_dir.json check/exclude_option/index.ts", + output: "check/exclude_option/exclude_option.ts.error.out", + exit_code: 1, +}); + #[test] fn cache_switching_config_then_no_config() { let context = TestContext::default(); diff --git a/cli/tests/testdata/check/exclude_option/deno.exclude_dir.json b/cli/tests/testdata/check/exclude_option/deno.exclude_dir.json new file mode 100644 index 00000000000000..2019f8953d3d50 --- /dev/null +++ b/cli/tests/testdata/check/exclude_option/deno.exclude_dir.json @@ -0,0 +1,5 @@ +{ + "exclude": [ + "ignored" + ] +} diff --git a/cli/tests/testdata/check/exclude_option/deno.exclude_glob.json b/cli/tests/testdata/check/exclude_option/deno.exclude_glob.json new file mode 100644 index 00000000000000..1d203ba089348e --- /dev/null +++ b/cli/tests/testdata/check/exclude_option/deno.exclude_glob.json @@ -0,0 +1,5 @@ +{ + "exclude": [ + "ignored/**/*" + ] +} diff --git a/cli/tests/testdata/check/exclude_option/deno.json b/cli/tests/testdata/check/exclude_option/deno.json new file mode 100644 index 00000000000000..a9eca74ca448a2 --- /dev/null +++ b/cli/tests/testdata/check/exclude_option/deno.json @@ -0,0 +1,3 @@ +{ + "exclude": [] +} diff --git a/cli/tests/testdata/check/exclude_option/exclude_option.ts.error.out b/cli/tests/testdata/check/exclude_option/exclude_option.ts.error.out new file mode 100644 index 00000000000000..abd1c125861e33 --- /dev/null +++ b/cli/tests/testdata/check/exclude_option/exclude_option.ts.error.out @@ -0,0 +1,4 @@ +error: TS2304 [ERROR]: Cannot find name 'nothing'. +export { nothing }; + ~~~~~~~ + at [WILDCARD] diff --git a/cli/tests/testdata/check/exclude_option/ignored/index.ts b/cli/tests/testdata/check/exclude_option/ignored/index.ts new file mode 100644 index 00000000000000..0419cf073c4b29 --- /dev/null +++ b/cli/tests/testdata/check/exclude_option/ignored/index.ts @@ -0,0 +1 @@ +export { nothing }; diff --git a/cli/tests/testdata/check/exclude_option/index.ts b/cli/tests/testdata/check/exclude_option/index.ts new file mode 100644 index 00000000000000..8335ca3a2e25a6 --- /dev/null +++ b/cli/tests/testdata/check/exclude_option/index.ts @@ -0,0 +1,5 @@ +import { nothing } from "./ignored/index.ts"; + +const foo = 1; + +export { foo, nothing };