1- use hir:: semantics:: Semantics ;
1+ use hir:: { file :: HirFileId , semantics:: Semantics } ;
22use itertools:: Itertools ;
3+ use utils:: line_index:: TextRange ;
34
45use crate :: {
56 FilePosition , RangeInfo ,
@@ -8,6 +9,7 @@ use crate::{
89 goto_definition,
910 navigation_target:: { NavTarget , ToNav } ,
1011 semantic_target:: { SemanticTarget , TargetIntent , resolve_semantic_target} ,
12+ source_targets:: SourceTarget ,
1113} ;
1214
1315pub ( crate ) fn goto_declaration (
@@ -24,14 +26,46 @@ pub(crate) fn goto_declaration(
2426 parsed_file. root ( ) ,
2527 goto_definition:: token_precedence,
2628 ) ;
27- let SemanticTarget :: Source ( target) = target. unique_for_intent ( TargetIntent :: Navigate ) ? else {
28- return None ;
29- } ;
29+ render_declaration_target (
30+ db,
31+ hir_file_id,
32+ & sema,
33+ target. targets_for_intent ( TargetIntent :: Navigate ) ,
34+ )
35+ }
36+
37+ fn render_declaration_target (
38+ db : & RootDb ,
39+ hir_file_id : HirFileId ,
40+ sema : & Semantics < RootDb > ,
41+ targets : Vec < SemanticTarget < ' _ > > ,
42+ ) -> Option < RangeInfo < Vec < NavTarget > > > {
43+ let mut ranges = Vec :: new ( ) ;
44+ let mut navs = Vec :: new ( ) ;
45+ for target in targets {
46+ let SemanticTarget :: Source ( target) = target else {
47+ return None ;
48+ } ;
49+ let target = render_source_declaration_target ( db, hir_file_id, sema, target) ?;
50+ ranges. push ( target. range ) ;
51+ navs. extend ( target. info ) ;
52+ }
53+
54+ let range = covering_range ( & ranges) ?;
55+ Some ( RangeInfo :: new ( range, navs. into_iter ( ) . unique ( ) . collect ( ) ) )
56+ }
57+
58+ fn render_source_declaration_target (
59+ db : & RootDb ,
60+ hir_file_id : HirFileId ,
61+ sema : & Semantics < RootDb > ,
62+ target : SourceTarget < ' _ > ,
63+ ) -> Option < RangeInfo < Vec < NavTarget > > > {
3064 let ( range, tokens) = target. into_parts ( ) ;
3165
3266 let origins = tokens
3367 . into_iter ( )
34- . filter_map ( |token| match DefinitionClass :: resolve ( & sema, hir_file_id, token) ? {
68+ . filter_map ( |token| match DefinitionClass :: resolve ( sema, hir_file_id, token) ? {
3569 DefinitionClass :: Definition ( definition) => {
3670 Some ( definition. declaration_origins ( ) . into_iter ( ) . collect_vec ( ) )
3771 }
@@ -52,3 +86,9 @@ pub(crate) fn goto_declaration(
5286
5387 Some ( RangeInfo :: new ( range, navs) )
5488}
89+
90+ fn covering_range ( ranges : & [ TextRange ] ) -> Option < TextRange > {
91+ let start = ranges. iter ( ) . map ( |range| range. start ( ) ) . min ( ) ?;
92+ let end = ranges. iter ( ) . map ( |range| range. end ( ) ) . max ( ) ?;
93+ Some ( TextRange :: new ( start, end) )
94+ }
0 commit comments