aboutsummaryrefslogtreecommitdiff
path: root/crates
diff options
context:
space:
mode:
Diffstat (limited to 'crates')
-rw-r--r--crates/completion/src/lib.rs6
-rw-r--r--crates/ide/src/lib.rs1
-rw-r--r--crates/rust-analyzer/src/handlers.rs56
-rw-r--r--crates/rust-analyzer/src/lsp_utils.rs8
4 files changed, 35 insertions, 36 deletions
diff --git a/crates/completion/src/lib.rs b/crates/completion/src/lib.rs
index 938c92dbb..066d589af 100644
--- a/crates/completion/src/lib.rs
+++ b/crates/completion/src/lib.rs
@@ -141,7 +141,7 @@ pub fn resolve_completion_edits(
141 position: FilePosition, 141 position: FilePosition,
142 full_import_path: &str, 142 full_import_path: &str,
143 imported_name: &str, 143 imported_name: &str,
144) -> Option<TextEdit> { 144) -> Option<Vec<TextEdit>> {
145 let ctx = CompletionContext::new(db, position, config)?; 145 let ctx = CompletionContext::new(db, position, config)?;
146 let anchor = ctx.name_ref_syntax.as_ref()?; 146 let anchor = ctx.name_ref_syntax.as_ref()?;
147 let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?; 147 let import_scope = ImportScope::find_insert_use_container(anchor.syntax(), &ctx.sema)?;
@@ -156,7 +156,9 @@ pub fn resolve_completion_edits(
156 }) 156 })
157 .find(|mod_path| mod_path.to_string() == full_import_path)?; 157 .find(|mod_path| mod_path.to_string() == full_import_path)?;
158 158
159 ImportEdit { import_path, import_scope, merge_behaviour: config.merge }.to_text_edit() 159 ImportEdit { import_path, import_scope, merge_behaviour: config.merge }
160 .to_text_edit()
161 .map(|edit| vec![edit])
160} 162}
161 163
162#[cfg(test)] 164#[cfg(test)]
diff --git a/crates/ide/src/lib.rs b/crates/ide/src/lib.rs
index 4a274f5ba..71068cac2 100644
--- a/crates/ide/src/lib.rs
+++ b/crates/ide/src/lib.rs
@@ -487,7 +487,6 @@ impl Analysis {
487 imported_name, 487 imported_name,
488 ) 488 )
489 })? 489 })?
490 .map(|edit| vec![edit])
491 .unwrap_or_default()) 490 .unwrap_or_default())
492 } 491 }
493 492
diff --git a/crates/rust-analyzer/src/handlers.rs b/crates/rust-analyzer/src/handlers.rs
index d6865e1d6..89c7fd2c7 100644
--- a/crates/rust-analyzer/src/handlers.rs
+++ b/crates/rust-analyzer/src/handlers.rs
@@ -8,9 +8,8 @@ use std::{
8}; 8};
9 9
10use ide::{ 10use ide::{
11 CompletionConfig, CompletionResolveCapability, FileId, FilePosition, FileRange, HoverAction, 11 CompletionResolveCapability, FileId, FilePosition, FileRange, HoverAction, HoverGotoTypeData,
12 HoverGotoTypeData, NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, SearchScope, 12 NavigationTarget, Query, RangeInfo, Runnable, RunnableKind, SearchScope, TextEdit,
13 TextEdit,
14}; 13};
15use itertools::Itertools; 14use itertools::Itertools;
16use lsp_server::ErrorCode; 15use lsp_server::ErrorCode;
@@ -578,14 +577,11 @@ pub(crate) fn handle_completion(
578 let mut new_completion_items = 577 let mut new_completion_items =
579 to_proto::completion_item(&line_index, line_endings, item.clone()); 578 to_proto::completion_item(&line_index, line_endings, item.clone());
580 579
581 for new_item in &mut new_completion_items { 580 if snap.config.completion.resolve_additional_edits_lazily() {
582 let _ = fill_resolve_data( 581 for new_item in &mut new_completion_items {
583 &mut new_item.data, 582 let _ = fill_resolve_data(&mut new_item.data, &item, &text_document_position)
584 &item, 583 .take();
585 &snap.config.completion, 584 }
586 &text_document_position,
587 )
588 .take();
589 } 585 }
590 586
591 new_completion_items 587 new_completion_items
@@ -600,12 +596,12 @@ pub(crate) fn handle_completion_resolve(
600 snap: GlobalStateSnapshot, 596 snap: GlobalStateSnapshot,
601 mut original_completion: CompletionItem, 597 mut original_completion: CompletionItem,
602) -> Result<CompletionItem> { 598) -> Result<CompletionItem> {
603 let _p = profile::span("handle_resolve_completion"); 599 let _p = profile::span("handle_completion_resolve");
604 600
605 if !all_edits_are_disjoint(&original_completion, &[]) { 601 if !all_edits_are_disjoint(&original_completion, &[]) {
606 return Err(LspError::new( 602 return Err(LspError::new(
607 ErrorCode::InvalidParams as i32, 603 ErrorCode::InvalidParams as i32,
608 "Received a completion with disjoint edits".into(), 604 "Received a completion with overlapping edits, this is not LSP-compliant".into(),
609 ) 605 )
610 .into()); 606 .into());
611 } 607 }
@@ -635,7 +631,7 @@ pub(crate) fn handle_completion_resolve(
635 let line_endings = snap.file_line_endings(file_id); 631 let line_endings = snap.file_line_endings(file_id);
636 let offset = from_proto::offset(&line_index, resolve_data.position.position); 632 let offset = from_proto::offset(&line_index, resolve_data.position.position);
637 633
638 let mut additional_edits = snap 634 let additional_edits = snap
639 .analysis 635 .analysis
640 .resolve_completion_edits( 636 .resolve_completion_edits(
641 &snap.config.completion, 637 &snap.config.completion,
@@ -652,13 +648,14 @@ pub(crate) fn handle_completion_resolve(
652 if !all_edits_are_disjoint(&original_completion, &additional_edits) { 648 if !all_edits_are_disjoint(&original_completion, &additional_edits) {
653 return Err(LspError::new( 649 return Err(LspError::new(
654 ErrorCode::InternalError as i32, 650 ErrorCode::InternalError as i32,
655 "Import edit is not disjoint with the original completion edits".into(), 651 "Import edit overlaps with the original completion edits, this is not LSP-compliant"
652 .into(),
656 ) 653 )
657 .into()); 654 .into());
658 } 655 }
659 656
660 if let Some(original_additional_edits) = original_completion.additional_text_edits.as_mut() { 657 if let Some(original_additional_edits) = original_completion.additional_text_edits.as_mut() {
661 original_additional_edits.extend(additional_edits.drain(..)) 658 original_additional_edits.extend(additional_edits.into_iter())
662 } else { 659 } else {
663 original_completion.additional_text_edits = Some(additional_edits); 660 original_completion.additional_text_edits = Some(additional_edits);
664 } 661 }
@@ -1634,22 +1631,19 @@ struct CompletionResolveData {
1634fn fill_resolve_data( 1631fn fill_resolve_data(
1635 resolve_data: &mut Option<serde_json::Value>, 1632 resolve_data: &mut Option<serde_json::Value>,
1636 item: &ide::CompletionItem, 1633 item: &ide::CompletionItem,
1637 completion_config: &CompletionConfig,
1638 position: &TextDocumentPositionParams, 1634 position: &TextDocumentPositionParams,
1639) -> Option<()> { 1635) -> Option<()> {
1640 if completion_config.resolve_additional_edits_lazily() { 1636 let import_edit = item.import_to_add()?;
1641 let import_edit = item.import_to_add()?; 1637 let full_import_path = import_edit.import_path.to_string();
1642 let full_import_path = import_edit.import_path.to_string(); 1638 let imported_name = import_edit.import_path.segments.clone().pop()?.to_string();
1643 let imported_name = import_edit.import_path.segments.clone().pop()?.to_string(); 1639
1644 1640 *resolve_data = Some(
1645 *resolve_data = Some( 1641 to_value(CompletionResolveData {
1646 to_value(CompletionResolveData { 1642 position: position.to_owned(),
1647 position: position.to_owned(), 1643 full_import_path,
1648 full_import_path, 1644 imported_name,
1649 imported_name, 1645 })
1650 }) 1646 .unwrap(),
1651 .unwrap(), 1647 );
1652 )
1653 }
1654 Some(()) 1648 Some(())
1655} 1649}
diff --git a/crates/rust-analyzer/src/lsp_utils.rs b/crates/rust-analyzer/src/lsp_utils.rs
index d5c1c1ad0..60c12e4e2 100644
--- a/crates/rust-analyzer/src/lsp_utils.rs
+++ b/crates/rust-analyzer/src/lsp_utils.rs
@@ -129,7 +129,8 @@ pub(crate) fn apply_document_changes(
129 } 129 }
130} 130}
131 131
132/// Checks that the edits inside the completion and the additional edits are disjoint. 132/// Checks that the edits inside the completion and the additional edits do not overlap.
133/// LSP explicitly forbits the additional edits to overlap both with the main edit and themselves.
133pub(crate) fn all_edits_are_disjoint( 134pub(crate) fn all_edits_are_disjoint(
134 completion: &lsp_types::CompletionItem, 135 completion: &lsp_types::CompletionItem,
135 additional_edits: &[lsp_types::TextEdit], 136 additional_edits: &[lsp_types::TextEdit],
@@ -150,7 +151,10 @@ pub(crate) fn all_edits_are_disjoint(
150 }; 151 };
151 edit_ranges.extend(additional_edits.iter().map(|edit| edit.range)); 152 edit_ranges.extend(additional_edits.iter().map(|edit| edit.range));
152 edit_ranges.sort_by_key(|range| (range.start, range.end)); 153 edit_ranges.sort_by_key(|range| (range.start, range.end));
153 edit_ranges.iter().zip(edit_ranges.iter().skip(1)).all(|(l, r)| l.end <= r.start) 154 edit_ranges
155 .iter()
156 .zip(edit_ranges.iter().skip(1))
157 .all(|(previous, next)| previous.end <= next.start)
154} 158}
155 159
156#[cfg(test)] 160#[cfg(test)]