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
, TraitAlias
, TypeAlias
, TypeParam
, Union
,
22 fn attrs(self, db
: &dyn HirDatabase
) -> AttrsWithOwner
;
23 fn docs(self, db
: &dyn HirDatabase
) -> Option
<Documentation
>;
28 ns
: Option
<Namespace
>,
29 ) -> Option
<ModuleDef
>;
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
<ModuleDef
> {
51 let def
= AttrDefId
::$
def_id(self.into());
52 resolve_doc_path(db
, def
, link
, ns
).map(ModuleDef
::from
)
60 (Variant
, EnumVariantId
),
64 (TraitAlias
, TraitAliasId
),
65 (TypeAlias
, TypeAliasId
),
67 (Function
, FunctionId
),
70 (GenericParam
, GenericParamId
),
74 macro_rules
! impl_has_attrs_enum
{
75 ($
($variant
:ident
),* for $
enum:ident
) => {$
(
76 impl HasAttrs
for $variant
{
77 fn attrs(self, db
: &dyn HirDatabase
) -> AttrsWithOwner
{
78 $
enum::$
variant(self).attrs(db
)
80 fn docs(self, db
: &dyn HirDatabase
) -> Option
<Documentation
> {
81 $
enum::$
variant(self).docs(db
)
83 fn resolve_doc_path(self, db
: &dyn HirDatabase
, link
: &str, ns
: Option
<Namespace
>) -> Option
<ModuleDef
> {
84 $
enum::$
variant(self).resolve_doc_path(db
, link
, ns
)
90 impl_has_attrs_enum
![Struct
, Union
, Enum
for Adt
];
91 impl_has_attrs_enum
![TypeParam
, ConstParam
, LifetimeParam
for GenericParam
];
93 impl HasAttrs
for AssocItem
{
94 fn attrs(self, db
: &dyn HirDatabase
) -> AttrsWithOwner
{
96 AssocItem
::Function(it
) => it
.attrs(db
),
97 AssocItem
::Const(it
) => it
.attrs(db
),
98 AssocItem
::TypeAlias(it
) => it
.attrs(db
),
102 fn docs(self, db
: &dyn HirDatabase
) -> Option
<Documentation
> {
104 AssocItem
::Function(it
) => it
.docs(db
),
105 AssocItem
::Const(it
) => it
.docs(db
),
106 AssocItem
::TypeAlias(it
) => it
.docs(db
),
112 db
: &dyn HirDatabase
,
114 ns
: Option
<Namespace
>,
115 ) -> Option
<ModuleDef
> {
117 AssocItem
::Function(it
) => it
.resolve_doc_path(db
, link
, ns
),
118 AssocItem
::Const(it
) => it
.resolve_doc_path(db
, link
, ns
),
119 AssocItem
::TypeAlias(it
) => it
.resolve_doc_path(db
, link
, ns
),
125 db
: &dyn HirDatabase
,
128 ns
: Option
<Namespace
>,
129 ) -> Option
<ModuleDefId
> {
130 let resolver
= match def
{
131 AttrDefId
::ModuleId(it
) => it
.resolver(db
.upcast()),
132 AttrDefId
::FieldId(it
) => it
.parent
.resolver(db
.upcast()),
133 AttrDefId
::AdtId(it
) => it
.resolver(db
.upcast()),
134 AttrDefId
::FunctionId(it
) => it
.resolver(db
.upcast()),
135 AttrDefId
::EnumVariantId(it
) => it
.parent
.resolver(db
.upcast()),
136 AttrDefId
::StaticId(it
) => it
.resolver(db
.upcast()),
137 AttrDefId
::ConstId(it
) => it
.resolver(db
.upcast()),
138 AttrDefId
::TraitId(it
) => it
.resolver(db
.upcast()),
139 AttrDefId
::TraitAliasId(it
) => it
.resolver(db
.upcast()),
140 AttrDefId
::TypeAliasId(it
) => it
.resolver(db
.upcast()),
141 AttrDefId
::ImplId(it
) => it
.resolver(db
.upcast()),
142 AttrDefId
::ExternBlockId(it
) => it
.resolver(db
.upcast()),
143 AttrDefId
::MacroId(it
) => it
.resolver(db
.upcast()),
144 AttrDefId
::GenericParamId(it
) => match it
{
145 GenericParamId
::TypeParamId(it
) => it
.parent(),
146 GenericParamId
::ConstParamId(it
) => it
.parent(),
147 GenericParamId
::LifetimeParamId(it
) => it
.parent
,
149 .resolver(db
.upcast()),
153 // FIXME: this is not how we should get a mod path here
154 let ast_path
= ast
::SourceFile
::parse(&format
!("type T = {link};"))
157 .find_map(ast
::Path
::cast
)?
;
158 if ast_path
.to_string() != link
{
161 ModPath
::from_src(db
.upcast(), ast_path
, &Hygiene
::new_unhygienic())?
164 let resolved
= resolver
.resolve_module_path_in_items(db
.upcast(), &modpath
);
165 let resolved
= if resolved
== PerNs
::none() {
166 resolver
.resolve_module_path_in_trait_assoc_items(db
.upcast(), &modpath
)?
171 Some(Namespace
::Types
) => resolved
.take_types(),
172 Some(Namespace
::Values
) => resolved
.take_values(),
173 Some(Namespace
::Macros
) => resolved
.take_macros().map(ModuleDefId
::MacroId
),
174 None
=> resolved
.iter_items().next().map(|it
| match it
{
175 ItemInNs
::Types(it
) => it
,
176 ItemInNs
::Values(it
) => it
,
177 ItemInNs
::Macros(it
) => ModuleDefId
::MacroId(it
),