1
0
Fork 0
mirror of https://github.com/denoland/deno.git synced 2024-11-21 15:04:11 -05:00

feat(cli): top-level exclude field in deno.json (#17778)

This commit is contained in:
scarf 2023-05-19 05:55:10 +09:00 committed by GitHub
parent 55db691174
commit a45f7f237b
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
2 changed files with 188 additions and 30 deletions

View file

@ -348,6 +348,13 @@ impl FilesConfig {
self.include.is_empty()
|| self.include.iter().any(|i| file_path.starts_with(i))
}
fn extend(self, rhs: Self) -> Self {
Self {
include: [self.include, rhs.include].concat(),
exclude: [self.exclude, rhs.exclude].concat(),
}
}
}
/// Choose between flat and nested files configuration.
@ -428,6 +435,13 @@ pub struct LintConfig {
pub report: Option<String>,
}
impl LintConfig {
pub fn with_files(self, files: FilesConfig) -> Self {
let files = self.files.extend(files);
Self { files, ..self }
}
}
#[derive(Clone, Copy, Debug, Serialize, Deserialize, PartialEq)]
#[serde(deny_unknown_fields, rename_all = "camelCase")]
pub enum ProseWrap {
@ -548,6 +562,13 @@ pub struct FmtConfig {
pub files: FilesConfig,
}
impl FmtConfig {
pub fn with_files(self, files: FilesConfig) -> Self {
let files = self.files.extend(files);
Self { files, ..self }
}
}
/// `test` config representation for serde
///
/// fields `include` and `exclude` are expanded from [SerializedFilesConfig].
@ -580,6 +601,13 @@ pub struct TestConfig {
pub files: FilesConfig,
}
impl TestConfig {
pub fn with_files(self, files: FilesConfig) -> Self {
let files = self.files.extend(files);
Self { files }
}
}
/// `bench` config representation for serde
///
/// fields `include` and `exclude` are expanded from [SerializedFilesConfig].
@ -612,6 +640,13 @@ pub struct BenchConfig {
pub files: FilesConfig,
}
impl BenchConfig {
pub fn with_files(self, files: FilesConfig) -> Self {
let files = self.files.extend(files);
Self { files }
}
}
#[derive(Clone, Debug, Deserialize, PartialEq)]
#[serde(untagged)]
pub enum LockConfig {
@ -632,6 +667,7 @@ pub struct ConfigFileJson {
pub test: Option<Value>,
pub bench: Option<Value>,
pub lock: Option<Value>,
pub exclude: Option<Value>,
}
#[derive(Clone, Debug)]
@ -844,44 +880,105 @@ impl ConfigFile {
self.json.imports.is_some() || self.json.scopes.is_some()
}
pub fn to_fmt_config(&self) -> Result<Option<FmtConfig>, AnyError> {
if let Some(config) = self.json.fmt.clone() {
let fmt_config: SerializedFmtConfig = serde_json::from_value(config)
.context("Failed to parse \"fmt\" configuration")?;
Ok(Some(fmt_config.into_resolved(&self.specifier)?))
pub fn to_files_config(&self) -> Result<Option<FilesConfig>, AnyError> {
let exclude: Vec<String> = if let Some(exclude) = self.json.exclude.clone()
{
serde_json::from_value(exclude)
.context("Failed to parse \"exclude\" configuration")?
} else {
Ok(None)
Vec::new()
};
let raw_files_config = SerializedFilesConfig {
exclude,
..Default::default()
};
Ok(Some(raw_files_config.into_resolved(&self.specifier)?))
}
pub fn to_fmt_config(&self) -> Result<Option<FmtConfig>, AnyError> {
let files_config = self.to_files_config()?;
let fmt_config = match self.json.fmt.clone() {
Some(config) => {
let fmt_config: SerializedFmtConfig = serde_json::from_value(config)
.context("Failed to parse \"fmt\" configuration")?;
Some(fmt_config.into_resolved(&self.specifier)?)
}
None => None,
};
if files_config.is_none() && fmt_config.is_none() {
return Ok(None);
}
let fmt_config = fmt_config.unwrap_or_default();
let files_config = files_config.unwrap_or_default();
Ok(Some(fmt_config.with_files(files_config)))
}
pub fn to_lint_config(&self) -> Result<Option<LintConfig>, AnyError> {
if let Some(config) = self.json.lint.clone() {
let lint_config: SerializedLintConfig = serde_json::from_value(config)
.context("Failed to parse \"lint\" configuration")?;
Ok(Some(lint_config.into_resolved(&self.specifier)?))
} else {
Ok(None)
let files_config = self.to_files_config()?;
let lint_config = match self.json.lint.clone() {
Some(config) => {
let lint_config: SerializedLintConfig = serde_json::from_value(config)
.context("Failed to parse \"lint\" configuration")?;
Some(lint_config.into_resolved(&self.specifier)?)
}
None => None,
};
if files_config.is_none() && lint_config.is_none() {
return Ok(None);
}
let lint_config = lint_config.unwrap_or_default();
let files_config = files_config.unwrap_or_default();
Ok(Some(lint_config.with_files(files_config)))
}
pub fn to_test_config(&self) -> Result<Option<TestConfig>, AnyError> {
if let Some(config) = self.json.test.clone() {
let test_config: SerializedTestConfig = serde_json::from_value(config)
.context("Failed to parse \"test\" configuration")?;
Ok(Some(test_config.into_resolved(&self.specifier)?))
} else {
Ok(None)
let files_config = self.to_files_config()?;
let test_config = match self.json.test.clone() {
Some(config) => {
let test_config: SerializedTestConfig = serde_json::from_value(config)
.context("Failed to parse \"test\" configuration")?;
Some(test_config.into_resolved(&self.specifier)?)
}
None => None,
};
if files_config.is_none() && test_config.is_none() {
return Ok(None);
}
let test_config = test_config.unwrap_or_default();
let files_config = files_config.unwrap_or_default();
Ok(Some(test_config.with_files(files_config)))
}
pub fn to_bench_config(&self) -> Result<Option<BenchConfig>, AnyError> {
if let Some(config) = self.json.bench.clone() {
let bench_config: SerializedBenchConfig = serde_json::from_value(config)
.context("Failed to parse \"bench\" configuration")?;
Ok(Some(bench_config.into_resolved(&self.specifier)?))
} else {
Ok(None)
let files_config = self.to_files_config()?;
let bench_config = match self.json.bench.clone() {
Some(config) => {
let bench_config: SerializedBenchConfig =
serde_json::from_value(config)
.context("Failed to parse \"bench\" configuration")?;
Some(bench_config.into_resolved(&self.specifier)?)
}
None => None,
};
if files_config.is_none() && bench_config.is_none() {
return Ok(None);
}
let bench_config = bench_config.unwrap_or_default();
let files_config = files_config.unwrap_or_default();
Ok(Some(bench_config.with_files(files_config)))
}
/// Return any tasks that are defined in the configuration file as a sequence
@ -1223,8 +1320,7 @@ mod tests {
let config_dir = ModuleSpecifier::parse("file:///deno/").unwrap();
let config_specifier = config_dir.join("tsconfig.json").unwrap();
let config_file = ConfigFile::new(config_text, &config_specifier).unwrap();
let (options_value, ignored) =
config_file.to_compiler_options().expect("error parsing");
let (options_value, ignored) = config_file.to_compiler_options().unwrap();
assert!(options_value.is_object());
let options = options_value.as_object().unwrap();
assert!(options.contains_key("strict"));
@ -1409,8 +1505,7 @@ mod tests {
let config_specifier =
ModuleSpecifier::parse("file:///deno/tsconfig.json").unwrap();
let config_file = ConfigFile::new(config_text, &config_specifier).unwrap();
let (options_value, _) =
config_file.to_compiler_options().expect("error parsing");
let (options_value, _) = config_file.to_compiler_options().unwrap();
assert!(options_value.is_object());
}
@ -1420,11 +1515,67 @@ mod tests {
let config_specifier =
ModuleSpecifier::parse("file:///deno/tsconfig.json").unwrap();
let config_file = ConfigFile::new(config_text, &config_specifier).unwrap();
let (options_value, _) =
config_file.to_compiler_options().expect("error parsing");
let (options_value, _) = config_file.to_compiler_options().unwrap();
assert!(options_value.is_object());
}
#[test]
fn test_parse_config_with_global_files() {
let config_text = r#"{
"exclude": ["foo/"],
"test": {
"exclude": ["npm/"],
},
"bench": {}
}"#;
let config_specifier =
ModuleSpecifier::parse("file:///deno/tsconfig.json").unwrap();
let config_file = ConfigFile::new(config_text, &config_specifier).unwrap();
let (options_value, _) = config_file.to_compiler_options().unwrap();
assert!(options_value.is_object());
let test_config = config_file.to_test_config().unwrap().unwrap();
assert_eq!(test_config.files.include, Vec::<PathBuf>::new());
assert_eq!(
test_config.files.exclude,
vec![PathBuf::from("/deno/npm/"), PathBuf::from("/deno/foo/")]
);
let bench_config = config_file.to_bench_config().unwrap().unwrap();
assert_eq!(
bench_config.files.exclude,
vec![PathBuf::from("/deno/foo/")]
);
}
#[test]
fn test_parse_config_with_global_files_only() {
let config_text = r#"{
"exclude": ["npm/"]
}"#;
let config_specifier =
ModuleSpecifier::parse("file:///deno/tsconfig.json").unwrap();
let config_file = ConfigFile::new(config_text, &config_specifier).unwrap();
let (options_value, _) = config_file.to_compiler_options().unwrap();
assert!(options_value.is_object());
let empty_include = Vec::<PathBuf>::new();
let files_config = config_file.to_files_config().unwrap().unwrap();
assert_eq!(files_config.include, empty_include);
assert_eq!(files_config.exclude, vec![PathBuf::from("/deno/npm/")]);
let lint_config = config_file.to_lint_config().unwrap().unwrap();
assert_eq!(lint_config.files.include, empty_include);
assert_eq!(lint_config.files.exclude, vec![PathBuf::from("/deno/npm/")]);
let fmt_config = config_file.to_fmt_config().unwrap().unwrap();
assert_eq!(fmt_config.files.include, empty_include);
assert_eq!(fmt_config.files.exclude, vec![PathBuf::from("/deno/npm/")],);
}
#[test]
fn test_parse_config_with_invalid_file() {
let config_text = "{foo:bar}";

View file

@ -223,6 +223,13 @@
}
}
},
"exclude": {
"type": "array",
"description": "List of files or directories that will be ignored by all other configurations.",
"items": {
"type": "string"
}
},
"lint": {
"description": "Configuration for linter",
"type": "object",