2
2
3
3
use std:: ops:: ControlFlow ;
4
4
5
- use base_db:: FileId ;
6
5
use hir_def:: {
7
6
attr:: AttrsWithOwner ,
8
7
item_scope:: ItemInNs ,
@@ -11,12 +10,8 @@ use hir_def::{
11
10
resolver:: { HasResolver , Resolver , TypeNs } ,
12
11
AssocItemId , AttrDefId , ModuleDefId ,
13
12
} ;
14
- use hir_expand:: {
15
- name:: Name ,
16
- span_map:: { RealSpanMap , SpanMapRef } ,
17
- } ;
13
+ use hir_expand:: { mod_path:: PathKind , name:: Name } ;
18
14
use hir_ty:: { db:: HirDatabase , method_resolution} ;
19
- use syntax:: { ast, AstNode } ;
20
15
21
16
use crate :: {
22
17
Adt , AsAssocItem , AssocItem , BuiltinType , Const , ConstParam , DocLinkDef , Enum , ExternCrateDecl ,
@@ -129,7 +124,7 @@ fn resolve_doc_path_on_(
129
124
AttrDefId :: GenericParamId ( _) => return None ,
130
125
} ;
131
126
132
- let mut modpath = modpath_from_str ( db , link) ?;
127
+ let mut modpath = modpath_from_str ( link) ?;
133
128
134
129
let resolved = resolver. resolve_module_path_in_items ( db. upcast ( ) , & modpath) ;
135
130
if resolved. is_none ( ) {
@@ -305,34 +300,37 @@ fn as_module_def_if_namespace_matches(
305
300
( ns. unwrap_or ( expected_ns) == expected_ns) . then ( || DocLinkDef :: ModuleDef ( def) )
306
301
}
307
302
308
- fn modpath_from_str ( db : & dyn HirDatabase , link : & str ) -> Option < ModPath > {
303
+ fn modpath_from_str ( link : & str ) -> Option < ModPath > {
309
304
// FIXME: this is not how we should get a mod path here.
310
305
let try_get_modpath = |link : & str | {
311
- let ast_path = ast:: SourceFile :: parse ( & format ! ( "type T = {link};" ) )
312
- . syntax_node ( )
313
- . descendants ( )
314
- . find_map ( ast:: Path :: cast) ?;
315
- if ast_path. syntax ( ) . text ( ) != link {
316
- return None ;
317
- }
318
- ModPath :: from_src (
319
- db. upcast ( ) ,
320
- ast_path,
321
- SpanMapRef :: RealSpanMap ( & RealSpanMap :: absolute ( FileId :: BOGUS ) ) ,
322
- )
306
+ let mut parts = link. split ( "::" ) ;
307
+ let mut first_segment = None ;
308
+ let kind = match parts. next ( ) ? {
309
+ "" => PathKind :: Abs ,
310
+ "crate" => PathKind :: Crate ,
311
+ "self" => PathKind :: Super ( 0 ) ,
312
+ "super" => {
313
+ let mut deg = 1 ;
314
+ while let Some ( segment) = parts. next ( ) {
315
+ if segment == "super" {
316
+ deg += 1 ;
317
+ } else {
318
+ first_segment = Some ( segment) ;
319
+ break ;
320
+ }
321
+ }
322
+ PathKind :: Super ( deg)
323
+ }
324
+ segment => {
325
+ first_segment = Some ( segment) ;
326
+ PathKind :: Plain
327
+ }
328
+ } ;
329
+ let parts = first_segment. into_iter ( ) . chain ( parts) . map ( |segment| match segment. parse ( ) {
330
+ Ok ( idx) => Name :: new_tuple_field ( idx) ,
331
+ Err ( _) => Name :: new_text_dont_use ( segment. into ( ) ) ,
332
+ } ) ;
333
+ Some ( ModPath :: from_segments ( kind, parts) )
323
334
} ;
324
-
325
- let full = try_get_modpath ( link) ;
326
- if full. is_some ( ) {
327
- return full;
328
- }
329
-
330
- // Tuple field names cannot be a part of `ModPath` usually, but rustdoc can
331
- // resolve doc paths like `TupleStruct::0`.
332
- // FIXME: Find a better way to handle these.
333
- let ( base, maybe_tuple_field) = link. rsplit_once ( "::" ) ?;
334
- let tuple_field = Name :: new_tuple_field ( maybe_tuple_field. parse ( ) . ok ( ) ?) ;
335
- let mut modpath = try_get_modpath ( base) ?;
336
- modpath. push_segment ( tuple_field) ;
337
- Some ( modpath)
335
+ try_get_modpath ( link)
338
336
}
0 commit comments