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
5 changes: 5 additions & 0 deletions .changeset/rich-beds-clap.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
---
"@biomejs/biome": patch
---

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.
11 changes: 10 additions & 1 deletion crates/biome_configuration/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -605,7 +605,7 @@ pub struct ConfigurationPayload {
pub external_resolution_base_path: Utf8PathBuf,
}

#[derive(Debug, Default, PartialEq, Clone)]
#[derive(Debug, Default, PartialEq, Clone, Eq, Hash)]
pub enum ConfigurationPathHint {
/// The default mode, not having a configuration file is not an error.
/// The path will be filled with the working directory if it is not filled at the time of usage.
Expand Down Expand Up @@ -651,4 +651,13 @@ impl ConfigurationPathHint {
pub const fn is_from_lsp(&self) -> bool {
matches!(self, Self::FromLsp(_))
}

pub fn to_path_buf(&self) -> Option<Utf8PathBuf> {
match self {
Self::None => None,
Self::FromWorkspace(path) | Self::FromLsp(path) | Self::FromUser(path) => {
Some(path.to_path_buf())
}
}
}
}
84 changes: 67 additions & 17 deletions crates/biome_lsp/src/handlers/text_document.rs
Original file line number Diff line number Diff line change
@@ -1,15 +1,16 @@
use std::sync::Arc;

use crate::diagnostics::LspError;
use crate::session::ConfigurationStatus;
use crate::utils::apply_document_changes;
use crate::{documents::Document, session::Session};
use biome_configuration::ConfigurationPathHint;
use biome_service::workspace::{
ChangeFileParams, CloseFileParams, DocumentFileSource, FeaturesBuilder, FileContent,
GetFileContentParams, IgnoreKind, OpenFileParams, PathIsIgnoredParams,
};
use tower_lsp_server::lsp_types;
use tower_lsp_server::lsp_types::MessageType;
use tracing::{debug, error, field};
use camino::Utf8PathBuf;
use std::sync::Arc;
use tower_lsp_server::{UriExt, lsp_types};
use tracing::{debug, error, field, info};

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

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

let status = session.configuration_status();
eprintln!("Session id {:?}", session.key);
let project_key = match session.project_for_path(&path) {
Some(project_key) => project_key,
None => {
info!("No open project for path: {path:?}. Opening new project.");

let project_path = path
.parent()
.map(|parent| parent.to_path_buf())
.unwrap_or_default();

// First check if the current file belongs to any registered workspace folder.
// If so, return that folder; otherwise, use the folder computed by did_open.
let project_path = if let Some(workspace_folders) = session.get_workspace_folders() {
if let Some(ws_root) = workspace_folders
.iter()
.filter_map(|folder| {
folder.uri.to_file_path().map(|p| {
Utf8PathBuf::from_path_buf(p.to_path_buf())
.expect("To have a valid UTF-8 path")
})
})
.find(|ws| project_path.starts_with(ws))
{
ws_root
} else {
project_path.clone()
}
} else if let Some(base_path) = session.base_path() {
if project_path.starts_with(&base_path) {
base_path
} else {
project_path.clone()
}
} else {
project_path
};

session.set_configuration_status(ConfigurationStatus::Loading);
eprintln!(
"Loading configuration from text_document {:?}",
&project_path
);
let status = session
.load_biome_configuration_file(ConfigurationPathHint::FromLsp(project_path), false)
.await;

session.set_configuration_status(status);

if status.is_loaded() {
match session.project_for_path(&path) {
Some(project_key) => project_key,

None => {
error!("Could not find project for {path}");

return Ok(());
}
}
} else {
error!("Configuration could not be loaded for {path}");

let project_key = if status.is_loaded() {
match session.project_for_path(&path) {
Some(project_key) => project_key,
None => {
error!("Could not find project for {path}");
return Ok(());
}
}
} else {
if status.is_plugin_error() {
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;
}
error!("Configuration could not be loaded for {path}");
return Ok(());
};

let is_ignored = session
Expand Down
24 changes: 5 additions & 19 deletions crates/biome_lsp/src/server.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,6 @@ use crate::session::{
};
use crate::utils::{into_lsp_error, panic_to_lsp_error};
use crate::{handlers, requests};
use biome_configuration::ConfigurationPathHint;
use biome_console::markup;
use biome_diagnostics::panic::PanicError;
use biome_fs::{ConfigName, MemoryFileSystem, OsFileSystem};
Expand Down Expand Up @@ -310,13 +309,10 @@ impl LanguageServer for LSPServer {
}

#[tracing::instrument(level = "debug", skip_all)]
async fn initialized(&self, params: InitializedParams) {
let _ = params;

async fn initialized(&self, _params: InitializedParams) {
info!("Attempting to load the configuration from 'biome.json' file");

self.session.load_extension_settings().await;
self.session.load_workspace_settings().await;
self.session.load_workspace_settings(false).await;

let msg = format!("Server initialized with PID: {}", std::process::id());
self.session
Expand Down Expand Up @@ -360,7 +356,7 @@ impl LanguageServer for LSPServer {
|| watched_file.ends_with(".editorconfig"))
{
self.session.load_extension_settings().await;
self.session.load_workspace_settings().await;
self.session.load_workspace_settings(true).await;
self.setup_capabilities().await;
self.session.update_all_diagnostics().await;
// for now we are only interested to the configuration file,
Expand Down Expand Up @@ -411,18 +407,8 @@ impl LanguageServer for LSPServer {
}
}

for added in &params.event.added {
if let Ok(project_path) = self.session.file_path(&added.uri) {
let status = self
.session
.load_biome_configuration_file(ConfigurationPathHint::FromWorkspace(
project_path.to_path_buf(),
))
.await;
debug!("Configuration status: {status:?}");
self.session.set_configuration_status(status);
}
}
self.session.update_workspace_folders(params.event.added);
self.session.load_workspace_settings(true).await;
}

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