Move the wasm lib, and cleanup rust directory and all references (#5585)
* git mv src/wasm-lib rust Signed-off-by: Jess Frazelle <github@jessfraz.com> * mv wasm-lib to workspace Signed-off-by: Jess Frazelle <github@jessfraz.com> * mv kcl-lib Signed-off-by: Jess Frazelle <github@jessfraz.com> * mv derive docs Signed-off-by: Jess Frazelle <github@jessfraz.com> * resolve file paths Signed-off-by: Jess Frazelle <github@jessfraz.com> * clippy Signed-off-by: Jess Frazelle <github@jessfraz.com> * move more shit Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix more paths Signed-off-by: Jess Frazelle <github@jessfraz.com> * make yarn build:wasm work Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix scripts Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixups Signed-off-by: Jess Frazelle <github@jessfraz.com> * better references Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix cargo ci Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix reference Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix more ci Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix tests Signed-off-by: Jess Frazelle <github@jessfraz.com> * cargo sort Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix script Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix Signed-off-by: Jess Frazelle <github@jessfraz.com> * fmt Signed-off-by: Jess Frazelle <github@jessfraz.com> * fix a dep Signed-off-by: Jess Frazelle <github@jessfraz.com> * sort Signed-off-by: Jess Frazelle <github@jessfraz.com> * remove unused deps Signed-off-by: Jess Frazelle <github@jessfraz.com> * Revert "remove unused deps" This reverts commit fbabdb062e275fd5cbc1476f8480a1afee15d972. * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> * deps; Signed-off-by: Jess Frazelle <github@jessfraz.com> * fixes Signed-off-by: Jess Frazelle <github@jessfraz.com> * updates Signed-off-by: Jess Frazelle <github@jessfraz.com> --------- Signed-off-by: Jess Frazelle <github@jessfraz.com>
This commit is contained in:
239
rust/kcl-lib/src/lsp/backend.rs
Normal file
239
rust/kcl-lib/src/lsp/backend.rs
Normal file
@ -0,0 +1,239 @@
|
||||
//! A shared backend trait for lsp servers memory and behavior.
|
||||
|
||||
use std::sync::Arc;
|
||||
|
||||
use anyhow::Result;
|
||||
use dashmap::DashMap;
|
||||
use tower_lsp::lsp_types::{
|
||||
CreateFilesParams, DeleteFilesParams, Diagnostic, DidChangeConfigurationParams, DidChangeTextDocumentParams,
|
||||
DidChangeWatchedFilesParams, DidChangeWorkspaceFoldersParams, DidCloseTextDocumentParams,
|
||||
DidOpenTextDocumentParams, DidSaveTextDocumentParams, InitializedParams, MessageType, RenameFilesParams,
|
||||
TextDocumentItem, WorkspaceFolder,
|
||||
};
|
||||
|
||||
use crate::fs::FileSystem;
|
||||
|
||||
/// A trait for the backend of the language server.
|
||||
#[async_trait::async_trait]
|
||||
pub trait Backend: Clone + Send + Sync
|
||||
where
|
||||
Self: 'static,
|
||||
{
|
||||
fn client(&self) -> &tower_lsp::Client;
|
||||
|
||||
fn fs(&self) -> &Arc<crate::fs::FileManager>;
|
||||
|
||||
async fn is_initialized(&self) -> bool;
|
||||
|
||||
async fn set_is_initialized(&self, is_initialized: bool);
|
||||
|
||||
async fn workspace_folders(&self) -> Vec<WorkspaceFolder>;
|
||||
|
||||
async fn add_workspace_folders(&self, folders: Vec<WorkspaceFolder>);
|
||||
|
||||
async fn remove_workspace_folders(&self, folders: Vec<WorkspaceFolder>);
|
||||
|
||||
/// Get the current code map.
|
||||
fn code_map(&self) -> &DashMap<String, Vec<u8>>;
|
||||
|
||||
/// Insert a new code map.
|
||||
async fn insert_code_map(&self, uri: String, text: Vec<u8>);
|
||||
|
||||
// Remove from code map.
|
||||
async fn remove_from_code_map(&self, uri: String) -> Option<Vec<u8>>;
|
||||
|
||||
/// Clear the current code state.
|
||||
async fn clear_code_state(&self);
|
||||
|
||||
/// Get the current diagnostics map.
|
||||
fn current_diagnostics_map(&self) -> &DashMap<String, Vec<Diagnostic>>;
|
||||
|
||||
/// On change event.
|
||||
async fn inner_on_change(&self, params: TextDocumentItem, force: bool);
|
||||
|
||||
/// Check if the file has diagnostics.
|
||||
async fn has_diagnostics(&self, uri: &str) -> bool {
|
||||
let Some(diagnostics) = self.current_diagnostics_map().get(uri) else {
|
||||
return false;
|
||||
};
|
||||
|
||||
!diagnostics.is_empty()
|
||||
}
|
||||
|
||||
async fn on_change(&self, params: TextDocumentItem) {
|
||||
// Check if the document is in the current code map and if it is the same as what we have
|
||||
// stored.
|
||||
let filename = params.uri.to_string();
|
||||
if let Some(current_code) = self.code_map().get(&filename) {
|
||||
if *current_code == params.text.as_bytes() && !self.has_diagnostics(&filename).await {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
self.insert_code_map(params.uri.to_string(), params.text.as_bytes().to_vec())
|
||||
.await;
|
||||
self.inner_on_change(params, false).await;
|
||||
}
|
||||
|
||||
async fn update_from_disk<P: AsRef<std::path::Path> + std::marker::Send>(&self, path: P) -> Result<()> {
|
||||
// Read over all the files in the directory and add them to our current code map.
|
||||
let files = self.fs().get_all_files(path.as_ref(), Default::default()).await?;
|
||||
for file in files {
|
||||
// Read the file.
|
||||
let contents = self.fs().read(&file, Default::default()).await?;
|
||||
let file_path = format!(
|
||||
"file://{}",
|
||||
file.as_path()
|
||||
.to_str()
|
||||
.ok_or_else(|| anyhow::anyhow!("could not get name of file: {:?}", file))?
|
||||
);
|
||||
self.insert_code_map(file_path, contents).await;
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn do_initialized(&self, params: InitializedParams) {
|
||||
self.client()
|
||||
.log_message(MessageType::INFO, format!("initialized: {:?}", params))
|
||||
.await;
|
||||
|
||||
self.set_is_initialized(true).await;
|
||||
}
|
||||
|
||||
async fn do_shutdown(&self) -> tower_lsp::jsonrpc::Result<()> {
|
||||
self.client()
|
||||
.log_message(MessageType::INFO, "shutdown".to_string())
|
||||
.await;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
async fn do_did_change_workspace_folders(&self, params: DidChangeWorkspaceFoldersParams) {
|
||||
// If we are adding a folder that we were previously on, we should not clear the
|
||||
// state.
|
||||
let should_clear = if !params.event.added.is_empty() {
|
||||
let mut should_clear = false;
|
||||
for folder in params.event.added.iter() {
|
||||
if !self
|
||||
.workspace_folders()
|
||||
.await
|
||||
.iter()
|
||||
.any(|f| f.uri == folder.uri && f.name == folder.name)
|
||||
{
|
||||
should_clear = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
should_clear
|
||||
} else {
|
||||
!(params.event.removed.is_empty() && params.event.added.is_empty())
|
||||
};
|
||||
|
||||
self.add_workspace_folders(params.event.added.clone()).await;
|
||||
self.remove_workspace_folders(params.event.removed).await;
|
||||
// Remove the code from the current code map.
|
||||
// We do this since it means the user is changing projects so let's refresh the state.
|
||||
if !self.code_map().is_empty() && should_clear {
|
||||
self.clear_code_state().await;
|
||||
}
|
||||
for added in params.event.added {
|
||||
// Try to read all the files in the project.
|
||||
let project_dir = added.uri.to_string().replace("file://", "");
|
||||
if let Err(err) = self.update_from_disk(&project_dir).await {
|
||||
self.client()
|
||||
.log_message(
|
||||
MessageType::WARNING,
|
||||
format!("updating from disk `{}` failed: {:?}", project_dir, err),
|
||||
)
|
||||
.await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn do_did_change_configuration(&self, params: DidChangeConfigurationParams) {
|
||||
self.client()
|
||||
.log_message(MessageType::INFO, format!("configuration changed: {:?}", params))
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn do_did_change_watched_files(&self, params: DidChangeWatchedFilesParams) {
|
||||
self.client()
|
||||
.log_message(MessageType::INFO, format!("watched files changed: {:?}", params))
|
||||
.await;
|
||||
}
|
||||
|
||||
async fn do_did_create_files(&self, params: CreateFilesParams) {
|
||||
self.client()
|
||||
.log_message(MessageType::INFO, format!("files created: {:?}", params))
|
||||
.await;
|
||||
// Create each file in the code map.
|
||||
for file in params.files {
|
||||
self.insert_code_map(file.uri.to_string(), Default::default()).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn do_did_rename_files(&self, params: RenameFilesParams) {
|
||||
self.client()
|
||||
.log_message(MessageType::INFO, format!("files renamed: {:?}", params))
|
||||
.await;
|
||||
// Rename each file in the code map.
|
||||
for file in params.files {
|
||||
if let Some(value) = self.remove_from_code_map(file.old_uri).await {
|
||||
// Rename the file if it exists.
|
||||
self.insert_code_map(file.new_uri.to_string(), value).await;
|
||||
} else {
|
||||
// Otherwise create it.
|
||||
self.insert_code_map(file.new_uri.to_string(), Default::default()).await;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
async fn do_did_delete_files(&self, params: DeleteFilesParams) {
|
||||
self.client()
|
||||
.log_message(MessageType::INFO, format!("files deleted: {:?}", params))
|
||||
.await;
|
||||
// Delete each file in the map.
|
||||
for file in params.files {
|
||||
self.remove_from_code_map(file.uri.to_string()).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn do_did_open(&self, params: DidOpenTextDocumentParams) {
|
||||
let new_params = TextDocumentItem {
|
||||
uri: params.text_document.uri,
|
||||
text: params.text_document.text,
|
||||
version: params.text_document.version,
|
||||
language_id: params.text_document.language_id,
|
||||
};
|
||||
self.on_change(new_params).await;
|
||||
}
|
||||
|
||||
async fn do_did_change(&self, mut params: DidChangeTextDocumentParams) {
|
||||
let new_params = TextDocumentItem {
|
||||
uri: params.text_document.uri,
|
||||
text: std::mem::take(&mut params.content_changes[0].text),
|
||||
version: params.text_document.version,
|
||||
language_id: Default::default(),
|
||||
};
|
||||
self.on_change(new_params).await;
|
||||
}
|
||||
|
||||
async fn do_did_save(&self, params: DidSaveTextDocumentParams) {
|
||||
if let Some(text) = params.text {
|
||||
let new_params = TextDocumentItem {
|
||||
uri: params.text_document.uri,
|
||||
text,
|
||||
version: Default::default(),
|
||||
language_id: Default::default(),
|
||||
};
|
||||
self.on_change(new_params).await;
|
||||
}
|
||||
}
|
||||
|
||||
async fn do_did_close(&self, params: DidCloseTextDocumentParams) {
|
||||
self.client()
|
||||
.log_message(MessageType::INFO, format!("document closed: {:?}", params))
|
||||
.await;
|
||||
}
|
||||
}
|
Reference in New Issue
Block a user