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.rs122
1 files changed, 120 insertions, 2 deletions
diff --git a/crates/hir/src/code_model.rs b/crates/hir/src/code_model.rs
index 3d92d0c0d..9395efe4f 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,10 +39,12 @@ 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},
45 has_source::HasSource, 46 has_source::HasSource,
47 link_rewrite::Resolvable,
46 HirDisplay, InFile, Name, 48 HirDisplay, InFile, Name,
47}; 49};
48 50
@@ -122,6 +124,33 @@ 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_doc_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 let doc_url = if doc_attr_q.exists() {
135 doc_attr_q.tt_values().map(|tt| {
136 let name = tt.token_trees.iter()
137 .skip_while(|tt| !matches!(tt, TokenTree::Leaf(Leaf::Ident(Ident{text: ref ident, ..})) if ident == "html_root_url"))
138 .skip(2)
139 .next();
140
141 match name {
142 Some(TokenTree::Leaf(Leaf::Literal(Literal{ref text, ..}))) => Some(text),
143 _ => None
144 }
145 }).flat_map(|t| t).next().map(|s| s.to_string())
146 } else {
147 None
148 };
149
150 doc_url
151 .map(|s| s.trim_matches('"').trim_end_matches("/").to_owned() + "/")
152 .map(|s| s.to_string())
153 }
125} 154}
126 155
127#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)] 156#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
@@ -198,7 +227,6 @@ impl ModuleDef {
198 ModuleDef::Function(it) => Some(it.name(db)), 227 ModuleDef::Function(it) => Some(it.name(db)),
199 ModuleDef::EnumVariant(it) => Some(it.name(db)), 228 ModuleDef::EnumVariant(it) => Some(it.name(db)),
200 ModuleDef::TypeAlias(it) => Some(it.name(db)), 229 ModuleDef::TypeAlias(it) => Some(it.name(db)),
201
202 ModuleDef::Module(it) => it.name(db), 230 ModuleDef::Module(it) => it.name(db),
203 ModuleDef::Const(it) => it.name(db), 231 ModuleDef::Const(it) => it.name(db),
204 ModuleDef::Static(it) => it.name(db), 232 ModuleDef::Static(it) => it.name(db),
@@ -206,6 +234,23 @@ impl ModuleDef {
206 ModuleDef::BuiltinType(it) => Some(it.as_name()), 234 ModuleDef::BuiltinType(it) => Some(it.as_name()),
207 } 235 }
208 } 236 }
237
238 pub fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
239 Some(match self {
240 ModuleDef::Module(m) => ModuleId::from(m.clone()).resolver(db),
241 ModuleDef::Function(f) => FunctionId::from(f.clone()).resolver(db),
242 ModuleDef::Adt(adt) => AdtId::from(adt.clone()).resolver(db),
243 ModuleDef::EnumVariant(ev) => {
244 GenericDefId::from(GenericDef::from(ev.clone())).resolver(db)
245 }
246 ModuleDef::Const(c) => GenericDefId::from(GenericDef::from(c.clone())).resolver(db),
247 ModuleDef::Static(s) => StaticId::from(s.clone()).resolver(db),
248 ModuleDef::Trait(t) => TraitId::from(t.clone()).resolver(db),
249 ModuleDef::TypeAlias(t) => ModuleId::from(t.module(db)).resolver(db),
250 // FIXME: This should be a resolver relative to `std/core`
251 ModuleDef::BuiltinType(_t) => None?,
252 })
253 }
209} 254}
210 255
211pub use hir_def::{ 256pub use hir_def::{
@@ -1771,3 +1816,76 @@ pub trait HasVisibility {
1771 vis.is_visible_from(db.upcast(), module.id) 1816 vis.is_visible_from(db.upcast(), module.id)
1772 } 1817 }
1773} 1818}
1819
1820impl Resolvable for ModuleDef {
1821 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1822 Some(match self {
1823 ModuleDef::Module(m) => ModuleId::from(m.clone()).resolver(db),
1824 ModuleDef::Function(f) => FunctionId::from(f.clone()).resolver(db),
1825 ModuleDef::Adt(adt) => AdtId::from(adt.clone()).resolver(db),
1826 ModuleDef::EnumVariant(ev) => {
1827 GenericDefId::from(GenericDef::from(ev.clone())).resolver(db)
1828 }
1829 ModuleDef::Const(c) => GenericDefId::from(GenericDef::from(c.clone())).resolver(db),
1830 ModuleDef::Static(s) => StaticId::from(s.clone()).resolver(db),
1831 ModuleDef::Trait(t) => TraitId::from(t.clone()).resolver(db),
1832 ModuleDef::TypeAlias(t) => ModuleId::from(t.module(db)).resolver(db),
1833 // FIXME: This should be a resolver relative to `std/core`
1834 ModuleDef::BuiltinType(_t) => None?,
1835 })
1836 }
1837
1838 fn try_into_module_def(self) -> Option<ModuleDef> {
1839 Some(self)
1840 }
1841}
1842
1843impl Resolvable for TypeParam {
1844 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1845 Some(Into::<ModuleId>::into(self.module(db)).resolver(db))
1846 }
1847
1848 fn try_into_module_def(self) -> Option<ModuleDef> {
1849 None
1850 }
1851}
1852
1853impl Resolvable for MacroDef {
1854 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1855 Some(Into::<ModuleId>::into(self.module(db)?).resolver(db))
1856 }
1857
1858 fn try_into_module_def(self) -> Option<ModuleDef> {
1859 None
1860 }
1861}
1862
1863impl Resolvable for Field {
1864 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1865 Some(Into::<VariantId>::into(Into::<VariantDef>::into(self.parent_def(db))).resolver(db))
1866 }
1867
1868 fn try_into_module_def(self) -> Option<ModuleDef> {
1869 None
1870 }
1871}
1872
1873impl Resolvable for ImplDef {
1874 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1875 Some(Into::<ModuleId>::into(self.module(db)).resolver(db))
1876 }
1877
1878 fn try_into_module_def(self) -> Option<ModuleDef> {
1879 None
1880 }
1881}
1882
1883impl Resolvable for Local {
1884 fn resolver<D: DefDatabase + HirDatabase>(&self, db: &D) -> Option<Resolver> {
1885 Some(Into::<ModuleId>::into(self.module(db)).resolver(db))
1886 }
1887
1888 fn try_into_module_def(self) -> Option<ModuleDef> {
1889 None
1890 }
1891}