summaryrefslogtreecommitdiff
path: root/support/texlab/src/features/workspace_command/change_environment.rs
diff options
context:
space:
mode:
Diffstat (limited to 'support/texlab/src/features/workspace_command/change_environment.rs')
-rw-r--r--support/texlab/src/features/workspace_command/change_environment.rs108
1 files changed, 108 insertions, 0 deletions
diff --git a/support/texlab/src/features/workspace_command/change_environment.rs b/support/texlab/src/features/workspace_command/change_environment.rs
new file mode 100644
index 0000000000..ef2c96eae1
--- /dev/null
+++ b/support/texlab/src/features/workspace_command/change_environment.rs
@@ -0,0 +1,108 @@
+use std::collections::hash_map::HashMap;
+
+use anyhow::Result;
+use lsp_types::{ApplyWorkspaceEditParams, TextDocumentPositionParams, TextEdit, WorkspaceEdit};
+use rowan::ast::AstNode;
+use serde::{Deserialize, Serialize};
+use thiserror::Error;
+
+use crate::{
+ normalize_uri,
+ util::{cursor::CursorContext, line_index_ext::LineIndexExt},
+ Db,
+};
+
+fn change_environment_context(
+ db: &dyn Db,
+ args: Vec<serde_json::Value>,
+) -> Result<CursorContext<Params>> {
+ let params: ChangeEnvironmentParams = serde_json::from_value(
+ args.into_iter()
+ .next()
+ .ok_or(ChangeEnvironmentError::MissingArg)?,
+ )
+ .map_err(ChangeEnvironmentError::InvalidArg)?;
+
+ let mut uri = params.text_document_position.text_document.uri;
+ normalize_uri(&mut uri);
+ let position = params.text_document_position.position;
+
+ CursorContext::new(
+ db,
+ &uri,
+ position,
+ Params {
+ new_name: params.new_name,
+ },
+ )
+ .ok_or(ChangeEnvironmentError::FailedCreatingContext.into())
+}
+
+pub fn change_environment(
+ db: &dyn Db,
+ args: Vec<serde_json::Value>,
+) -> Option<((), ApplyWorkspaceEditParams)> {
+ let context = change_environment_context(db, args).ok()?;
+ let (beg, end) = context.find_environment()?;
+
+ let beg_name = beg.to_string();
+ let end_name = end.to_string();
+
+ if beg_name != end_name {
+ return None;
+ }
+ let new_name = &context.params.new_name;
+
+ let line_index = context.document.line_index(db);
+ let mut changes = HashMap::default();
+ changes.insert(
+ context.document.location(db).uri(db).clone(),
+ vec![
+ TextEdit::new(
+ line_index.line_col_lsp_range(beg.syntax().text_range()),
+ new_name.clone(),
+ ),
+ TextEdit::new(
+ line_index.line_col_lsp_range(end.syntax().text_range()),
+ new_name.clone(),
+ ),
+ ],
+ );
+
+ Some((
+ (),
+ ApplyWorkspaceEditParams {
+ label: Some(format!("change environment: {} -> {}", beg_name, new_name)),
+ edit: WorkspaceEdit::new(changes),
+ },
+ ))
+}
+
+#[derive(Debug, Error)]
+pub enum ChangeEnvironmentError {
+ #[error("rename parameters was not provided as an argument")]
+ MissingArg,
+
+ #[error("invalid argument: {0}")]
+ InvalidArg(serde_json::Error),
+
+ #[error("failed creating context")]
+ FailedCreatingContext,
+
+ #[error("could not create workspaces edit")]
+ CouldNotCreateWorkspaceEdit,
+}
+
+#[derive(Debug, Eq, PartialEq, Clone, Deserialize, Serialize)]
+#[serde(rename_all = "camelCase")]
+pub struct ChangeEnvironmentParams {
+ #[serde(flatten)]
+ pub text_document_position: TextDocumentPositionParams,
+
+ pub new_name: String,
+}
+
+#[derive(Debug)]
+pub struct Params {
+ new_name: String,
+}