@@ -29,7 +29,9 @@ pub(crate) fn complete_item_list(
2929 kind : & ItemListKind ,
3030) {
3131 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 ( _) ) {
3335 add_keywords ( acc, ctx, Some ( kind) ) ;
3436 }
3537
@@ -75,73 +77,95 @@ fn add_keywords(acc: &mut Completions, ctx: &CompletionContext<'_>, kind: Option
7577
7678 let in_item_list = matches ! ( kind, Some ( ItemListKind :: SourceFile | ItemListKind :: Module ) | None ) ;
7779 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+
7985 let in_trait = matches ! ( kind, Some ( ItemListKind :: Trait ) ) ;
80- let in_trait_impl = matches ! ( kind, Some ( ItemListKind :: TraitImpl ( _) ) ) ;
8186 let in_inherent_impl = matches ! ( kind, Some ( ItemListKind :: Impl ) ) ;
82- let no_vis_qualifiers = ctx. qualifier_ctx . vis_node . is_none ( ) ;
8387 let in_block = kind. is_none ( ) ;
8488
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+ }
101100
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+ }
108108
109- return ;
109+ if in_item_list || in_assoc_non_trait_impl {
110+ add_keyword ( "fn" , "fn $1($2) {\n $0\n }" ) ;
110111 }
111112
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 {
117114 add_keyword ( "trait" , "trait $1 {\n $0\n }" ) ;
118- add_keyword ( "union" , "union $1 {\n $0\n }" ) ;
119- add_keyword ( "use" , "use $0" ) ;
120115 if no_vis_qualifiers {
121116 add_keyword ( "impl" , "impl $1 {\n $0\n }" ) ;
122117 }
123118 }
124119
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" ) ;
129122 }
130123
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+ }
140126
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" ) ;
145154 }
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" ) ;
146170 }
147171}
0 commit comments