@@ -34,11 +34,13 @@ impl From<Documentation> for String {
3434
3535pub trait HasDocs : HasAttrs {
3636 fn docs ( self , db : & dyn HirDatabase ) -> Option < Documentation > ;
37+ fn docs_with_rangemap ( self , db : & dyn HirDatabase ) -> Option < ( Documentation , DocsRangeMap ) > ;
3738 fn resolve_doc_path (
3839 self ,
3940 db : & dyn HirDatabase ,
4041 link : & str ,
4142 ns : Option < hir:: Namespace > ,
43+ is_inner_doc : bool ,
4244 ) -> Option < hir:: DocLinkDef > ;
4345}
4446/// A struct to map text ranges from [`Documentation`] back to TextRanges in the syntax tree.
@@ -53,7 +55,7 @@ pub struct DocsRangeMap {
5355
5456impl DocsRangeMap {
5557 /// Maps a [`TextRange`] relative to the documentation string back to its AST range
56- pub fn map ( & self , range : TextRange ) -> Option < InFile < TextRange > > {
58+ pub fn map ( & self , range : TextRange ) -> Option < ( InFile < TextRange > , AttrId ) > {
5759 let found = self . mapping . binary_search_by ( |( probe, ..) | probe. ordering ( range) ) . ok ( ) ?;
5860 let ( line_docs_range, idx, original_line_src_range) = self . mapping [ found] ;
5961 if !line_docs_range. contains_range ( range) {
@@ -71,7 +73,7 @@ impl DocsRangeMap {
7173 text_range. end ( ) + original_line_src_range. start ( ) + relative_range. start ( ) ,
7274 string. syntax ( ) . text_range ( ) . len ( ) . min ( range. len ( ) ) ,
7375 ) ;
74- Some ( InFile { file_id, value : range } )
76+ Some ( ( InFile { file_id, value : range } , idx ) )
7577 }
7678 Either :: Right ( comment) => {
7779 let text_range = comment. syntax ( ) . text_range ( ) ;
@@ -82,10 +84,22 @@ impl DocsRangeMap {
8284 + relative_range. start ( ) ,
8385 text_range. len ( ) . min ( range. len ( ) ) ,
8486 ) ;
85- Some ( InFile { file_id, value : range } )
87+ Some ( ( InFile { file_id, value : range } , idx ) )
8688 }
8789 }
8890 }
91+
92+ pub fn shift_docstring_line_range ( self , offset : TextSize ) -> DocsRangeMap {
93+ let mapping = self
94+ . mapping
95+ . into_iter ( )
96+ . map ( |( buf_offset, id, base_offset) | {
97+ let buf_offset = buf_offset. checked_add ( offset) . unwrap ( ) ;
98+ ( buf_offset, id, base_offset)
99+ } )
100+ . collect_vec ( ) ;
101+ DocsRangeMap { source_map : self . source_map , mapping }
102+ }
89103}
90104
91105pub fn docs_with_rangemap (
@@ -161,13 +175,20 @@ macro_rules! impl_has_docs {
161175 fn docs( self , db: & dyn HirDatabase ) -> Option <Documentation > {
162176 docs_from_attrs( & self . attrs( db) ) . map( Documentation )
163177 }
178+ fn docs_with_rangemap(
179+ self ,
180+ db: & dyn HirDatabase ,
181+ ) -> Option <( Documentation , DocsRangeMap ) > {
182+ docs_with_rangemap( db, & self . attrs( db) )
183+ }
164184 fn resolve_doc_path(
165185 self ,
166186 db: & dyn HirDatabase ,
167187 link: & str ,
168- ns: Option <hir:: Namespace >
188+ ns: Option <hir:: Namespace >,
189+ is_inner_doc: bool ,
169190 ) -> Option <hir:: DocLinkDef > {
170- resolve_doc_path_on( db, self , link, ns)
191+ resolve_doc_path_on( db, self , link, ns, is_inner_doc )
171192 }
172193 }
173194 ) * } ;
@@ -184,13 +205,21 @@ macro_rules! impl_has_docs_enum {
184205 fn docs( self , db: & dyn HirDatabase ) -> Option <Documentation > {
185206 hir:: $enum:: $variant( self ) . docs( db)
186207 }
208+
209+ fn docs_with_rangemap(
210+ self ,
211+ db: & dyn HirDatabase ,
212+ ) -> Option <( Documentation , DocsRangeMap ) > {
213+ hir:: $enum:: $variant( self ) . docs_with_rangemap( db)
214+ }
187215 fn resolve_doc_path(
188216 self ,
189217 db: & dyn HirDatabase ,
190218 link: & str ,
191- ns: Option <hir:: Namespace >
219+ ns: Option <hir:: Namespace >,
220+ is_inner_doc: bool ,
192221 ) -> Option <hir:: DocLinkDef > {
193- hir:: $enum:: $variant( self ) . resolve_doc_path( db, link, ns)
222+ hir:: $enum:: $variant( self ) . resolve_doc_path( db, link, ns, is_inner_doc )
194223 }
195224 }
196225 ) * } ;
@@ -207,16 +236,25 @@ impl HasDocs for hir::AssocItem {
207236 }
208237 }
209238
239+ fn docs_with_rangemap ( self , db : & dyn HirDatabase ) -> Option < ( Documentation , DocsRangeMap ) > {
240+ match self {
241+ hir:: AssocItem :: Function ( it) => it. docs_with_rangemap ( db) ,
242+ hir:: AssocItem :: Const ( it) => it. docs_with_rangemap ( db) ,
243+ hir:: AssocItem :: TypeAlias ( it) => it. docs_with_rangemap ( db) ,
244+ }
245+ }
246+
210247 fn resolve_doc_path (
211248 self ,
212249 db : & dyn HirDatabase ,
213250 link : & str ,
214251 ns : Option < hir:: Namespace > ,
252+ is_inner_doc : bool ,
215253 ) -> Option < hir:: DocLinkDef > {
216254 match self {
217- hir:: AssocItem :: Function ( it) => it. resolve_doc_path ( db, link, ns) ,
218- hir:: AssocItem :: Const ( it) => it. resolve_doc_path ( db, link, ns) ,
219- hir:: AssocItem :: TypeAlias ( it) => it. resolve_doc_path ( db, link, ns) ,
255+ hir:: AssocItem :: Function ( it) => it. resolve_doc_path ( db, link, ns, is_inner_doc ) ,
256+ hir:: AssocItem :: Const ( it) => it. resolve_doc_path ( db, link, ns, is_inner_doc ) ,
257+ hir:: AssocItem :: TypeAlias ( it) => it. resolve_doc_path ( db, link, ns, is_inner_doc ) ,
220258 }
221259 }
222260}
@@ -238,13 +276,36 @@ impl HasDocs for hir::ExternCrateDecl {
238276 }
239277 . map ( Documentation :: new)
240278 }
279+
280+ fn docs_with_rangemap ( self , db : & dyn HirDatabase ) -> Option < ( Documentation , DocsRangeMap ) > {
281+ let crate_docs = docs_with_rangemap ( db, & self . resolved_crate ( db) ?. root_module ( ) . attrs ( db) ) ;
282+ let decl_docs = docs_with_rangemap ( db, & self . attrs ( db) ) ;
283+ match ( decl_docs, crate_docs) {
284+ ( None , None ) => None ,
285+ ( Some ( decl_docs) , None ) => Some ( decl_docs) ,
286+ ( None , Some ( crate_docs) ) => Some ( crate_docs) ,
287+ (
288+ Some ( ( Documentation ( mut decl_docs) , mut decl_range_map) ) ,
289+ Some ( ( Documentation ( crate_docs) , crate_range_map) ) ,
290+ ) => {
291+ decl_docs. push ( '\n' ) ;
292+ decl_docs. push ( '\n' ) ;
293+ let offset = TextSize :: new ( decl_docs. len ( ) as u32 ) ;
294+ decl_docs += & crate_docs;
295+ let crate_range_map = crate_range_map. shift_docstring_line_range ( offset) ;
296+ decl_range_map. mapping . extend ( crate_range_map. mapping ) ;
297+ Some ( ( Documentation ( decl_docs) , decl_range_map) )
298+ }
299+ }
300+ }
241301 fn resolve_doc_path (
242302 self ,
243303 db : & dyn HirDatabase ,
244304 link : & str ,
245305 ns : Option < hir:: Namespace > ,
306+ is_inner_doc : bool ,
246307 ) -> Option < hir:: DocLinkDef > {
247- resolve_doc_path_on ( db, self , link, ns)
308+ resolve_doc_path_on ( db, self , link, ns, is_inner_doc )
248309 }
249310}
250311
0 commit comments