diff options
Diffstat (limited to 'support/texlab/src/features/rename/entry.rs')
-rw-r--r-- | support/texlab/src/features/rename/entry.rs | 131 |
1 files changed, 28 insertions, 103 deletions
diff --git a/support/texlab/src/features/rename/entry.rs b/support/texlab/src/features/rename/entry.rs index 4861b63570..6eac79030b 100644 --- a/support/texlab/src/features/rename/entry.rs +++ b/support/texlab/src/features/rename/entry.rs @@ -1,7 +1,8 @@ -use std::collections::HashMap; +use std::sync::Arc; -use lsp_types::{Range, RenameParams, TextEdit, WorkspaceEdit}; -use rowan::ast::AstNode; +use lsp_types::RenameParams; +use rowan::{ast::AstNode, TextRange}; +use rustc_hash::FxHashMap; use crate::{ features::cursor::{CursorContext, HasPosition}, @@ -9,139 +10,63 @@ use crate::{ bibtex::{self, HasName}, latex, }, - DocumentData, LineIndexExt, + DocumentData, }; -pub fn prepare_entry_rename<P: HasPosition>(context: &CursorContext<P>) -> Option<Range> { +use super::{Indel, RenameResult}; + +pub(super) fn prepare_entry_rename<P: HasPosition>( + context: &CursorContext<P>, +) -> Option<TextRange> { let (_, range) = context .find_citation_key_word() .or_else(|| context.find_entry_key())?; - Some( - context - .request - .main_document() - .line_index - .line_col_lsp_range(range), - ) + Some(range) } -pub fn rename_entry(context: &CursorContext<RenameParams>) -> Option<WorkspaceEdit> { +pub(super) fn rename_entry(context: &CursorContext<RenameParams>) -> Option<RenameResult> { prepare_entry_rename(context)?; let (key_text, _) = context .find_citation_key_word() .or_else(|| context.find_entry_key())?; - let mut changes = HashMap::new(); + let mut changes = FxHashMap::default(); for document in context.request.workspace.documents_by_uri.values() { + let uri = Arc::clone(&document.uri); match &document.data { DocumentData::Latex(data) => { - let edits: Vec<_> = latex::SyntaxNode::new_root(data.green.clone()) + let root = latex::SyntaxNode::new_root(data.green.clone()); + let edits: Vec<_> = root .descendants() .filter_map(latex::Citation::cast) .filter_map(|citation| citation.key_list()) .flat_map(|keys| keys.keys()) .filter(|key| key.to_string() == key_text) - .map(|key| { - document - .line_index - .line_col_lsp_range(latex::small_range(&key)) + .map(|key| Indel { + delete: latex::small_range(&key), + insert: context.request.params.new_name.clone(), }) - .map(|range| TextEdit::new(range, context.request.params.new_name.clone())) .collect(); - changes.insert(document.uri.as_ref().clone(), edits); + changes.insert(uri, edits); } DocumentData::Bibtex(data) => { - let edits: Vec<_> = bibtex::SyntaxNode::new_root(data.green.clone()) + let root = bibtex::SyntaxNode::new_root(data.green.clone()); + let edits: Vec<_> = root .descendants() .filter_map(bibtex::Entry::cast) .filter_map(|entry| entry.name_token()) .filter(|key| key.text() == key_text) - .map(|key| document.line_index.line_col_lsp_range(key.text_range())) - .map(|range| TextEdit::new(range, context.request.params.new_name.clone())) + .map(|key| Indel { + delete: key.text_range(), + insert: context.request.params.new_name.clone(), + }) .collect(); - changes.insert(document.uri.as_ref().clone(), edits); + changes.insert(uri, edits); } DocumentData::BuildLog(_) => {} } } - Some(WorkspaceEdit::new(changes)) -} - -#[cfg(test)] -mod tests { - use lsp_types::TextEdit; - - use crate::{features::testing::FeatureTester, RangeExt}; - - use super::*; - - #[test] - fn test_entry() { - let tester = FeatureTester::builder() - .files(vec![ - ("main.bib", r#"@article{foo, bar = baz}"#), - ("main.tex", "\\addbibresource{main.bib}\n\\cite{foo}"), - ]) - .main("main.bib") - .line(0) - .character(9) - .new_name("qux") - .build(); - - let uri1 = tester.uri("main.bib"); - let uri2 = tester.uri("main.tex"); - let request = tester.rename(); - - let context = CursorContext::new(request); - let actual_edit = rename_entry(&context).unwrap(); - - let mut expected_changes = HashMap::new(); - expected_changes.insert( - uri1.as_ref().clone(), - vec![TextEdit::new(Range::new_simple(0, 9, 0, 12), "qux".into())], - ); - expected_changes.insert( - uri2.as_ref().clone(), - vec![TextEdit::new(Range::new_simple(1, 6, 1, 9), "qux".into())], - ); - let expected_edit = WorkspaceEdit::new(expected_changes); - - assert_eq!(actual_edit, expected_edit); - } - - #[test] - fn test_citation() { - let tester = FeatureTester::builder() - .files(vec![ - ("main.bib", r#"@article{foo, bar = baz}"#), - ("main.tex", "\\addbibresource{main.bib}\n\\cite{foo}"), - ]) - .main("main.tex") - .line(1) - .character(6) - .new_name("qux") - .build(); - - let uri1 = tester.uri("main.bib"); - let uri2 = tester.uri("main.tex"); - let request = tester.rename(); - - let context = CursorContext::new(request); - let actual_edit = rename_entry(&context).unwrap(); - - let mut expected_changes = HashMap::new(); - expected_changes.insert( - uri1.as_ref().clone(), - vec![TextEdit::new(Range::new_simple(0, 9, 0, 12), "qux".into())], - ); - expected_changes.insert( - uri2.as_ref().clone(), - vec![TextEdit::new(Range::new_simple(1, 6, 1, 9), "qux".into())], - ); - let expected_edit = WorkspaceEdit::new(expected_changes); - - assert_eq!(actual_edit, expected_edit); - } + Some(RenameResult { changes }) } |