@@ -29,7 +29,9 @@ pub(crate) fn complete_item_list(
29
29
kind : & ItemListKind ,
30
30
) {
31
31
let _p = tracing:: info_span!( "complete_item_list" ) . entered ( ) ;
32
- if path_ctx. is_trivial_path ( ) {
32
+
33
+ // We handle completions for trait-impls in [`item_list::trait_impl`]
34
+ if path_ctx. is_trivial_path ( ) && !matches ! ( kind, ItemListKind :: TraitImpl ( _) ) {
33
35
add_keywords ( acc, ctx, Some ( kind) ) ;
34
36
}
35
37
@@ -75,73 +77,95 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option
75
77
76
78
let in_item_list = matches ! ( kind, Some ( ItemListKind :: SourceFile | ItemListKind :: Module ) | None ) ;
77
79
let in_assoc_non_trait_impl = matches ! ( kind, Some ( ItemListKind :: Impl | ItemListKind :: Trait ) ) ;
78
- let in_extern_block = matches ! ( kind, Some ( ItemListKind :: ExternBlock ) ) ;
80
+
81
+ let in_extern_block = matches ! ( kind, Some ( ItemListKind :: ExternBlock { .. } ) ) ;
82
+ let in_unsafe_extern_block =
83
+ matches ! ( kind, Some ( ItemListKind :: ExternBlock { is_unsafe: true } ) ) ;
84
+
79
85
let in_trait = matches ! ( kind, Some ( ItemListKind :: Trait ) ) ;
80
- let in_trait_impl = matches ! ( kind, Some ( ItemListKind :: TraitImpl ( _) ) ) ;
81
86
let in_inherent_impl = matches ! ( kind, Some ( ItemListKind :: Impl ) ) ;
82
- let no_vis_qualifiers = ctx. qualifier_ctx . vis_node . is_none ( ) ;
83
87
let in_block = kind. is_none ( ) ;
84
88
85
- let missing_qualifiers = [
86
- ctx. qualifier_ctx . unsafe_tok . is_none ( ) . then_some ( ( "unsafe" , "unsafe $0" ) ) ,
87
- ctx. qualifier_ctx . async_tok . is_none ( ) . then_some ( ( "async" , "async $0" ) ) ,
88
- ] ;
89
-
90
- if !in_trait_impl {
91
- // handle qualifier tokens
92
- if missing_qualifiers. iter ( ) . any ( Option :: is_none) {
93
- // only complete missing qualifiers
94
- missing_qualifiers. iter ( ) . filter_map ( |x| * x) . for_each ( |( kw, snippet) | {
95
- add_keyword ( kw, snippet) ;
96
- } ) ;
97
-
98
- if in_item_list || in_assoc_non_trait_impl {
99
- add_keyword ( "fn" , "fn $1($2) {\n $0\n }" ) ;
100
- }
89
+ let no_vis_qualifiers = ctx. qualifier_ctx . vis_node . is_none ( ) ;
90
+ let has_unsafe_kw = ctx. qualifier_ctx . unsafe_tok . is_some ( ) ;
91
+ let has_async_kw = ctx. qualifier_ctx . async_tok . is_some ( ) ;
92
+ let has_safe_kw = ctx. qualifier_ctx . safe_tok . is_some ( ) ;
93
+
94
+ // Some keywords are invalid after non-vis qualifiers, so we handle them first.
95
+ if ( has_unsafe_kw || has_safe_kw) && in_extern_block {
96
+ add_keyword ( "fn" , "fn $1($2);" ) ;
97
+ add_keyword ( "static" , "static $1: $2;" ) ;
98
+ return ;
99
+ }
101
100
102
- if ctx. qualifier_ctx . unsafe_tok . is_some ( ) && in_item_list {
103
- add_keyword ( "trait" , "trait $1 {\n $0\n }" ) ;
104
- if no_vis_qualifiers {
105
- add_keyword ( "impl" , "impl $1 {\n $0\n }" ) ;
106
- }
107
- }
101
+ if has_unsafe_kw || has_async_kw {
102
+ if !has_unsafe_kw {
103
+ add_keyword ( "unsafe" , "unsafe $0" ) ;
104
+ }
105
+ if !has_async_kw {
106
+ add_keyword ( "async" , "async $0" ) ;
107
+ }
108
108
109
- return ;
109
+ if in_item_list || in_assoc_non_trait_impl {
110
+ add_keyword ( "fn" , "fn $1($2) {\n $0\n }" ) ;
110
111
}
111
112
112
- if in_item_list {
113
- add_keyword ( "enum" , "enum $1 {\n $0\n }" ) ;
114
- add_keyword ( "mod" , "mod $0" ) ;
115
- add_keyword ( "static" , "static $0" ) ;
116
- add_keyword ( "struct" , "struct $0" ) ;
113
+ if has_unsafe_kw && in_item_list {
117
114
add_keyword ( "trait" , "trait $1 {\n $0\n }" ) ;
118
- add_keyword ( "union" , "union $1 {\n $0\n }" ) ;
119
- add_keyword ( "use" , "use $0" ) ;
120
115
if no_vis_qualifiers {
121
116
add_keyword ( "impl" , "impl $1 {\n $0\n }" ) ;
122
117
}
123
118
}
124
119
125
- if !in_trait && !in_block && no_vis_qualifiers {
126
- add_keyword ( "pub(crate)" , "pub(crate) $0" ) ;
127
- add_keyword ( "pub(super)" , "pub(super) $0" ) ;
128
- add_keyword ( "pub" , "pub $0" ) ;
120
+ if !has_async_kw && no_vis_qualifiers && in_item_list {
121
+ add_keyword ( "extern" , "extern $0" ) ;
129
122
}
130
123
131
- if in_extern_block {
132
- add_keyword ( "fn" , "fn $1($2);" ) ;
133
- } else {
134
- if !in_inherent_impl {
135
- if !in_trait {
136
- add_keyword ( "extern" , "extern $0" ) ;
137
- }
138
- add_keyword ( "type" , "type $0" ) ;
139
- }
124
+ return ;
125
+ }
140
126
141
- add_keyword ( "fn" , "fn $1($2) {\n $0\n }" ) ;
142
- add_keyword ( "unsafe" , "unsafe $0" ) ;
143
- add_keyword ( "const" , "const $0" ) ;
144
- add_keyword ( "async" , "async $0" ) ;
127
+ // ...and the rest deals with cases without any non-vis qualifiers.
128
+
129
+ // Visibility qualifiers
130
+ if !in_trait && !in_block && no_vis_qualifiers {
131
+ add_keyword ( "pub(crate)" , "pub(crate) $0" ) ;
132
+ add_keyword ( "pub(super)" , "pub(super) $0" ) ;
133
+ add_keyword ( "pub" , "pub $0" ) ;
134
+ }
135
+
136
+ // Keywords that are valid in `item_list`
137
+ if in_item_list {
138
+ add_keyword ( "enum" , "enum $1 {\n $0\n }" ) ;
139
+ add_keyword ( "mod" , "mod $0" ) ;
140
+ add_keyword ( "static" , "static $0" ) ;
141
+ add_keyword ( "struct" , "struct $0" ) ;
142
+ add_keyword ( "trait" , "trait $1 {\n $0\n }" ) ;
143
+ add_keyword ( "union" , "union $1 {\n $0\n }" ) ;
144
+ add_keyword ( "use" , "use $0" ) ;
145
+ if no_vis_qualifiers {
146
+ add_keyword ( "impl" , "impl $1 {\n $0\n }" ) ;
147
+ }
148
+ }
149
+
150
+ if in_extern_block {
151
+ add_keyword ( "unsafe" , "unsafe $0" ) ;
152
+ if in_unsafe_extern_block {
153
+ add_keyword ( "safe" , "safe $0" ) ;
145
154
}
155
+
156
+ add_keyword ( "fn" , "fn $1($2);" ) ;
157
+ add_keyword ( "static" , "static $1: $2;" ) ;
158
+ } else {
159
+ if !in_inherent_impl {
160
+ if !in_trait {
161
+ add_keyword ( "extern" , "extern $0" ) ;
162
+ }
163
+ add_keyword ( "type" , "type $0" ) ;
164
+ }
165
+
166
+ add_keyword ( "fn" , "fn $1($2) {\n $0\n }" ) ;
167
+ add_keyword ( "unsafe" , "unsafe $0" ) ;
168
+ add_keyword ( "const" , "const $0" ) ;
169
+ add_keyword ( "async" , "async $0" ) ;
146
170
}
147
171
}
0 commit comments