diff options
Diffstat (limited to 'crates')
-rw-r--r-- | crates/completion/src/lib.rs | 6 | ||||
-rw-r--r-- | crates/ide/src/lib.rs | 1 | ||||
-rw-r--r-- | crates/rust-analyzer/src/handlers.rs | 56 | ||||
-rw-r--r-- | crates/rust-analyzer/src/lsp_utils.rs | 8 |
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 | ||
10 | use ide::{ | 10 | use 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 | }; |
15 | use itertools::Itertools; | 14 | use itertools::Itertools; |
16 | use lsp_server::ErrorCode; | 15 | use 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 { | |||
1634 | fn fill_resolve_data( | 1631 | fn 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. | ||
133 | pub(crate) fn all_edits_are_disjoint( | 134 | pub(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)] |