Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
7 changes: 7 additions & 0 deletions .changeset/fix-monorepo-glob-resolution.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
---
"@biomejs/biome": patch
---

Fixed [#8518](https://github.com/biomejs/biome/issues/8518), where globally excluded files in a monorepo were still being processed when using `"extends": "//"`.

When a package-level configuration extends the root configuration with `"extends": "//"`, glob patterns (such as those in `files.includes`) are now correctly resolved relative to the project root directory, instead of the current workspace directory.
10 changes: 8 additions & 2 deletions crates/biome_service/src/workspace/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1074,6 +1074,7 @@ impl Workspace for WorkspaceServer {
let mut diagnostics: Vec<biome_diagnostics::serde::Diagnostic> = vec![];
let workspace_directory = workspace_directory.map(|p| p.to_path_buf());
let is_root = configuration.is_root();
let extends_root = configuration.extends_root();
let mut settings = if !is_root {
if !self.projects.is_project_registered(project_key) {
return Err(WorkspaceError::no_project());
Expand All @@ -1092,17 +1093,22 @@ impl Workspace for WorkspaceServer {
.ok_or_else(WorkspaceError::no_project)?
};

let resolution_directory = if extends_root {
self.projects.get_project_path(project_key)
} else {
workspace_directory.clone()
};
settings.merge_with_configuration(
configuration,
workspace_directory.clone(),
resolution_directory.clone(),
extended_configurations
.into_iter()
.map(|(path, config)| (path.into(), config))
.collect(),
)?;

let plugin_diagnostics = self.load_plugins(
&workspace_directory.clone().unwrap_or_default(),
&resolution_directory.clone().unwrap_or_default(),
&settings.as_all_plugins(),
);

Expand Down
67 changes: 67 additions & 0 deletions crates/biome_service/src/workspace/server.tests.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,10 @@ use biome_configuration::{
FormatterConfiguration, JsConfiguration,
javascript::{JsFormatterConfiguration, JsParserConfiguration},
};
use biome_deserialize::json::deserialize_from_json_str;
use biome_formatter::{IndentStyle, LineWidth};
use biome_fs::MemoryFileSystem;
use biome_json_parser::JsonParserOptions;
use biome_rowan::TextSize;

use crate::test_utils::setup_workspace_and_open_project;
Expand Down Expand Up @@ -471,3 +473,68 @@ fn pull_diagnostics_and_actions_for_js_file() {

insta::assert_debug_snapshot!(result)
}

#[test]
fn extends_root_resolves_globs_from_project_root() {
const NESTED_CONFIGURATION: &str = r#"
{
"extends": "//",
"files": {
"includes": ["./packages/pkg-a/src/**"]
}
}
"#;

let fs = MemoryFileSystem::default();
fs.insert(
Utf8PathBuf::from("/project/packages/pkg-a/src/index.ts"),
b"const a = 1;",
);
fs.insert(
Utf8PathBuf::from("/project/packages/pkg-a/tests/index.ts"),
b"const a = 1;",
);

let (workspace, project_key) = setup_workspace_and_open_project(fs, "/project");

let configuration = deserialize_from_json_str::<Configuration>(
NESTED_CONFIGURATION,
JsonParserOptions::default().with_allow_comments(),
"biome.jsonc",
)
.into_deserialized()
.expect("valid nested config");

workspace
.update_settings(UpdateSettingsParams {
project_key,
configuration,
workspace_directory: Some(BiomePath::new("/project/packages/pkg-a")),
extended_configurations: Default::default(),
})
.unwrap();

let src_is_ignored = workspace
.is_path_ignored(PathIsIgnoredParams {
project_key,
path: BiomePath::new("/project/packages/pkg-a/src/index.ts"),
features: FeatureName::empty(),
ignore_kind: IgnoreKind::Path,
})
.unwrap();

let tests_is_ignored = workspace
.is_path_ignored(PathIsIgnoredParams {
project_key,
path: BiomePath::new("/project/packages/pkg-a/tests/index.ts"),
features: FeatureName::empty(),
ignore_kind: IgnoreKind::Path,
})
.unwrap();

assert!(
!src_is_ignored,
"src file should be included when glob is resolved from project root"
);
assert!(tests_is_ignored, "file outside includes should be ignored");
}
Loading