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, + #[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, 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);