aboutsummaryrefslogtreecommitdiff
path: root/crates/completion/src/render.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/completion/src/render.rs')
-rw-r--r--crates/completion/src/render.rs191
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
11mod builder_ext; 11mod builder_ext;
12 12
13use hir::{Documentation, HasAttrs, HirDisplay, Mutability, ScopeDef, Type}; 13use hir::{
14use ide_db::{helpers::SnippetCap, RootDatabase}; 14 AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type,
15};
16use ide_db::{helpers::SnippetCap, RootDatabase, SymbolKind};
15use syntax::TextRange; 17use syntax::TextRange;
16use test_utils::mark; 18use 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
280fn compute_score_from_active( 317fn 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]
487fn something_deprecated() {} 538fn something_deprecated() {}
488#[deprecated(since = "1.0.0")] 539#[rustc_deprecated(since = "1.0.0")]
489fn something_else_deprecated() {} 540fn something_else_deprecated() {}
490 541
491fn main() { som$0 } 542fn 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: () };
855fn go(world: &WorldSnapshot) { go(w$0) } 922fn 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 }