diff --git a/crates/assists/src/handlers/qualify_path.rs b/crates/assists/src/handlers/qualify_path.rs index af8a11d0355..b0b0d31b449 100644 --- a/crates/assists/src/handlers/qualify_path.rs +++ b/crates/assists/src/handlers/qualify_path.rs @@ -1,6 +1,6 @@ use std::iter; -use hir::AsName; +use hir::{AsAssocItem, AsName}; use ide_db::helpers::{import_assets::ImportCandidate, mod_path_to_ast}; use ide_db::RootDatabase; use syntax::{ diff --git a/crates/completion/src/completions/flyimport.rs b/crates/completion/src/completions/flyimport.rs index 47e797ac8bf..dc0b38a165d 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 4b3c9702a44..4f622d28aea 100644 --- a/crates/completion/src/render.rs +++ b/crates/completion/src/render.rs @@ -10,7 +10,9 @@ 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; @@ -87,7 +89,24 @@ fn source_range(&self) -> TextRange { } fn is_deprecated(&self, node: impl HasAttrs) -> bool { - node.attrs(self.db()).by_key("deprecated").exists() + let attrs = node.attrs(self.db()); + 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 { @@ -206,8 +225,6 @@ fn render_resolution( } }; - 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 { @@ -253,13 +270,14 @@ fn render_resolution( } } - 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 { @@ -275,6 +293,16 @@ fn docs(&self, resolution: &ScopeDef) -> Option { _ => 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( @@ -485,7 +513,7 @@ fn sets_deprecated_flag_in_items() { r#" #[deprecated] fn something_deprecated() {} -#[deprecated(since = "1.0.0")] +#[rustc_deprecated(since = "1.0.0")] fn something_else_deprecated() {} fn main() { som$0 } @@ -494,8 +522,8 @@ fn main() { som$0 } [ CompletionItem { label: "main()", - source_range: 121..124, - delete: 121..124, + source_range: 127..130, + delete: 127..130, insert: "main()$0", kind: Function, lookup: "main", @@ -503,8 +531,8 @@ fn main() { som$0 } }, CompletionItem { label: "something_deprecated()", - source_range: 121..124, - delete: 121..124, + source_range: 127..130, + delete: 127..130, insert: "something_deprecated()$0", kind: Function, lookup: "something_deprecated", @@ -513,8 +541,8 @@ fn main() { som$0 } }, CompletionItem { label: "something_else_deprecated()", - source_range: 121..124, - delete: 121..124, + source_range: 127..130, + delete: 127..130, insert: "something_else_deprecated()$0", kind: Function, lookup: "something_else_deprecated", diff --git a/crates/completion/src/render/const_.rs b/crates/completion/src/render/const_.rs index ce924f30952..e46452d4e4b 100644 --- a/crates/completion/src/render/const_.rs +++ b/crates/completion/src/render/const_.rs @@ -38,7 +38,10 @@ fn render(self) -> Option { 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 f5b0ce3e317..8f4c6621146 100644 --- a/crates/completion/src/render/function.rs +++ b/crates/completion/src/render/function.rs @@ -44,7 +44,9 @@ fn render(self, import_to_add: Option) -> CompletionItem { 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 69b445b9c69..29287143a51 100644 --- a/crates/completion/src/render/type_alias.rs +++ b/crates/completion/src/render/type_alias.rs @@ -38,7 +38,10 @@ fn render(self) -> Option { 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 3faf861b9af..baff833051b 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 }) diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs index 2950f08b8f0..5a4c2790612 100644 --- a/crates/hir/src/code_model.rs +++ b/crates/hir/src/code_model.rs @@ -272,15 +272,6 @@ pub fn diagnostics(self, db: &dyn HirDatabase, sink: &mut DiagnosticSink) { hir_ty::diagnostics::validate_module_item(db, module.id.krate, id, sink) } - - pub fn as_assoc_item(self, db: &dyn HirDatabase) -> Option { - match self { - ModuleDef::Function(f) => f.as_assoc_item(db), - ModuleDef::Const(c) => c.as_assoc_item(db), - ModuleDef::TypeAlias(t) => t.as_assoc_item(db), - _ => None, - } - } } impl Module { @@ -1060,6 +1051,16 @@ fn as_assoc_item(self, db: &dyn HirDatabase) -> Option { as_assoc_item(db, AssocItem::TypeAlias, self.id) } } +impl AsAssocItem for ModuleDef { + fn as_assoc_item(self, db: &dyn HirDatabase) -> Option { + match self { + ModuleDef::Function(it) => it.as_assoc_item(db), + ModuleDef::Const(it) => it.as_assoc_item(db), + ModuleDef::TypeAlias(it) => it.as_assoc_item(db), + _ => None, + } + } +} fn as_assoc_item(db: &dyn HirDatabase, ctor: CTOR, id: ID) -> Option where ID: Lookup>,