@@ -152,17 +152,22 @@ pub(crate) fn complete_attribute_path(
152152 } ) ;
153153
154154 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}" ) ;
166171 }
167172 }
168173
@@ -197,6 +202,7 @@ struct AttrCompletion {
197202 label : & ' static str ,
198203 lookup : Option < & ' static str > ,
199204 snippet : Option < & ' static str > ,
205+ qualifiers : & ' static [ & ' static str ] ,
200206 prefer_inner : bool ,
201207}
202208
@@ -205,6 +211,10 @@ impl AttrCompletion {
205211 self . lookup . unwrap_or ( self . label )
206212 }
207213
214+ const fn qualifiers ( self , qualifiers : & ' static [ & ' static str ] ) -> AttrCompletion {
215+ AttrCompletion { qualifiers, ..self }
216+ }
217+
208218 const fn prefer_inner ( self ) -> AttrCompletion {
209219 AttrCompletion { prefer_inner : true , ..self }
210220 }
@@ -215,7 +225,7 @@ const fn attr(
215225 lookup : Option < & ' static str > ,
216226 snippet : Option < & ' static str > ,
217227) -> AttrCompletion {
218- AttrCompletion { label, lookup, snippet, prefer_inner : false }
228+ AttrCompletion { label, lookup, snippet, qualifiers : & [ ] , prefer_inner : false }
219229}
220230
221231macro_rules! attrs {
@@ -324,8 +334,14 @@ const ATTRIBUTES: &[AttrCompletion] = &[
324334 attr ( "deny(…)" , Some ( "deny" ) , Some ( "deny(${0:lint})" ) ) ,
325335 attr ( r#"deprecated"# , Some ( "deprecated" ) , Some ( r#"deprecated"# ) ) ,
326336 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" ] ) ,
329345 attr ( r#"doc = "…""# , Some ( "doc" ) , Some ( r#"doc = "${0:docs}""# ) ) ,
330346 attr ( r#"doc(alias = "…")"# , Some ( "docalias" ) , Some ( r#"doc(alias = "${0:docs}")"# ) ) ,
331347 attr ( r#"doc(hidden)"# , Some ( "dochidden" ) , Some ( r#"doc(hidden)"# ) ) ,
0 commit comments