@@ -152,17 +152,22 @@ pub(crate) fn complete_attribute_path(
152
152
} ) ;
153
153
154
154
let add_completion = |attr_completion : & AttrCompletion | {
155
- // if we already have the qualifier of the completion, then trim it from the label and the snippet
156
- let mut label = attr_completion. label ;
157
- let mut snippet = attr_completion. snippet ;
158
- if let Some ( name_ref) = qualifier_path. and_then ( |q| q. as_single_name_ref ( ) ) {
159
- if let Some ( ( label_qual, label_seg) ) = attr_completion. label . split_once ( "::" ) {
160
- if name_ref. text ( ) == label_qual {
161
- label = label_seg;
162
- snippet = snippet. map ( |snippet| {
163
- snippet. trim_start_matches ( label_qual) . trim_start_matches ( "::" )
164
- } ) ;
165
- }
155
+ // if we don't already have the qualifiers of the completion, then
156
+ // add the missing parts to the label and snippet
157
+ let mut label = attr_completion. label . to_owned ( ) ;
158
+ let mut snippet = attr_completion. snippet . map ( |s| s. to_owned ( ) ) ;
159
+ let segments = qualifier_path. iter ( ) . flat_map ( |q| q. segments ( ) ) . collect :: < Vec < _ > > ( ) ;
160
+ let qualifiers = attr_completion. qualifiers ;
161
+ let matching_qualifiers = segments
162
+ . iter ( )
163
+ . zip ( qualifiers)
164
+ . take_while ( |( s, q) | s. name_ref ( ) . is_some_and ( |t| t. text ( ) == * * q) )
165
+ . count ( ) ;
166
+ if matching_qualifiers != qualifiers. len ( ) {
167
+ let prefix = qualifiers[ matching_qualifiers..] . join ( "::" ) ;
168
+ label = format ! ( "{prefix}::{label}" ) ;
169
+ if let Some ( s) = snippet. as_mut ( ) {
170
+ * s = format ! ( "{prefix}::{s}" ) ;
166
171
}
167
172
}
168
173
@@ -197,6 +202,7 @@ struct AttrCompletion {
197
202
label : & ' static str ,
198
203
lookup : Option < & ' static str > ,
199
204
snippet : Option < & ' static str > ,
205
+ qualifiers : & ' static [ & ' static str ] ,
200
206
prefer_inner : bool ,
201
207
}
202
208
@@ -205,6 +211,10 @@ impl AttrCompletion {
205
211
self . lookup . unwrap_or ( self . label )
206
212
}
207
213
214
+ const fn qualifiers ( self , qualifiers : & ' static [ & ' static str ] ) -> AttrCompletion {
215
+ AttrCompletion { qualifiers, ..self }
216
+ }
217
+
208
218
const fn prefer_inner ( self ) -> AttrCompletion {
209
219
AttrCompletion { prefer_inner : true , ..self }
210
220
}
@@ -215,7 +225,7 @@ const fn attr(
215
225
lookup : Option < & ' static str > ,
216
226
snippet : Option < & ' static str > ,
217
227
) -> AttrCompletion {
218
- AttrCompletion { label, lookup, snippet, prefer_inner : false }
228
+ AttrCompletion { label, lookup, snippet, qualifiers : & [ ] , prefer_inner : false }
219
229
}
220
230
221
231
macro_rules! attrs {
@@ -324,8 +334,14 @@ const ATTRIBUTES: &[AttrCompletion] = &[
324
334
attr ( "deny(…)" , Some ( "deny" ) , Some ( "deny(${0:lint})" ) ) ,
325
335
attr ( r#"deprecated"# , Some ( "deprecated" ) , Some ( r#"deprecated"# ) ) ,
326
336
attr ( "derive(…)" , Some ( "derive" ) , Some ( r#"derive(${0:Debug})"# ) ) ,
327
- attr ( "diagnostic::do_not_recommend" , None , None ) ,
328
- attr ( "diagnostic::on_unimplemented" , None , Some ( r#"diagnostic::on_unimplemented(${0:keys})"# ) ) ,
337
+ attr ( "do_not_recommend" , Some ( "diagnostic::do_not_recommend" ) , None )
338
+ . qualifiers ( & [ "diagnostic" ] ) ,
339
+ attr (
340
+ "on_unimplemented" ,
341
+ Some ( "diagnostic::on_unimplemented" ) ,
342
+ Some ( r#"on_unimplemented(${0:keys})"# ) ,
343
+ )
344
+ . qualifiers ( & [ "diagnostic" ] ) ,
329
345
attr ( r#"doc = "…""# , Some ( "doc" ) , Some ( r#"doc = "${0:docs}""# ) ) ,
330
346
attr ( r#"doc(alias = "…")"# , Some ( "docalias" ) , Some ( r#"doc(alias = "${0:docs}")"# ) ) ,
331
347
attr ( r#"doc(hidden)"# , Some ( "dochidden" ) , Some ( r#"doc(hidden)"# ) ) ,
0 commit comments