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,
/// 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,

View File

@ -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,

View File

@ -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;

View File

@ -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))

View File

@ -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);