@@ -20,7 +20,7 @@ use hir_def::{
20
20
type_ref:: { Mutability , TypeRef } ,
21
21
AdtId , AssocContainerId , ConstId , DefWithBodyId , EnumId , FunctionId , GenericDefId , HasModule ,
22
22
ImplId , LocalEnumVariantId , LocalFieldId , LocalModuleId , Lookup , ModuleId , StaticId , StructId ,
23
- TraitId , TypeAliasId , TypeParamId , UnionId ,
23
+ TraitId , TypeAliasId , TypeParamId , UnionId , VariantId ,
24
24
} ;
25
25
use hir_expand:: {
26
26
diagnostics:: DiagnosticSink ,
@@ -39,9 +39,11 @@ use syntax::{
39
39
ast:: { self , AttrsOwner , NameOwner } ,
40
40
AstNode , SmolStr ,
41
41
} ;
42
+ use tt:: { Ident , Leaf , Literal , TokenTree } ;
42
43
43
44
use crate :: {
44
45
db:: { DefDatabase , HirDatabase } ,
46
+ doc_links:: Resolvable ,
45
47
has_source:: HasSource ,
46
48
HirDisplay , InFile , Name ,
47
49
} ;
@@ -122,6 +124,31 @@ impl Crate {
122
124
pub fn all ( db : & dyn HirDatabase ) -> Vec < Crate > {
123
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
154
#[ derive( Debug , Clone , Copy , PartialEq , Eq , Hash ) ]
@@ -198,7 +225,6 @@ impl ModuleDef {
198
225
ModuleDef :: Function ( it) => Some ( it. name ( db) ) ,
199
226
ModuleDef :: EnumVariant ( it) => Some ( it. name ( db) ) ,
200
227
ModuleDef :: TypeAlias ( it) => Some ( it. name ( db) ) ,
201
-
202
228
ModuleDef :: Module ( it) => it. name ( db) ,
203
229
ModuleDef :: Const ( it) => it. name ( db) ,
204
230
ModuleDef :: Static ( it) => it. name ( db) ,
@@ -1771,3 +1797,76 @@ pub trait HasVisibility {
1771
1797
vis. is_visible_from ( db. upcast ( ) , module. id )
1772
1798
}
1773
1799
}
1800
+
1801
+ impl 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
+
1824
+ impl 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
+
1834
+ impl 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
+
1844
+ impl 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
+
1854
+ impl 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
+
1864
+ impl 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
+ }
0 commit comments