Skip to content

Commit de98918

Browse files
authored
feat: add plugins to override config (#6117)
1 parent 3b9c4cf commit de98918

File tree

14 files changed

+400
-20
lines changed

14 files changed

+400
-20
lines changed

Cargo.lock

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

crates/biome_configuration/src/overrides.rs

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@ use crate::analyzer::{LinterEnabled, RuleDomains};
33
use crate::formatter::{FormatWithErrorsEnabled, FormatterEnabled};
44
use crate::html::HtmlConfiguration;
55
use crate::max_size::MaxSize;
6+
use crate::plugins::Plugins;
67
use crate::{
78
CssConfiguration, GraphqlConfiguration, GritConfiguration, JsConfiguration, JsonConfiguration,
89
Rules,
@@ -68,6 +69,10 @@ pub struct OverridePattern {
6869
/// Specific configuration for the filesystem
6970
#[serde(skip_serializing_if = "Option::is_none")]
7071
pub files: Option<OverrideFilesConfiguration>,
72+
73+
/// Specific configuration for additional plugins
74+
#[serde(skip_serializing_if = "Option::is_none")]
75+
pub plugins: Option<Plugins>,
7176
}
7277

7378
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]

crates/biome_configuration/src/plugins.rs

Lines changed: 19 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,10 @@ use biome_deserialize::{
33
};
44
use biome_deserialize_macros::{Deserializable, Merge};
55
use serde::{Deserialize, Serialize};
6-
use std::str::FromStr;
6+
use std::{
7+
ops::{Deref, DerefMut},
8+
str::FromStr,
9+
};
710

811
#[derive(Clone, Debug, Default, Deserialize, Deserializable, Eq, Merge, PartialEq, Serialize)]
912
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
@@ -12,7 +15,7 @@ pub struct Plugins(pub Vec<PluginConfiguration>);
1215

1316
impl Plugins {
1417
pub fn iter(&self) -> impl Iterator<Item = &PluginConfiguration> {
15-
self.0.iter()
18+
self.deref().iter()
1619
}
1720
}
1821

@@ -24,6 +27,20 @@ impl FromStr for Plugins {
2427
}
2528
}
2629

30+
impl Deref for Plugins {
31+
type Target = Vec<PluginConfiguration>;
32+
33+
fn deref(&self) -> &Self::Target {
34+
&self.0
35+
}
36+
}
37+
38+
impl DerefMut for Plugins {
39+
fn deref_mut(&mut self) -> &mut Self::Target {
40+
&mut self.0
41+
}
42+
}
43+
2744
#[derive(Clone, Debug, Deserialize, Eq, PartialEq, Serialize)]
2845
#[cfg_attr(feature = "schema", derive(schemars::JsonSchema))]
2946
#[serde(rename_all = "camelCase", deny_unknown_fields, untagged)]

crates/biome_configuration/tests/invalid/overrides/incorrect_key.json.snap

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
---
22
source: crates/biome_configuration/tests/spec_tests.rs
3+
assertion_line: 58
34
expression: incorrect_key.json
45
---
56
incorrect_key.json:4:4 deserialize ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
@@ -26,3 +27,4 @@ incorrect_key.json:4:4 deserialize ━━━━━━━━━━━━━━━
2627
- linter
2728
- assist
2829
- files
30+
- plugins

crates/biome_plugin_loader/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@ version = "0.0.1"
1212

1313
[dependencies]
1414
biome_analyze = { workspace = true }
15+
biome_configuration = { workspace = true }
1516
biome_console = { workspace = true }
1617
biome_deserialize = { workspace = true }
1718
biome_deserialize_macros = { workspace = true }

crates/biome_plugin_loader/src/diagnostics.rs

Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@ pub enum PluginDiagnostic {
3333

3434
/// When an analyzer rule plugin uses an unsupported file format.
3535
UnsupportedRuleFormat(UnsupportedRuleFormat),
36+
37+
/// When plugin is requested but not loaded
38+
NotLoaded(NotLoaded),
3639
}
3740

3841
impl From<CompileError> for PluginDiagnostic {
@@ -88,6 +91,18 @@ impl PluginDiagnostic {
8891
message: MessageAndDescription::from(markup! {{message}}.to_owned()),
8992
})
9093
}
94+
95+
pub fn not_loaded(path: Utf8PathBuf) -> Self {
96+
Self::NotLoaded(NotLoaded {
97+
message: MessageAndDescription::from(
98+
markup! {
99+
"Plugin is requested but not loaded: "
100+
<Emphasis>{path.to_string()}</Emphasis>
101+
}
102+
.to_owned(),
103+
),
104+
})
105+
}
91106
}
92107

93108
impl Debug for PluginDiagnostic {
@@ -161,6 +176,17 @@ pub struct UnsupportedRuleFormat {
161176
pub message: MessageAndDescription,
162177
}
163178

179+
#[derive(Debug, Serialize, Deserialize, Diagnostic)]
180+
#[diagnostic(
181+
category = "plugin",
182+
severity = Error,
183+
)]
184+
pub struct NotLoaded {
185+
#[message]
186+
#[description]
187+
pub message: MessageAndDescription,
188+
}
189+
164190
#[cfg(test)]
165191
mod test {
166192
use crate::plugin_manifest::PluginManifest;
Lines changed: 35 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
use biome_analyze::AnalyzerPluginVec;
2+
use biome_configuration::plugins::{PluginConfiguration, Plugins};
23
use camino::Utf8PathBuf;
34
use papaya::HashMap;
4-
use rustc_hash::FxBuildHasher;
5+
use rustc_hash::{FxBuildHasher, FxHashSet};
56

6-
use crate::BiomePlugin;
7+
use crate::{BiomePlugin, PluginDiagnostic};
78

89
/// Cache for storing loaded plugins in memory.
910
///
@@ -18,12 +19,38 @@ impl PluginCache {
1819
self.0.pin().insert(path, plugin);
1920
}
2021

21-
/// Returns the loaded analyzer plugins.
22-
pub fn get_analyzer_plugins(&self) -> AnalyzerPluginVec {
23-
let mut plugins = AnalyzerPluginVec::new();
24-
for plugin in self.0.pin().values() {
25-
plugins.extend_from_slice(&plugin.analyzer_plugins);
22+
/// Returns the loaded and matched analyzer plugins, deduped
23+
pub fn get_analyzer_plugins(
24+
&self,
25+
plugin_configs: &Plugins,
26+
) -> Result<AnalyzerPluginVec, Vec<PluginDiagnostic>> {
27+
let mut result = AnalyzerPluginVec::new();
28+
let mut seen = FxHashSet::default();
29+
let mut diagnostics: Vec<PluginDiagnostic> = Vec::new();
30+
31+
let map = self.0.pin();
32+
for plugin_config in plugin_configs.iter() {
33+
match plugin_config {
34+
PluginConfiguration::Path(plugin_path) => {
35+
if seen.insert(plugin_path) {
36+
let path_buf = Utf8PathBuf::from(plugin_path);
37+
match map.get(path_buf.as_path()) {
38+
Some(plugin) => {
39+
result.extend_from_slice(&plugin.analyzer_plugins);
40+
}
41+
None => {
42+
diagnostics.push(PluginDiagnostic::not_loaded(path_buf));
43+
}
44+
}
45+
}
46+
}
47+
}
48+
}
49+
50+
if !diagnostics.is_empty() {
51+
return Err(diagnostics);
2652
}
27-
plugins
53+
54+
Ok(result)
2855
}
2956
}

crates/biome_service/src/settings.rs

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -220,6 +220,37 @@ impl Settings {
220220
result
221221
}
222222

223+
/// Returns the plugins that should be enabled for the given `path`, taking overrides into account.
224+
pub fn get_plugins_for_path(&self, path: &Utf8Path) -> Cow<Plugins> {
225+
let mut result = Cow::Borrowed(&self.plugins);
226+
227+
for pattern in &self.override_settings.patterns {
228+
if pattern.is_file_included(path) {
229+
result.to_mut().extend_from_slice(&pattern.plugins);
230+
}
231+
}
232+
233+
result
234+
}
235+
236+
/// Return all plugins configured in setting
237+
pub fn as_all_plugins(&self) -> Cow<Plugins> {
238+
let mut result = Cow::Borrowed(&self.plugins);
239+
240+
let all_override_plugins = self
241+
.override_settings
242+
.patterns
243+
.iter()
244+
.flat_map(|pattern| pattern.plugins.iter().cloned())
245+
.collect::<Vec<_>>();
246+
247+
if !all_override_plugins.is_empty() {
248+
result.to_mut().0.extend(all_override_plugins);
249+
}
250+
251+
result
252+
}
253+
223254
pub fn is_formatter_enabled(&self) -> bool {
224255
self.formatter.is_enabled()
225256
}
@@ -1240,6 +1271,8 @@ pub struct OverrideSettingPattern {
12401271
pub languages: LanguageListSettings,
12411272
/// Files specific settings
12421273
pub files: OverrideFilesSettings,
1274+
/// Additional plugins to be applied
1275+
pub plugins: Plugins,
12431276
}
12441277

12451278
impl OverrideSettingPattern {
@@ -1516,6 +1549,7 @@ pub fn to_override_settings(
15161549
actions: assist.actions,
15171550
})
15181551
.unwrap_or_default();
1552+
let plugins = pattern.plugins.unwrap_or_default();
15191553

15201554
let files = pattern
15211555
.files
@@ -1549,6 +1583,7 @@ pub fn to_override_settings(
15491583
assist,
15501584
languages,
15511585
files,
1586+
plugins,
15521587
};
15531588

15541589
override_settings.patterns.push(pattern_setting);
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
---
2+
source: crates/biome_service/src/workspace.tests.rs
3+
expression: plugin_diagnostics
4+
---
5+
[
6+
Diagnostic {
7+
category: Some(
8+
Category {
9+
name: "plugin",
10+
link: None,
11+
},
12+
),
13+
severity: Error,
14+
description: "Prefer object spread instead of `Object.assign()`",
15+
message: "Prefer object spread instead of `Object.assign()`",
16+
advices: Advices {
17+
advices: [],
18+
},
19+
verbose_advices: Advices {
20+
advices: [],
21+
},
22+
location: Location {
23+
path: Some(
24+
File(
25+
"/project/a.ts",
26+
),
27+
),
28+
span: Some(
29+
25..39,
30+
),
31+
source_code: None,
32+
},
33+
tags: DiagnosticTags(
34+
BitFlags<DiagnosticTag> {
35+
bits: 0b0,
36+
},
37+
),
38+
source: None,
39+
},
40+
]
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
---
2+
source: crates/biome_service/src/workspace.tests.rs
3+
expression: plugin_diagnostics
4+
---
5+
[
6+
Diagnostic {
7+
category: Some(
8+
Category {
9+
name: "plugin",
10+
link: None,
11+
},
12+
),
13+
severity: Error,
14+
description: "Prefer object spread instead of `Object.assign()`",
15+
message: "Prefer object spread instead of `Object.assign()`",
16+
advices: Advices {
17+
advices: [],
18+
},
19+
verbose_advices: Advices {
20+
advices: [],
21+
},
22+
location: Location {
23+
path: Some(
24+
File(
25+
"/project/lib/b.ts",
26+
),
27+
),
28+
span: Some(
29+
25..39,
30+
),
31+
source_code: None,
32+
},
33+
tags: DiagnosticTags(
34+
BitFlags<DiagnosticTag> {
35+
bits: 0b0,
36+
},
37+
),
38+
source: None,
39+
},
40+
Diagnostic {
41+
category: Some(
42+
Category {
43+
name: "plugin",
44+
link: None,
45+
},
46+
),
47+
severity: Error,
48+
description: "Consider using `for...in` loop instead of `Object.keys()` for simple object iteration.",
49+
message: "Consider using `for...in` loop instead of `Object.keys()` for simple object iteration.",
50+
advices: Advices {
51+
advices: [],
52+
},
53+
verbose_advices: Advices {
54+
advices: [],
55+
},
56+
location: Location {
57+
path: Some(
58+
File(
59+
"/project/lib/b.ts",
60+
),
61+
),
62+
span: Some(
63+
67..81,
64+
),
65+
source_code: None,
66+
},
67+
tags: DiagnosticTags(
68+
BitFlags<DiagnosticTag> {
69+
bits: 0b0,
70+
},
71+
),
72+
source: None,
73+
},
74+
]

0 commit comments

Comments
 (0)