From 745892fbddea56040139108277e728b53fd8fc11 Mon Sep 17 00:00:00 2001 From: Norbert Preining Date: Thu, 28 May 2020 03:03:21 +0000 Subject: CTAN sync 202005280303 --- support/texlab/src/rename/latex_env.rs | 157 +++++++++++++++++++++++++++++++++ 1 file changed, 157 insertions(+) create mode 100644 support/texlab/src/rename/latex_env.rs (limited to 'support/texlab/src/rename/latex_env.rs') diff --git a/support/texlab/src/rename/latex_env.rs b/support/texlab/src/rename/latex_env.rs new file mode 100644 index 0000000000..6e302ef8b6 --- /dev/null +++ b/support/texlab/src/rename/latex_env.rs @@ -0,0 +1,157 @@ +use crate::{ + feature::{FeatureProvider, FeatureRequest}, + protocol::{ + Position, Range, RangeExt, RenameParams, TextDocumentPositionParams, TextEdit, + WorkspaceEdit, + }, + syntax::{latex, SyntaxNode}, + workspace::DocumentContent, +}; +use async_trait::async_trait; +use std::collections::HashMap; + +#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)] +pub struct LatexEnvironmentPrepareRenameProvider; + +#[async_trait] +impl FeatureProvider for LatexEnvironmentPrepareRenameProvider { + type Params = TextDocumentPositionParams; + type Output = Option; + + async fn execute<'a>(&'a self, req: &'a FeatureRequest) -> Self::Output { + let pos = req.params.position; + let (left_name, right_name) = find_environment(&req.current().content, pos)?; + let range = if left_name.range().contains(pos) { + left_name.range() + } else { + right_name.range() + }; + Some(range) + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy, Default)] +pub struct LatexEnvironmentRenameProvider; + +#[async_trait] +impl FeatureProvider for LatexEnvironmentRenameProvider { + type Params = RenameParams; + type Output = Option; + + async fn execute<'a>(&'a self, req: &'a FeatureRequest) -> Self::Output { + let (left_name, right_name) = find_environment( + &req.current().content, + req.params.text_document_position.position, + )?; + let edits = vec![ + TextEdit::new(left_name.range(), req.params.new_name.clone()), + TextEdit::new(right_name.range(), req.params.new_name.clone()), + ]; + let mut changes = HashMap::new(); + changes.insert(req.current().uri.clone().into(), edits); + Some(WorkspaceEdit::new(changes)) + } +} + +fn find_environment( + content: &DocumentContent, + pos: Position, +) -> Option<(&latex::Token, &latex::Token)> { + if let DocumentContent::Latex(table) = content { + for env in &table.environments { + if let Some(left_name) = env.left.name(&table) { + if let Some(right_name) = env.right.name(&table) { + if left_name.range().contains(pos) || right_name.range().contains(pos) { + return Some((left_name, right_name)); + } + } + } + } + } + None +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::feature::FeatureTester; + use indoc::indoc; + + #[tokio::test] + async fn environment() { + let actual_edit = FeatureTester::new() + .file( + "main.tex", + indoc!( + r#" + \begin{foo} + \end{bar} + "# + ), + ) + .main("main.tex") + .position(0, 8) + .new_name("baz") + .test_rename(LatexEnvironmentRenameProvider) + .await + .unwrap(); + + let mut expected_changes = HashMap::new(); + expected_changes.insert( + FeatureTester::uri("main.tex").into(), + vec![ + TextEdit::new(Range::new_simple(0, 7, 0, 10), "baz".into()), + TextEdit::new(Range::new_simple(1, 5, 1, 8), "baz".into()), + ], + ); + + assert_eq!(actual_edit, WorkspaceEdit::new(expected_changes)); + } + + #[tokio::test] + async fn command() { + let actual_edit = FeatureTester::new() + .file( + "main.tex", + indoc!( + r#" + \begin{foo} + \end{bar} + "# + ), + ) + .main("main.tex") + .position(0, 5) + .new_name("baz") + .test_rename(LatexEnvironmentRenameProvider) + .await; + + assert_eq!(actual_edit, None); + } + + #[tokio::test] + async fn empty_latex_document() { + let actual_edit = FeatureTester::new() + .file("main.tex", "") + .main("main.tex") + .position(0, 0) + .new_name("") + .test_rename(LatexEnvironmentRenameProvider) + .await; + + assert_eq!(actual_edit, None); + } + + #[tokio::test] + async fn empty_bibtex_document() { + let actual_edit = FeatureTester::new() + .file("main.bib", "") + .main("main.bib") + .position(0, 0) + .new_name("") + .test_rename(LatexEnvironmentRenameProvider) + .await; + + assert_eq!(actual_edit, None); + } +} -- cgit v1.2.3