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.
This commit is contained in:
nokazn 2024-01-04 10:43:17 +09:00 committed by GitHub
parent 00970daea2
commit a0b6872359
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
9 changed files with 103 additions and 4 deletions

View file

@ -311,6 +311,23 @@ fn resolve_fmt_options(
options
}
#[derive(Clone, Debug, Default)]
pub struct CheckOptions {
pub exclude: Vec<PathBuf>,
}
impl CheckOptions {
pub fn resolve(
maybe_files_config: Option<FilesConfig>,
) -> Result<Self, AnyError> {
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<CheckOptions, AnyError> {
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,

View file

@ -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::<Result<Vec<_>, _>>()?;
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<ModuleSpecifier> {
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::<Vec<_>>()
}
}
pub struct ModuleCodeSource {

View file

@ -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();

View file

@ -0,0 +1,5 @@
{
"exclude": [
"ignored"
]
}

View file

@ -0,0 +1,5 @@
{
"exclude": [
"ignored/**/*"
]
}

View file

@ -0,0 +1,3 @@
{
"exclude": []
}

View file

@ -0,0 +1,4 @@
error: TS2304 [ERROR]: Cannot find name 'nothing'.
export { nothing };
~~~~~~~
at [WILDCARD]

View file

@ -0,0 +1 @@
export { nothing };

View file

@ -0,0 +1,5 @@
import { nothing } from "./ignored/index.ts";
const foo = 1;
export { foo, nothing };