Skip to content

Commit bbaaaa6

Browse files
committed
perf: only query settings once
1 parent f890861 commit bbaaaa6

4 files changed

Lines changed: 84 additions & 85 deletions

File tree

.changeset/max-managers-mandate.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
---
2+
"@biomejs/biome": patch
3+
---
4+
5+
Fixed an issue with the `files.maxSize` setting. Previously the setting would always be looked up in the root settings, even in monorepos where a closer `biome.json` is available. It now correctly uses the nearest configuration.

crates/biome_service/src/projects.rs

Lines changed: 0 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -327,31 +327,6 @@ impl Projects {
327327

328328
belongs_to_project && !belongs_to_other
329329
}
330-
331-
/// Returns the maximum file size setting for the given project.
332-
pub fn get_max_file_size(&self, project_key: ProjectKey, file_path: &Utf8Path) -> usize {
333-
let limit = self
334-
.0
335-
.pin()
336-
.get(&project_key)
337-
.and_then(|data| {
338-
data.root_settings
339-
.override_settings
340-
.patterns
341-
.iter()
342-
.find_map(|pattern| {
343-
if pattern.is_file_included(file_path) {
344-
pattern.files.max_size
345-
} else {
346-
None
347-
}
348-
})
349-
.or(data.root_settings.files.max_size)
350-
})
351-
.unwrap_or_default();
352-
353-
usize::from(limit)
354-
}
355330
}
356331

357332
#[inline]

crates/biome_service/src/settings.rs

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1162,6 +1162,25 @@ impl Settings {
11621162
.unwrap_or_default()
11631163
.into()
11641164
}
1165+
1166+
/// Returns the maximum file size setting for the given `file_path`.
1167+
pub fn get_max_file_size(&self, file_path: &Utf8Path) -> usize {
1168+
let limit = self
1169+
.override_settings
1170+
.patterns
1171+
.iter()
1172+
.find_map(|pattern| {
1173+
if pattern.is_file_included(file_path) {
1174+
pattern.files.max_size
1175+
} else {
1176+
None
1177+
}
1178+
})
1179+
.or(self.files.max_size)
1180+
.unwrap_or_default();
1181+
1182+
usize::from(limit)
1183+
}
11651184
}
11661185

11671186
#[derive(Clone, Debug, Default)]

crates/biome_service/src/workspace/server.rs

Lines changed: 60 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@ use crate::workspace::document::EmbeddedLanguageSnippets;
1818
use append_only_vec::AppendOnlyVec;
1919
use biome_analyze::{AnalyzerPluginVec, RuleCategory};
2020
use biome_configuration::bool::Bool;
21+
use biome_configuration::max_size::MaxSize;
2122
use biome_configuration::plugins::{PluginConfiguration, Plugins};
2223
use biome_configuration::vcs::VcsClientKind;
2324
use biome_configuration::{BiomeDiagnostic, Configuration, ConfigurationPathHint};
@@ -292,6 +293,11 @@ impl WorkspaceServer {
292293

293294
let mut source = document_file_source.unwrap_or(DocumentFileSource::from_path(&path));
294295

296+
let settings = self
297+
.projects
298+
.get_settings_based_on_path(project_key, &path)
299+
.ok_or_else(WorkspaceError::no_project)?;
300+
295301
if let DocumentFileSource::Js(js) = &mut source {
296302
match path.extension() {
297303
Some("js") => {
@@ -308,10 +314,6 @@ impl WorkspaceServer {
308314
_ => {}
309315
}
310316
if !js.is_typescript() && !js.is_jsx() {
311-
let settings = self
312-
.projects
313-
.get_settings_based_on_path(project_key, &biome_path)
314-
.ok_or_else(WorkspaceError::no_project)?;
315317
let jsx_everywhere = settings
316318
.languages
317319
.javascript
@@ -333,7 +335,7 @@ impl WorkspaceServer {
333335
let mut file_source_index = self.insert_source(source);
334336

335337
let size = content.len();
336-
let limit = self.projects.get_max_file_size(project_key, path.as_path());
338+
let limit = settings.get_max_file_size(&path);
337339

338340
let syntax = if size > limit {
339341
Some(Err(FileTooLarge { size, limit }))
@@ -342,9 +344,9 @@ impl WorkspaceServer {
342344
} else {
343345
let mut node_cache = NodeCache::default();
344346
let parsed = self.parse(
345-
project_key,
346347
&path,
347348
&content,
349+
&settings,
348350
file_source_index,
349351
&mut node_cache,
350352
)?;
@@ -363,19 +365,14 @@ impl WorkspaceServer {
363365
Some(Ok(parsed.any_parse))
364366
};
365367

366-
// Second-pass parsing for HTML files with embedded JavaScript and CSS content
367-
let embedded_snippets = if let Some(DocumentFileSource::Html(_)) =
368-
self.get_source(file_source_index)
369-
&& let Some(Ok(any_parse)) = &syntax
370-
&& let Some(html_root) = biome_html_syntax::HtmlRoot::cast(any_parse.syntax())
371-
{
372-
let mut node_cache = NodeCache::default();
368+
// Second-pass parsing for HTML files with embedded JavaScript and CSS
369+
// content.
370+
let embedded_snippets = if let Some(Ok(parse)) = &syntax {
373371
self.parse_embedded_language_snippets(
374-
project_key,
375372
&biome_path,
376-
&source,
377-
&html_root,
378-
&mut node_cache,
373+
parse,
374+
&settings,
375+
file_source_index,
379376
|file_source| self.insert_source(file_source),
380377
)?
381378
} else {
@@ -502,21 +499,26 @@ impl WorkspaceServer {
502499
/// parsing.
503500
fn parse_embedded_language_snippets(
504501
&self,
505-
project_key: ProjectKey,
506502
path: &BiomePath,
507-
source: &DocumentFileSource,
508-
html_root: &HtmlRoot,
509-
cache: &mut NodeCache,
503+
parse: &AnyParse,
504+
settings: &Settings,
505+
file_source_index: usize,
510506
source_index_fn: impl Fn(DocumentFileSource) -> usize,
511507
) -> Result<EmbeddedLanguageSnippets, WorkspaceError> {
508+
let (source, html_root) = match self.get_source(file_source_index) {
509+
Some(source @ DocumentFileSource::Html(_)) => match HtmlRoot::cast(parse.syntax()) {
510+
Some(html_root) => (source, html_root),
511+
None => return Ok(Default::default()),
512+
},
513+
_ => return Ok(Default::default()),
514+
};
515+
512516
let mut scripts = Vec::new();
513517
let mut json = Vec::new();
514518
let mut styles = Vec::new();
515519

516-
let settings = self
517-
.projects
518-
.get_settings_based_on_path(project_key, path)
519-
.ok_or_else(WorkspaceError::no_project)?;
520+
let mut cache = NodeCache::default();
521+
520522
// Walk through all HTML elements looking for script and style tags
521523
for element in html_root.syntax().descendants() {
522524
let Some(element) = HtmlElement::cast(element) else {
@@ -527,34 +529,36 @@ impl WorkspaceServer {
527529

528530
if let Some(script_type) = element.get_script_type() {
529531
if script_type.is_javascript() {
530-
let options = settings.parse_options::<JsLanguage>(path, source);
532+
let options = settings.parse_options::<JsLanguage>(path, &source);
531533

532534
if let Some(list) = parse_embedded_js_script(
533535
element,
534536
script_type,
535-
cache,
537+
&mut cache,
536538
options,
537539
|file_source| source_index_fn(file_source.into()),
538540
) {
539541
scripts.extend(list)
540542
}
541543
} else if script_type.is_json() {
542-
let options = settings.parse_options::<JsonLanguage>(path, source);
544+
let options = settings.parse_options::<JsonLanguage>(path, &source);
543545

544546
if let Some(list) =
545-
parse_embedded_json(element, cache, options, |file_source| {
547+
parse_embedded_json(element, &mut cache, options, |file_source| {
546548
source_index_fn(file_source.into())
547549
})
548550
{
549551
json.extend(list)
550552
}
551553
}
552554
} else if element.is_style_tag() {
553-
let options = settings.parse_options::<CssLanguage>(path, source);
555+
let options = settings.parse_options::<CssLanguage>(path, &source);
554556

555-
if let Some(list) = parse_embedded_style(element, cache, options, |file_source| {
556-
source_index_fn(file_source.into())
557-
}) {
557+
if let Some(list) =
558+
parse_embedded_style(element, &mut cache, options, |file_source| {
559+
source_index_fn(file_source.into())
560+
})
561+
{
558562
styles.extend(list)
559563
}
560564
}
@@ -569,9 +573,9 @@ impl WorkspaceServer {
569573

570574
fn parse(
571575
&self,
572-
project_key: ProjectKey,
573576
path: &Utf8Path,
574577
content: &str,
578+
settings: &Settings,
575579
file_source_index: usize,
576580
node_cache: &mut NodeCache,
577581
) -> Result<ParseResult, WorkspaceError> {
@@ -585,15 +589,11 @@ impl WorkspaceServer {
585589
.parse
586590
.ok_or_else(self.build_capability_error(path))?;
587591

588-
let settings = self
589-
.projects
590-
.get_settings_based_on_path(project_key, path)
591-
.ok_or_else(WorkspaceError::no_project)?;
592592
let parsed = parse(
593593
&BiomePath::new(path),
594594
file_source,
595595
content,
596-
&settings,
596+
settings,
597597
node_cache,
598598
);
599599
Ok(parsed)
@@ -1254,7 +1254,11 @@ impl Workspace for WorkspaceServer {
12541254
let file_size = document.content.len();
12551255
let limit = self
12561256
.projects
1257-
.get_max_file_size(params.project_key, params.path.as_path());
1257+
.get_settings_based_on_path(params.project_key, &params.path)
1258+
.map_or_else(
1259+
|| MaxSize::default().into(),
1260+
|settings| settings.get_max_file_size(&params.path),
1261+
);
12581262
Ok(CheckFileSizeResult { file_size, limit })
12591263
}
12601264

@@ -1276,11 +1280,17 @@ impl Workspace for WorkspaceServer {
12761280

12771281
if existing_version.is_some_and(|existing_version| existing_version >= version) {
12781282
warn!(%version, %path, "outdated_file_change");
1283+
// Safely ignore older versions.
12791284
return Ok(ChangeFileResult {
1280-
diagnostics: vec![],
1281-
}); // Safely ignore older versions.
1285+
diagnostics: Vec::new(),
1286+
});
12821287
}
12831288

1289+
let settings = self
1290+
.projects
1291+
.get_settings_based_on_path(project_key, &path)
1292+
.ok_or_else(WorkspaceError::no_project)?;
1293+
12841294
// We remove the node cache for the document, if it exists.
12851295
// This is done so that we need to hold the lock as short as possible
12861296
// (it's released directly after the statement). The potential downside
@@ -1293,27 +1303,17 @@ impl Workspace for WorkspaceServer {
12931303
let persist_node_cache = node_cache.is_some();
12941304
let mut node_cache = node_cache.unwrap_or_default();
12951305

1296-
let parsed = self.parse(project_key, &path, &content, index, &mut node_cache)?;
1306+
let parsed = self.parse(&path, &content, &settings, index, &mut node_cache)?;
12971307
let root = parsed.any_parse.root();
12981308

12991309
// Second-pass parsing for HTML files with embedded JavaScript and CSS content
1300-
let embedded_snippets = if let Some(file_source) = self.get_source(index)
1301-
&& matches!(file_source, DocumentFileSource::Html(_))
1302-
&& let Some(html_root) =
1303-
biome_html_syntax::HtmlRoot::cast(parsed.any_parse.syntax().clone())
1304-
{
1305-
let mut embedded_node_cache = NodeCache::default();
1306-
self.parse_embedded_language_snippets(
1307-
project_key,
1308-
&path,
1309-
&file_source,
1310-
&html_root,
1311-
&mut embedded_node_cache,
1312-
|file_source| self.insert_source(file_source),
1313-
)?
1314-
} else {
1315-
Default::default()
1316-
};
1310+
let embedded_snippets = self.parse_embedded_language_snippets(
1311+
&path,
1312+
&parsed.any_parse,
1313+
&settings,
1314+
index,
1315+
|file_source| self.insert_source(file_source),
1316+
)?;
13171317

13181318
let document = Document {
13191319
content,

0 commit comments

Comments
 (0)