about summary refs log tree commit diff
diff options
context:
space:
mode:
authorbors <bors@rust-lang.org>2022-08-23 12:30:50 +0000
committerbors <bors@rust-lang.org>2022-08-23 12:30:50 +0000
commit631ed2a518e81b73630162e1330bb0447e76c30c (patch)
tree31905797d50914ce117ae9a95efe1d5b77e72f9d
parent6627b473e2dc4aa918bceeffb6baadac5e887494 (diff)
parent6c5d15800ea3b8297bf42221c449e633ef3926d6 (diff)
downloadrust-631ed2a518e81b73630162e1330bb0447e76c30c.tar.gz
rust-631ed2a518e81b73630162e1330bb0447e76c30c.zip
Auto merge of #13092 - Veykril:ref-match-completion, r=Veykril
fix: Fix reference autocompletions using incorrect offsets in macro inputs

Fixes https://github.com/rust-lang/rust-analyzer/issues/13035
-rw-r--r--crates/ide-completion/src/context.rs3
-rw-r--r--crates/ide-completion/src/context/analysis.rs3
-rw-r--r--crates/ide-completion/src/render.rs27
-rw-r--r--crates/ide-completion/src/render/function.rs16
-rw-r--r--crates/ide-completion/src/render/literal.rs8
5 files changed, 41 insertions, 16 deletions
diff --git a/crates/ide-completion/src/context.rs b/crates/ide-completion/src/context.rs
index 759742d3472..a5e854b74df 100644
--- a/crates/ide-completion/src/context.rs
+++ b/crates/ide-completion/src/context.rs
@@ -64,8 +64,11 @@ pub(crate) struct PathCompletionCtx {
     pub(super) qualified: Qualified,
     /// The parent of the path we are completing.
     pub(super) parent: Option<ast::Path>,
+    #[allow(dead_code)]
     /// The path of which we are completing the segment
     pub(super) path: ast::Path,
+    /// The path of which we are completing the segment in the original file
+    pub(crate) original_path: Option<ast::Path>,
     pub(super) kind: PathKind,
     /// Whether the path segment has type args or not.
     pub(super) has_type_args: bool,
diff --git a/crates/ide-completion/src/context/analysis.rs b/crates/ide-completion/src/context/analysis.rs
index 22ec7cead49..01dd9a234f5 100644
--- a/crates/ide-completion/src/context/analysis.rs
+++ b/crates/ide-completion/src/context/analysis.rs
@@ -588,12 +588,15 @@ impl<'a> CompletionContext<'a> {
         };
 
         let path = segment.parent_path();
+        let original_path = find_node_in_file_compensated(sema, original_file, &path);
+
         let mut path_ctx = PathCompletionCtx {
             has_call_parens: false,
             has_macro_bang: false,
             qualified: Qualified::No,
             parent: None,
             path: path.clone(),
+            original_path,
             kind: PathKind::Item { kind: ItemListKind::SourceFile },
             has_type_args: false,
             use_tree_parent: false,
diff --git a/crates/ide-completion/src/render.rs b/crates/ide-completion/src/render.rs
index a2cf6d68e5b..86302cb0678 100644
--- a/crates/ide-completion/src/render.rs
+++ b/crates/ide-completion/src/render.rs
@@ -323,9 +323,7 @@ fn render_resolution_path(
             ..CompletionRelevance::default()
         });
 
-        if let Some(ref_match) = compute_ref_match(completion, &ty) {
-            item.ref_match(ref_match, path_ctx.path.syntax().text_range().start());
-        }
+        path_ref_match(completion, path_ctx, &ty, &mut item);
     };
     item
 }
@@ -453,6 +451,29 @@ fn compute_ref_match(
     None
 }
 
+fn path_ref_match(
+    completion: &CompletionContext<'_>,
+    path_ctx: &PathCompletionCtx,
+    ty: &hir::Type,
+    item: &mut Builder,
+) {
+    if let Some(original_path) = &path_ctx.original_path {
+        // At least one char was typed by the user already, in that case look for the original path
+        if let Some(original_path) = completion.sema.original_ast_node(original_path.clone()) {
+            if let Some(ref_match) = compute_ref_match(completion, ty) {
+                item.ref_match(ref_match, original_path.syntax().text_range().start());
+            }
+        }
+    } else {
+        // completion requested on an empty identifier, there is no path here yet.
+        // FIXME: This might create inconsistent completions where we show a ref match in macro inputs
+        // as long as nothing was typed yet
+        if let Some(ref_match) = compute_ref_match(completion, ty) {
+            item.ref_match(ref_match, completion.position.offset);
+        }
+    }
+}
+
 #[cfg(test)]
 mod tests {
     use std::cmp;
diff --git a/crates/ide-completion/src/render/function.rs b/crates/ide-completion/src/render/function.rs
index 9cf64691298..37612084604 100644
--- a/crates/ide-completion/src/render/function.rs
+++ b/crates/ide-completion/src/render/function.rs
@@ -79,18 +79,18 @@ fn render(
         ..ctx.completion_relevance()
     });
 
-    if let Some(ref_match) = compute_ref_match(completion, &ret_type) {
-        match func_kind {
-            FuncKind::Function(path_ctx) => {
-                item.ref_match(ref_match, path_ctx.path.syntax().text_range().start());
-            }
-            FuncKind::Method(DotAccess { receiver: Some(receiver), .. }, _) => {
-                if let Some(original_expr) = completion.sema.original_ast_node(receiver.clone()) {
+    match func_kind {
+        FuncKind::Function(path_ctx) => {
+            super::path_ref_match(completion, path_ctx, &ret_type, &mut item);
+        }
+        FuncKind::Method(DotAccess { receiver: Some(receiver), .. }, _) => {
+            if let Some(original_expr) = completion.sema.original_ast_node(receiver.clone()) {
+                if let Some(ref_match) = compute_ref_match(completion, &ret_type) {
                     item.ref_match(ref_match, original_expr.syntax().text_range().start());
                 }
             }
-            _ => (),
         }
+        _ => (),
     }
 
     item.set_documentation(ctx.docs(func))
diff --git a/crates/ide-completion/src/render/literal.rs b/crates/ide-completion/src/render/literal.rs
index af9c88a7e0a..0c791ac570c 100644
--- a/crates/ide-completion/src/render/literal.rs
+++ b/crates/ide-completion/src/render/literal.rs
@@ -2,13 +2,12 @@
 
 use hir::{db::HirDatabase, Documentation, HasAttrs, StructKind};
 use ide_db::SymbolKind;
-use syntax::AstNode;
 
 use crate::{
     context::{CompletionContext, PathCompletionCtx, PathKind},
     item::{Builder, CompletionItem},
     render::{
-        compute_ref_match, compute_type_match,
+        compute_type_match,
         variant::{
             format_literal_label, format_literal_lookup, render_record_lit, render_tuple_lit,
             visible_fields, RenderedLiteral,
@@ -125,9 +124,8 @@ fn render(
         type_match: compute_type_match(ctx.completion, &ty),
         ..ctx.completion_relevance()
     });
-    if let Some(ref_match) = compute_ref_match(completion, &ty) {
-        item.ref_match(ref_match, path_ctx.path.syntax().text_range().start());
-    }
+
+    super::path_ref_match(completion, path_ctx, &ty, &mut item);
 
     if let Some(import_to_add) = ctx.import_to_add {
         item.add_import(import_to_add);