Skip to content

Commit

Permalink
Refactor the server.rs module in the language server. (FuelLabs#4673)
Browse files Browse the repository at this point in the history
## Description
This PR refactors most of the code that was in `server.rs`.
Specifically, the call backs have been moved to
`handlers/notification.rs` and `handlers/request.rs`. This was inspired
by `rust-analyzer`s approach.

the `server.rs` module now looks like:

```rust
#[tower_lsp::async_trait]
impl LanguageServer for ServerState {
    async fn initialize(&self, params: InitializeParams) -> Result<InitializeResult> {
        request::handle_initialize(self, params)
    }

    async fn shutdown(&self) -> Result<()> {
        self.shutdown_server()
    }

    async fn did_open(&self, params: DidOpenTextDocumentParams) {
        notification::handle_did_open_text_document(self, params).await;
    }

    async fn did_change(&self, params: DidChangeTextDocumentParams) {
        notification::handle_did_change_text_document(self, params).await;
    }

    async fn did_save(&self, params: DidSaveTextDocumentParams) {
        notification::handle_did_save_text_document(self, params).await;
    }

    async fn did_change_watched_files(&self, params: DidChangeWatchedFilesParams) {
        notification::handle_did_change_watched_files(self, params).await;
    }

    async fn hover(&self, params: HoverParams) -> Result<Option<Hover>> {
        request::handle_hover(self, params)
    }

    async fn code_action(&self, params: CodeActionParams) -> Result<Option<CodeActionResponse>> {
        request::handle_code_action(self, params)
    }

    async fn code_lens(&self, params: CodeLensParams) -> Result<Option<Vec<CodeLens>>> {
        request::handle_code_lens(self, params)
    }
    
    etc ...
}
```


A new type called `ServerState` now holds the config, keyword docs,
client and the map of sessions. No new functionality has been added
apart from refactoring the code.

This is needed for the new event loop, I decided to separate that into a
follow up PR to make things a bit more manageable.

closes FuelLabs#4672
  • Loading branch information
JoshuaBatty authored Jun 19, 2023
1 parent 26581f5 commit fd2b56d
Show file tree
Hide file tree
Showing 9 changed files with 895 additions and 675 deletions.
102 changes: 102 additions & 0 deletions sway-lsp/src/handlers/notification.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
//! This module is responsible for implementing handlers for Language Server
//! Protocol. This module specifically handles notification messages sent by the Client.
use crate::{capabilities, core::sync, server_state::ServerState};
use forc_pkg::PackageManifestFile;
use lsp_types::{
DidChangeTextDocumentParams, DidChangeWatchedFilesParams, DidOpenTextDocumentParams,
DidSaveTextDocumentParams, FileChangeType,
};

pub(crate) async fn handle_did_open_text_document(
state: &ServerState,
params: DidOpenTextDocumentParams,
) {
match state
.sessions
.uri_and_session_from_workspace(&params.text_document.uri)
{
Ok((uri, session)) => {
session.handle_open_file(&uri);
state
.parse_project(uri, params.text_document.uri, session.clone())
.await;
}
Err(err) => tracing::error!("{}", err.to_string()),
}
}

pub(crate) async fn handle_did_change_text_document(
state: &ServerState,
params: DidChangeTextDocumentParams,
) {
let config = state.config.read().on_enter.clone();
match state
.sessions
.uri_and_session_from_workspace(&params.text_document.uri)
{
Ok((uri, session)) => {
// handle on_enter capabilities if they are enabled
capabilities::on_enter(&config, &state.client, &session, &uri.clone(), &params).await;

// update this file with the new changes and write to disk
match session.write_changes_to_file(&uri, params.content_changes) {
Ok(_) => {
state
.parse_project(uri, params.text_document.uri.clone(), session)
.await;
}
Err(err) => tracing::error!("{}", err.to_string()),
}
}
Err(err) => tracing::error!("{}", err.to_string()),
}
}

pub(crate) async fn handle_did_save_text_document(
state: &ServerState,
params: DidSaveTextDocumentParams,
) {
match state
.sessions
.uri_and_session_from_workspace(&params.text_document.uri)
{
Ok((uri, session)) => {
// overwrite the contents of the tmp/folder with everything in
// the current workspace. (resync)
if let Err(err) = session.sync.clone_manifest_dir_to_temp() {
tracing::error!("{}", err.to_string().as_str());
}

let _ = session
.sync
.manifest_path()
.and_then(|manifest_path| PackageManifestFile::from_dir(&manifest_path).ok())
.map(|manifest| {
if let Some(temp_manifest_path) = &session.sync.temp_manifest_path() {
sync::edit_manifest_dependency_paths(&manifest, temp_manifest_path)
}
});
state
.parse_project(uri, params.text_document.uri, session)
.await;
}
Err(err) => tracing::error!("{}", err.to_string()),
}
}

pub(crate) async fn handle_did_change_watched_files(
state: &ServerState,
params: DidChangeWatchedFilesParams,
) {
for event in params.changes {
if event.typ == FileChangeType::DELETED {
match state.sessions.uri_and_session_from_workspace(&event.uri) {
Ok((uri, session)) => {
let _ = session.remove_document(&uri);
}
Err(err) => tracing::error!("{}", err.to_string()),
}
}
}
}
Loading

0 comments on commit fd2b56d

Please sign in to comment.