@@ -5,15 +5,15 @@ use crate::{
55 navigation_target:: { self , ToNav } ,
66 FilePosition , NavigationTarget , RangeInfo , TryToNav , UpmappingResult ,
77} ;
8- use hir:: { AsAssocItem , AssocItem , FileRange , InFile , MacroFileIdExt , ModuleDef , Semantics } ;
8+ use hir:: { Adt , AsAssocItem , AssocItem , FileRange , InFile , MacroFileIdExt , ModuleDef , Semantics } ;
99use ide_db:: {
1010 base_db:: { AnchoredPath , FileLoader , SourceDatabase } ,
1111 defs:: { Definition , IdentClass } ,
1212 helpers:: pick_best_token,
1313 RootDatabase , SymbolKind ,
1414} ;
1515use itertools:: Itertools ;
16-
16+ use ide_db :: famous_defs :: FamousDefs ;
1717use span:: { Edition , FileId } ;
1818use syntax:: {
1919 ast:: { self , HasLoopBody } ,
@@ -41,6 +41,22 @@ pub(crate) fn goto_definition(
4141) -> Option < RangeInfo < Vec < NavigationTarget > > > {
4242 let sema = & Semantics :: new ( db) ;
4343 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+
4460 let edition =
4561 sema. attach_first_edition ( file_id) . map ( |it| it. edition ( ) ) . unwrap_or ( Edition :: CURRENT ) ;
4662 let original_token = pick_best_token ( file. token_at_offset ( offset) , |kind| match kind {
@@ -420,7 +436,7 @@ fn expr_to_nav(
420436mod tests {
421437 use ide_db:: FileRange ;
422438 use itertools:: Itertools ;
423-
439+ use syntax :: SmolStr ;
424440 use crate :: fixture;
425441
426442 #[ track_caller]
@@ -450,6 +466,39 @@ mod tests {
450466 assert ! ( navs. is_empty( ) , "didn't expect this to resolve anywhere: {navs:?}" )
451467 }
452468
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+
453502 #[ test]
454503 fn goto_def_in_included_file ( ) {
455504 check (
0 commit comments