From ca6548827634155f28e75bc6cb2e734d2d5d1e95 Mon Sep 17 00:00:00 2001
From: Kirill Bulatov <mail4score@gmail.com>
Date: Tue, 19 Jan 2021 01:08:59 +0200
Subject: Show deprecated completions for deprecated traits

---
 crates/completion/src/completions/flyimport.rs | 12 ++++---
 crates/completion/src/render.rs                | 47 ++++++++++++++++++++------
 crates/completion/src/render/const_.rs         |  5 ++-
 crates/completion/src/render/function.rs       |  4 ++-
 crates/completion/src/render/type_alias.rs     |  5 ++-
 crates/completion/src/test_utils.rs            |  3 ++
 6 files changed, 58 insertions(+), 18 deletions(-)

(limited to 'crates/completion/src')

diff --git a/crates/completion/src/completions/flyimport.rs b/crates/completion/src/completions/flyimport.rs
index 47e797ac8..dc0b38a16 100644
--- a/crates/completion/src/completions/flyimport.rs
+++ b/crates/completion/src/completions/flyimport.rs
@@ -48,7 +48,7 @@
 //! Note that having this flag set to `true` does not guarantee that the feature is enabled: your client needs to have the corredponding
 //! capability enabled.
 
-use hir::{ModPath, ScopeDef};
+use hir::{AsAssocItem, ModPath, ScopeDef};
 use ide_db::helpers::{
     import_assets::{ImportAssets, ImportCandidate},
     insert_use::ImportScope,
@@ -601,11 +601,12 @@ fn main() {
     }
 
     #[test]
-    fn zero_input_assoc_item_completion() {
+    fn zero_input_deprecated_assoc_item_completion() {
         check(
             r#"
 //- /lib.rs crate:dep
 pub mod test_mod {
+    #[deprecated]
     pub trait TestTrait {
         const SPECIAL_CONST: u8;
         type HumbleType;
@@ -628,7 +629,7 @@ fn main() {
 }
         "#,
             expect![[r#"
-                        me random_method() (dep::test_mod::TestTrait) fn random_method(&self)
+                        me random_method() (dep::test_mod::TestTrait) fn random_method(&self) DEPRECATED
                 "#]],
         );
 
@@ -636,6 +637,7 @@ fn main() {
             r#"
 //- /lib.rs crate:dep
 pub mod test_mod {
+    #[deprecated]
     pub trait TestTrait {
         const SPECIAL_CONST: u8;
         type HumbleType;
@@ -657,8 +659,8 @@ fn main() {
 }
 "#,
             expect![[r#"
-                ct SPECIAL_CONST (dep::test_mod::TestTrait)
-                fn weird_function() (dep::test_mod::TestTrait) fn weird_function()
+                ct SPECIAL_CONST (dep::test_mod::TestTrait) DEPRECATED
+                fn weird_function() (dep::test_mod::TestTrait) fn weird_function() DEPRECATED
         "#]],
         );
     }
diff --git a/crates/completion/src/render.rs b/crates/completion/src/render.rs
index dbb30d233..4f622d28a 100644
--- a/crates/completion/src/render.rs
+++ b/crates/completion/src/render.rs
@@ -10,7 +10,9 @@ pub(crate) mod type_alias;
 
 mod builder_ext;
 
-use hir::{Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type};
+use hir::{
+    AsAssocItem, Documentation, HasAttrs, HirDisplay, ModuleDef, Mutability, ScopeDef, Type,
+};
 use ide_db::{helpers::SnippetCap, RootDatabase};
 use syntax::TextRange;
 use test_utils::mark;
@@ -91,6 +93,22 @@ impl<'a> RenderContext<'a> {
         attrs.by_key("deprecated").exists() || attrs.by_key("rustc_deprecated").exists()
     }
 
+    fn is_deprecated_assoc_item(&self, as_assoc_item: impl AsAssocItem) -> bool {
+        let db = self.db();
+        let assoc = match as_assoc_item.as_assoc_item(db) {
+            Some(assoc) => assoc,
+            None => return false,
+        };
+
+        let is_assoc_deprecated = match assoc {
+            hir::AssocItem::Function(it) => self.is_deprecated(it),
+            hir::AssocItem::Const(it) => self.is_deprecated(it),
+            hir::AssocItem::TypeAlias(it) => self.is_deprecated(it),
+        };
+        is_assoc_deprecated
+            || assoc.containing_trait(db).map(|trait_| self.is_deprecated(trait_)).unwrap_or(false)
+    }
+
     fn docs(&self, node: impl HasAttrs) -> Option<Documentation> {
         node.docs(self.db())
     }
@@ -207,8 +225,6 @@ impl<'a> Render<'a> {
             }
         };
 
-        let docs = self.docs(resolution);
-
         let mut item =
             CompletionItem::new(completion_kind, self.ctx.source_range(), local_name.clone());
         if let ScopeDef::Local(local) = resolution {
@@ -254,13 +270,14 @@ impl<'a> Render<'a> {
             }
         }
 
-        let item = item
-            .kind(kind)
-            .add_import(import_to_add)
-            .set_documentation(docs)
-            .set_ref_match(ref_match)
-            .build();
-        Some(item)
+        Some(
+            item.kind(kind)
+                .add_import(import_to_add)
+                .set_ref_match(ref_match)
+                .set_documentation(self.docs(resolution))
+                .set_deprecated(self.is_deprecated(resolution))
+                .build(),
+        )
     }
 
     fn docs(&self, resolution: &ScopeDef) -> Option<Documentation> {
@@ -276,6 +293,16 @@ impl<'a> Render<'a> {
             _ => None,
         }
     }
+
+    fn is_deprecated(&self, resolution: &ScopeDef) -> bool {
+        match resolution {
+            ScopeDef::ModuleDef(it) => self.ctx.is_deprecated_assoc_item(*it),
+            ScopeDef::MacroDef(it) => self.ctx.is_deprecated(*it),
+            ScopeDef::GenericParam(it) => self.ctx.is_deprecated(*it),
+            ScopeDef::AdtSelfType(it) => self.ctx.is_deprecated(*it),
+            _ => false,
+        }
+    }
 }
 
 fn compute_score_from_active(
diff --git a/crates/completion/src/render/const_.rs b/crates/completion/src/render/const_.rs
index ce924f309..e46452d4e 100644
--- a/crates/completion/src/render/const_.rs
+++ b/crates/completion/src/render/const_.rs
@@ -38,7 +38,10 @@ impl<'a> ConstRender<'a> {
         let item = CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name)
             .kind(CompletionItemKind::Const)
             .set_documentation(self.ctx.docs(self.const_))
-            .set_deprecated(self.ctx.is_deprecated(self.const_))
+            .set_deprecated(
+                self.ctx.is_deprecated(self.const_)
+                    || self.ctx.is_deprecated_assoc_item(self.const_),
+            )
             .detail(detail)
             .build();
 
diff --git a/crates/completion/src/render/function.rs b/crates/completion/src/render/function.rs
index f5b0ce3e3..8f4c66211 100644
--- a/crates/completion/src/render/function.rs
+++ b/crates/completion/src/render/function.rs
@@ -44,7 +44,9 @@ impl<'a> FunctionRender<'a> {
         CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), self.name.clone())
             .kind(self.kind())
             .set_documentation(self.ctx.docs(self.func))
-            .set_deprecated(self.ctx.is_deprecated(self.func))
+            .set_deprecated(
+                self.ctx.is_deprecated(self.func) || self.ctx.is_deprecated_assoc_item(self.func),
+            )
             .detail(self.detail())
             .add_call_parens(self.ctx.completion, self.name, params)
             .add_import(import_to_add)
diff --git a/crates/completion/src/render/type_alias.rs b/crates/completion/src/render/type_alias.rs
index 69b445b9c..29287143a 100644
--- a/crates/completion/src/render/type_alias.rs
+++ b/crates/completion/src/render/type_alias.rs
@@ -38,7 +38,10 @@ impl<'a> TypeAliasRender<'a> {
         let item = CompletionItem::new(CompletionKind::Reference, self.ctx.source_range(), name)
             .kind(CompletionItemKind::TypeAlias)
             .set_documentation(self.ctx.docs(self.type_alias))
-            .set_deprecated(self.ctx.is_deprecated(self.type_alias))
+            .set_deprecated(
+                self.ctx.is_deprecated(self.type_alias)
+                    || self.ctx.is_deprecated_assoc_item(self.type_alias),
+            )
             .detail(detail)
             .build();
 
diff --git a/crates/completion/src/test_utils.rs b/crates/completion/src/test_utils.rs
index 3faf861b9..baff83305 100644
--- a/crates/completion/src/test_utils.rs
+++ b/crates/completion/src/test_utils.rs
@@ -83,6 +83,9 @@ pub(crate) fn completion_list_with_config(
                 let width = label_width.saturating_sub(monospace_width(it.label()));
                 format_to!(buf, "{:width$} {}", "", detail, width = width);
             }
+            if it.deprecated() {
+                format_to!(buf, " DEPRECATED");
+            }
             format_to!(buf, "\n");
             buf
         })
-- 
cgit v1.2.3