1- use std:: fs:: read_to_string;
1+ use std:: { fs:: read_to_string, path :: Path } ;
22
33use anyhow:: Result ;
44use rust_lsp:: lsp_types:: { Location , Position , Range } ;
5- use slog_scope:: { info, debug } ;
6- use tree_sitter:: { Node , Parser , Point , Tree , Query , QueryCursor } ;
5+ use slog_scope:: { debug , info, trace } ;
6+ use tree_sitter:: { Node , Parser , Point , Query , QueryCursor , Tree } ;
77use url:: Url ;
88
9- macro_rules! find_function_str {
10- ( ) => {
9+ use crate :: linemap:: LineMap ;
10+
11+ macro_rules! find_function_def_str {
12+ ( ) => {
1113 r#"
1214 (
1315 (function_declarator
1416 (identifier) @function)
15- (#match? @function "{}")
17+ (#match? @function "{}")
18+ )
19+ "#
20+ } ;
21+ }
22+
23+ macro_rules! find_function_refs_str {
24+ ( ) => {
25+ r#"
26+ (
27+ (call_expression
28+ (identifier) @call)
29+ (#match? @call "{}")
1630 )
1731 "#
1832 } ;
1933}
2034pub struct ParserContext < ' a > {
2135 source : String ,
2236 tree : Tree ,
37+ linemap : LineMap ,
2338 parser : & ' a mut Parser ,
2439}
2540
2641impl < ' a > ParserContext < ' a > {
27- pub fn new ( parser : & ' a mut Parser , document_uri : & Url ) -> Result < Self > {
28- let source = read_to_string ( document_uri . path ( ) ) ?;
42+ pub fn new ( parser : & ' a mut Parser , path : & Path ) -> Result < Self > {
43+ let source = read_to_string ( path) ?;
2944
3045 let tree = parser. parse ( & source, None ) . unwrap ( ) ;
3146
32- Ok ( ParserContext { source, tree, parser } )
47+ let linemap = LineMap :: new ( & source) ;
48+
49+ Ok ( ParserContext {
50+ source,
51+ tree,
52+ linemap,
53+ parser,
54+ } )
3355 }
3456
35- pub fn find_definitions ( & self , document_uri : & Url , point : Position ) -> Result < Vec < Location > > {
57+ pub fn find_definitions ( & self , path : & Path , point : Position ) -> Result < Option < Vec < Location > > > {
3658 let current_node = match self . find_node_at_point ( point) {
3759 Some ( node) => node,
38- None => return Ok ( vec ! [ ] ) ,
60+ None => return Ok ( None ) ,
3961 } ;
4062
4163 let parent = match current_node. parent ( ) {
4264 Some ( parent) => parent,
43- None => return Ok ( vec ! [ ] ) ,
65+ None => return Ok ( None ) ,
4466 } ;
4567
4668 let query = match ( current_node. kind ( ) , parent. kind ( ) ) {
4769 ( _, "call_expression" ) => {
48- format ! ( find_function_str !( ) , current_node. utf8_text( self . source. as_bytes( ) ) ?)
70+ format ! ( find_function_def_str !( ) , current_node. utf8_text( self . source. as_bytes( ) ) ?)
4971 }
50- _ => return Ok ( vec ! [ ] ) ,
72+ _ => return Ok ( None ) ,
5173 } ;
5274
5375 let ts_query = Query :: new ( tree_sitter_glsl:: language ( ) , query. as_str ( ) ) ?;
54-
5576 let mut query_cursor = QueryCursor :: new ( ) ;
5677
5778 let mut locations = vec ! [ ] ;
5879
59- for m in query_cursor. matches ( & ts_query, self . tree . root_node ( ) , self . source . as_bytes ( ) ) {
80+ for m in query_cursor. matches ( & ts_query, self . root_node ( ) , self . source . as_bytes ( ) ) {
6081 for capture in m. captures {
6182 let start = capture. node . start_position ( ) ;
6283 let end = capture. node . end_position ( ) ;
6384
6485 locations. push ( Location {
65- uri : document_uri . clone ( ) ,
86+ uri : Url :: from_file_path ( path ) . unwrap ( ) ,
6687 range : Range {
6788 start : Position {
6889 line : start. row as u32 ,
@@ -79,32 +100,98 @@ impl<'a> ParserContext<'a> {
79100
80101 info ! ( "finished searching for definitions" ; "definitions" => format!( "{:?}" , locations) ) ;
81102
82- Ok ( locations)
103+ Ok ( Some ( locations) )
83104 }
84105
85- pub fn find_references ( & self ) -> Result < Vec < Location > > {
86- Ok ( vec ! [ ] )
106+ pub fn find_references ( & self , path : & Path , point : Position ) -> Result < Option < Vec < Location > > > {
107+ let current_node = match self . find_node_at_point ( point) {
108+ Some ( node) => node,
109+ None => return Ok ( None ) ,
110+ } ;
111+
112+ let parent = match current_node. parent ( ) {
113+ Some ( parent) => parent,
114+ None => return Ok ( None ) ,
115+ } ;
116+
117+ let query = match ( current_node. kind ( ) , parent. kind ( ) ) {
118+ ( _, "function_declarator" ) => {
119+ format ! ( find_function_refs_str!( ) , current_node. utf8_text( self . source. as_bytes( ) ) ?)
120+ }
121+ _ => return Ok ( None ) ,
122+ } ;
123+
124+ let ts_query = Query :: new ( tree_sitter_glsl:: language ( ) , query. as_str ( ) ) ?;
125+ let mut query_cursor = QueryCursor :: new ( ) ;
126+
127+ let mut locations = vec ! [ ] ;
128+
129+ for m in query_cursor. matches ( & ts_query, self . root_node ( ) , self . source . as_bytes ( ) ) {
130+ for capture in m. captures {
131+ let start = capture. node . start_position ( ) ;
132+ let end = capture. node . end_position ( ) ;
133+
134+ locations. push ( Location {
135+ uri : Url :: from_file_path ( path) . unwrap ( ) ,
136+ range : Range {
137+ start : Position {
138+ line : start. row as u32 ,
139+ character : start. column as u32 ,
140+ } ,
141+ end : Position {
142+ line : end. row as u32 ,
143+ character : end. column as u32 ,
144+ } ,
145+ } ,
146+ } ) ;
147+ }
148+ }
149+
150+ Ok ( Some ( locations) )
87151 }
88152
89153 fn root_node ( & self ) -> Node {
90154 self . tree . root_node ( )
91155 }
92156
93- fn find_node_at_point ( & self , point : Position ) -> Option < Node > {
94- match self . root_node ( ) . named_descendant_for_point_range (
95- Point {
96- row : point. line as usize ,
97- column : ( point. character - 1 ) as usize ,
98- } ,
99- Point {
100- row : point. line as usize ,
101- column : point. character as usize ,
102- } ,
103- ) {
157+ fn find_node_at_point ( & self , pos : Position ) -> Option < Node > {
158+ // if we're at the end of an ident, we need to look _back_ one char instead
159+ // for tree-sitter to find the right node.
160+ let look_behind = {
161+ let offset = self . linemap . offset_for_position ( pos) ;
162+ let char_at = self . source . as_bytes ( ) [ offset] ;
163+ trace ! ( "looking for non-alpha for point adjustment" ;
164+ "offset" => offset,
165+ "char" => char_at as char ,
166+ "point" => format!( "{:?}" , pos) ,
167+ "look_behind" => !char_at. is_ascii_alphabetic( ) ) ;
168+ !char_at. is_ascii_alphabetic ( )
169+ } ;
170+
171+ let mut start = Point {
172+ row : pos. line as usize ,
173+ column : pos. character as usize ,
174+ } ;
175+ let mut end = Point {
176+ row : pos. line as usize ,
177+ column : pos. character as usize ,
178+ } ;
179+
180+ if look_behind {
181+ start. column -= 1 ;
182+ } else {
183+ end. column += 1 ;
184+ }
185+
186+ match self . root_node ( ) . named_descendant_for_point_range ( start, end) {
104187 Some ( node) => {
105- debug ! ( "found a node" ; "node" => format!( "{:?}" , node) ) ;
188+ debug ! ( "found a node" ;
189+ "node" => format!( "{:?}" , node) ,
190+ "text" => node. utf8_text( self . source. as_bytes( ) ) . unwrap( ) ,
191+ "start" => format!( "{}" , start) ,
192+ "end" => format!( "{}" , end) ) ;
106193 Some ( node)
107- } ,
194+ }
108195 None => None ,
109196 }
110197 }
0 commit comments