Skip to content

Commit 00e1a6b

Browse files
fix(lsp): project loading (#7418)
Co-authored-by: coderabbitai[bot] <136622811+coderabbitai[bot]@users.noreply.github.com>
1 parent 576baf4 commit 00e1a6b

File tree

5 files changed

+187
-52
lines changed

5 files changed

+187
-52
lines changed

.changeset/rich-beds-clap.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 [#7411](https://github.com/biomejs/biome/issues/7411). The Biome Language Server had a regression where opening an editor with a file already open wouldn't load the project settings correctly.

crates/biome_configuration/src/lib.rs

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -605,7 +605,7 @@ pub struct ConfigurationPayload {
605605
pub external_resolution_base_path: Utf8PathBuf,
606606
}
607607

608-
#[derive(Debug, Default, PartialEq, Clone)]
608+
#[derive(Debug, Default, PartialEq, Clone, Eq, Hash)]
609609
pub enum ConfigurationPathHint {
610610
/// The default mode, not having a configuration file is not an error.
611611
/// The path will be filled with the working directory if it is not filled at the time of usage.
@@ -651,4 +651,13 @@ impl ConfigurationPathHint {
651651
pub const fn is_from_lsp(&self) -> bool {
652652
matches!(self, Self::FromLsp(_))
653653
}
654+
655+
pub fn to_path_buf(&self) -> Option<Utf8PathBuf> {
656+
match self {
657+
Self::None => None,
658+
Self::FromWorkspace(path) | Self::FromLsp(path) | Self::FromUser(path) => {
659+
Some(path.to_path_buf())
660+
}
661+
}
662+
}
654663
}

crates/biome_lsp/src/handlers/text_document.rs

Lines changed: 67 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,16 @@
1-
use std::sync::Arc;
2-
31
use crate::diagnostics::LspError;
2+
use crate::session::ConfigurationStatus;
43
use crate::utils::apply_document_changes;
54
use crate::{documents::Document, session::Session};
5+
use biome_configuration::ConfigurationPathHint;
66
use biome_service::workspace::{
77
ChangeFileParams, CloseFileParams, DocumentFileSource, FeaturesBuilder, FileContent,
88
GetFileContentParams, IgnoreKind, OpenFileParams, PathIsIgnoredParams,
99
};
10-
use tower_lsp_server::lsp_types;
11-
use tower_lsp_server::lsp_types::MessageType;
12-
use tracing::{debug, error, field};
10+
use camino::Utf8PathBuf;
11+
use std::sync::Arc;
12+
use tower_lsp_server::{UriExt, lsp_types};
13+
use tracing::{debug, error, field, info};
1314

1415
/// Handler for `textDocument/didOpen` LSP notification
1516
#[tracing::instrument(
@@ -31,22 +32,71 @@ pub(crate) async fn did_open(
3132

3233
let path = session.file_path(&url)?;
3334

34-
let status = session.configuration_status();
35+
eprintln!("Session id {:?}", session.key);
36+
let project_key = match session.project_for_path(&path) {
37+
Some(project_key) => project_key,
38+
None => {
39+
info!("No open project for path: {path:?}. Opening new project.");
40+
41+
let project_path = path
42+
.parent()
43+
.map(|parent| parent.to_path_buf())
44+
.unwrap_or_default();
45+
46+
// First check if the current file belongs to any registered workspace folder.
47+
// If so, return that folder; otherwise, use the folder computed by did_open.
48+
let project_path = if let Some(workspace_folders) = session.get_workspace_folders() {
49+
if let Some(ws_root) = workspace_folders
50+
.iter()
51+
.filter_map(|folder| {
52+
folder.uri.to_file_path().map(|p| {
53+
Utf8PathBuf::from_path_buf(p.to_path_buf())
54+
.expect("To have a valid UTF-8 path")
55+
})
56+
})
57+
.find(|ws| project_path.starts_with(ws))
58+
{
59+
ws_root
60+
} else {
61+
project_path.clone()
62+
}
63+
} else if let Some(base_path) = session.base_path() {
64+
if project_path.starts_with(&base_path) {
65+
base_path
66+
} else {
67+
project_path.clone()
68+
}
69+
} else {
70+
project_path
71+
};
72+
73+
session.set_configuration_status(ConfigurationStatus::Loading);
74+
eprintln!(
75+
"Loading configuration from text_document {:?}",
76+
&project_path
77+
);
78+
let status = session
79+
.load_biome_configuration_file(ConfigurationPathHint::FromLsp(project_path), false)
80+
.await;
81+
82+
session.set_configuration_status(status);
83+
84+
if status.is_loaded() {
85+
match session.project_for_path(&path) {
86+
Some(project_key) => project_key,
87+
88+
None => {
89+
error!("Could not find project for {path}");
90+
91+
return Ok(());
92+
}
93+
}
94+
} else {
95+
error!("Configuration could not be loaded for {path}");
3596

36-
let project_key = if status.is_loaded() {
37-
match session.project_for_path(&path) {
38-
Some(project_key) => project_key,
39-
None => {
40-
error!("Could not find project for {path}");
4197
return Ok(());
4298
}
4399
}
44-
} else {
45-
if status.is_plugin_error() {
46-
session.client.show_message(MessageType::WARNING, "The plugin loading has failed. Biome will report only parsing errors until the file is fixed or its usage is disabled.").await;
47-
}
48-
error!("Configuration could not be loaded for {path}");
49-
return Ok(());
50100
};
51101

52102
let is_ignored = session

crates/biome_lsp/src/server.rs

Lines changed: 5 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,6 @@ use crate::session::{
66
};
77
use crate::utils::{into_lsp_error, panic_to_lsp_error};
88
use crate::{handlers, requests};
9-
use biome_configuration::ConfigurationPathHint;
109
use biome_console::markup;
1110
use biome_diagnostics::panic::PanicError;
1211
use biome_fs::{ConfigName, MemoryFileSystem, OsFileSystem};
@@ -310,13 +309,10 @@ impl LanguageServer for LSPServer {
310309
}
311310

312311
#[tracing::instrument(level = "debug", skip_all)]
313-
async fn initialized(&self, params: InitializedParams) {
314-
let _ = params;
315-
312+
async fn initialized(&self, _params: InitializedParams) {
316313
info!("Attempting to load the configuration from 'biome.json' file");
317-
318314
self.session.load_extension_settings().await;
319-
self.session.load_workspace_settings().await;
315+
self.session.load_workspace_settings(false).await;
320316

321317
let msg = format!("Server initialized with PID: {}", std::process::id());
322318
self.session
@@ -360,7 +356,7 @@ impl LanguageServer for LSPServer {
360356
|| watched_file.ends_with(".editorconfig"))
361357
{
362358
self.session.load_extension_settings().await;
363-
self.session.load_workspace_settings().await;
359+
self.session.load_workspace_settings(true).await;
364360
self.setup_capabilities().await;
365361
self.session.update_all_diagnostics().await;
366362
// for now we are only interested to the configuration file,
@@ -411,18 +407,8 @@ impl LanguageServer for LSPServer {
411407
}
412408
}
413409

414-
for added in &params.event.added {
415-
if let Ok(project_path) = self.session.file_path(&added.uri) {
416-
let status = self
417-
.session
418-
.load_biome_configuration_file(ConfigurationPathHint::FromWorkspace(
419-
project_path.to_path_buf(),
420-
))
421-
.await;
422-
debug!("Configuration status: {status:?}");
423-
self.session.set_configuration_status(status);
424-
}
425-
}
410+
self.session.update_workspace_folders(params.event.added);
411+
self.session.load_workspace_settings(true).await;
426412
}
427413

428414
async fn code_action(&self, params: CodeActionParams) -> LspResult<Option<CodeActionResponse>> {

0 commit comments

Comments
 (0)