Skip to content

Commit 0be4120

Browse files
committed
fix: resolve root biome.json when workspace is a non-root package
1 parent ab7bb22 commit 0be4120

File tree

1 file changed

+53
-1
lines changed

1 file changed

+53
-1
lines changed

src/biome.rs

Lines changed: 53 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -116,6 +116,58 @@ impl BiomeExtension {
116116
None
117117
}
118118

119+
// Mirrors biome's Configuration::is_root() logic:
120+
// - explicit "root": true → root
121+
// - explicit "root": false → not root
122+
// - "extends": "//" implies "root": false (the "root" field may be omitted)
123+
// - no "root" field, no "extends": "//" → root (implicit default)
124+
fn config_is_root(json: &Value) -> bool {
125+
if let Some(root) = json.get("root").and_then(|v| v.as_bool()) {
126+
return root;
127+
}
128+
let extends_root = json.get("extends").and_then(|v| v.as_str()) == Some("//");
129+
!extends_root
130+
}
131+
132+
// Returns the directory to use as configurationPath for the biome LSP.
133+
// If the found config is not a root config, traverses parent directories to
134+
// find the nearest ancestor config that is a root config.
135+
fn find_root_config_dir(
136+
&self,
137+
worktree: &zed::Worktree,
138+
config_relative_path: &str,
139+
) -> Option<PathBuf> {
140+
let content = worktree.read_text_file(config_relative_path).ok()?;
141+
let json: Value = serde_json::from_str(&content).ok()?;
142+
143+
if Self::config_is_root(&json) {
144+
return Path::new(&worktree.root_path())
145+
.join(config_relative_path)
146+
.parent()
147+
.map(|p| p.to_path_buf());
148+
}
149+
150+
// Not a root config — traverse parent directories to find the root config
151+
let mut current = Path::new(&worktree.root_path())
152+
.parent()
153+
.map(|p| p.to_path_buf());
154+
while let Some(dir) = current {
155+
for config_name in BIOME_CONFIG_PATHS {
156+
let candidate = dir.join(config_name);
157+
if let Ok(content) = std::fs::read_to_string(&candidate) {
158+
if let Ok(json) = serde_json::from_str::<Value>(&content) {
159+
if Self::config_is_root(&json) {
160+
return Some(dir);
161+
}
162+
}
163+
}
164+
}
165+
current = dir.parent().map(|p| p.to_path_buf());
166+
}
167+
168+
None
169+
}
170+
119171
fn require_config_file(&self, settings: &Value) -> bool {
120172
settings
121173
.get("require_config_file")
@@ -206,7 +258,7 @@ impl zed::Extension for BiomeExtension {
206258

207259
let config_path = self
208260
.config_path(worktree, &settings)
209-
.map(|p| Path::new(&worktree.root_path()).join(p));
261+
.and_then(|p| self.find_root_config_dir(worktree, &p));
210262

211263
Ok(Some(serde_json::json!({
212264
"biome": {

0 commit comments

Comments
 (0)