1 //! Attributes & documentation for hir types.
5 attr::{AttrsWithOwner, Documentation},
10 AttrDefId, GenericParamId, ModuleDefId,
12 use hir_expand::{hygiene::Hygiene, MacroDefId};
13 use hir_ty::db::HirDatabase;
14 use syntax::{ast, AstNode};
17 Adt, AssocItem, Const, ConstParam, Enum, Field, Function, GenericParam, Impl, LifetimeParam,
18 MacroDef, Module, ModuleDef, Static, Struct, Trait, TypeAlias, TypeParam, Union, Variant,
22 fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner;
23 fn docs(self, db: &dyn HirDatabase) -> Option<Documentation>;
28 ns: Option<Namespace>,
29 ) -> Option<Either<ModuleDef, MacroDef>>;
32 #[derive(PartialEq, Eq, Hash, Copy, Clone, Debug)]
39 macro_rules! impl_has_attrs {
40 ($(($def:ident, $def_id:ident),)*) => {$(
41 impl HasAttrs for $def {
42 fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner {
43 let def = AttrDefId::$def_id(self.into());
46 fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
47 let def = AttrDefId::$def_id(self.into());
50 fn resolve_doc_path(self, db: &dyn HirDatabase, link: &str, ns: Option<Namespace>) -> Option<Either<ModuleDef, MacroDef>> {
51 let def = AttrDefId::$def_id(self.into());
52 resolve_doc_path(db, def, link, ns).map(|it| it.map_left(ModuleDef::from).map_right(MacroDef::from))
60 (Variant, EnumVariantId),
64 (TypeAlias, TypeAliasId),
65 (MacroDef, MacroDefId),
66 (Function, FunctionId),
69 (GenericParam, GenericParamId),
73 macro_rules! impl_has_attrs_enum {
74 ($($variant:ident),* for $enum:ident) => {$(
75 impl HasAttrs for $variant {
76 fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner {
77 $enum::$variant(self).attrs(db)
79 fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
80 $enum::$variant(self).docs(db)
82 fn resolve_doc_path(self, db: &dyn HirDatabase, link: &str, ns: Option<Namespace>) -> Option<Either<ModuleDef, MacroDef>> {
83 $enum::$variant(self).resolve_doc_path(db, link, ns)
89 impl_has_attrs_enum![Struct, Union, Enum for Adt];
90 impl_has_attrs_enum![TypeParam, ConstParam, LifetimeParam for GenericParam];
92 impl HasAttrs for AssocItem {
93 fn attrs(self, db: &dyn HirDatabase) -> AttrsWithOwner {
95 AssocItem::Function(it) => it.attrs(db),
96 AssocItem::Const(it) => it.attrs(db),
97 AssocItem::TypeAlias(it) => it.attrs(db),
101 fn docs(self, db: &dyn HirDatabase) -> Option<Documentation> {
103 AssocItem::Function(it) => it.docs(db),
104 AssocItem::Const(it) => it.docs(db),
105 AssocItem::TypeAlias(it) => it.docs(db),
111 db: &dyn HirDatabase,
113 ns: Option<Namespace>,
114 ) -> Option<Either<ModuleDef, MacroDef>> {
116 AssocItem::Function(it) => it.resolve_doc_path(db, link, ns),
117 AssocItem::Const(it) => it.resolve_doc_path(db, link, ns),
118 AssocItem::TypeAlias(it) => it.resolve_doc_path(db, link, ns),
124 db: &dyn HirDatabase,
127 ns: Option<Namespace>,
128 ) -> Option<Either<ModuleDefId, MacroDefId>> {
129 let resolver = match def {
130 AttrDefId::ModuleId(it) => it.resolver(db.upcast()),
131 AttrDefId::FieldId(it) => it.parent.resolver(db.upcast()),
132 AttrDefId::AdtId(it) => it.resolver(db.upcast()),
133 AttrDefId::FunctionId(it) => it.resolver(db.upcast()),
134 AttrDefId::EnumVariantId(it) => it.parent.resolver(db.upcast()),
135 AttrDefId::StaticId(it) => it.resolver(db.upcast()),
136 AttrDefId::ConstId(it) => it.resolver(db.upcast()),
137 AttrDefId::TraitId(it) => it.resolver(db.upcast()),
138 AttrDefId::TypeAliasId(it) => it.resolver(db.upcast()),
139 AttrDefId::ImplId(it) => it.resolver(db.upcast()),
140 AttrDefId::ExternBlockId(it) => it.resolver(db.upcast()),
141 AttrDefId::GenericParamId(it) => match it {
142 GenericParamId::TypeParamId(it) => it.parent,
143 GenericParamId::LifetimeParamId(it) => it.parent,
144 GenericParamId::ConstParamId(it) => it.parent,
146 .resolver(db.upcast()),
148 AttrDefId::MacroDefId(_) => return None,
152 let ast_path = ast::SourceFile::parse(&format!("type T = {};", link))
155 .find_map(ast::Path::cast)?;
156 if ast_path.to_string() != link {
159 ModPath::from_src(db.upcast(), ast_path, &Hygiene::new_unhygienic())?
162 let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath);
163 let resolved = if resolved == PerNs::none() {
164 resolver.resolve_module_path_in_trait_assoc_items(db.upcast(), &modpath)?
169 Some(Namespace::Types) => resolved.take_types().map(Either::Left),
170 Some(Namespace::Values) => resolved.take_values().map(Either::Left),
171 Some(Namespace::Macros) => resolved.take_macros().map(Either::Right),
172 None => resolved.iter_items().next().map(|it| match it {
173 ItemInNs::Types(it) => Either::Left(it),
174 ItemInNs::Values(it) => Either::Left(it),
175 ItemInNs::Macros(it) => Either::Right(it),