Skip to content

Commit 64fafe3

Browse files
committed
refactor(langauge_server): introdude LSPFileSystem
1 parent 137896a commit 64fafe3

File tree

3 files changed

+69
-0
lines changed

3 files changed

+69
-0
lines changed

crates/oxc_language_server/src/capabilities.rs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ pub struct Capabilities {
1414
pub workspace_execute_command: bool,
1515
pub workspace_configuration: bool,
1616
pub dynamic_watchers: bool,
17+
pub dynamic_formatting: bool,
1718
}
1819

1920
impl From<ClientCapabilities> for Capabilities {
@@ -39,13 +40,20 @@ impl From<ClientCapabilities> for Capabilities {
3940
watched_files.dynamic_registration.is_some_and(|dynamic| dynamic)
4041
})
4142
});
43+
// TODO: enable it when we support formatting
44+
// let formatting = value.text_document.as_ref().is_some_and(|text_document| {
45+
// text_document.formatting.is_some_and(|formatting| {
46+
// formatting.dynamic_registration.is_some_and(|dynamic| dynamic)
47+
// })
48+
// });
4249

4350
Self {
4451
code_action_provider,
4552
workspace_apply_edit,
4653
workspace_execute_command,
4754
workspace_configuration,
4855
dynamic_watchers,
56+
dynamic_formatting: false,
4957
}
5058
}
5159
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
use std::sync::Arc;
2+
3+
use tower_lsp_server::lsp_types::Uri;
4+
5+
use crate::ConcurrentHashMap;
6+
7+
pub struct LSPFileSystem {
8+
files: Arc<ConcurrentHashMap<Uri, String>>,
9+
}
10+
11+
impl LSPFileSystem {
12+
pub fn new() -> Self {
13+
Self { files: Arc::new(ConcurrentHashMap::default()) }
14+
}
15+
16+
pub fn clear(&self) {
17+
self.files.pin().clear();
18+
}
19+
20+
pub fn set(&self, uri: &Uri, content: String) {
21+
self.files.pin().insert(uri.clone(), content);
22+
}
23+
24+
#[expect(dead_code)] // used for the oxc_formatter in the future
25+
pub fn get(&self, uri: &Uri) -> Option<String> {
26+
self.files.pin().get(uri).cloned()
27+
}
28+
29+
pub fn remove(&self, uri: &Uri) {
30+
self.files.pin().remove(uri);
31+
}
32+
}

crates/oxc_language_server/src/main.rs

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ use tower_lsp_server::{
2222
mod capabilities;
2323
mod code_actions;
2424
mod commands;
25+
mod file_system;
2526
mod formatter;
2627
mod linter;
2728
mod options;
@@ -36,6 +37,8 @@ use linter::server_linter::ServerLinterRun;
3637
use options::{Options, WorkspaceOption};
3738
use worker::WorkspaceWorker;
3839

40+
use crate::file_system::LSPFileSystem;
41+
3942
type ConcurrentHashMap<K, V> = papaya::HashMap<K, V, FxBuildHasher>;
4043

4144
const OXC_CONFIG_FILE: &str = ".oxlintrc.json";
@@ -51,6 +54,7 @@ struct Backend {
5154
// 2. `workspace/didChangeWorkspaceFolders` request
5255
workspace_workers: Arc<RwLock<Vec<WorkspaceWorker>>>,
5356
capabilities: OnceCell<Capabilities>,
57+
file_system: Arc<RwLock<LSPFileSystem>>,
5458
}
5559

5660
impl LanguageServer for Backend {
@@ -203,6 +207,9 @@ impl LanguageServer for Backend {
203207

204208
async fn shutdown(&self) -> Result<()> {
205209
self.clear_all_diagnostics().await;
210+
if self.capabilities.get().is_some_and(|option| option.dynamic_formatting) {
211+
self.file_system.write().await.clear();
212+
}
206213
Ok(())
207214
}
208215

@@ -444,6 +451,12 @@ impl LanguageServer for Backend {
444451
let Some(worker) = workers.iter().find(|worker| worker.is_responsible_for_uri(uri)) else {
445452
return;
446453
};
454+
455+
if self.capabilities.get().is_some_and(|option| option.dynamic_formatting) {
456+
// saving the file means we can read again from the file system
457+
self.file_system.write().await.remove(uri);
458+
}
459+
447460
if let Some(diagnostics) = worker.lint_file(uri, None, ServerLinterRun::OnSave).await {
448461
self.client
449462
.publish_diagnostics(
@@ -464,6 +477,13 @@ impl LanguageServer for Backend {
464477
return;
465478
};
466479
let content = params.content_changes.first().map(|c| c.text.clone());
480+
481+
if self.capabilities.get().is_some_and(|option| option.dynamic_formatting)
482+
&& let Some(content) = &content
483+
{
484+
self.file_system.write().await.set(uri, content.to_string());
485+
}
486+
467487
if let Some(diagnostics) = worker.lint_file(uri, content, ServerLinterRun::OnType).await {
468488
self.client
469489
.publish_diagnostics(
@@ -483,6 +503,11 @@ impl LanguageServer for Backend {
483503
};
484504

485505
let content = params.text_document.text;
506+
507+
if self.capabilities.get().is_some_and(|option| option.dynamic_formatting) {
508+
self.file_system.write().await.set(uri, content.to_string());
509+
}
510+
486511
if let Some(diagnostics) =
487512
worker.lint_file(uri, Some(content), ServerLinterRun::Always).await
488513
{
@@ -502,6 +527,9 @@ impl LanguageServer for Backend {
502527
let Some(worker) = workers.iter().find(|worker| worker.is_responsible_for_uri(uri)) else {
503528
return;
504529
};
530+
if self.capabilities.get().is_some_and(|option| option.dynamic_formatting) {
531+
self.file_system.write().await.remove(uri);
532+
}
505533
worker.remove_diagnostics(&params.text_document.uri).await;
506534
}
507535

@@ -626,6 +654,7 @@ async fn main() {
626654
client,
627655
workspace_workers: Arc::new(RwLock::new(vec![])),
628656
capabilities: OnceCell::new(),
657+
file_system: Arc::new(RwLock::new(LSPFileSystem::new())),
629658
})
630659
.finish();
631660

0 commit comments

Comments
 (0)