Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 238b183

Browse files
committed
refactor(linter): use fast-glob instead of globset for GlobSet (#12870)
closes #12825
1 parent ed40581 commit 238b183

File tree

8 files changed

+52
-89
lines changed

8 files changed

+52
-89
lines changed

Cargo.lock

Lines changed: 0 additions & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -191,7 +191,6 @@ fast-glob = "1.0.0"
191191
fixedbitset = "0.5.7"
192192
flate2 = "1.1.2"
193193
futures = "0.3.31"
194-
globset = "0.4.16"
195194
handlebars = "6.3.2"
196195
hashbrown = { version = "0.15.4", default-features = false }
197196
humansize = "2.1.3"

crates/oxc_linter/Cargo.toml

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,6 @@ constcat = { workspace = true }
5252
convert_case = { workspace = true }
5353
cow-utils = { workspace = true }
5454
fast-glob = { workspace = true }
55-
globset = { workspace = true }
5655
icu_segmenter = { workspace = true }
5756
indexmap = { workspace = true, features = ["rayon"] }
5857
itertools = { workspace = true }

crates/oxc_linter/src/config/config_store.rs

Lines changed: 18 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -144,8 +144,9 @@ impl Config {
144144
})
145145
.unwrap_or(path);
146146

147+
let path = relative_path.to_string_lossy();
147148
let overrides_to_apply =
148-
self.overrides.iter().filter(|config| config.files.is_match(relative_path));
149+
self.overrides.iter().filter(|config| config.files.is_match(path.as_ref()));
149150

150151
let mut overrides_to_apply = overrides_to_apply.peekable();
151152

@@ -373,7 +374,7 @@ mod test {
373374
let base_rules = vec![no_explicit_any()];
374375
let overrides = ResolvedOxlintOverrides::new(vec![ResolvedOxlintOverride {
375376
env: None,
376-
files: GlobSet::new(vec!["*.test.{ts,tsx}"]).unwrap(),
377+
files: GlobSet::new(vec!["*.test.{ts,tsx}"]),
377378
plugins: None,
378379
globals: None,
379380
rules: ResolvedOxlintOverrideRules { builtin_rules: vec![], external_rules: vec![] },
@@ -404,7 +405,7 @@ mod test {
404405
let base_rules = vec![no_explicit_any()];
405406
let overrides = ResolvedOxlintOverrides::new(vec![ResolvedOxlintOverride {
406407
env: None,
407-
files: GlobSet::new(vec!["*.test.{ts,tsx}"]).unwrap(),
408+
files: GlobSet::new(vec!["*.test.{ts,tsx}"]),
408409
plugins: Some(LintPlugins::new(
409410
BuiltinLintPlugins::REACT
410411
.union(BuiltinLintPlugins::TYPESCRIPT)
@@ -441,7 +442,7 @@ mod test {
441442
let base_rules = vec![no_explicit_any()];
442443
let overrides = ResolvedOxlintOverrides::new(vec![ResolvedOxlintOverride {
443444
env: None,
444-
files: GlobSet::new(vec!["*.test.{ts,tsx}"]).unwrap(),
445+
files: GlobSet::new(vec!["*.test.{ts,tsx}"]),
445446
plugins: None,
446447
globals: None,
447448
rules: ResolvedOxlintOverrideRules {
@@ -478,7 +479,7 @@ mod test {
478479
let base_rules = vec![no_explicit_any()];
479480
let overrides = ResolvedOxlintOverrides::new(vec![ResolvedOxlintOverride {
480481
env: None,
481-
files: GlobSet::new(vec!["src/**/*.{ts,tsx}"]).unwrap(),
482+
files: GlobSet::new(vec!["src/**/*.{ts,tsx}"]),
482483
plugins: None,
483484
globals: None,
484485
rules: ResolvedOxlintOverrideRules {
@@ -515,7 +516,7 @@ mod test {
515516
let base_rules = vec![no_explicit_any()];
516517
let overrides = ResolvedOxlintOverrides::new(vec![ResolvedOxlintOverride {
517518
env: None,
518-
files: GlobSet::new(vec!["src/**/*.{ts,tsx}"]).unwrap(),
519+
files: GlobSet::new(vec!["src/**/*.{ts,tsx}"]),
519520
plugins: None,
520521
globals: None,
521522
rules: ResolvedOxlintOverrideRules {
@@ -561,7 +562,7 @@ mod test {
561562
let overrides = ResolvedOxlintOverrides::new(vec![
562563
ResolvedOxlintOverride {
563564
env: None,
564-
files: GlobSet::new(vec!["*.jsx", "*.tsx"]).unwrap(),
565+
files: GlobSet::new(vec!["*.jsx", "*.tsx"]),
565566
plugins: Some(LintPlugins::new(BuiltinLintPlugins::REACT, FxHashSet::default())),
566567
globals: None,
567568
rules: ResolvedOxlintOverrideRules {
@@ -571,7 +572,7 @@ mod test {
571572
},
572573
ResolvedOxlintOverride {
573574
env: None,
574-
files: GlobSet::new(vec!["*.ts", "*.tsx"]).unwrap(),
575+
files: GlobSet::new(vec!["*.ts", "*.tsx"]),
575576
plugins: Some(LintPlugins::new(
576577
BuiltinLintPlugins::TYPESCRIPT,
577578
FxHashSet::default(),
@@ -622,7 +623,7 @@ mod test {
622623
};
623624
let overrides = ResolvedOxlintOverrides::new(vec![ResolvedOxlintOverride {
624625
env: Some(OxlintEnv::from_iter(["es2024".to_string()])),
625-
files: GlobSet::new(vec!["*.tsx"]).unwrap(),
626+
files: GlobSet::new(vec!["*.tsx"]),
626627
plugins: None,
627628
globals: None,
628629
rules: ResolvedOxlintOverrideRules { builtin_rules: vec![], external_rules: vec![] },
@@ -649,7 +650,7 @@ mod test {
649650
path: None,
650651
};
651652
let overrides = ResolvedOxlintOverrides::new(vec![ResolvedOxlintOverride {
652-
files: GlobSet::new(vec!["*.tsx"]).unwrap(),
653+
files: GlobSet::new(vec!["*.tsx"]),
653654
env: Some(from_json!({ "es2024": false })),
654655
plugins: None,
655656
globals: None,
@@ -678,7 +679,7 @@ mod test {
678679
};
679680

680681
let overrides = ResolvedOxlintOverrides::new(vec![ResolvedOxlintOverride {
681-
files: GlobSet::new(vec!["*.tsx"]).unwrap(),
682+
files: GlobSet::new(vec!["*.tsx"]),
682683
env: None,
683684
plugins: None,
684685
globals: Some(from_json!({ "React": "readonly", "Secret": "writeable" })),
@@ -712,7 +713,7 @@ mod test {
712713
};
713714

714715
let overrides = ResolvedOxlintOverrides::new(vec![ResolvedOxlintOverride {
715-
files: GlobSet::new(vec!["*.tsx"]).unwrap(),
716+
files: GlobSet::new(vec!["*.tsx"]),
716717
env: None,
717718
plugins: None,
718719
globals: Some(from_json!({ "React": "off", "Secret": "off" })),
@@ -761,7 +762,7 @@ mod test {
761762
// First override: typescript plugin for *.{ts,tsx,mts}
762763
ResolvedOxlintOverride {
763764
env: None,
764-
files: GlobSet::new(vec!["*.{ts,tsx,mts}"]).unwrap(),
765+
files: GlobSet::new(vec!["*.{ts,tsx,mts}"]),
765766
plugins: Some(LintPlugins::new(
766767
BuiltinLintPlugins::TYPESCRIPT,
767768
FxHashSet::default(),
@@ -775,7 +776,7 @@ mod test {
775776
// Second override: react plugin for *.{ts,tsx} with jsx-filename-extension turned off
776777
ResolvedOxlintOverride {
777778
env: None,
778-
files: GlobSet::new(vec!["*.{ts,tsx}"]).unwrap(),
779+
files: GlobSet::new(vec!["*.{ts,tsx}"]),
779780
plugins: Some(LintPlugins::new(BuiltinLintPlugins::REACT, FxHashSet::default())),
780781
globals: None,
781782
rules: ResolvedOxlintOverrideRules {
@@ -789,7 +790,7 @@ mod test {
789790
// Third override: unicorn plugin for *.{ts,tsx,mts}
790791
ResolvedOxlintOverride {
791792
env: None,
792-
files: GlobSet::new(vec!["*.{ts,tsx,mts}"]).unwrap(),
793+
files: GlobSet::new(vec!["*.{ts,tsx,mts}"]),
793794
plugins: Some(LintPlugins::new(BuiltinLintPlugins::UNICORN, FxHashSet::default())),
794795
globals: None,
795796
rules: ResolvedOxlintOverrideRules {
@@ -849,7 +850,7 @@ mod test {
849850
// Override adds react plugin (new plugin not in root)
850851
let overrides = ResolvedOxlintOverrides::new(vec![ResolvedOxlintOverride {
851852
env: None,
852-
files: GlobSet::new(vec!["*.tsx"]).unwrap(),
853+
files: GlobSet::new(vec!["*.tsx"]),
853854
plugins: Some(LintPlugins::new(BuiltinLintPlugins::REACT, FxHashSet::default())),
854855
globals: None,
855856
rules: ResolvedOxlintOverrideRules { builtin_rules: vec![], external_rules: vec![] },
@@ -897,7 +898,7 @@ mod test {
897898
// Override adds typescript plugin
898899
let overrides = ResolvedOxlintOverrides::new(vec![ResolvedOxlintOverride {
899900
env: None,
900-
files: GlobSet::new(vec!["*.tsx"]).unwrap(),
901+
files: GlobSet::new(vec!["*.tsx"]),
901902
plugins: Some(LintPlugins::new(BuiltinLintPlugins::TYPESCRIPT, FxHashSet::default())),
902903
globals: None,
903904
rules: ResolvedOxlintOverrideRules { builtin_rules: vec![], external_rules: vec![] },

crates/oxc_linter/src/config/overrides.rs

Lines changed: 31 additions & 68 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,10 @@
11
use std::{
22
borrow::Cow,
33
ops::{Deref, DerefMut},
4-
path::Path,
54
};
65

76
use schemars::{JsonSchema, r#gen, schema::Schema};
8-
use serde::{Deserialize, Deserializer, Serialize, Serializer, de};
7+
use serde::{Deserialize, Deserializer, Serialize};
98

109
use crate::{LintPlugins, OxlintEnv, OxlintGlobals, config::OxlintRules};
1110

@@ -97,74 +96,38 @@ pub struct OxlintOverride {
9796
pub rules: OxlintRules,
9897
}
9998

100-
/// A glob pattern.
101-
///
102-
/// Thin wrapper around [`globset::GlobSet`] because that struct doesn't implement Serialize or schemars
103-
/// traits.
104-
#[derive(Clone, Default)]
105-
pub struct GlobSet {
106-
/// Raw patterns from the config. Inefficient, but required for [serialization](Serialize),
107-
/// which in turn is required for `--print-config`.
108-
raw: Vec<String>,
109-
globs: globset::GlobSet,
110-
}
111-
112-
impl GlobSet {
113-
pub fn new<S: AsRef<str>, I: IntoIterator<Item = S>>(
114-
patterns: I,
115-
) -> Result<Self, globset::Error> {
116-
let patterns = patterns.into_iter();
117-
let size_hint = patterns.size_hint();
118-
119-
let mut builder = globset::GlobSetBuilder::new();
120-
let mut raw = Vec::with_capacity(size_hint.1.unwrap_or(size_hint.0));
121-
122-
for pattern in patterns {
123-
let pattern = pattern.as_ref();
124-
let glob = globset::Glob::new(pattern)?;
125-
builder.add(glob);
126-
raw.push(pattern.to_string());
127-
}
128-
129-
let globs = builder.build()?;
130-
Ok(Self { raw, globs })
131-
}
132-
133-
pub fn is_match<P: AsRef<Path>>(&self, path: P) -> bool {
134-
self.globs.is_match(path)
135-
}
136-
}
137-
138-
impl std::fmt::Debug for GlobSet {
139-
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
140-
f.debug_tuple("GlobSet").field(&self.raw).finish()
141-
}
142-
}
143-
144-
impl Serialize for GlobSet {
145-
fn serialize<S: Serializer>(&self, serializer: S) -> Result<S::Ok, S::Error> {
146-
self.raw.serialize(serializer)
147-
}
148-
}
99+
/// A set of glob patterns.
100+
#[derive(Debug, Default, Clone, Serialize, JsonSchema)]
101+
pub struct GlobSet(Vec<String>);
149102

150103
impl<'de> Deserialize<'de> for GlobSet {
151104
fn deserialize<D: Deserializer<'de>>(deserializer: D) -> Result<Self, D::Error> {
152-
let globs = Vec::<String>::deserialize(deserializer)?;
153-
Self::new(globs).map_err(de::Error::custom)
105+
Ok(Self::new(Vec::<String>::deserialize(deserializer)?))
154106
}
155107
}
156108

157-
impl JsonSchema for GlobSet {
158-
fn schema_name() -> String {
159-
Self::schema_id().into()
160-
}
161-
162-
fn schema_id() -> Cow<'static, str> {
163-
Cow::Borrowed("GlobSet")
164-
}
165-
166-
fn json_schema(r#gen: &mut r#gen::SchemaGenerator) -> Schema {
167-
r#gen.subschema_for::<Vec<String>>()
109+
impl GlobSet {
110+
pub fn new<S: AsRef<str>, I: IntoIterator<Item = S>>(patterns: I) -> Self {
111+
Self(
112+
patterns
113+
.into_iter()
114+
.map(|pat| {
115+
let pattern = pat.as_ref();
116+
if pattern.contains('/') {
117+
pattern.to_owned()
118+
} else {
119+
let mut s = String::with_capacity(pattern.len() + 3);
120+
s.push_str("**/");
121+
s.push_str(pattern);
122+
s
123+
}
124+
})
125+
.collect::<Vec<_>>(),
126+
)
127+
}
128+
129+
pub fn is_match(&self, path: &str) -> bool {
130+
self.0.iter().any(|glob| fast_glob::glob_match(glob, path))
168131
}
169132
}
170133

@@ -182,15 +145,15 @@ mod test {
182145
"files": ["*.tsx",],
183146
}))
184147
.unwrap();
185-
assert!(config.files.globs.is_match("/some/path/foo.tsx"));
186-
assert!(!config.files.globs.is_match("/some/path/foo.ts"));
148+
assert!(config.files.is_match("/some/path/foo.tsx"));
149+
assert!(!config.files.is_match("/some/path/foo.ts"));
187150

188151
let config: OxlintOverride = from_value(json!({
189152
"files": ["lib/*.ts",],
190153
}))
191154
.unwrap();
192-
assert!(config.files.globs.is_match("lib/foo.ts"));
193-
assert!(!config.files.globs.is_match("src/foo.ts"));
155+
assert!(config.files.is_match("lib/foo.ts"));
156+
assert!(!config.files.is_match("src/foo.ts"));
194157
}
195158

196159
#[test]

crates/oxc_linter/src/snapshots/schema_json.snap

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -193,6 +193,7 @@ expression: json
193193
}
194194
},
195195
"GlobSet": {
196+
"description": "A set of glob patterns.",
196197
"type": "array",
197198
"items": {
198199
"type": "string"

npm/oxlint/configuration_schema.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -189,6 +189,7 @@
189189
}
190190
},
191191
"GlobSet": {
192+
"description": "A set of glob patterns.",
192193
"type": "array",
193194
"items": {
194195
"type": "string"

tasks/website/src/linter/snapshots/schema_markdown.snap

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ type: `object`
214214
type: `string[]`
215215

216216

217-
217+
A set of glob patterns.
218218

219219

220220
#### overrides[n].rules

0 commit comments

Comments
 (0)