Skip to content

Commit

Permalink
refactor(config): remove overrides.include
Browse files Browse the repository at this point in the history
  • Loading branch information
Conaclos committed Feb 22, 2025
1 parent c0fb646 commit f83164d
Show file tree
Hide file tree
Showing 23 changed files with 143 additions and 1,890 deletions.
12 changes: 9 additions & 3 deletions crates/biome_cli/src/execute/migrate/eslint_to_biome.rs
Original file line number Diff line number Diff line change
Expand Up @@ -75,7 +75,8 @@ impl eslint_eslint::FlatConfigData {
}
let includes =
to_biome_includes(&flat_config_object.files, &flat_config_object.ignores);
override_pat.includes = (!includes.is_empty()).then_some(includes);
override_pat.includes = (!includes.is_empty())
.then_some(biome_configuration::OverrideGlobs::Globs(includes.into()));
if let Some(rules) = flat_config_object.rules {
if !rules.is_empty() {
override_pat.linter = Some(biome_config::OverrideLinterConfiguration {
Expand Down Expand Up @@ -155,7 +156,8 @@ impl eslint_eslint::LegacyConfigData {
override_pattern.javascript = Some(js_config)
}
let includes = to_biome_includes(&override_elt.files, &override_elt.excluded_files);
override_pattern.includes = (!includes.is_empty()).then_some(includes);
override_pattern.includes = (!includes.is_empty())
.then_some(biome_configuration::OverrideGlobs::Globs(includes.into()));
if !override_elt.rules.is_empty() {
override_pattern.linter = Some(biome_config::OverrideLinterConfiguration {
rules: Some(override_elt.rules.into_biome_rules(options, &mut results)),
Expand Down Expand Up @@ -355,6 +357,7 @@ fn to_biome_includes(
#[cfg(test)]
mod tests {
use super::*;
use biome_configuration::OverrideGlobs;
use eslint_eslint::*;
use std::borrow::Cow;

Expand Down Expand Up @@ -449,7 +452,10 @@ mod tests {
let overrides = biome_config.overrides.unwrap();
assert_eq!(overrides.0.len(), 1);
let override0 = overrides.0.into_iter().next().unwrap();
assert_eq!(override0.includes.unwrap(), ["*.ts".parse().unwrap()],);
assert_eq!(
override0.includes.unwrap(),
OverrideGlobs::Globs(["*.ts".parse().unwrap()].into_iter().collect()),
);
assert_eq!(
override0
.linter
Expand Down
4 changes: 2 additions & 2 deletions crates/biome_cli/src/execute/migrate/prettier.rs
Original file line number Diff line number Diff line change
Expand Up @@ -291,12 +291,12 @@ impl TryFrom<Override> for biome_configuration::OverridePattern {
type Error = ParseFormatNumberError;
fn try_from(Override { files, options }: Override) -> Result<Self, Self::Error> {
let mut result = biome_configuration::OverridePattern {
includes: Some(
includes: Some(biome_configuration::OverrideGlobs::Globs(
files
.into_iter()
.filter_map(|glob| glob.parse().ok())
.collect(),
),
)),
..Default::default()
};
if options.print_width.is_some()
Expand Down
2 changes: 1 addition & 1 deletion crates/biome_cli/tests/commands/migrate_eslint.rs
Original file line number Diff line number Diff line change
Expand Up @@ -678,7 +678,7 @@ fn migrate_eslintrcjson_extended_rules() {
fn migrate_merge_with_overrides() {
let biomejson = r#"{
"overrides": [{
"include": ["*.js"],
"includes": ["*.js"],
"linter": { "enabled": false }
}]
}"#;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ expression: redactor(content)
{
"overrides": [
{
"include": ["*.js"],
"includes": ["*.js"],
"linter": { "enabled": false }
}
]
Expand Down Expand Up @@ -53,13 +53,13 @@ biome.json migrate ━━━━━━━━━━━━━━━━━━━━
1 1 │ {
2 │ - ········"overrides":·[{
3 │ - ············"include":·["*.js"],
3 │ - ············"includes":·["*.js"],
4 │ - ············"linter":·{·"enabled":·false·}
5 │ - ········}]
6 │ - ····}
2 │ + → "linter":·{·"rules":·{·"recommended":·false·},·"includes":·["**"]·},
3 │ + → "overrides":·[
4 │ + → → {·"include":·["*.js"],·"linter":·{·"enabled":·false·}·},
4 │ + → → {·"includes":·["*.js"],·"linter":·{·"enabled":·false·}·},
5 │ + → → {
6 │ + → → → "includes":·["bin/*.js",·"lib/*.js",·"!*.test.js"],
7 │ + → → → "linter":·{·"rules":·{·"suspicious":·{·"noDoubleEquals":·"off"·}·}·}
Expand Down
248 changes: 13 additions & 235 deletions crates/biome_configuration/src/editorconfig.rs
Original file line number Diff line number Diff line change
Expand Up @@ -17,8 +17,8 @@ use serde::{Deserialize, Deserializer};

use crate::{
diagnostics::{EditorConfigDiagnostic, ParseFailedDiagnostic},
Configuration, FormatterConfiguration, OverrideFormatterConfiguration, OverridePattern,
Overrides,
Configuration, FormatterConfiguration, OverrideFormatterConfiguration, OverrideGlobs,
OverridePattern, Overrides,
};

pub fn parse_str(s: &str) -> Result<EditorConfig, EditorConfigDiagnostic> {
Expand Down Expand Up @@ -48,28 +48,20 @@ impl EditorConfig {
formatter: self.options.remove("*").map(|o| o.to_biome()),
..Default::default()
};
let mut errors = vec![];
let overrides: Vec<_> = self
.options
.into_iter()
.map(|(k, v)| {
let patterns = match expand_unknown_glob_patterns(&k) {
Ok(patterns) => patterns
.into_iter()
.map(hack_convert_double_star)
.map(String::into_boxed_str)
.collect(),
Err(err) => {
errors.push(err);
vec![k.into_boxed_str()]
}
};

OverridePattern {
include: Some(patterns),
formatter: Some(v.to_biome_override()),
..Default::default()
}
.filter_map(|(k, v)| {
// Ignore glob patterns thatc annot be parsed
Some((
biome_glob::editorconfig::EditorconfigGlob::try_from(k).ok()?,
v,
))
})
.map(|(glob, v)| OverridePattern {
includes: Some(OverrideGlobs::EditorconfigGlob(Box::new(glob))),
formatter: Some(v.to_biome_override()),
..Default::default()
})
.collect();
config.overrides = Some(Overrides(overrides));
Expand Down Expand Up @@ -184,160 +176,6 @@ where
}
}

/// Turn an unknown glob pattern into a list of known glob patterns. This is part of a hack to support all editorconfig patterns.
///
/// TODO: remove in biome 2.0
fn expand_unknown_glob_patterns(pattern: &str) -> Result<Vec<Box<str>>, EditorConfigDiagnostic> {
struct Variants {
/// index of the { character
start: usize,
/// index of the } character
end: usize,
variants: Option<VariantType>,
}

impl Variants {
fn new(start: usize) -> Self {
Self {
start,
end: start,
variants: None,
}
}

fn parse_to_variants(&mut self, s: &str) -> Result<(), EditorConfigDiagnostic> {
let s = s.trim_start_matches('{').trim_end_matches('}');
if s.contains("..") {
let mut parts = s.split("..");
let start = parts.next().ok_or_else(|| {
EditorConfigDiagnostic::invalid_glob_pattern(
s,
"Range pattern must have exactly two parts",
)
})?;
let end = parts.next().ok_or_else(|| {
EditorConfigDiagnostic::invalid_glob_pattern(
s,
"Range pattern must have exactly two parts",
)
})?;
if parts.next().is_some() {
return Err(EditorConfigDiagnostic::invalid_glob_pattern(
s,
"Range pattern must have exactly two parts",
));
}

let start = start.parse().map_err(|err| {
EditorConfigDiagnostic::invalid_glob_pattern(
s,
format!("Error parsing the start of the range: {err}"),
)
})?;
let end = end.parse().map_err(|err| {
EditorConfigDiagnostic::invalid_glob_pattern(
s,
format!("Error parsing the end of the range: {err}"),
)
})?;
self.variants = Some(VariantType::Range((start, end)));
} else {
self.variants = Some(VariantType::List(
s.split(',').map(|s| s.to_string()).collect(),
));
}

Ok(())
}

fn variants(&self) -> Vec<String> {
match &self.variants {
Some(VariantType::List(ref list)) => list.clone(),
Some(VariantType::Range((start, end))) => {
let mut variants = vec![];
for i in *start..=*end {
variants.push(i.to_string());
}
variants
}
None => vec![],
}
}
}

enum VariantType {
List(Vec<String>),
Range((i64, i64)),
}

let mut all_variants = vec![];
let mut current_variants = None;
for (index, byte) in pattern.bytes().enumerate() {
match byte {
b'{' => {
if current_variants.is_none() {
current_variants = Some(Variants::new(index));
} else {
// TODO: error, recursive brace expansion is not supported
}
}
b'}' => {
if let Some(mut v) = current_variants.take() {
v.end = index;
v.parse_to_variants(&pattern[v.start..=v.end])?;
all_variants.push(v);
}
}
_ => {}
}
}

if all_variants.is_empty() {
return Ok(vec![pattern.to_string().into_boxed_str()]);
}

let mut expanded_patterns = Vec::new();
for variants in all_variants.iter().rev() {
if expanded_patterns.is_empty() {
for variant in &variants.variants() {
let mut pattern = pattern.to_string();
pattern.replace_range(variants.start..=variants.end, variant);
expanded_patterns.push(pattern.into_boxed_str());
}
} else {
let mut new_patterns = Vec::new();
for existing in &expanded_patterns {
for variant in &variants.variants() {
let mut pattern = existing.to_string();
pattern.replace_range(variants.start..=variants.end, variant);
new_patterns.push(pattern.into_boxed_str());
}
}
expanded_patterns = new_patterns;
}
}

Ok(expanded_patterns)
}

/// The EditorConfig spec allows for patterns like `**.yml`, which is not supported by biome. This function corrects such patterns so that they can be parsed by biome's glob parser.
fn hack_convert_double_star(pattern: impl AsRef<str>) -> String {
pattern
.as_ref()
.split('/')
.map(|component| {
if component == "**" {
component.to_string()
} else if component.contains("**") {
component.replace("**", "**/*")
} else {
component.to_string()
}
})
.collect::<Vec<_>>()
.join("/")
}

#[cfg(test)]
mod tests {
use super::*;
Expand Down Expand Up @@ -448,64 +286,4 @@ insert_final_newline = unset
EditorconfigValue::Default
));
}

#[test]
fn should_expand_glob_pattern_list() {
let pattern = "package.json";
let mut expanded =
expand_unknown_glob_patterns(pattern).expect("Failed to expand glob pattern");
expanded.sort();
assert_eq!(expanded, ["package.json".into()]);

let pattern = "{package.json,.travis.yml}";
let mut expanded =
expand_unknown_glob_patterns(pattern).expect("Failed to expand glob pattern");
expanded.sort();
assert_eq!(expanded, [".travis.yml".into(), "package.json".into()]);
}

#[test]
fn should_expand_glob_pattern_list_2() {
let pattern = "**/{foo,bar}.{test,spec}.js";
let mut expanded =
expand_unknown_glob_patterns(pattern).expect("Failed to expand glob pattern");
expanded.sort();
assert_eq!(
expanded,
[
"**/bar.spec.js".into(),
"**/bar.test.js".into(),
"**/foo.spec.js".into(),
"**/foo.test.js".into(),
]
);
}

#[test]
fn should_expand_glob_pattern_range() {
let pattern = "**/bar.{1..4}.js";
let mut expanded =
expand_unknown_glob_patterns(pattern).expect("Failed to expand glob pattern");
expanded.sort();
assert_eq!(
expanded,
[
"**/bar.1.js".into(),
"**/bar.2.js".into(),
"**/bar.3.js".into(),
"**/bar.4.js".into()
]
);
}

#[test]
fn should_correct_double_star() {
let pattern = "**.yml";
let corrected = hack_convert_double_star(pattern);
assert_eq!(corrected, "**/*.yml",);

let pattern = "**/*.yml";
let corrected = hack_convert_double_star(pattern);
assert_eq!(corrected, "**/*.yml",);
}
}
4 changes: 2 additions & 2 deletions crates/biome_configuration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -49,8 +49,8 @@ pub use html::{html_configuration, HtmlConfiguration};
pub use javascript::{js_configuration, JsConfiguration};
pub use json::{json_configuration, JsonConfiguration};
pub use overrides::{
OverrideAssistConfiguration, OverrideFormatterConfiguration, OverrideLinterConfiguration,
OverridePattern, Overrides,
OverrideAssistConfiguration, OverrideFormatterConfiguration, OverrideGlobs,
OverrideLinterConfiguration, OverridePattern, Overrides,
};
use plugins::Plugins;
use serde::{Deserialize, Serialize};
Expand Down
Loading

0 comments on commit f83164d

Please sign in to comment.