Skip to content

Commit 735b542

Browse files
bors[bot]Veykril
andauthored
Merge #11201
11201: fix: Fix completions not considering ancestor items for attribute search r=Veykril a=Veykril Turns out we never filled the `CompletionContext` with the attribute expansion of attributed impls and traits when typing in the assoc items, as we were only considering the assoc item to have an attribute to expand. bors r+ Co-authored-by: Lukas Wirth <[email protected]>
2 parents 149981f + bd91327 commit 735b542

File tree

1 file changed

+40
-27
lines changed

1 file changed

+40
-27
lines changed

crates/ide_completion/src/context.rs

Lines changed: 40 additions & 27 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
//! See `CompletionContext` structure.
22
3+
use std::iter;
4+
35
use base_db::SourceDatabaseExt;
46
use hir::{Local, Name, ScopeDef, Semantics, SemanticsScope, Type, TypeInfo};
57
use ide_db::{
@@ -431,12 +433,17 @@ impl<'a> CompletionContext<'a> {
431433
mut fake_ident_token: SyntaxToken,
432434
) {
433435
let _p = profile::span("CompletionContext::expand_and_fill");
434-
loop {
435-
// Expand attributes
436-
if let (Some(actual_item), Some(item_with_fake_ident)) = (
437-
find_node_at_offset::<ast::Item>(&original_file, offset),
438-
find_node_at_offset::<ast::Item>(&speculative_file, offset),
439-
) {
436+
'expansion: loop {
437+
let parent_item =
438+
|item: &ast::Item| item.syntax().ancestors().skip(1).find_map(ast::Item::cast);
439+
let ancestor_items = iter::successors(
440+
Option::zip(
441+
find_node_at_offset::<ast::Item>(&original_file, offset),
442+
find_node_at_offset::<ast::Item>(&speculative_file, offset),
443+
),
444+
|(a, b)| parent_item(a).zip(parent_item(b)),
445+
);
446+
for (actual_item, item_with_fake_ident) in ancestor_items {
440447
match (
441448
self.sema.expand_attr_macro(&actual_item),
442449
self.sema.speculative_expand_attr_macro(
@@ -445,19 +452,22 @@ impl<'a> CompletionContext<'a> {
445452
fake_ident_token.clone(),
446453
),
447454
) {
448-
(Some(actual_expansion), Some(speculative_expansion)) => {
449-
let new_offset = speculative_expansion.1.text_range().start();
455+
// maybe parent items have attributes
456+
(None, None) => (),
457+
// successful expansions
458+
(Some(actual_expansion), Some((fake_expansion, fake_mapped_token))) => {
459+
let new_offset = fake_mapped_token.text_range().start();
450460
if new_offset > actual_expansion.text_range().end() {
451-
break;
461+
break 'expansion;
452462
}
453463
original_file = actual_expansion;
454-
speculative_file = speculative_expansion.0;
455-
fake_ident_token = speculative_expansion.1;
464+
speculative_file = fake_expansion;
465+
fake_ident_token = fake_mapped_token;
456466
offset = new_offset;
457-
continue;
467+
continue 'expansion;
458468
}
459-
(None, None) => (),
460-
_ => break,
469+
// exactly one expansion failed, inconsistent state so stop expanding completely
470+
_ => break 'expansion,
461471
}
462472
}
463473

@@ -477,28 +487,31 @@ impl<'a> CompletionContext<'a> {
477487
None => break,
478488
};
479489

480-
if let (Some(actual_expansion), Some(speculative_expansion)) = (
490+
match (
481491
self.sema.expand(&actual_macro_call),
482492
self.sema.speculative_expand(
483493
&actual_macro_call,
484494
&speculative_args,
485-
fake_ident_token,
495+
fake_ident_token.clone(),
486496
),
487497
) {
488-
let new_offset = speculative_expansion.1.text_range().start();
489-
if new_offset > actual_expansion.text_range().end() {
490-
break;
498+
// successful expansions
499+
(Some(actual_expansion), Some((fake_expansion, fake_mapped_token))) => {
500+
let new_offset = fake_mapped_token.text_range().start();
501+
if new_offset > actual_expansion.text_range().end() {
502+
break;
503+
}
504+
original_file = actual_expansion;
505+
speculative_file = fake_expansion;
506+
fake_ident_token = fake_mapped_token;
507+
offset = new_offset;
508+
continue;
491509
}
492-
original_file = actual_expansion;
493-
speculative_file = speculative_expansion.0;
494-
fake_ident_token = speculative_expansion.1;
495-
offset = new_offset;
496-
} else {
497-
break;
510+
_ => break,
498511
}
499-
} else {
500-
break;
501512
}
513+
514+
break;
502515
}
503516

504517
self.fill(&original_file, speculative_file, offset);

0 commit comments

Comments
 (0)