Skip to content

Commit eee400b

Browse files
committed
docs(language_server): docs for Backend struct
1 parent ee9ecbe commit eee400b

File tree

1 file changed

+75
-3
lines changed

1 file changed

+75
-3
lines changed

crates/oxc_language_server/src/backend.rs

Lines changed: 75 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,10 @@ use crate::{
2929
worker::WorkspaceWorker,
3030
};
3131

32+
/// The Backend implements the LanguageServer trait to handle LSP requests and notifications.
33+
///
34+
/// It manages multiple WorkspaceWorkers, each corresponding to a workspace folder.
35+
/// Depending on the client's capabilities, it can dynamically register features and start up other services.
3236
pub struct Backend {
3337
client: Client,
3438
// Each Workspace has it own worker with Linter (and in the future the formatter).
@@ -39,11 +43,21 @@ pub struct Backend {
3943
// 1. `initialize` request with workspace folders
4044
// 2. `workspace/didChangeWorkspaceFolders` request
4145
workspace_workers: Arc<RwLock<Vec<WorkspaceWorker>>>,
46+
// Capabilities of the language server, set once during `initialize` request.
47+
// Depending on the client capabilities, the server supports different capabilities.
4248
capabilities: OnceCell<Capabilities>,
49+
// A simple in-memory file system to store the content of open files.
50+
// The client will send the content of in-memory files on `textDocument/didOpen` and `textDocument/didChange`.
51+
// This is only needed when the client supports `textDocument/formatting` request,
4352
file_system: Arc<RwLock<LSPFileSystem>>,
4453
}
4554

4655
impl LanguageServer for Backend {
56+
/// Initialize the language server with the given parameters.
57+
/// This method sets up workspace workers, capabilities, and starts the
58+
/// [WorkspaceWorker]s if the client sent the configuration with initialization options.
59+
///
60+
/// @link <https://microsoft.github.io/language-server-protocol/specifications/specification-current/#initialize>
4761
#[expect(deprecated)] // `params.root_uri` is deprecated, we are only falling back to it if no workspace folder is provided
4862
async fn initialize(&self, params: InitializeParams) -> Result<InitializeResult> {
4963
let server_version = env!("CARGO_PKG_VERSION");
@@ -134,6 +148,11 @@ impl LanguageServer for Backend {
134148
})
135149
}
136150

151+
/// The `initialized` notification is sent from the client to the server after the `initialize` request.
152+
/// This method registers dynamic capabilities like file watchers and formatting if the client supports it.
153+
/// It also starts the [WorkspaceWorker]s if they did not start during initialization.
154+
///
155+
/// @link <https://microsoft.github.io/language-server-protocol/specifications/specification-current/#initialized>
137156
async fn initialized(&self, _params: InitializedParams) {
138157
debug!("oxc initialized.");
139158
let Some(capabilities) = self.capabilities.get() else {
@@ -209,6 +228,10 @@ impl LanguageServer for Backend {
209228
}
210229
}
211230

231+
/// The `shutdown` request is sent from the client to the server to ask for a graceful shutdown.
232+
/// This method clears all diagnostics and the in-memory file system if dynamic formatting is enabled.
233+
///
234+
/// @link <https://microsoft.github.io/language-server-protocol/specifications/specification-current/#shutdown>
212235
async fn shutdown(&self) -> Result<()> {
213236
self.clear_all_diagnostics().await;
214237
if self.capabilities.get().is_some_and(|option| option.dynamic_formatting) {
@@ -217,6 +240,12 @@ impl LanguageServer for Backend {
217240
Ok(())
218241
}
219242

243+
/// The `workspace/didChangeConfiguration` notification is sent from the client to the server
244+
/// when the server configuration has changed in the client.
245+
/// This method updates the configuration of each [WorkspaceWorker] and restarts them if necessary.
246+
/// It also manages dynamic registrations for file watchers and formatting based on the new configuration.
247+
///
248+
/// @link <https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_didChangeConfiguration>
220249
async fn did_change_configuration(&self, params: DidChangeConfigurationParams) {
221250
let workers = self.workspace_workers.read().await;
222251
let new_diagnostics: papaya::HashMap<String, Vec<Diagnostic>, FxBuildHasher> =
@@ -354,6 +383,10 @@ impl LanguageServer for Backend {
354383
}
355384
}
356385

386+
/// The `workspace/didChangeWatchedFiles` notification is sent from the client to the server.
387+
/// This notification is sent when a configuration file of a tool changes (example: `.oxlintrc.json`).
388+
///
389+
/// @link <https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_didChangeWatchedFiles>
357390
async fn did_change_watched_files(&self, params: DidChangeWatchedFilesParams) {
358391
let workers = self.workspace_workers.read().await;
359392
// ToDo: what if an empty changes flag is passed?
@@ -393,6 +426,13 @@ impl LanguageServer for Backend {
393426
self.publish_all_diagnostics(x).await;
394427
}
395428

429+
/// The `workspace/didChangeWorkspaceFolders` notification is sent from the client to the server.
430+
/// The server will start new [WorkspaceWorker]s for added workspace folders
431+
/// and stop and remove [WorkspaceWorker]s for removed workspace folders including:
432+
/// - clearing diagnostics
433+
/// - unregistering file watchers
434+
///
435+
/// @link <https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_didChangeWorkspaceFolders>
396436
async fn did_change_workspace_folders(&self, params: DidChangeWorkspaceFoldersParams) {
397437
let mut workers = self.workspace_workers.write().await;
398438
let mut cleared_diagnostics = vec![];
@@ -471,6 +511,10 @@ impl LanguageServer for Backend {
471511
}
472512
}
473513

514+
/// The `textDocument/didSave` notification is sent from the client to the server.
515+
/// It will remove the in-memory file content, because the file is saved to disk.
516+
///
517+
/// @link <https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_didSave>
474518
async fn did_save(&self, params: DidSaveTextDocumentParams) {
475519
debug!("oxc server did save");
476520
let uri = &params.text_document.uri;
@@ -495,8 +539,10 @@ impl LanguageServer for Backend {
495539
}
496540
}
497541

498-
/// When the document changed, it may not be written to disk, so we should
499-
/// get the file context from the language client
542+
/// The `textDocument/didChange` notification is sent from the client to the server.
543+
/// It will update the in-memory file content if the client supports dynamic formatting.
544+
///
545+
/// @link <https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_didChange>
500546
async fn did_change(&self, params: DidChangeTextDocumentParams) {
501547
let uri = &params.text_document.uri;
502548
let workers = self.workspace_workers.read().await;
@@ -522,6 +568,10 @@ impl LanguageServer for Backend {
522568
}
523569
}
524570

571+
/// The `textDocument/didOpen` notification is sent from the client to the server.
572+
/// It will add the in-memory file content if the client supports dynamic formatting.
573+
///
574+
/// @link <https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_didOpen>
525575
async fn did_open(&self, params: DidOpenTextDocumentParams) {
526576
let uri = &params.text_document.uri;
527577
let workers = self.workspace_workers.read().await;
@@ -548,6 +598,10 @@ impl LanguageServer for Backend {
548598
}
549599
}
550600

601+
/// The `textDocument/didClose` notification is sent from the client to the server.
602+
/// It will remove the in-memory file content if the client supports dynamic formatting.
603+
///
604+
/// @link <https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_didClose>
551605
async fn did_close(&self, params: DidCloseTextDocumentParams) {
552606
let uri = &params.text_document.uri;
553607
let workers = self.workspace_workers.read().await;
@@ -560,6 +614,10 @@ impl LanguageServer for Backend {
560614
worker.remove_diagnostics(&params.text_document.uri).await;
561615
}
562616

617+
/// The `textDocument/codeAction` request is sent from the client to the server.
618+
/// It will return code actions or commands for the given range.
619+
///
620+
/// @link <https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_codeAction>
563621
async fn code_action(&self, params: CodeActionParams) -> Result<Option<CodeActionResponse>> {
564622
let uri = &params.text_document.uri;
565623
let workers = self.workspace_workers.read().await;
@@ -582,6 +640,11 @@ impl LanguageServer for Backend {
582640
Ok(Some(code_actions))
583641
}
584642

643+
/// The `workspace/executeCommand` request is sent from the client to the server.
644+
/// It will execute the given command with the provided arguments.
645+
/// Currently, only the `fixAll` command is supported.
646+
///
647+
/// @link <https://microsoft.github.io/language-server-protocol/specifications/specification-current/#workspace_executeCommand>
585648
async fn execute_command(
586649
&self,
587650
params: ExecuteCommandParams,
@@ -618,6 +681,10 @@ impl LanguageServer for Backend {
618681
Err(Error::invalid_request())
619682
}
620683

684+
/// The `textDocument/formatting` request is sent from the client to the server.
685+
/// It will return text edits to format the document if formatting is enabled for the workspace.
686+
///
687+
/// @link <https://microsoft.github.io/language-server-protocol/specifications/specification-current/#textDocument_formatting>
621688
async fn formatting(&self, params: DocumentFormattingParams) -> Result<Option<Vec<TextEdit>>> {
622689
let uri = &params.text_document.uri;
623690
let workers = self.workspace_workers.read().await;
@@ -629,6 +696,10 @@ impl LanguageServer for Backend {
629696
}
630697

631698
impl Backend {
699+
/// Create a new Backend with the given client.
700+
/// The Backend will manage multiple [WorkspaceWorker]s and their configurations.
701+
/// It also holds the capabilities of the language server and an in-memory file system.
702+
/// The client is used to communicate with the LSP client.
632703
pub fn new(client: Client) -> Self {
633704
Self {
634705
client,
@@ -670,7 +741,7 @@ impl Backend {
670741
options
671742
}
672743

673-
// clears all diagnostics for workspace folders
744+
/// clears all diagnostics for workspace folders
674745
async fn clear_all_diagnostics(&self) {
675746
let mut cleared_diagnostics = vec![];
676747
let workers = &*self.workspace_workers.read().await;
@@ -680,6 +751,7 @@ impl Backend {
680751
self.publish_all_diagnostics(&cleared_diagnostics).await;
681752
}
682753

754+
/// Publish diagnostics for all files.
683755
async fn publish_all_diagnostics(&self, result: &[(String, Vec<Diagnostic>)]) {
684756
join_all(result.iter().map(|(path, diagnostics)| {
685757
self.client.publish_diagnostics(Uri::from_str(path).unwrap(), diagnostics.clone(), None)

0 commit comments

Comments
 (0)