//! Attributes & documentation for hir types.
use hir_def::{
attr::Attrs,
- db::DefDatabase,
docs::Documentation,
resolver::{HasResolver, Resolver},
AdtId, AttrDefId, FunctionId, GenericDefId, ModuleId, StaticId, TraitId, VariantId,
impl_has_attrs_adt![Struct, Union, Enum];
impl Resolvable for ModuleDef {
- fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
+ fn resolver(&self, db: &dyn HirDatabase) -> Option<Resolver> {
Some(match self {
- ModuleDef::Module(m) => ModuleId::from(m.clone()).resolver(db),
- ModuleDef::Function(f) => FunctionId::from(f.clone()).resolver(db),
- ModuleDef::Adt(adt) => AdtId::from(adt.clone()).resolver(db),
+ ModuleDef::Module(m) => ModuleId::from(m.clone()).resolver(db.upcast()),
+ ModuleDef::Function(f) => FunctionId::from(f.clone()).resolver(db.upcast()),
+ ModuleDef::Adt(adt) => AdtId::from(adt.clone()).resolver(db.upcast()),
ModuleDef::EnumVariant(ev) => {
- GenericDefId::from(GenericDef::from(ev.clone())).resolver(db)
+ GenericDefId::from(GenericDef::from(ev.clone())).resolver(db.upcast())
}
- ModuleDef::Const(c) => GenericDefId::from(GenericDef::from(c.clone())).resolver(db),
- ModuleDef::Static(s) => StaticId::from(s.clone()).resolver(db),
- ModuleDef::Trait(t) => TraitId::from(t.clone()).resolver(db),
- ModuleDef::TypeAlias(t) => ModuleId::from(t.module(db)).resolver(db),
+ ModuleDef::Const(c) => {
+ GenericDefId::from(GenericDef::from(c.clone())).resolver(db.upcast())
+ }
+ ModuleDef::Static(s) => StaticId::from(s.clone()).resolver(db.upcast()),
+ ModuleDef::Trait(t) => TraitId::from(t.clone()).resolver(db.upcast()),
+ ModuleDef::TypeAlias(t) => ModuleId::from(t.module(db)).resolver(db.upcast()),
// FIXME: This should be a resolver relative to `std/core`
ModuleDef::BuiltinType(_t) => None?,
})
}
impl Resolvable for TypeParam {
- fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
- Some(ModuleId::from(self.module(db)).resolver(db))
+ fn resolver(&self, db: &dyn HirDatabase) -> Option<Resolver> {
+ Some(ModuleId::from(self.module(db)).resolver(db.upcast()))
}
fn try_into_module_def(self) -> Option<ModuleDef> {
}
impl Resolvable for MacroDef {
- fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
- Some(ModuleId::from(self.module(db)?).resolver(db))
+ fn resolver(&self, db: &dyn HirDatabase) -> Option<Resolver> {
+ Some(ModuleId::from(self.module(db)?).resolver(db.upcast()))
}
fn try_into_module_def(self) -> Option<ModuleDef> {
}
impl Resolvable for Field {
- fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
- Some(VariantId::from(self.parent_def(db)).resolver(db))
+ fn resolver(&self, db: &dyn HirDatabase) -> Option<Resolver> {
+ Some(VariantId::from(self.parent_def(db)).resolver(db.upcast()))
}
fn try_into_module_def(self) -> Option<ModuleDef> {
}
impl Resolvable for ImplDef {
- fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
- Some(ModuleId::from(self.module(db)).resolver(db))
+ fn resolver(&self, db: &dyn HirDatabase) -> Option<Resolver> {
+ Some(ModuleId::from(self.module(db)).resolver(db.upcast()))
}
fn try_into_module_def(self) -> Option<ModuleDef> {
}
impl Resolvable for Local {
- fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
- Some(ModuleId::from(self.module(db)).resolver(db))
+ fn resolver(&self, db: &dyn HirDatabase) -> Option<Resolver> {
+ Some(ModuleId::from(self.module(db)).resolver(db.upcast()))
}
fn try_into_module_def(self) -> Option<ModuleDef> {
use std::iter::once;
-use hir_def::{db::DefDatabase, resolver::Resolver};
+use hir_def::resolver::Resolver;
use itertools::Itertools;
use syntax::ast::Path;
use url::Url;
use crate::{db::HirDatabase, Adt, AsName, Crate, Hygiene, ItemInNs, ModPath, ModuleDef};
-pub fn resolve_doc_link<T: Resolvable + Clone, D: DefDatabase + HirDatabase>(
- db: &D,
+pub fn resolve_doc_link<T: Resolvable + Clone>(
+ db: &dyn HirDatabase,
definition: &T,
link_text: &str,
link_target: &str,
) -> Option<(String, String)> {
- try_resolve_intra(db, definition, link_text, &link_target).or_else(|| {
- let definition = definition.clone().try_into_module_def()?;
- try_resolve_path(db, &definition, &link_target)
+ let resolver = definition.resolver(db)?;
+ let module_def = definition.clone().try_into_module_def();
+ resolve_doc_link_impl(db, &resolver, module_def, link_text, link_target)
+}
+
+fn resolve_doc_link_impl(
+ db: &dyn HirDatabase,
+ resolver: &Resolver,
+ module_def: Option<ModuleDef>,
+ link_text: &str,
+ link_target: &str,
+) -> Option<(String, String)> {
+ try_resolve_intra(db, &resolver, link_text, &link_target).or_else(|| {
+ try_resolve_path(db, &module_def?, &link_target)
.map(|target| (target, link_text.to_string()))
})
}
/// Try to resolve path to local documentation via intra-doc-links (i.e. `super::gateway::Shard`).
///
/// See [RFC1946](https://github.com/rust-lang/rfcs/blob/master/text/1946-intra-rustdoc-links.md).
-fn try_resolve_intra<T: Resolvable, D: DefDatabase + HirDatabase>(
- db: &D,
- definition: &T,
+fn try_resolve_intra(
+ db: &dyn HirDatabase,
+ resolver: &Resolver,
link_text: &str,
link_target: &str,
) -> Option<(String, String)> {
let path = Path::parse(doclink.path).ok()?;
let modpath = ModPath::from_src(path, &Hygiene::new_unhygienic()).unwrap();
- // Resolve it relative to symbol's location (according to the RFC this should consider small scopes)
- let resolver = definition.resolver(db)?;
-
- let resolved = resolver.resolve_module_path_in_items(db, &modpath);
+ let resolved = resolver.resolve_module_path_in_items(db.upcast(), &modpath);
let (defid, namespace) = match doclink.namespace {
// FIXME: .or(resolved.macros)
None => resolved
/// Sealed trait used solely for the generic bound on [`resolve_doc_link`].
pub trait Resolvable {
- fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver>;
+ fn resolver(&self, db: &dyn HirDatabase) -> Option<Resolver>;
fn try_into_module_def(self) -> Option<ModuleDef>;
}