1
1
//! Completion of names from the current scope in expression position.
2
2
3
3
use hir:: ScopeDef ;
4
+ use ide_db:: FxHashSet ;
4
5
5
6
use crate :: {
6
7
context:: { PathCompletionCtx , PathKind , PathQualifierCtx } ,
@@ -20,8 +21,129 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
20
21
_ => return ,
21
22
} ;
22
23
24
+ let scope_def_applicable = |def| {
25
+ use hir:: { GenericParam :: * , ModuleDef :: * } ;
26
+ match def {
27
+ ScopeDef :: GenericParam ( LifetimeParam ( _) ) | ScopeDef :: Label ( _) => false ,
28
+ // Don't suggest attribute macros and derives.
29
+ ScopeDef :: ModuleDef ( Macro ( mac) ) => mac. is_fn_like ( ctx. db ) ,
30
+ _ => true ,
31
+ }
32
+ } ;
33
+
23
34
match qualifier {
24
- Some ( PathQualifierCtx { .. } ) => return ,
35
+ Some ( PathQualifierCtx { is_infer_qualifier, resolution, .. } ) => {
36
+ if * is_infer_qualifier {
37
+ ctx. traits_in_scope ( )
38
+ . 0
39
+ . into_iter ( )
40
+ . flat_map ( |it| hir:: Trait :: from ( it) . items ( ctx. sema . db ) )
41
+ . for_each ( |item| add_assoc_item ( acc, ctx, item) ) ;
42
+ return ;
43
+ }
44
+ let resolution = match resolution {
45
+ Some ( it) => it,
46
+ None => return ,
47
+ } ;
48
+ // Add associated types on type parameters and `Self`.
49
+ ctx. scope . assoc_type_shorthand_candidates ( resolution, |_, alias| {
50
+ acc. add_type_alias ( ctx, alias) ;
51
+ None :: < ( ) >
52
+ } ) ;
53
+ match resolution {
54
+ hir:: PathResolution :: Def ( hir:: ModuleDef :: Module ( module) ) => {
55
+ let module_scope = module. scope ( ctx. db , Some ( ctx. module ) ) ;
56
+ for ( name, def) in module_scope {
57
+ if scope_def_applicable ( def) {
58
+ acc. add_resolution ( ctx, name, def) ;
59
+ }
60
+ }
61
+ }
62
+
63
+ hir:: PathResolution :: Def (
64
+ def @ ( hir:: ModuleDef :: Adt ( _)
65
+ | hir:: ModuleDef :: TypeAlias ( _)
66
+ | hir:: ModuleDef :: BuiltinType ( _) ) ,
67
+ ) => {
68
+ if let & hir:: ModuleDef :: Adt ( hir:: Adt :: Enum ( e) ) = def {
69
+ add_enum_variants ( acc, ctx, e) ;
70
+ }
71
+ let ty = match def {
72
+ hir:: ModuleDef :: Adt ( adt) => adt. ty ( ctx. db ) ,
73
+ hir:: ModuleDef :: TypeAlias ( a) => {
74
+ let ty = a. ty ( ctx. db ) ;
75
+ if let Some ( hir:: Adt :: Enum ( e) ) = ty. as_adt ( ) {
76
+ cov_mark:: hit!( completes_variant_through_alias) ;
77
+ add_enum_variants ( acc, ctx, e) ;
78
+ }
79
+ ty
80
+ }
81
+ hir:: ModuleDef :: BuiltinType ( builtin) => {
82
+ cov_mark:: hit!( completes_primitive_assoc_const) ;
83
+ builtin. ty ( ctx. db )
84
+ }
85
+ _ => unreachable ! ( ) ,
86
+ } ;
87
+
88
+ // XXX: For parity with Rust bug #22519, this does not complete Ty::AssocType.
89
+ // (where AssocType is defined on a trait, not an inherent impl)
90
+
91
+ ty. iterate_path_candidates (
92
+ ctx. db ,
93
+ & ctx. scope ,
94
+ & ctx. traits_in_scope ( ) . 0 ,
95
+ Some ( ctx. module ) ,
96
+ None ,
97
+ |item| {
98
+ add_assoc_item ( acc, ctx, item) ;
99
+ None :: < ( ) >
100
+ } ,
101
+ ) ;
102
+
103
+ // Iterate assoc types separately
104
+ ty. iterate_assoc_items ( ctx. db , ctx. krate , |item| {
105
+ if let hir:: AssocItem :: TypeAlias ( ty) = item {
106
+ acc. add_type_alias ( ctx, ty)
107
+ }
108
+ None :: < ( ) >
109
+ } ) ;
110
+ }
111
+ hir:: PathResolution :: Def ( hir:: ModuleDef :: Trait ( t) ) => {
112
+ // Handles `Trait::assoc` as well as `<Ty as Trait>::assoc`.
113
+ for item in t. items ( ctx. db ) {
114
+ add_assoc_item ( acc, ctx, item) ;
115
+ }
116
+ }
117
+ hir:: PathResolution :: TypeParam ( _) | hir:: PathResolution :: SelfType ( _) => {
118
+ let ty = match resolution {
119
+ hir:: PathResolution :: TypeParam ( param) => param. ty ( ctx. db ) ,
120
+ hir:: PathResolution :: SelfType ( impl_def) => impl_def. self_ty ( ctx. db ) ,
121
+ _ => return ,
122
+ } ;
123
+
124
+ if let Some ( hir:: Adt :: Enum ( e) ) = ty. as_adt ( ) {
125
+ add_enum_variants ( acc, ctx, e) ;
126
+ }
127
+ let mut seen = FxHashSet :: default ( ) ;
128
+ ty. iterate_path_candidates (
129
+ ctx. db ,
130
+ & ctx. scope ,
131
+ & ctx. traits_in_scope ( ) . 0 ,
132
+ Some ( ctx. module ) ,
133
+ None ,
134
+ |item| {
135
+ // We might iterate candidates of a trait multiple times here, so deduplicate
136
+ // them.
137
+ if seen. insert ( item) {
138
+ add_assoc_item ( acc, ctx, item) ;
139
+ }
140
+ None :: < ( ) >
141
+ } ,
142
+ ) ;
143
+ }
144
+ _ => ( ) ,
145
+ }
146
+ }
25
147
None if is_absolute_path => acc. add_crate_roots ( ctx) ,
26
148
None => {
27
149
acc. add_nameref_keywords_with_colon ( ctx) ;
@@ -33,17 +155,22 @@ pub(crate) fn complete_expr_path(acc: &mut Completions, ctx: &CompletionContext)
33
155
} ) ;
34
156
}
35
157
ctx. process_all_names ( & mut |name, def| {
36
- use hir:: { GenericParam :: * , ModuleDef :: * } ;
37
- let add_resolution = match def {
38
- ScopeDef :: GenericParam ( LifetimeParam ( _) ) | ScopeDef :: Label ( _) => false ,
39
- // Don't suggest attribute macros and derives.
40
- ScopeDef :: ModuleDef ( Macro ( mac) ) => mac. is_fn_like ( ctx. db ) ,
41
- _ => true ,
42
- } ;
43
- if add_resolution {
158
+ if scope_def_applicable ( def) {
44
159
acc. add_resolution ( ctx, name, def) ;
45
160
}
46
161
} ) ;
47
162
}
48
163
}
49
164
}
165
+
166
+ fn add_assoc_item ( acc : & mut Completions , ctx : & CompletionContext , item : hir:: AssocItem ) {
167
+ match item {
168
+ hir:: AssocItem :: Function ( func) => acc. add_function ( ctx, func, None ) ,
169
+ hir:: AssocItem :: Const ( ct) => acc. add_const ( ctx, ct) ,
170
+ hir:: AssocItem :: TypeAlias ( ty) => acc. add_type_alias ( ctx, ty) ,
171
+ }
172
+ }
173
+
174
+ fn add_enum_variants ( acc : & mut Completions , ctx : & CompletionContext , e : hir:: Enum ) {
175
+ e. variants ( ctx. db ) . into_iter ( ) . for_each ( |variant| acc. add_enum_variant ( ctx, variant, None ) ) ;
176
+ }
0 commit comments