From cb3767f28a2f9e443b816b17d5d07b6a1cff90ab Mon Sep 17 00:00:00 2001 From: Martin Asquino Date: Mon, 4 Nov 2019 10:33:10 -0300 Subject: HirDatabase stored attributes --- crates/ra_hir/src/code_model.rs | 1 + crates/ra_hir/src/code_model/attrs.rs | 92 ++++++++++++++++++++++++ crates/ra_hir/src/db.rs | 4 ++ crates/ra_hir/src/lib.rs | 1 + crates/ra_ide_api/src/completion/presentation.rs | 27 ++++--- 5 files changed, 111 insertions(+), 14 deletions(-) create mode 100644 crates/ra_hir/src/code_model/attrs.rs diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs index 181c5d47a..c29c2448e 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -2,6 +2,7 @@ pub(crate) mod src; pub(crate) mod docs; +pub(crate) mod attrs; use std::sync::Arc; diff --git a/crates/ra_hir/src/code_model/attrs.rs b/crates/ra_hir/src/code_model/attrs.rs new file mode 100644 index 000000000..f7db36b66 --- /dev/null +++ b/crates/ra_hir/src/code_model/attrs.rs @@ -0,0 +1,92 @@ +//! FIXME: write short doc here + +use crate::{ + db::{AstDatabase, DefDatabase, HirDatabase}, + Adt, Const, Enum, EnumVariant, FieldSource, Function, HasSource, MacroDef, Module, Static, + Struct, StructField, Trait, TypeAlias, Union, +}; +use hir_def::attr::Attr; +use hir_expand::hygiene::Hygiene; +use ra_syntax::ast; +use std::sync::Arc; + +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum AttrDef { + Module(Module), + StructField(StructField), + Adt(Adt), + Function(Function), + EnumVariant(EnumVariant), + Static(Static), + Const(Const), + Trait(Trait), + TypeAlias(TypeAlias), + MacroDef(MacroDef), +} + +impl_froms!( + AttrDef: Module, + StructField, + Adt(Struct, Enum, Union), + EnumVariant, + Static, + Const, + Function, + Trait, + TypeAlias, + MacroDef +); + +pub trait Attrs { + fn attrs(&self, db: &impl HirDatabase) -> Option>; +} + +pub(crate) fn attributes_query( + db: &(impl DefDatabase + AstDatabase), + def: AttrDef, +) -> Option> { + match def { + AttrDef::Module(it) => { + let src = it.declaration_source(db)?; + let hygiene = Hygiene::new(db, src.file_id); + Attr::from_attrs_owner(&src.ast, &hygiene) + } + AttrDef::StructField(it) => match it.source(db).ast { + FieldSource::Named(named) => { + let src = it.source(db); + let hygiene = Hygiene::new(db, src.file_id); + Attr::from_attrs_owner(&named, &hygiene) + } + FieldSource::Pos(..) => None, + }, + AttrDef::Adt(it) => match it { + Adt::Struct(it) => attrs_from_ast(it, db), + Adt::Enum(it) => attrs_from_ast(it, db), + Adt::Union(it) => attrs_from_ast(it, db), + }, + AttrDef::EnumVariant(it) => attrs_from_ast(it, db), + AttrDef::Static(it) => attrs_from_ast(it, db), + AttrDef::Const(it) => attrs_from_ast(it, db), + AttrDef::Function(it) => attrs_from_ast(it, db), + AttrDef::Trait(it) => attrs_from_ast(it, db), + AttrDef::TypeAlias(it) => attrs_from_ast(it, db), + AttrDef::MacroDef(it) => attrs_from_ast(it, db), + } +} + +fn attrs_from_ast(node: T, db: &D) -> Option> +where + T: HasSource, + T::Ast: ast::AttrsOwner, + D: DefDatabase + AstDatabase, +{ + let src = node.source(db); + let hygiene = Hygiene::new(db, src.file_id); + Attr::from_attrs_owner(&src.ast, &hygiene) +} + +impl + Copy> Attrs for T { + fn attrs(&self, db: &impl HirDatabase) -> Option> { + db.attrs((*self).into()) + } +} diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index eb66325f7..799cc0209 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -2,6 +2,7 @@ use std::sync::Arc; +use hir_def::attr::Attr; use ra_db::salsa; use ra_syntax::SmolStr; @@ -75,6 +76,9 @@ pub trait DefDatabase: HirDebugDatabase + DefDatabase2 { #[salsa::invoke(crate::code_model::docs::documentation_query)] fn documentation(&self, def: crate::DocDef) -> Option; + + #[salsa::invoke(crate::code_model::attrs::attributes_query)] + fn attrs(&self, def: crate::AttrDef) -> Option>; } #[salsa::query_group(HirDatabaseStorage)] diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index 3ba99d92d..4003f0b7a 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -61,6 +61,7 @@ use crate::{ids::MacroFileKind, resolve::Resolver}; pub use crate::{ adt::VariantDef, code_model::{ + attrs::{AttrDef, Attrs}, docs::{DocDef, Docs, Documentation}, src::{HasBodySource, HasSource}, Adt, AssocItem, Const, ConstData, Container, Crate, CrateDependency, DefWithBody, Enum, diff --git a/crates/ra_ide_api/src/completion/presentation.rs b/crates/ra_ide_api/src/completion/presentation.rs index cb55d1875..d861303b7 100644 --- a/crates/ra_ide_api/src/completion/presentation.rs +++ b/crates/ra_ide_api/src/completion/presentation.rs @@ -1,8 +1,8 @@ //! This modules takes care of rendering various definitions as completion items. -use hir::{db::HirDatabase, Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; +use hir::{db::HirDatabase, Attrs, Docs, HasSource, HirDisplay, ScopeDef, Ty, TypeWalk}; use join_to_string::join; -use ra_syntax::ast::{AttrsOwner, NameOwner}; +use ra_syntax::ast::NameOwner; use test_utils::tested_by; use crate::completion::{ @@ -18,11 +18,7 @@ impl Completions { field: hir::StructField, substs: &hir::Substs, ) { - let ast_node = field.source(ctx.db).ast; - let is_deprecated = match ast_node { - hir::FieldSource::Named(m) => is_deprecated(m), - hir::FieldSource::Pos(m) => is_deprecated(m), - }; + let is_deprecated = is_deprecated(field, ctx.db); CompletionItem::new( CompletionKind::Reference, ctx.source_range(), @@ -185,7 +181,7 @@ impl Completions { CompletionItem::new(CompletionKind::Reference, ctx.source_range(), ¯o_declaration) .kind(CompletionItemKind::Macro) .set_documentation(docs.clone()) - .set_deprecated(is_deprecated(ast_node)) + .set_deprecated(is_deprecated(macro_, ctx.db)) .detail(detail); builder = if ctx.use_item_syntax.is_some() { @@ -218,7 +214,7 @@ impl Completions { CompletionItemKind::Function }) .set_documentation(func.docs(ctx.db)) - .set_deprecated(is_deprecated(ast_node)) + .set_deprecated(is_deprecated(func, ctx.db)) .detail(detail); // Add `<>` for generic types @@ -250,7 +246,7 @@ impl Completions { CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string()) .kind(CompletionItemKind::Const) .set_documentation(constant.docs(ctx.db)) - .set_deprecated(is_deprecated(ast_node)) + .set_deprecated(is_deprecated(constant, ctx.db)) .detail(detail) .add_to(self); } @@ -266,13 +262,13 @@ impl Completions { CompletionItem::new(CompletionKind::Reference, ctx.source_range(), name.text().to_string()) .kind(CompletionItemKind::TypeAlias) .set_documentation(type_alias.docs(ctx.db)) - .set_deprecated(is_deprecated(type_def)) + .set_deprecated(is_deprecated(type_alias, ctx.db)) .detail(detail) .add_to(self); } pub(crate) fn add_enum_variant(&mut self, ctx: &CompletionContext, variant: hir::EnumVariant) { - let is_deprecated = is_deprecated(variant.source(ctx.db).ast); + let is_deprecated = is_deprecated(variant, ctx.db); let name = match variant.name(ctx.db) { Some(it) => it, None => return, @@ -291,8 +287,11 @@ impl Completions { } } -fn is_deprecated(node: impl AttrsOwner) -> bool { - node.attrs().filter_map(|x| x.simple_name()).any(|x| x == "deprecated") +fn is_deprecated(node: impl Attrs, db: &impl HirDatabase) -> bool { + match node.attrs(db) { + None => false, + Some(attrs) => attrs.iter().any(|x| x.is_simple_atom("deprecated")), + } } fn has_non_default_type_params(def: hir::GenericDef, db: &db::RootDatabase) -> bool { -- cgit v1.2.3