1 //! Attributes & documentation for hir types.
4 attr::{AttrsWithOwner, Documentation},
9 AttrDefId, GenericParamId, ModuleDefId,
11 use hir_expand::hygiene::Hygiene;
12 use hir_ty::db::HirDatabase;
13 use syntax::{ast, AstNode};
16 Adt, AssocItem, Const, ConstParam, Enum, Field, Function, GenericParam, Impl, LifetimeParam,
17 Macro, Module, ModuleDef, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant,
21 fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner;
22 fn docs(self, db: &dyn HirDatabase) -> Option<Documentation>;
27 ns: Option<Namespace>,
28 ) -> Option<ModuleDef>;
31 #[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
38 macro_rules! impl_has_attrs {
39 ($(($def:ident, $def_id:ident),)*) => {$(
40 impl HasAttrs for $def {
41 fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner {
42 let def = AttrDefId::$def_id(self.into());
45 fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
46 let def = AttrDefId::$def_id(self.into());
49 fn resolve_doc_path(self, db: &dyn HirDatabase, link: &str, ns: Option<Namespace>) -> Option<ModuleDef> {
50 let def = AttrDefId::$def_id(self.into());
51 resolve_doc_path(db, def, link, ns).map(ModuleDef::from)
59 (Variant, EnumVariantId),
63 (TypeAlias, TypeAliasId),
65 (Function, FunctionId),
68 (GenericParam, GenericParamId),
72 macro_rules! impl_has_attrs_enum {
73 ($($variant:ident),* for $enum:ident) => {$(
74 impl HasAttrs for $variant {
75 fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner {
76 $enum::$variant(self).attrs(db)
78 fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
79 $enum::$variant(self).docs(db)
81 fn resolve_doc_path(self, db: &dyn HirDatabase, link: &str, ns: Option<Namespace>) -> Option<ModuleDef> {
82 $enum::$variant(self).resolve_doc_path(db, link, ns)
88 impl_has_attrs_enum![Struct, Union, Enum for Adt];
89 impl_has_attrs_enum![TypeParam, ConstParam, LifetimeParam for GenericParam];
91 impl HasAttrs for AssocItem {
92 fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner {
94 AssocItem::Function(it) => it.attrs(db),
95 AssocItem::Const(it) => it.attrs(db),
96 AssocItem::TypeAlias(it) => it.attrs(db),
100 fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
102 AssocItem::Function(it) => it.docs(db),
103 AssocItem::Const(it) => it.docs(db),
104 AssocItem::TypeAlias(it) => it.docs(db),
110 db: &dyn HirDatabase,
112 ns: Option<Namespace>,
113 ) -> Option<ModuleDef> {
115 AssocItem::Function(it) => it.resolve_doc_path(db, link, ns),
116 AssocItem::Const(it) => it.resolve_doc_path(db, link, ns),
117 AssocItem::TypeAlias(it) => it.resolve_doc_path(db, link, ns),
123 db: &dyn HirDatabase,
126 ns: Option<Namespace>,
127 ) -> Option<ModuleDefId> {
128 let resolver = match def {
129 AttrDefId::ModuleId(it) => it.resolver(db.upcast()),
130 AttrDefId::FieldId(it) => it.parent.resolver(db.upcast()),
131 AttrDefId::AdtId(it) => it.resolver(db.upcast()),
132 AttrDefId::FunctionId(it) => it.resolver(db.upcast()),
133 AttrDefId::EnumVariantId(it) => it.parent.resolver(db.upcast()),
134 AttrDefId::StaticId(it) => it.resolver(db.upcast()),
135 AttrDefId::ConstId(it) => it.resolver(db.upcast()),
136 AttrDefId::TraitId(it) => it.resolver(db.upcast()),
137 AttrDefId::TypeAliasId(it) => it.resolver(db.upcast()),
138 AttrDefId::ImplId(it) => it.resolver(db.upcast()),
139 AttrDefId::ExternBlockId(it) => it.resolver(db.upcast()),
140 AttrDefId::MacroId(it) => it.resolver(db.upcast()),
141 AttrDefId::GenericParamId(it) => match it {
142 GenericParamId::TypeParamId(it) => it.parent(),
143 GenericParamId::ConstParamId(it) => it.parent(),
144 GenericParamId::LifetimeParamId(it) => it.parent,
146 .resolver(db.upcast()),
150 // FIXME: this is not how we should get a mod path here
151 let ast_path = ast::SourceFile::parse(&format!("type T = {};", link))
154 .find_map(ast::Path::cast)?;
155 if ast_path.to_string() != link {
158 ModPath::from_src(db.upcast(), ast_path, &Hygiene::new_unhygienic())?
161 let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath);
162 let resolved = if resolved == PerNs::none() {
163 resolver.resolve_module_path_in_trait_assoc_items(db.upcast(), &modpath)?
168 Some(Namespace::Types) => resolved.take_types(),
169 Some(Namespace::Values) => resolved.take_values(),
170 Some(Namespace::Macros) => resolved.take_macros().map(ModuleDefId::MacroId),
171 None => resolved.iter_items().next().map(|it| match it {
172 ItemInNs::Types(it) => it,
173 ItemInNs::Values(it) => it,
174 ItemInNs::Macros(it) => ModuleDefId::MacroId(it),