mirror of
				https://github.com/rust-lang/rust-analyzer.git
				synced 2025-11-03 13:13:18 +00:00 
			
		
		
		
	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:
		
							parent
							
								
									dea163970a
								
							
						
					
					
						commit
						6c5d15800e
					
				@ -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,
 | 
			
		||||
 | 
			
		||||
@ -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,
 | 
			
		||||
 | 
			
		||||
@ -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;
 | 
			
		||||
 | 
			
		||||
@ -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))
 | 
			
		||||
 | 
			
		||||
@ -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);
 | 
			
		||||
 | 
			
		||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user