diff options
Diffstat (limited to 'crates/completion/src/render.rs')
-rw-r--r-- | crates/completion/src/render.rs | 191 |
1 files changed, 129 insertions, 62 deletions
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs index 820dd01d1..fa594b5e5 100644 --- a/crates/completion/src/render.rs +++ b/crates/completion/src/render.rs | |||
@@ -10,8 +10,10 @@ pub(crate) mod type_alias; | |||
10 | 10 | ||
11 | mod builder_ext; | 11 | mod builder_ext; |
12 | 12 | ||
13 | use hir::{Documentation, HasAttrs, HirDisplay, Mutability, ScopeDef, Type}; | 13 | use hir::{ |
14 | use ide_db::{helpers::SnippetCap, RootDatabase}; | 14 | AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type, |
15 | }; | ||
16 | use ide_db::{helpers::SnippetCap, RootDatabase, SymbolKind}; | ||
15 | use syntax::TextRange; | 17 | use syntax::TextRange; |
16 | use test_utils::mark; | 18 | use test_utils::mark; |
17 | 19 | ||
@@ -51,16 +53,16 @@ pub(crate) fn render_resolution_with_import<'a>( | |||
51 | import_edit: ImportEdit, | 53 | import_edit: ImportEdit, |
52 | resolution: &ScopeDef, | 54 | resolution: &ScopeDef, |
53 | ) -> Option<CompletionItem> { | 55 | ) -> Option<CompletionItem> { |
54 | Render::new(ctx) | 56 | let local_name = match resolution { |
55 | .render_resolution( | 57 | ScopeDef::ModuleDef(ModuleDef::Function(f)) => f.name(ctx.completion.db).to_string(), |
56 | import_edit.import_path.segments.last()?.to_string(), | 58 | ScopeDef::ModuleDef(ModuleDef::Const(c)) => c.name(ctx.completion.db)?.to_string(), |
57 | Some(import_edit), | 59 | ScopeDef::ModuleDef(ModuleDef::TypeAlias(t)) => t.name(ctx.completion.db).to_string(), |
58 | resolution, | 60 | _ => import_edit.import_path.segments.last()?.to_string(), |
59 | ) | 61 | }; |
60 | .map(|mut item| { | 62 | Render::new(ctx).render_resolution(local_name, Some(import_edit), resolution).map(|mut item| { |
61 | item.completion_kind = CompletionKind::Magic; | 63 | item.completion_kind = CompletionKind::Magic; |
62 | item | 64 | item |
63 | }) | 65 | }) |
64 | } | 66 | } |
65 | 67 | ||
66 | /// Interface for data and methods required for items rendering. | 68 | /// Interface for data and methods required for items rendering. |
@@ -87,7 +89,24 @@ impl<'a> RenderContext<'a> { | |||
87 | } | 89 | } |
88 | 90 | ||
89 | fn is_deprecated(&self, node: impl HasAttrs) -> bool { | 91 | fn is_deprecated(&self, node: impl HasAttrs) -> bool { |
90 | node.attrs(self.db()).by_key("deprecated").exists() | 92 | let attrs = node.attrs(self.db()); |
93 | attrs.by_key("deprecated").exists() || attrs.by_key("rustc_deprecated").exists() | ||
94 | } | ||
95 | |||
96 | fn is_deprecated_assoc_item(&self, as_assoc_item: impl AsAssocItem) -> bool { | ||
97 | let db = self.db(); | ||
98 | let assoc = match as_assoc_item.as_assoc_item(db) { | ||
99 | Some(assoc) => assoc, | ||
100 | None => return false, | ||
101 | }; | ||
102 | |||
103 | let is_assoc_deprecated = match assoc { | ||
104 | hir::AssocItem::Function(it) => self.is_deprecated(it), | ||
105 | hir::AssocItem::Const(it) => self.is_deprecated(it), | ||
106 | hir::AssocItem::TypeAlias(it) => self.is_deprecated(it), | ||
107 | }; | ||
108 | is_assoc_deprecated | ||
109 | || assoc.containing_trait(db).map(|trait_| self.is_deprecated(trait_)).unwrap_or(false) | ||
91 | } | 110 | } |
92 | 111 | ||
93 | fn docs(&self, node: impl HasAttrs) -> Option<Documentation> { | 112 | fn docs(&self, node: impl HasAttrs) -> Option<Documentation> { |
@@ -127,7 +146,7 @@ impl<'a> Render<'a> { | |||
127 | self.ctx.source_range(), | 146 | self.ctx.source_range(), |
128 | name.to_string(), | 147 | name.to_string(), |
129 | ) | 148 | ) |
130 | .kind(CompletionItemKind::Field) | 149 | .kind(SymbolKind::Field) |
131 | .detail(ty.display(self.ctx.db()).to_string()) | 150 | .detail(ty.display(self.ctx.db()).to_string()) |
132 | .set_documentation(field.docs(self.ctx.db())) | 151 | .set_documentation(field.docs(self.ctx.db())) |
133 | .set_deprecated(is_deprecated); | 152 | .set_deprecated(is_deprecated); |
@@ -141,7 +160,7 @@ impl<'a> Render<'a> { | |||
141 | 160 | ||
142 | fn add_tuple_field(&mut self, field: usize, ty: &Type) -> CompletionItem { | 161 | fn add_tuple_field(&mut self, field: usize, ty: &Type) -> CompletionItem { |
143 | CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), field.to_string()) | 162 | CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), field.to_string()) |
144 | .kind(CompletionItemKind::Field) | 163 | .kind(SymbolKind::Field) |
145 | .detail(ty.display(self.ctx.db()).to_string()) | 164 | .detail(ty.display(self.ctx.db()).to_string()) |
146 | .build() | 165 | .build() |
147 | } | 166 | } |
@@ -168,7 +187,7 @@ impl<'a> Render<'a> { | |||
168 | if self.ctx.completion.is_pat_binding_or_const | 187 | if self.ctx.completion.is_pat_binding_or_const |
169 | | self.ctx.completion.is_irrefutable_pat_binding => | 188 | | self.ctx.completion.is_irrefutable_pat_binding => |
170 | { | 189 | { |
171 | CompletionItemKind::EnumVariant | 190 | CompletionItemKind::SymbolKind(SymbolKind::Variant) |
172 | } | 191 | } |
173 | ScopeDef::ModuleDef(Variant(var)) => { | 192 | ScopeDef::ModuleDef(Variant(var)) => { |
174 | let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None); | 193 | let item = render_variant(self.ctx, import_to_add, Some(local_name), *var, None); |
@@ -179,20 +198,29 @@ impl<'a> Render<'a> { | |||
179 | return item; | 198 | return item; |
180 | } | 199 | } |
181 | 200 | ||
182 | ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::Module, | 201 | ScopeDef::ModuleDef(Module(..)) => CompletionItemKind::SymbolKind(SymbolKind::Module), |
183 | ScopeDef::ModuleDef(Adt(hir::Adt::Struct(_))) => CompletionItemKind::Struct, | 202 | ScopeDef::ModuleDef(Adt(adt)) => CompletionItemKind::SymbolKind(match adt { |
184 | // FIXME: add CompletionItemKind::Union | 203 | hir::Adt::Struct(_) => SymbolKind::Struct, |
185 | ScopeDef::ModuleDef(Adt(hir::Adt::Union(_))) => CompletionItemKind::Struct, | 204 | // FIXME: add CompletionItemKind::Union |
186 | ScopeDef::ModuleDef(Adt(hir::Adt::Enum(_))) => CompletionItemKind::Enum, | 205 | hir::Adt::Union(_) => SymbolKind::Struct, |
187 | ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::Const, | 206 | hir::Adt::Enum(_) => SymbolKind::Enum, |
188 | ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::Static, | 207 | }), |
189 | ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::Trait, | 208 | ScopeDef::ModuleDef(Const(..)) => CompletionItemKind::SymbolKind(SymbolKind::Const), |
190 | ScopeDef::ModuleDef(TypeAlias(..)) => CompletionItemKind::TypeAlias, | 209 | ScopeDef::ModuleDef(Static(..)) => CompletionItemKind::SymbolKind(SymbolKind::Static), |
210 | ScopeDef::ModuleDef(Trait(..)) => CompletionItemKind::SymbolKind(SymbolKind::Trait), | ||
211 | ScopeDef::ModuleDef(TypeAlias(..)) => { | ||
212 | CompletionItemKind::SymbolKind(SymbolKind::TypeAlias) | ||
213 | } | ||
191 | ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType, | 214 | ScopeDef::ModuleDef(BuiltinType(..)) => CompletionItemKind::BuiltinType, |
192 | ScopeDef::GenericParam(..) => CompletionItemKind::TypeParam, | 215 | ScopeDef::GenericParam(param) => CompletionItemKind::SymbolKind(match param { |
193 | ScopeDef::Local(..) => CompletionItemKind::Binding, | 216 | hir::GenericParam::TypeParam(_) => SymbolKind::TypeParam, |
194 | // (does this need its own kind?) | 217 | hir::GenericParam::LifetimeParam(_) => SymbolKind::LifetimeParam, |
195 | ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => CompletionItemKind::TypeParam, | 218 | hir::GenericParam::ConstParam(_) => SymbolKind::ConstParam, |
219 | }), | ||
220 | ScopeDef::Local(..) => CompletionItemKind::SymbolKind(SymbolKind::Local), | ||
221 | ScopeDef::AdtSelfType(..) | ScopeDef::ImplSelfType(..) => { | ||
222 | CompletionItemKind::SymbolKind(SymbolKind::SelfParam) | ||
223 | } | ||
196 | ScopeDef::Unknown => { | 224 | ScopeDef::Unknown => { |
197 | let item = CompletionItem::new( | 225 | let item = CompletionItem::new( |
198 | CompletionKind::Reference, | 226 | CompletionKind::Reference, |
@@ -206,8 +234,6 @@ impl<'a> Render<'a> { | |||
206 | } | 234 | } |
207 | }; | 235 | }; |
208 | 236 | ||
209 | let docs = self.docs(resolution); | ||
210 | |||
211 | let mut item = | 237 | let mut item = |
212 | CompletionItem::new(completion_kind, self.ctx.source_range(), local_name.clone()); | 238 | CompletionItem::new(completion_kind, self.ctx.source_range(), local_name.clone()); |
213 | if let ScopeDef::Local(local) = resolution { | 239 | if let ScopeDef::Local(local) = resolution { |
@@ -253,13 +279,14 @@ impl<'a> Render<'a> { | |||
253 | } | 279 | } |
254 | } | 280 | } |
255 | 281 | ||
256 | let item = item | 282 | Some( |
257 | .kind(kind) | 283 | item.kind(kind) |
258 | .add_import(import_to_add) | 284 | .add_import(import_to_add) |
259 | .set_documentation(docs) | 285 | .set_ref_match(ref_match) |
260 | .set_ref_match(ref_match) | 286 | .set_documentation(self.docs(resolution)) |
261 | .build(); | 287 | .set_deprecated(self.is_deprecated(resolution)) |
262 | Some(item) | 288 | .build(), |
289 | ) | ||
263 | } | 290 | } |
264 | 291 | ||
265 | fn docs(&self, resolution: &ScopeDef) -> Option<Documentation> { | 292 | fn docs(&self, resolution: &ScopeDef) -> Option<Documentation> { |
@@ -275,6 +302,16 @@ impl<'a> Render<'a> { | |||
275 | _ => None, | 302 | _ => None, |
276 | } | 303 | } |
277 | } | 304 | } |
305 | |||
306 | fn is_deprecated(&self, resolution: &ScopeDef) -> bool { | ||
307 | match resolution { | ||
308 | ScopeDef::ModuleDef(it) => self.ctx.is_deprecated_assoc_item(*it), | ||
309 | ScopeDef::MacroDef(it) => self.ctx.is_deprecated(*it), | ||
310 | ScopeDef::GenericParam(it) => self.ctx.is_deprecated(*it), | ||
311 | ScopeDef::AdtSelfType(it) => self.ctx.is_deprecated(*it), | ||
312 | _ => false, | ||
313 | } | ||
314 | } | ||
278 | } | 315 | } |
279 | 316 | ||
280 | fn compute_score_from_active( | 317 | fn compute_score_from_active( |
@@ -372,7 +409,9 @@ fn main() { Foo::Fo$0 } | |||
372 | source_range: 54..56, | 409 | source_range: 54..56, |
373 | delete: 54..56, | 410 | delete: 54..56, |
374 | insert: "Foo", | 411 | insert: "Foo", |
375 | kind: EnumVariant, | 412 | kind: SymbolKind( |
413 | Variant, | ||
414 | ), | ||
376 | detail: "{ x: i32, y: i32 }", | 415 | detail: "{ x: i32, y: i32 }", |
377 | }, | 416 | }, |
378 | ] | 417 | ] |
@@ -395,7 +434,9 @@ fn main() { Foo::Fo$0 } | |||
395 | source_range: 46..48, | 434 | source_range: 46..48, |
396 | delete: 46..48, | 435 | delete: 46..48, |
397 | insert: "Foo($0)", | 436 | insert: "Foo($0)", |
398 | kind: EnumVariant, | 437 | kind: SymbolKind( |
438 | Variant, | ||
439 | ), | ||
399 | lookup: "Foo", | 440 | lookup: "Foo", |
400 | detail: "(i32, i32)", | 441 | detail: "(i32, i32)", |
401 | trigger_call_info: true, | 442 | trigger_call_info: true, |
@@ -420,7 +461,9 @@ fn main() { Foo::Fo$0 } | |||
420 | source_range: 35..37, | 461 | source_range: 35..37, |
421 | delete: 35..37, | 462 | delete: 35..37, |
422 | insert: "Foo", | 463 | insert: "Foo", |
423 | kind: EnumVariant, | 464 | kind: SymbolKind( |
465 | Variant, | ||
466 | ), | ||
424 | detail: "()", | 467 | detail: "()", |
425 | }, | 468 | }, |
426 | ] | 469 | ] |
@@ -444,7 +487,9 @@ fn main() { let _: m::Spam = S$0 } | |||
444 | source_range: 75..76, | 487 | source_range: 75..76, |
445 | delete: 75..76, | 488 | delete: 75..76, |
446 | insert: "Spam::Bar($0)", | 489 | insert: "Spam::Bar($0)", |
447 | kind: EnumVariant, | 490 | kind: SymbolKind( |
491 | Variant, | ||
492 | ), | ||
448 | lookup: "Spam::Bar", | 493 | lookup: "Spam::Bar", |
449 | detail: "(i32)", | 494 | detail: "(i32)", |
450 | trigger_call_info: true, | 495 | trigger_call_info: true, |
@@ -454,14 +499,18 @@ fn main() { let _: m::Spam = S$0 } | |||
454 | source_range: 75..76, | 499 | source_range: 75..76, |
455 | delete: 75..76, | 500 | delete: 75..76, |
456 | insert: "m", | 501 | insert: "m", |
457 | kind: Module, | 502 | kind: SymbolKind( |
503 | Module, | ||
504 | ), | ||
458 | }, | 505 | }, |
459 | CompletionItem { | 506 | CompletionItem { |
460 | label: "m::Spam::Foo", | 507 | label: "m::Spam::Foo", |
461 | source_range: 75..76, | 508 | source_range: 75..76, |
462 | delete: 75..76, | 509 | delete: 75..76, |
463 | insert: "m::Spam::Foo", | 510 | insert: "m::Spam::Foo", |
464 | kind: EnumVariant, | 511 | kind: SymbolKind( |
512 | Variant, | ||
513 | ), | ||
465 | lookup: "Spam::Foo", | 514 | lookup: "Spam::Foo", |
466 | detail: "()", | 515 | detail: "()", |
467 | }, | 516 | }, |
@@ -470,7 +519,9 @@ fn main() { let _: m::Spam = S$0 } | |||
470 | source_range: 75..76, | 519 | source_range: 75..76, |
471 | delete: 75..76, | 520 | delete: 75..76, |
472 | insert: "main()$0", | 521 | insert: "main()$0", |
473 | kind: Function, | 522 | kind: SymbolKind( |
523 | Function, | ||
524 | ), | ||
474 | lookup: "main", | 525 | lookup: "main", |
475 | detail: "fn main()", | 526 | detail: "fn main()", |
476 | }, | 527 | }, |
@@ -485,7 +536,7 @@ fn main() { let _: m::Spam = S$0 } | |||
485 | r#" | 536 | r#" |
486 | #[deprecated] | 537 | #[deprecated] |
487 | fn something_deprecated() {} | 538 | fn something_deprecated() {} |
488 | #[deprecated(since = "1.0.0")] | 539 | #[rustc_deprecated(since = "1.0.0")] |
489 | fn something_else_deprecated() {} | 540 | fn something_else_deprecated() {} |
490 | 541 | ||
491 | fn main() { som$0 } | 542 | fn main() { som$0 } |
@@ -494,29 +545,35 @@ fn main() { som$0 } | |||
494 | [ | 545 | [ |
495 | CompletionItem { | 546 | CompletionItem { |
496 | label: "main()", | 547 | label: "main()", |
497 | source_range: 121..124, | 548 | source_range: 127..130, |
498 | delete: 121..124, | 549 | delete: 127..130, |
499 | insert: "main()$0", | 550 | insert: "main()$0", |
500 | kind: Function, | 551 | kind: SymbolKind( |
552 | Function, | ||
553 | ), | ||
501 | lookup: "main", | 554 | lookup: "main", |
502 | detail: "fn main()", | 555 | detail: "fn main()", |
503 | }, | 556 | }, |
504 | CompletionItem { | 557 | CompletionItem { |
505 | label: "something_deprecated()", | 558 | label: "something_deprecated()", |
506 | source_range: 121..124, | 559 | source_range: 127..130, |
507 | delete: 121..124, | 560 | delete: 127..130, |
508 | insert: "something_deprecated()$0", | 561 | insert: "something_deprecated()$0", |
509 | kind: Function, | 562 | kind: SymbolKind( |
563 | Function, | ||
564 | ), | ||
510 | lookup: "something_deprecated", | 565 | lookup: "something_deprecated", |
511 | detail: "fn something_deprecated()", | 566 | detail: "fn something_deprecated()", |
512 | deprecated: true, | 567 | deprecated: true, |
513 | }, | 568 | }, |
514 | CompletionItem { | 569 | CompletionItem { |
515 | label: "something_else_deprecated()", | 570 | label: "something_else_deprecated()", |
516 | source_range: 121..124, | 571 | source_range: 127..130, |
517 | delete: 121..124, | 572 | delete: 127..130, |
518 | insert: "something_else_deprecated()$0", | 573 | insert: "something_else_deprecated()$0", |
519 | kind: Function, | 574 | kind: SymbolKind( |
575 | Function, | ||
576 | ), | ||
520 | lookup: "something_else_deprecated", | 577 | lookup: "something_else_deprecated", |
521 | detail: "fn something_else_deprecated()", | 578 | detail: "fn something_else_deprecated()", |
522 | deprecated: true, | 579 | deprecated: true, |
@@ -537,7 +594,9 @@ fn foo() { A { the$0 } } | |||
537 | source_range: 57..60, | 594 | source_range: 57..60, |
538 | delete: 57..60, | 595 | delete: 57..60, |
539 | insert: "the_field", | 596 | insert: "the_field", |
540 | kind: Field, | 597 | kind: SymbolKind( |
598 | Field, | ||
599 | ), | ||
541 | detail: "u32", | 600 | detail: "u32", |
542 | deprecated: true, | 601 | deprecated: true, |
543 | }, | 602 | }, |
@@ -577,7 +636,9 @@ impl S { | |||
577 | source_range: 94..94, | 636 | source_range: 94..94, |
578 | delete: 94..94, | 637 | delete: 94..94, |
579 | insert: "foo", | 638 | insert: "foo", |
580 | kind: Field, | 639 | kind: SymbolKind( |
640 | Field, | ||
641 | ), | ||
581 | detail: "{unknown}", | 642 | detail: "{unknown}", |
582 | documentation: Documentation( | 643 | documentation: Documentation( |
583 | "Field docs", | 644 | "Field docs", |
@@ -608,7 +669,9 @@ use self::E::*; | |||
608 | source_range: 10..12, | 669 | source_range: 10..12, |
609 | delete: 10..12, | 670 | delete: 10..12, |
610 | insert: "E", | 671 | insert: "E", |
611 | kind: Enum, | 672 | kind: SymbolKind( |
673 | Enum, | ||
674 | ), | ||
612 | documentation: Documentation( | 675 | documentation: Documentation( |
613 | "enum docs", | 676 | "enum docs", |
614 | ), | 677 | ), |
@@ -618,7 +681,9 @@ use self::E::*; | |||
618 | source_range: 10..12, | 681 | source_range: 10..12, |
619 | delete: 10..12, | 682 | delete: 10..12, |
620 | insert: "V", | 683 | insert: "V", |
621 | kind: EnumVariant, | 684 | kind: SymbolKind( |
685 | Variant, | ||
686 | ), | ||
622 | detail: "()", | 687 | detail: "()", |
623 | documentation: Documentation( | 688 | documentation: Documentation( |
624 | "variant docs", | 689 | "variant docs", |
@@ -629,7 +694,9 @@ use self::E::*; | |||
629 | source_range: 10..12, | 694 | source_range: 10..12, |
630 | delete: 10..12, | 695 | delete: 10..12, |
631 | insert: "my", | 696 | insert: "my", |
632 | kind: Module, | 697 | kind: SymbolKind( |
698 | Module, | ||
699 | ), | ||
633 | documentation: Documentation( | 700 | documentation: Documentation( |
634 | "mod docs", | 701 | "mod docs", |
635 | ), | 702 | ), |
@@ -855,7 +922,7 @@ struct WorldSnapshot { _f: () }; | |||
855 | fn go(world: &WorldSnapshot) { go(w$0) } | 922 | fn go(world: &WorldSnapshot) { go(w$0) } |
856 | "#, | 923 | "#, |
857 | expect![[r#" | 924 | expect![[r#" |
858 | bn world [type+name] | 925 | lc world [type+name] |
859 | st WorldSnapshot [] | 926 | st WorldSnapshot [] |
860 | fn go(…) [] | 927 | fn go(…) [] |
861 | "#]], | 928 | "#]], |
@@ -872,7 +939,7 @@ fn f(foo: &Foo) { f(foo, w$0) } | |||
872 | expect![[r#" | 939 | expect![[r#" |
873 | st Foo [] | 940 | st Foo [] |
874 | fn f(…) [] | 941 | fn f(…) [] |
875 | bn foo [] | 942 | lc foo [] |
876 | "#]], | 943 | "#]], |
877 | ); | 944 | ); |
878 | } | 945 | } |