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
This commit is contained in:
bors 2022-08-23 12:30:50 +00:00
commit 631ed2a518
5 changed files with 41 additions and 16 deletions

View File

@ -64,8 +64,11 @@ pub(crate) struct PathCompletionCtx {
pub(super) qualified: Qualified, pub(super) qualified: Qualified,
/// The parent of the path we are completing. /// The parent of the path we are completing.
pub(super) parent: Option<ast::Path>, pub(super) parent: Option<ast::Path>,
#[allow(dead_code)]
/// The path of which we are completing the segment /// The path of which we are completing the segment
pub(super) path: ast::Path, 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, pub(super) kind: PathKind,
/// Whether the path segment has type args or not. /// Whether the path segment has type args or not.
pub(super) has_type_args: bool, pub(super) has_type_args: bool,

View File

@ -588,12 +588,15 @@ impl<'a> CompletionContext<'a> {
}; };
let path = segment.parent_path(); let path = segment.parent_path();
let original_path = find_node_in_file_compensated(sema, original_file, &path);
let mut path_ctx = PathCompletionCtx { let mut path_ctx = PathCompletionCtx {
has_call_parens: false, has_call_parens: false,
has_macro_bang: false, has_macro_bang: false,
qualified: Qualified::No, qualified: Qualified::No,
parent: None, parent: None,
path: path.clone(), path: path.clone(),
original_path,
kind: PathKind::Item { kind: ItemListKind::SourceFile }, kind: PathKind::Item { kind: ItemListKind::SourceFile },
has_type_args: false, has_type_args: false,
use_tree_parent: false, use_tree_parent: false,

View File

@ -323,9 +323,7 @@ fn render_resolution_path(
..CompletionRelevance::default() ..CompletionRelevance::default()
}); });
if let Some(ref_match) = compute_ref_match(completion, &ty) { path_ref_match(completion, path_ctx, &ty, &mut item);
item.ref_match(ref_match, path_ctx.path.syntax().text_range().start());
}
}; };
item item
} }
@ -453,6 +451,29 @@ fn compute_ref_match(
None 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)] #[cfg(test)]
mod tests { mod tests {
use std::cmp; use std::cmp;

View File

@ -79,18 +79,18 @@ fn render(
..ctx.completion_relevance() ..ctx.completion_relevance()
}); });
if let Some(ref_match) = compute_ref_match(completion, &ret_type) { match func_kind {
match func_kind { FuncKind::Function(path_ctx) => {
FuncKind::Function(path_ctx) => { super::path_ref_match(completion, path_ctx, &ret_type, &mut item);
item.ref_match(ref_match, path_ctx.path.syntax().text_range().start()); }
} FuncKind::Method(DotAccess { receiver: Some(receiver), .. }, _) => {
FuncKind::Method(DotAccess { receiver: Some(receiver), .. }, _) => { if let Some(original_expr) = completion.sema.original_ast_node(receiver.clone()) {
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.ref_match(ref_match, original_expr.syntax().text_range().start());
} }
} }
_ => (),
} }
_ => (),
} }
item.set_documentation(ctx.docs(func)) item.set_documentation(ctx.docs(func))

View File

@ -2,13 +2,12 @@
use hir::{db::HirDatabase, Documentation, HasAttrs, StructKind}; use hir::{db::HirDatabase, Documentation, HasAttrs, StructKind};
use ide_db::SymbolKind; use ide_db::SymbolKind;
use syntax::AstNode;
use crate::{ use crate::{
context::{CompletionContext, PathCompletionCtx, PathKind}, context::{CompletionContext, PathCompletionCtx, PathKind},
item::{Builder, CompletionItem}, item::{Builder, CompletionItem},
render::{ render::{
compute_ref_match, compute_type_match, compute_type_match,
variant::{ variant::{
format_literal_label, format_literal_lookup, render_record_lit, render_tuple_lit, format_literal_label, format_literal_lookup, render_record_lit, render_tuple_lit,
visible_fields, RenderedLiteral, visible_fields, RenderedLiteral,
@ -125,9 +124,8 @@ fn render(
type_match: compute_type_match(ctx.completion, &ty), type_match: compute_type_match(ctx.completion, &ty),
..ctx.completion_relevance() ..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 { if let Some(import_to_add) = ctx.import_to_add {
item.add_import(import_to_add); item.add_import(import_to_add);