aboutsummaryrefslogtreecommitdiff
path: root/crates/ra_hir/src/code_model.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/ra_hir/src/code_model.rs')
-rw-r--r--crates/ra_hir/src/code_model.rs104
1 files changed, 103 insertions, 1 deletions
diff --git a/crates/ra_hir/src/code_model.rs b/crates/ra_hir/src/code_model.rs
index 8284ab757..8154e9bf6 100644
--- a/crates/ra_hir/src/code_model.rs
+++ b/crates/ra_hir/src/code_model.rs
@@ -16,7 +16,7 @@ use hir_def::{
16 type_ref::{Mutability, TypeRef}, 16 type_ref::{Mutability, TypeRef},
17 AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, 17 AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule,
18 ImplId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId, 18 ImplId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId,
19 TraitId, TypeAliasId, TypeParamId, UnionId, 19 TraitId, TypeAliasId, TypeParamId, UnionId, VariantId,
20}; 20};
21use hir_expand::{ 21use hir_expand::{
22 diagnostics::DiagnosticSink, 22 diagnostics::DiagnosticSink,
@@ -35,12 +35,14 @@ use ra_syntax::{
35 ast::{self, AttrsOwner, NameOwner}, 35 ast::{self, AttrsOwner, NameOwner},
36 AstNode, 36 AstNode,
37}; 37};
38use ra_tt::{Ident, Leaf, Literal, TokenTree};
38use rustc_hash::FxHashSet; 39use rustc_hash::FxHashSet;
39use stdx::impl_from; 40use stdx::impl_from;
40 41
41use crate::{ 42use crate::{
42 db::{DefDatabase, HirDatabase}, 43 db::{DefDatabase, HirDatabase},
43 has_source::HasSource, 44 has_source::HasSource,
45 link_rewrite::Resolvable,
44 HirDisplay, InFile, Name, 46 HirDisplay, InFile, Name,
45}; 47};
46 48
@@ -120,6 +122,33 @@ impl Crate {
120 pub fn all(db: &dyn HirDatabase) -> Vec<Crate> { 122 pub fn all(db: &dyn HirDatabase) -> Vec<Crate> {
121 db.crate_graph().iter().map(|id| Crate { id }).collect() 123 db.crate_graph().iter().map(|id| Crate { id }).collect()
122 } 124 }
125
126 /// Try to get the root URL of the documentation of a crate.
127 pub fn get_doc_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> {
128 // Look for #![doc(html_root_url = "...")]
129 let attrs = db.attrs(AttrDef::from(self.root_module(db)?).into());
130 let doc_attr_q = attrs.by_key("doc");
131
132 let doc_url = if doc_attr_q.exists() {
133 doc_attr_q.tt_values().map(|tt| {
134 let name = tt.token_trees.iter()
135 .skip_while(|tt| !matches!(tt, TokenTree::Leaf(Leaf::Ident(Ident{text: ref ident, ..})) if ident == "html_root_url"))
136 .skip(2)
137 .next();
138
139 match name {
140 Some(TokenTree::Leaf(Leaf::Literal(Literal{ref text, ..}))) => Some(text),
141 _ => None
142 }
143 }).flat_map(|t| t).next().map(|s| s.to_string())
144 } else {
145 None
146 };
147
148 doc_url
149 .map(|s| s.trim_matches('"').trim_end_matches("/").to_owned() + "/")
150 .map(|s| s.to_string())
151 }
123} 152}
124 153
125#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 154#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -1709,3 +1738,76 @@ pub trait HasVisibility {
1709 vis.is_visible_from(db.upcast(), module.id) 1738 vis.is_visible_from(db.upcast(), module.id)
1710 } 1739 }
1711} 1740}
1741
1742impl Resolvable for ModuleDef {
1743 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1744 Some(match self {
1745 ModuleDef::Module(m) => ModuleId::from(m.clone()).resolver(db),
1746 ModuleDef::Function(f) => FunctionId::from(f.clone()).resolver(db),
1747 ModuleDef::Adt(adt) => AdtId::from(adt.clone()).resolver(db),
1748 ModuleDef::EnumVariant(ev) => {
1749 GenericDefId::from(GenericDef::from(ev.clone())).resolver(db)
1750 }
1751 ModuleDef::Const(c) => GenericDefId::from(GenericDef::from(c.clone())).resolver(db),
1752 ModuleDef::Static(s) => StaticId::from(s.clone()).resolver(db),
1753 ModuleDef::Trait(t) => TraitId::from(t.clone()).resolver(db),
1754 ModuleDef::TypeAlias(t) => ModuleId::from(t.module(db)).resolver(db),
1755 // FIXME: This should be a resolver relative to `std/core`
1756 ModuleDef::BuiltinType(_t) => None?,
1757 })
1758 }
1759
1760 fn try_into_module_def(self) -> Option<ModuleDef> {
1761 Some(self)
1762 }
1763}
1764
1765impl Resolvable for TypeParam {
1766 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1767 Some(Into::<ModuleId>::into(self.module(db)).resolver(db))
1768 }
1769
1770 fn try_into_module_def(self) -> Option<ModuleDef> {
1771 None
1772 }
1773}
1774
1775impl Resolvable for MacroDef {
1776 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1777 Some(Into::<ModuleId>::into(self.module(db)?).resolver(db))
1778 }
1779
1780 fn try_into_module_def(self) -> Option<ModuleDef> {
1781 None
1782 }
1783}
1784
1785impl Resolvable for Field {
1786 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1787 Some(Into::<VariantId>::into(Into::<VariantDef>::into(self.parent_def(db))).resolver(db))
1788 }
1789
1790 fn try_into_module_def(self) -> Option<ModuleDef> {
1791 None
1792 }
1793}
1794
1795impl Resolvable for ImplDef {
1796 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1797 Some(Into::<ModuleId>::into(self.module(db)).resolver(db))
1798 }
1799
1800 fn try_into_module_def(self) -> Option<ModuleDef> {
1801 None
1802 }
1803}
1804
1805impl Resolvable for Local {
1806 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1807 Some(Into::<ModuleId>::into(self.module(db)).resolver(db))
1808 }
1809
1810 fn try_into_module_def(self) -> Option<ModuleDef> {
1811 None
1812 }
1813}