aboutsummaryrefslogtreecommitdiff
path: root/crates/hir/src/code_model.rs
diff options
context:
space:
mode:
Diffstat (limited to 'crates/hir/src/code_model.rs')
-rw-r--r--crates/hir/src/code_model.rs103
1 files changed, 101 insertions, 2 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index 3d92d0c0d..94dd7f6f5 100644
--- a/crates/hir/src/code_model.rs
+++ b/crates/hir/src/code_model.rs
@@ -20,7 +20,7 @@ use hir_def::{
20 type_ref::{Mutability, TypeRef}, 20 type_ref::{Mutability, TypeRef},
21 AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule, 21 AdtId, AssocContainerId, ConstId, DefWithBodyId, EnumId, FunctionId, GenericDefId, HasModule,
22 ImplId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId, 22 ImplId, LocalEnumVariantId, LocalFieldId, LocalModuleId, Lookup, ModuleId, StaticId, StructId,
23 TraitId, TypeAliasId, TypeParamId, UnionId, 23 TraitId, TypeAliasId, TypeParamId, UnionId, VariantId,
24}; 24};
25use hir_expand::{ 25use hir_expand::{
26 diagnostics::DiagnosticSink, 26 diagnostics::DiagnosticSink,
@@ -39,9 +39,11 @@ use syntax::{
39 ast::{self, AttrsOwner, NameOwner}, 39 ast::{self, AttrsOwner, NameOwner},
40 AstNode, SmolStr, 40 AstNode, SmolStr,
41}; 41};
42use tt::{Ident, Leaf, Literal, TokenTree};
42 43
43use crate::{ 44use crate::{
44 db::{DefDatabase, HirDatabase}, 45 db::{DefDatabase, HirDatabase},
46 doc_links::Resolvable,
45 has_source::HasSource, 47 has_source::HasSource,
46 HirDisplay, InFile, Name, 48 HirDisplay, InFile, Name,
47}; 49};
@@ -122,6 +124,31 @@ impl Crate {
122 pub fn all(db: &dyn HirDatabase) -> Vec<Crate> { 124 pub fn all(db: &dyn HirDatabase) -> Vec<Crate> {
123 db.crate_graph().iter().map(|id| Crate { id }).collect() 125 db.crate_graph().iter().map(|id| Crate { id }).collect()
124 } 126 }
127
128 /// Try to get the root URL of the documentation of a crate.
129 pub fn get_html_root_url(self: &Crate, db: &dyn HirDatabase) -> Option<String> {
130 // Look for #![doc(html_root_url = "...")]
131 let attrs = db.attrs(AttrDef::from(self.root_module(db)).into());
132 let doc_attr_q = attrs.by_key("doc");
133
134 if !doc_attr_q.exists() {
135 return None;
136 }
137
138 let doc_url = doc_attr_q.tt_values().map(|tt| {
139 let name = tt.token_trees.iter()
140 .skip_while(|tt| !matches!(tt, TokenTree::Leaf(Leaf::Ident(Ident{text: ref ident, ..})) if ident == "html_root_url"))
141 .skip(2)
142 .next();
143
144 match name {
145 Some(TokenTree::Leaf(Leaf::Literal(Literal{ref text, ..}))) => Some(text),
146 _ => None
147 }
148 }).flat_map(|t| t).next();
149
150 doc_url.map(|s| s.trim_matches('"').trim_end_matches("/").to_owned() + "/")
151 }
125} 152}
126 153
127#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 154#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -198,7 +225,6 @@ impl ModuleDef {
198 ModuleDef::Function(it) => Some(it.name(db)), 225 ModuleDef::Function(it) => Some(it.name(db)),
199 ModuleDef::EnumVariant(it) => Some(it.name(db)), 226 ModuleDef::EnumVariant(it) => Some(it.name(db)),
200 ModuleDef::TypeAlias(it) => Some(it.name(db)), 227 ModuleDef::TypeAlias(it) => Some(it.name(db)),
201
202 ModuleDef::Module(it) => it.name(db), 228 ModuleDef::Module(it) => it.name(db),
203 ModuleDef::Const(it) => it.name(db), 229 ModuleDef::Const(it) => it.name(db),
204 ModuleDef::Static(it) => it.name(db), 230 ModuleDef::Static(it) => it.name(db),
@@ -1771,3 +1797,76 @@ pub trait HasVisibility {
1771 vis.is_visible_from(db.upcast(), module.id) 1797 vis.is_visible_from(db.upcast(), module.id)
1772 } 1798 }
1773} 1799}
1800
1801impl Resolvable for ModuleDef {
1802 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1803 Some(match self {
1804 ModuleDef::Module(m) => ModuleId::from(m.clone()).resolver(db),
1805 ModuleDef::Function(f) => FunctionId::from(f.clone()).resolver(db),
1806 ModuleDef::Adt(adt) => AdtId::from(adt.clone()).resolver(db),
1807 ModuleDef::EnumVariant(ev) => {
1808 GenericDefId::from(GenericDef::from(ev.clone())).resolver(db)
1809 }
1810 ModuleDef::Const(c) => GenericDefId::from(GenericDef::from(c.clone())).resolver(db),
1811 ModuleDef::Static(s) => StaticId::from(s.clone()).resolver(db),
1812 ModuleDef::Trait(t) => TraitId::from(t.clone()).resolver(db),
1813 ModuleDef::TypeAlias(t) => ModuleId::from(t.module(db)).resolver(db),
1814 // FIXME: This should be a resolver relative to `std/core`
1815 ModuleDef::BuiltinType(_t) => None?,
1816 })
1817 }
1818
1819 fn try_into_module_def(self) -> Option<ModuleDef> {
1820 Some(self)
1821 }
1822}
1823
1824impl Resolvable for TypeParam {
1825 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1826 Some(Into::<ModuleId>::into(self.module(db)).resolver(db))
1827 }
1828
1829 fn try_into_module_def(self) -> Option<ModuleDef> {
1830 None
1831 }
1832}
1833
1834impl Resolvable for MacroDef {
1835 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1836 Some(Into::<ModuleId>::into(self.module(db)?).resolver(db))
1837 }
1838
1839 fn try_into_module_def(self) -> Option<ModuleDef> {
1840 None
1841 }
1842}
1843
1844impl Resolvable for Field {
1845 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1846 Some(Into::<VariantId>::into(Into::<VariantDef>::into(self.parent_def(db))).resolver(db))
1847 }
1848
1849 fn try_into_module_def(self) -> Option<ModuleDef> {
1850 None
1851 }
1852}
1853
1854impl Resolvable for ImplDef {
1855 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1856 Some(Into::<ModuleId>::into(self.module(db)).resolver(db))
1857 }
1858
1859 fn try_into_module_def(self) -> Option<ModuleDef> {
1860 None
1861 }
1862}
1863
1864impl Resolvable for Local {
1865 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1866 Some(Into::<ModuleId>::into(self.module(db)).resolver(db))
1867 }
1868
1869 fn try_into_module_def(self) -> Option<ModuleDef> {
1870 None
1871 }
1872}