Skip to content

Commit b1ab577

Browse files
committed
Enable qualifier completions for derives
1 parent 2abe19e commit b1ab577

File tree

2 files changed

+123
-83
lines changed

2 files changed

+123
-83
lines changed

crates/ide_completion/src/completions/attribute/derive.rs

Lines changed: 87 additions & 53 deletions
Original file line numberDiff line numberDiff line change
@@ -1,77 +1,111 @@
11
//! Completion for derives
2-
use hir::{HasAttrs, Macro};
2+
use hir::{HasAttrs, ScopeDef};
33
use ide_db::SymbolKind;
44
use itertools::Itertools;
55
use syntax::SmolStr;
66

77
use crate::{
8-
context::{CompletionContext, PathCompletionCtx, PathKind},
8+
context::{CompletionContext, PathCompletionCtx, PathKind, PathQualifierCtx},
99
item::CompletionItem,
1010
Completions,
1111
};
1212

1313
pub(crate) fn complete_derive(acc: &mut Completions, ctx: &CompletionContext) {
14-
match ctx.path_context {
15-
// FIXME: Enable qualified completions
16-
Some(PathCompletionCtx { kind: Some(PathKind::Derive), qualifier: None, .. }) => (),
14+
let (qualifier, is_absolute_path) = match ctx.path_context {
15+
Some(PathCompletionCtx {
16+
kind: Some(PathKind::Derive),
17+
ref qualifier,
18+
is_absolute_path,
19+
..
20+
}) => (qualifier, is_absolute_path),
1721
_ => return,
18-
}
22+
};
1923

2024
let core = ctx.famous_defs().core();
2125

22-
for (name, mac) in get_derives_in_scope(ctx) {
23-
if ctx.existing_derives.contains(&mac) {
24-
continue;
25-
}
26+
match qualifier {
27+
Some(PathQualifierCtx { resolution, is_super_chain, .. }) => {
28+
if *is_super_chain {
29+
acc.add_keyword(ctx, "super::");
30+
}
2631

27-
let name = name.to_smol_str();
28-
let (label, lookup) = match (core, mac.module(ctx.db).krate()) {
29-
// show derive dependencies for `core`/`std` derives
30-
(Some(core), mac_krate) if core == mac_krate => {
31-
if let Some(derive_completion) = DEFAULT_DERIVE_DEPENDENCIES
32-
.iter()
33-
.find(|derive_completion| derive_completion.label == name)
34-
{
35-
let mut components = vec![derive_completion.label];
36-
components.extend(derive_completion.dependencies.iter().filter(
37-
|&&dependency| {
38-
!ctx.existing_derives
39-
.iter()
40-
.map(|it| it.name(ctx.db))
41-
.any(|it| it.to_smol_str() == dependency)
42-
},
43-
));
44-
let lookup = components.join(", ");
45-
let label = Itertools::intersperse(components.into_iter().rev(), ", ");
46-
(SmolStr::from_iter(label), Some(lookup))
47-
} else {
48-
(name, None)
32+
let module = match resolution {
33+
Some(hir::PathResolution::Def(hir::ModuleDef::Module(it))) => it,
34+
_ => return,
35+
};
36+
37+
for (name, def) in module.scope(ctx.db, ctx.module) {
38+
let add_def = match def {
39+
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) => {
40+
!ctx.existing_derives.contains(&mac) && mac.is_derive(ctx.db)
41+
}
42+
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => true,
43+
_ => false,
44+
};
45+
if add_def {
46+
acc.add_resolution(ctx, name, def);
4947
}
5048
}
51-
_ => (name, None),
52-
};
53-
54-
let mut item = CompletionItem::new(SymbolKind::Derive, ctx.source_range(), label);
55-
if let Some(docs) = mac.docs(ctx.db) {
56-
item.documentation(docs);
49+
return;
5750
}
58-
if let Some(lookup) = lookup {
59-
item.lookup_by(lookup);
60-
}
61-
item.add_to(acc);
62-
}
63-
}
51+
None if is_absolute_path => acc.add_crate_roots(ctx),
52+
// only show modules in a fresh UseTree
53+
None => {
54+
ctx.process_all_names(&mut |name, def| {
55+
let mac = match def {
56+
ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac))
57+
if !ctx.existing_derives.contains(&mac) && mac.is_derive(ctx.db) =>
58+
{
59+
mac
60+
}
61+
ScopeDef::ModuleDef(hir::ModuleDef::Module(_)) => {
62+
return acc.add_resolution(ctx, name, def);
63+
}
64+
_ => return,
65+
};
6466

65-
fn get_derives_in_scope(ctx: &CompletionContext) -> Vec<(hir::Name, Macro)> {
66-
let mut result = Vec::default();
67-
ctx.process_all_names(&mut |name, scope_def| {
68-
if let hir::ScopeDef::ModuleDef(hir::ModuleDef::Macro(mac)) = scope_def {
69-
if mac.kind(ctx.db) == hir::MacroKind::Derive {
70-
result.push((name, mac));
71-
}
67+
match (core, mac.module(ctx.db).krate()) {
68+
// show derive dependencies for `core`/`std` derives
69+
(Some(core), mac_krate) if core == mac_krate && qualifier.is_none() => {}
70+
_ => return acc.add_resolution(ctx, name, def),
71+
};
72+
73+
let name_ = name.to_smol_str();
74+
let find = DEFAULT_DERIVE_DEPENDENCIES
75+
.iter()
76+
.find(|derive_completion| derive_completion.label == name_);
77+
78+
match find {
79+
Some(derive_completion) => {
80+
let mut components = vec![derive_completion.label];
81+
components.extend(derive_completion.dependencies.iter().filter(
82+
|&&dependency| {
83+
!ctx.existing_derives
84+
.iter()
85+
.map(|it| it.name(ctx.db))
86+
.any(|it| it.to_smol_str() == dependency)
87+
},
88+
));
89+
let lookup = components.join(", ");
90+
let label = Itertools::intersperse(components.into_iter().rev(), ", ");
91+
92+
let mut item = CompletionItem::new(
93+
SymbolKind::Derive,
94+
ctx.source_range(),
95+
SmolStr::from_iter(label),
96+
);
97+
if let Some(docs) = mac.docs(ctx.db) {
98+
item.documentation(docs);
99+
}
100+
item.lookup_by(lookup);
101+
item.add_to(acc);
102+
}
103+
None => acc.add_resolution(ctx, name, def),
104+
}
105+
});
106+
acc.add_nameref_keywords(ctx);
72107
}
73-
});
74-
result
108+
}
75109
}
76110

77111
struct DeriveDependencies {

crates/ide_completion/src/tests/attribute.rs

Lines changed: 36 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -688,13 +688,17 @@ mod derive {
688688
#[derive($0)] struct Test;
689689
"#,
690690
expect![[r#"
691-
de Default
691+
md core
692+
de Default pub macro Default
692693
de Clone, Copy
693-
de PartialEq
694+
de PartialEq pub macro PartialEq
694695
de PartialEq, Eq
695696
de PartialEq, Eq, PartialOrd, Ord
696-
de Clone
697+
de Clone pub macro Clone
697698
de PartialEq, PartialOrd
699+
kw self::
700+
kw super::
701+
kw crate::
698702
"#]],
699703
);
700704
}
@@ -707,12 +711,16 @@ mod derive {
707711
#[derive(serde::Serialize, PartialEq, $0)] struct Test;
708712
"#,
709713
expect![[r#"
710-
de Default
714+
md core
715+
de Default pub macro Default
711716
de Clone, Copy
712717
de Eq
713718
de Eq, PartialOrd, Ord
714-
de Clone
719+
de Clone pub macro Clone
715720
de PartialOrd
721+
kw self::
722+
kw super::
723+
kw crate::
716724
"#]],
717725
)
718726
}
@@ -725,36 +733,20 @@ mod derive {
725733
#[derive($0 serde::Serialize, PartialEq)] struct Test;
726734
"#,
727735
expect![[r#"
728-
de Default
736+
md core
737+
de Default pub macro Default
729738
de Clone, Copy
730739
de Eq
731740
de Eq, PartialOrd, Ord
732-
de Clone
741+
de Clone pub macro Clone
733742
de PartialOrd
743+
kw self::
744+
kw super::
745+
kw crate::
734746
"#]],
735747
)
736748
}
737749

738-
#[test]
739-
fn derive_no_attrs() {
740-
check_derive(
741-
r#"
742-
//- proc_macros: identity
743-
//- minicore: derive
744-
#[derive($0)] struct Test;
745-
"#,
746-
expect![[r#""#]],
747-
);
748-
check_derive(
749-
r#"
750-
//- proc_macros: identity
751-
//- minicore: derive
752-
#[derive(i$0)] struct Test;
753-
"#,
754-
expect![[r#""#]],
755-
);
756-
}
757-
758750
#[test]
759751
fn derive_flyimport() {
760752
check_derive(
@@ -764,6 +756,11 @@ mod derive {
764756
#[derive(der$0)] struct Test;
765757
"#,
766758
expect![[r#"
759+
md proc_macros
760+
md core
761+
kw self::
762+
kw super::
763+
kw crate::
767764
de DeriveIdentity (use proc_macros::DeriveIdentity) pub macro derive_identity
768765
"#]],
769766
);
@@ -775,7 +772,12 @@ use proc_macros::DeriveIdentity;
775772
#[derive(der$0)] struct Test;
776773
"#,
777774
expect![[r#"
778-
de DeriveIdentity
775+
de DeriveIdentity pub macro derive_identity
776+
md proc_macros
777+
md core
778+
kw self::
779+
kw super::
780+
kw crate::
779781
"#]],
780782
);
781783
}
@@ -805,15 +807,19 @@ use proc_macros::DeriveIdentity;
805807
//- minicore: derive, copy, clone
806808
#[derive(proc_macros::$0)] struct Test;
807809
"#,
808-
expect![[r#""#]],
810+
expect![[r#"
811+
de DeriveIdentity pub macro derive_identity
812+
"#]],
809813
);
810814
check_derive(
811815
r#"
812816
//- proc_macros: derive_identity
813817
//- minicore: derive, copy, clone
814818
#[derive(proc_macros::C$0)] struct Test;
815819
"#,
816-
expect![[r#""#]],
820+
expect![[r#"
821+
de DeriveIdentity pub macro derive_identity
822+
"#]],
817823
);
818824
}
819825
}

0 commit comments

Comments
 (0)