From 552ba868afc8f72202ac834d07bbeb330aca007d Mon Sep 17 00:00:00 2001 From: Aleksey Kladov Date: Sat, 23 Nov 2019 11:14:10 +0300 Subject: [PATCH] Move attrs query to hir_def --- crates/ra_hir/src/code_model.rs | 56 +++++++++++++++-- crates/ra_hir/src/code_model/attrs.rs | 91 --------------------------- crates/ra_hir/src/code_model/src.rs | 19 +++--- crates/ra_hir/src/db.rs | 4 -- crates/ra_hir/src/from_id.rs | 10 ++- crates/ra_hir/src/lib.rs | 9 ++- crates/ra_hir_def/src/attr.rs | 66 ++++++++++++++++++- crates/ra_hir_def/src/db.rs | 6 +- crates/ra_hir_def/src/lib.rs | 33 +++++++++- crates/ra_hir_def/src/nameres.rs | 31 ++++++++- 10 files changed, 202 insertions(+), 123 deletions(-) delete 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 9f8c6c4a52b..496b4ee8a4e 100644 --- a/crates/ra_hir/src/code_model.rs +++ b/crates/ra_hir/src/code_model.rs @@ -2,7 +2,6 @@ pub(crate) mod src; pub(crate) mod docs; -pub(crate) mod attrs; use std::sync::Arc; @@ -13,8 +12,8 @@ nameres::per_ns::PerNs, resolver::{HasResolver, TypeNs}, type_ref::TypeRef, - ContainerId, CrateModuleId, HasModule, ImplId, LocalEnumVariantId, LocalStructFieldId, Lookup, - ModuleId, UnionId, + AdtId, ContainerId, CrateModuleId, EnumVariantId, HasModule, ImplId, LocalEnumVariantId, + LocalStructFieldId, Lookup, ModuleId, StructFieldId, UnionId, }; use hir_expand::{ diagnostics::DiagnosticSink, @@ -110,7 +109,7 @@ pub enum ModuleDef { BuiltinType ); -pub use hir_def::ModuleSource; +pub use hir_def::{attr::Attrs, ModuleSource}; impl Module { pub(crate) fn new(krate: Crate, crate_module_id: CrateModuleId) -> Module { @@ -991,3 +990,52 @@ fn from(def: PerNs) -> Self { .unwrap_or(ScopeDef::Unknown) } } + +#[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 HasAttrs { + fn attrs(self, db: &impl DefDatabase) -> Attrs; +} + +impl> HasAttrs for T { + fn attrs(self, db: &impl DefDatabase) -> Attrs { + let def = self.into(); + match def { + AttrDef::Module(it) => db.attrs(it.id.into()), + AttrDef::StructField(it) => db.attrs(StructFieldId::from(it).into()), + AttrDef::Adt(it) => db.attrs(AdtId::from(it).into()), + AttrDef::Function(it) => db.attrs(it.id.into()), + AttrDef::EnumVariant(it) => db.attrs(EnumVariantId::from(it).into()), + AttrDef::Static(it) => db.attrs(it.id.into()), + AttrDef::Const(it) => db.attrs(it.id.into()), + AttrDef::Trait(it) => db.attrs(it.id.into()), + AttrDef::TypeAlias(it) => db.attrs(it.id.into()), + AttrDef::MacroDef(it) => db.attrs(it.id.into()), + } + } +} diff --git a/crates/ra_hir/src/code_model/attrs.rs b/crates/ra_hir/src/code_model/attrs.rs deleted file mode 100644 index 96da8c88c44..00000000000 --- a/crates/ra_hir/src/code_model/attrs.rs +++ /dev/null @@ -1,91 +0,0 @@ -//! 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, Attrs}; -use hir_expand::hygiene::Hygiene; -use ra_syntax::ast; - -#[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 HasAttrs { - fn attrs(&self, db: &impl HirDatabase) -> Attrs; -} - -pub(crate) fn attributes_query(db: &(impl DefDatabase + AstDatabase), def: AttrDef) -> Attrs { - match def { - AttrDef::Module(it) => { - let src = match it.declaration_source(db) { - Some(it) => it, - None => return Attrs::default(), - }; - let hygiene = Hygiene::new(db, src.file_id); - Attr::from_attrs_owner(&src.value, &hygiene) - } - AttrDef::StructField(it) => match it.source(db).value { - FieldSource::Named(named) => { - let src = it.source(db); - let hygiene = Hygiene::new(db, src.file_id); - Attr::from_attrs_owner(&named, &hygiene) - } - FieldSource::Pos(..) => Attrs::default(), - }, - 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) -> Attrs -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.value, &hygiene) -} - -impl + Copy> HasAttrs for T { - fn attrs(&self, db: &impl HirDatabase) -> Attrs { - db.attrs((*self).into()) - } -} diff --git a/crates/ra_hir/src/code_model/src.rs b/crates/ra_hir/src/code_model/src.rs index a45c062bf4c..09bacf5790a 100644 --- a/crates/ra_hir/src/code_model/src.rs +++ b/crates/ra_hir/src/code_model/src.rs @@ -1,13 +1,14 @@ //! FIXME: write short doc here use hir_def::{HasChildSource, HasSource as _, Lookup, VariantId}; +use hir_expand::either::Either; use ra_syntax::ast::{self, AstNode}; use crate::{ db::{AstDatabase, DefDatabase, HirDatabase}, ids::AstItemDef, - Const, Either, Enum, EnumVariant, FieldSource, Function, HasBody, HirFileId, MacroDef, Module, - ModuleSource, Static, Struct, StructField, Trait, TypeAlias, Union, + Const, Enum, EnumVariant, FieldSource, Function, HasBody, MacroDef, Module, ModuleSource, + Static, Struct, StructField, Trait, TypeAlias, Union, }; pub use hir_expand::Source; @@ -23,11 +24,11 @@ impl Module { /// Returns a node which defines this module. That is, a file or a `mod foo {}` with items. pub fn definition_source(self, db: &(impl DefDatabase + AstDatabase)) -> Source { let def_map = db.crate_def_map(self.id.krate); - let decl_id = def_map[self.id.module_id].declaration; - let file_id = def_map[self.id.module_id].definition; - let value = ModuleSource::new(db, file_id, decl_id); - let file_id = file_id.map(HirFileId::from).unwrap_or_else(|| decl_id.unwrap().file_id()); - Source { file_id, value } + let src = def_map[self.id.module_id].definition_source(db); + src.map(|it| match it { + Either::A(it) => ModuleSource::SourceFile(it), + Either::B(it) => ModuleSource::Module(it), + }) } /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. @@ -37,9 +38,7 @@ pub fn declaration_source( db: &(impl DefDatabase + AstDatabase), ) -> Option> { let def_map = db.crate_def_map(self.id.krate); - let decl = def_map[self.id.module_id].declaration?; - let value = decl.to_node(db); - Some(Source { file_id: decl.file_id(), value }) + def_map[self.id.module_id].declaration_source(db) } } diff --git a/crates/ra_hir/src/db.rs b/crates/ra_hir/src/db.rs index 85d46b485f4..c3f698ea039 100644 --- a/crates/ra_hir/src/db.rs +++ b/crates/ra_hir/src/db.rs @@ -2,7 +2,6 @@ use std::sync::Arc; -use hir_def::attr::Attrs; use ra_db::salsa; use ra_syntax::SmolStr; @@ -46,9 +45,6 @@ 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) -> Attrs; } #[salsa::query_group(HirDatabaseStorage)] diff --git a/crates/ra_hir/src/from_id.rs b/crates/ra_hir/src/from_id.rs index 8900fc1f240..5d7af00ab98 100644 --- a/crates/ra_hir/src/from_id.rs +++ b/crates/ra_hir/src/from_id.rs @@ -5,13 +5,13 @@ use hir_def::{ AdtId, AssocItemId, ConstId, DefWithBodyId, EnumId, EnumVariantId, FunctionId, GenericDefId, - ModuleDefId, StaticId, StructId, TypeAliasId, UnionId, VariantId, + ModuleDefId, StaticId, StructFieldId, StructId, TypeAliasId, UnionId, VariantId, }; use crate::{ ty::{CallableDef, TypableDef}, Adt, AssocItem, Const, Crate, DefWithBody, EnumVariant, Function, GenericDef, ModuleDef, - Static, TypeAlias, VariantDef, + Static, StructField, TypeAlias, VariantDef, }; impl From for Crate { @@ -234,3 +234,9 @@ fn from(def: VariantDef) -> Self { } } } + +impl From for StructFieldId { + fn from(def: StructField) -> Self { + StructFieldId { parent: def.parent.into(), local_id: def.id } + } +} diff --git a/crates/ra_hir/src/lib.rs b/crates/ra_hir/src/lib.rs index e164c9b3275..152590cd171 100644 --- a/crates/ra_hir/src/lib.rs +++ b/crates/ra_hir/src/lib.rs @@ -51,13 +51,12 @@ fn from(it: $sv) -> $e { pub use crate::{ code_model::{ - attrs::{AttrDef, HasAttrs}, docs::{DocDef, Docs, Documentation}, src::{HasBodySource, HasSource}, - Adt, AssocItem, Const, Container, Crate, CrateDependency, DefWithBody, Enum, EnumVariant, - FieldSource, Function, GenericDef, GenericParam, HasBody, ImplBlock, Local, MacroDef, - Module, ModuleDef, ModuleSource, ScopeDef, Static, Struct, StructField, Trait, TypeAlias, - Union, VariantDef, + Adt, AssocItem, AttrDef, Const, Container, Crate, CrateDependency, DefWithBody, Enum, + EnumVariant, FieldSource, Function, GenericDef, GenericParam, HasAttrs, HasBody, ImplBlock, + Local, MacroDef, Module, ModuleDef, ModuleSource, ScopeDef, Static, Struct, StructField, + Trait, TypeAlias, Union, VariantDef, }, expr::ExprScopes, from_source::FromSource, diff --git a/crates/ra_hir_def/src/attr.rs b/crates/ra_hir_def/src/attr.rs index 7a9d0fdf440..ce397f6b06c 100644 --- a/crates/ra_hir_def/src/attr.rs +++ b/crates/ra_hir_def/src/attr.rs @@ -2,7 +2,7 @@ use std::{ops, sync::Arc}; -use hir_expand::hygiene::Hygiene; +use hir_expand::{either::Either, hygiene::Hygiene, AstId}; use mbe::ast_to_token_tree; use ra_cfg::CfgOptions; use ra_syntax::{ @@ -11,7 +11,9 @@ }; use tt::Subtree; -use crate::path::Path; +use crate::{ + db::DefDatabase2, path::Path, AdtId, AstItemDef, AttrDefId, HasChildSource, HasSource, Lookup, +}; #[derive(Default, Debug, Clone, PartialEq, Eq)] pub struct Attrs { @@ -30,6 +32,46 @@ fn deref(&self) -> &[Attr] { } impl Attrs { + pub(crate) fn attrs_query(db: &impl DefDatabase2, def: AttrDefId) -> Attrs { + match def { + AttrDefId::ModuleId(module) => { + let def_map = db.crate_def_map(module.krate); + let src = match def_map[module.module_id].declaration_source(db) { + Some(it) => it, + None => return Attrs::default(), + }; + let hygiene = Hygiene::new(db, src.file_id); + Attr::from_attrs_owner(&src.value, &hygiene) + } + AttrDefId::StructFieldId(it) => { + let src = it.parent.child_source(db); + match &src.value[it.local_id] { + Either::A(_tuple) => Attrs::default(), + Either::B(record) => { + let hygiene = Hygiene::new(db, src.file_id); + Attr::from_attrs_owner(record, &hygiene) + } + } + } + AttrDefId::AdtId(it) => match it { + AdtId::StructId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db), + AdtId::EnumId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), + AdtId::UnionId(it) => attrs_from_ast(it.0.lookup_intern(db).ast_id, db), + }, + AttrDefId::EnumVariantId(it) => { + let src = it.parent.child_source(db); + let hygiene = Hygiene::new(db, src.file_id); + Attr::from_attrs_owner(&src.value[it.local_id], &hygiene) + } + AttrDefId::StaticId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), + AttrDefId::ConstId(it) => attrs_from_loc(it.lookup(db), db), + AttrDefId::FunctionId(it) => attrs_from_loc(it.lookup(db), db), + AttrDefId::TraitId(it) => attrs_from_ast(it.lookup_intern(db).ast_id, db), + AttrDefId::TypeAliasId(it) => attrs_from_loc(it.lookup(db), db), + AttrDefId::MacroDefId(it) => attrs_from_ast(it.ast_id, db), + } + } + pub fn has_atom(&self, atom: &str) -> bool { self.iter().any(|it| it.is_simple_atom(atom)) } @@ -106,3 +148,23 @@ pub fn is_cfg_enabled(&self, cfg_options: &CfgOptions) -> Option { cfg_options.is_cfg_enabled(self.as_cfg()?) } } + +fn attrs_from_ast(src: AstId, db: &D) -> Attrs +where + N: ast::AttrsOwner, + D: DefDatabase2, +{ + let hygiene = Hygiene::new(db, src.file_id()); + Attr::from_attrs_owner(&src.to_node(db), &hygiene) +} + +fn attrs_from_loc(node: T, db: &D) -> Attrs +where + T: HasSource, + T::Value: ast::AttrsOwner, + D: DefDatabase2, +{ + let src = node.source(db); + let hygiene = Hygiene::new(db, src.file_id); + Attr::from_attrs_owner(&src.value, &hygiene) +} diff --git a/crates/ra_hir_def/src/db.rs b/crates/ra_hir_def/src/db.rs index 2c660ab88bd..e91e741bb9b 100644 --- a/crates/ra_hir_def/src/db.rs +++ b/crates/ra_hir_def/src/db.rs @@ -7,6 +7,7 @@ use crate::{ adt::{EnumData, StructData}, + attr::Attrs, body::{scope::ExprScopes, Body, BodySourceMap}, data::{ConstData, FunctionData, ImplData, TraitData, TypeAliasData}, generics::GenericParams, @@ -14,7 +15,7 @@ raw::{ImportSourceMap, RawItems}, CrateDefMap, }, - ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, ImplId, ItemLoc, StaticId, + AttrDefId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, ImplId, ItemLoc, StaticId, StructOrUnionId, TraitId, TypeAliasId, }; @@ -87,4 +88,7 @@ fn raw_items_with_source_map( #[salsa::invoke(GenericParams::generic_params_query)] fn generic_params(&self, def: GenericDefId) -> Arc; + + #[salsa::invoke(Attrs::attrs_query)] + fn attrs(&self, def: AttrDefId) -> Attrs; } diff --git a/crates/ra_hir_def/src/lib.rs b/crates/ra_hir_def/src/lib.rs index 2edf743abba..1bcdf9b7891 100644 --- a/crates/ra_hir_def/src/lib.rs +++ b/crates/ra_hir_def/src/lib.rs @@ -32,7 +32,7 @@ use std::hash::{Hash, Hasher}; -use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, Source}; +use hir_expand::{ast_id_map::FileAstId, db::AstDatabase, AstId, HirFileId, MacroDefId, Source}; use ra_arena::{impl_arena_id, map::ArenaMap, RawId}; use ra_db::{salsa, CrateId, FileId}; use ra_syntax::{ast, AstNode, SyntaxNode}; @@ -280,8 +280,8 @@ pub enum VariantId { #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] pub struct StructFieldId { - parent: VariantId, - local_id: LocalStructFieldId, + pub parent: VariantId, + pub local_id: LocalStructFieldId, } #[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] @@ -477,6 +477,33 @@ pub enum GenericDefId { ConstId ); +#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)] +pub enum AttrDefId { + ModuleId(ModuleId), + StructFieldId(StructFieldId), + AdtId(AdtId), + FunctionId(FunctionId), + EnumVariantId(EnumVariantId), + StaticId(StaticId), + ConstId(ConstId), + TraitId(TraitId), + TypeAliasId(TypeAliasId), + MacroDefId(MacroDefId), +} + +impl_froms!( + AttrDefId: ModuleId, + StructFieldId, + AdtId(StructId, EnumId, UnionId), + EnumVariantId, + StaticId, + ConstId, + FunctionId, + TraitId, + TypeAliasId, + MacroDefId +); + trait Intern { type ID; fn intern(self, db: &impl db::DefDatabase2) -> Self::ID; diff --git a/crates/ra_hir_def/src/nameres.rs b/crates/ra_hir_def/src/nameres.rs index c01e020ef12..6723465a591 100644 --- a/crates/ra_hir_def/src/nameres.rs +++ b/crates/ra_hir_def/src/nameres.rs @@ -58,7 +58,10 @@ use std::sync::Arc; -use hir_expand::{ast_id_map::FileAstId, diagnostics::DiagnosticSink, name::Name, MacroDefId}; +use hir_expand::{ + ast_id_map::FileAstId, diagnostics::DiagnosticSink, either::Either, name::Name, MacroDefId, + Source, +}; use once_cell::sync::Lazy; use ra_arena::Arena; use ra_db::{CrateId, Edition, FileId}; @@ -116,12 +119,15 @@ pub struct ModuleData { pub parent: Option, pub children: FxHashMap, pub scope: ModuleScope, + + // FIXME: these can't be both null, we need a three-state enum here. /// None for root pub declaration: Option>, /// None for inline modules. /// /// Note that non-inline modules, by definition, live inside non-macro file. pub definition: Option, + pub impls: Vec, } @@ -285,6 +291,29 @@ pub fn modules_for_file(&self, file_id: FileId) -> impl Iterator Source> { + if let Some(file_id) = self.definition { + let sf = db.parse(file_id).tree(); + return Source::new(file_id.into(), Either::A(sf)); + } + let decl = self.declaration.unwrap(); + Source::new(decl.file_id(), Either::B(decl.to_node(db))) + } + + /// Returns a node which declares this module, either a `mod foo;` or a `mod foo {}`. + /// `None` for the crate root. + pub fn declaration_source(&self, db: &impl DefDatabase2) -> Option> { + let decl = self.declaration?; + let value = decl.to_node(db); + Some(Source { file_id: decl.file_id(), value }) + } +} + mod diagnostics { use hir_expand::diagnostics::DiagnosticSink; use ra_db::RelativePathBuf;