diff --git a/cli/args/mod.rs b/cli/args/mod.rs index 6366ce2603..dd9ae36e3b 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 445cf4902d..f795761086 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 fb699072e5..36b80149d4 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 0000000000..2019f8953d --- /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 0000000000..1d203ba089 --- /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 0000000000..a9eca74ca4 --- /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 0000000000..abd1c12586 --- /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 0000000000..0419cf073c --- /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 0000000000..8335ca3a2e --- /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 };