diff options
Diffstat (limited to 'support/texlab/src/rename/latex_command.rs')
-rw-r--r-- | support/texlab/src/rename/latex_command.rs | 114 |
1 files changed, 114 insertions, 0 deletions
diff --git a/support/texlab/src/rename/latex_command.rs b/support/texlab/src/rename/latex_command.rs new file mode 100644 index 0000000000..52bac7a8c9 --- /dev/null +++ b/support/texlab/src/rename/latex_command.rs @@ -0,0 +1,114 @@ +use crate::syntax::*; +use crate::workspace::*; +use futures_boxed::boxed; +use lsp_types::*; +use std::collections::HashMap; +use std::sync::Arc; + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct LatexCommandPrepareRenameProvider; + +impl FeatureProvider for LatexCommandPrepareRenameProvider { + type Params = TextDocumentPositionParams; + type Output = Option<Range>; + + #[boxed] + async fn execute<'a>( + &'a self, + request: &'a FeatureRequest<TextDocumentPositionParams>, + ) -> Option<Range> { + let position = request.params.position; + find_command(&request.document().tree, position).map(|cmd| cmd.range()) + } +} + +#[derive(Debug, PartialEq, Eq, Clone, Copy)] +pub struct LatexCommandRenameProvider; + +impl FeatureProvider for LatexCommandRenameProvider { + type Params = RenameParams; + type Output = Option<WorkspaceEdit>; + + #[boxed] + async fn execute<'a>( + &'a self, + request: &'a FeatureRequest<RenameParams>, + ) -> Option<WorkspaceEdit> { + let command = find_command( + &request.document().tree, + request.params.text_document_position.position, + )?; + let mut changes = HashMap::new(); + for document in request.related_documents() { + if let SyntaxTree::Latex(tree) = &document.tree { + let edits: Vec<TextEdit> = tree + .commands + .iter() + .filter(|cmd| cmd.name.text() == command.name.text()) + .map(|cmd| { + TextEdit::new(cmd.name.range(), format!("\\{}", request.params.new_name)) + }) + .collect(); + changes.insert(document.uri.clone().into(), edits); + } + } + Some(WorkspaceEdit::new(changes)) + } +} + +fn find_command(tree: &SyntaxTree, position: Position) -> Option<Arc<LatexCommand>> { + if let SyntaxTree::Latex(tree) = tree { + tree.find_command_by_name(position) + } else { + None + } +} + +#[cfg(test)] +mod tests { + use super::*; + use crate::range::RangeExt; + use lsp_types::{Position, Range}; + + #[test] + fn test() { + let edit = test_feature( + LatexCommandRenameProvider, + FeatureSpec { + files: vec![ + FeatureSpec::file("foo.tex", "\\include{bar.tex}\n\\baz"), + FeatureSpec::file("bar.tex", "\\baz"), + ], + main_file: "foo.tex", + position: Position::new(1, 2), + new_name: "qux", + ..FeatureSpec::default() + }, + ); + let mut changes = HashMap::new(); + changes.insert( + FeatureSpec::uri("foo.tex"), + vec![TextEdit::new(Range::new_simple(1, 0, 1, 4), "\\qux".into())], + ); + changes.insert( + FeatureSpec::uri("bar.tex"), + vec![TextEdit::new(Range::new_simple(0, 0, 0, 4), "\\qux".into())], + ); + assert_eq!(edit, Some(WorkspaceEdit::new(changes))); + } + + #[test] + fn test_bibtex() { + let edit = test_feature( + LatexCommandRenameProvider, + FeatureSpec { + files: vec![FeatureSpec::file("foo.bib", "@article{foo, bar = baz}")], + main_file: "foo.bib", + position: Position::new(0, 14), + new_name: "qux", + ..FeatureSpec::default() + }, + ); + assert_eq!(edit, None); + } +} |