@@ -17,8 +17,11 @@ pub fn goto(
1717 tree : & Tree ,
1818 symbols_map : & impl SymbolsMap ,
1919) -> Option < GotoDefinitionResponse > {
20- let start = tree:: try_get_identifier ( tree, line, col) ?;
21- let name = rope. byte_slice ( start. byte_range ( ) ) . to_string ( ) ;
20+ // note: R allows to call strings like "function_name"().
21+ // also useful for S4: e.g. to goto "Person" definition in
22+ // setMethod("age", "Person", ...) or setClass("Employee", contains = "Person")
23+ let ( start, byte_range) = tree:: try_get_identifier_or_string ( tree, line, col) ?;
24+ let name = rope. byte_slice ( byte_range) . to_string ( ) ;
2225
2326 tracing:: debug!( ?name, start = start. kind( ) , "goto definition" ) ;
2427
@@ -35,23 +38,26 @@ pub fn goto(
3538 ) ) ) ;
3639 }
3740
38- let is_local_scope = tree:: find_containing_function ( start) . is_some ( ) ;
41+ let is_global_scope = tree:: find_containing_function ( start) . is_none ( ) ;
3942
4043 let globals = symbols_map. filter_map (
4144 |path, symbols| {
4245 let other_uri = Uri :: from_file_path ( path) . unwrap ( ) ;
43- // Only include locations from other files
44- ( if is_local_scope || & other_uri != uri {
45- symbols
46- } else {
47- & [ ]
48- } )
49- . iter ( )
50- . filter ( |symbol| symbol. name == name)
51- . map ( move |symbol| Location {
52- uri : other_uri. clone ( ) ,
53- range : symbol. range ,
54- } )
46+ // note that s4 and r6 are not found by find_previous_definition.
47+ // therefore if is same file and global scope we must ignore later defintions
48+ let ignore_later = is_global_scope && * uri == other_uri;
49+ let name = & name;
50+ symbols
51+ . iter ( )
52+ . filter ( move |symbol| {
53+ symbol. name == * name
54+ && ( !ignore_later
55+ || symbol. range . end < utils:: point_to_position ( start. start_position ( ) ) )
56+ } )
57+ . map ( move |symbol| Location {
58+ uri : other_uri. clone ( ) ,
59+ range : symbol. range ,
60+ } )
5561 } ,
5662 128 ,
5763 ) ;
@@ -115,10 +121,9 @@ mod tests {
115121
116122 fn setup_a ( src : & str , line : usize , col : usize ) -> Option < ( usize , usize ) > {
117123 let rope = Rope :: from_str ( src) ;
118- let mut parser = tree:: new_parser ( ) ;
119- let tree = tree:: parse ( & mut parser, src, None ) ;
120- let start = tree:: try_get_identifier ( & tree, line, col) . unwrap ( ) ;
121- let name = rope. byte_slice ( start. byte_range ( ) ) . to_string ( ) ;
124+ let tree = tree:: parse ( & mut tree:: new_parser ( ) , src, None ) ;
125+ let ( start, byte_range) = tree:: try_get_identifier_or_string ( & tree, line, col) ?;
126+ let name = rope. byte_slice ( byte_range) . to_string ( ) ;
122127 find_previous_definition ( start, & rope, & name) . map ( |node| {
123128 let point = node. start_position ( ) ;
124129 ( point. row , point. column )
@@ -127,24 +132,25 @@ mod tests {
127132
128133 fn setup_b ( src : & str , line : usize , col : usize ) -> Option < String > {
129134 let rope = Rope :: from_str ( src) ;
130- let mut parser = tree:: new_parser ( ) ;
131- let tree = tree:: parse ( & mut parser, src, None ) ;
132- tree:: try_get_identifier ( & tree, line, col)
133- . map ( |node| rope. byte_slice ( node. byte_range ( ) ) . to_string ( ) )
135+ let tree = tree:: parse ( & mut tree:: new_parser ( ) , src, None ) ;
136+ tree:: try_get_identifier_or_string ( & tree, line, col)
137+ . map ( |( _, byte_range) | rope. byte_slice ( byte_range) . to_string ( ) )
134138 }
135139
136140 #[ test]
137- fn try_get_identifier_returns_none_for_non_identifier ( ) {
141+ fn try_get_identifier_base ( ) {
138142 let src = indoc ! { r#"
139143 123
140- "string"
141144 x <- 1
142- x
145+ x
146+ setMethod("age", "Person", \(x) x@age)
143147 "# } ;
144148 assert_eq ! ( setup_b( src, 0 , 0 ) , None ) ;
145- assert_eq ! ( setup_b( src, 1 , 0 ) , None ) ;
146- assert_eq ! ( setup_b( src, 2 , 0 ) , Some ( "x" . to_string( ) ) ) ;
147- assert_eq ! ( setup_b( src, 3 , 0 ) , None ) ;
149+ assert_eq ! ( setup_b( src, 1 , 0 ) , Some ( "x" . into( ) ) ) ;
150+ assert_eq ! ( setup_b( src, 2 , 0 ) , None ) ;
151+ assert_eq ! ( setup_b( src, 3 , 17 ) , Some ( "Person" . into( ) ) ) ;
152+ // assert_eq!(setup_b(src, 3, 18), Some("Person".into()));
153+ assert_eq ! ( setup_b( src, 3 , 24 ) , Some ( "Person" . into( ) ) ) ;
148154 }
149155
150156 #[ test]
0 commit comments