@@ -5,15 +5,15 @@ use crate::{
5
5
navigation_target:: { self , ToNav } ,
6
6
FilePosition , NavigationTarget , RangeInfo , TryToNav , UpmappingResult ,
7
7
} ;
8
- use hir:: { AsAssocItem , AssocItem , FileRange , InFile , MacroFileIdExt , ModuleDef , Semantics } ;
8
+ use hir:: { Adt , AsAssocItem , AssocItem , FileRange , InFile , MacroFileIdExt , ModuleDef , Semantics } ;
9
9
use ide_db:: {
10
10
base_db:: { AnchoredPath , FileLoader , SourceDatabase } ,
11
11
defs:: { Definition , IdentClass } ,
12
12
helpers:: pick_best_token,
13
13
RootDatabase , SymbolKind ,
14
14
} ;
15
15
use itertools:: Itertools ;
16
-
16
+ use ide_db :: famous_defs :: FamousDefs ;
17
17
use span:: { Edition , FileId } ;
18
18
use syntax:: {
19
19
ast:: { self , HasLoopBody } ,
@@ -41,6 +41,22 @@ pub(crate) fn goto_definition(
41
41
) -> Option < RangeInfo < Vec < NavigationTarget > > > {
42
42
let sema = & Semantics :: new ( db) ;
43
43
let file = sema. parse_guess_edition ( file_id) . syntax ( ) . clone ( ) ;
44
+
45
+ if let syntax:: TokenAtOffset :: Single ( tok) = file. token_at_offset ( offset) {
46
+ if let Some ( module) = sema. file_to_module_def ( file_id) {
47
+ let famous_defs = FamousDefs ( sema, module. krate ( ) ) ;
48
+ let maybe_famous_struct = match tok. kind ( ) {
49
+ T ! [ ..] => famous_defs. core_ops_Range ( ) ,
50
+ T ! [ ..=] => famous_defs. core_ops_RangeInclusive ( ) ,
51
+ _ => None
52
+ } ;
53
+ if let Some ( fstruct) = maybe_famous_struct {
54
+ let target = def_to_nav ( db, Definition :: Adt ( Adt :: Struct ( fstruct) ) ) ;
55
+ return Some ( RangeInfo :: new ( tok. text_range ( ) , target) ) ;
56
+ }
57
+ }
58
+ }
59
+
44
60
let edition =
45
61
sema. attach_first_edition ( file_id) . map ( |it| it. edition ( ) ) . unwrap_or ( Edition :: CURRENT ) ;
46
62
let original_token = pick_best_token ( file. token_at_offset ( offset) , |kind| match kind {
@@ -420,7 +436,7 @@ fn expr_to_nav(
420
436
mod tests {
421
437
use ide_db:: FileRange ;
422
438
use itertools:: Itertools ;
423
-
439
+ use syntax :: SmolStr ;
424
440
use crate :: fixture;
425
441
426
442
#[ track_caller]
@@ -450,6 +466,39 @@ mod tests {
450
466
assert ! ( navs. is_empty( ) , "didn't expect this to resolve anywhere: {navs:?}" )
451
467
}
452
468
469
+
470
+ #[ test]
471
+ fn goto_def_range_inclusive ( ) {
472
+ let ra_fixture = r#"
473
+ //- minicore: range
474
+ fn f(a: usize, b: usize) {
475
+ for _ in a..$0=b {
476
+
477
+ }
478
+ }
479
+ "# ;
480
+ let ( analysis, position, _) = fixture:: annotations ( ra_fixture) ;
481
+ let mut navs = analysis. goto_definition ( position) . unwrap ( ) . expect ( "no definition found" ) . info ;
482
+ let Some ( target) = navs. pop ( ) else { panic ! ( "no target found" ) } ;
483
+ assert_eq ! ( target. name, SmolStr :: new_inline( "RangeInclusive" ) ) ;
484
+ }
485
+
486
+ #[ test]
487
+ fn goto_def_range_half_open ( ) {
488
+ let ra_fixture = r#"
489
+ //- minicore: range
490
+ fn f(a: usize, b: usize) {
491
+ for _ in a.$0.b {
492
+
493
+ }
494
+ }
495
+ "# ;
496
+ let ( analysis, position, _) = fixture:: annotations ( ra_fixture) ;
497
+ let mut navs = analysis. goto_definition ( position) . unwrap ( ) . expect ( "no definition found" ) . info ;
498
+ let Some ( target) = navs. pop ( ) else { panic ! ( "no target found" ) } ;
499
+ assert_eq ! ( target. name, SmolStr :: new_inline( "Range" ) ) ;
500
+ }
501
+
453
502
#[ test]
454
503
fn goto_def_in_included_file ( ) {
455
504
check (
0 commit comments