Skip to content

Commit 3957eae

Browse files
committed
go-to-def for same-file functions from function calls working
1 parent 616b7ce commit 3957eae

File tree

2 files changed

+133
-18
lines changed

2 files changed

+133
-18
lines changed

server/src/main.rs

Lines changed: 22 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use petgraph::stable_graph::NodeIndex;
77
use serde::Deserialize;
88
use serde_json::{from_value, Value};
99

10-
use tree_sitter::{Parser, Point};
10+
use tree_sitter::Parser;
1111
use url_norm::FromUrl;
1212

1313
use walkdir::WalkDir;
@@ -48,6 +48,7 @@ mod logging;
4848
mod lsp_ext;
4949
mod merge_views;
5050
mod opengl;
51+
mod navigation;
5152
mod url_norm;
5253

5354
#[cfg(test)]
@@ -670,23 +671,26 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
670671
}
671672

672673
fn goto_definition(&mut self, params: TextDocumentPositionParams, completable: LSCompletable<Vec<Location>>) {
673-
let source = fs::read_to_string(params.text_document.uri.path()).unwrap();
674-
let tree = self.tree_sitter.borrow_mut().parse(source, None).unwrap();
675-
676-
let node_at_pos = tree.root_node().named_descendant_for_point_range(
677-
Point {
678-
row: params.position.line as usize,
679-
column: params.position.character as usize,
680-
},
681-
Point {
682-
row: params.position.line as usize,
683-
column: (params.position.character + 1) as usize,
684-
},
685-
);
686-
687-
info!("found a node"; "node" => format!("{:?}", node_at_pos));
688-
689-
completable.complete(Err(Self::error_not_available(())));
674+
logging::slog_with_trace_id(|| {
675+
let parser = &mut self.tree_sitter.borrow_mut();
676+
let parser_ctx = match navigation::ParserContext::new(parser, params.text_document.uri.clone()) {
677+
Ok(ctx) => ctx,
678+
Err(e) => return completable.complete(Err(MethodError{
679+
code: 42069,
680+
message: format!("error building parser context: {}", e),
681+
data: (),
682+
})),
683+
};
684+
685+
match parser_ctx.find_definitions(params.text_document.uri, params.position) {
686+
Ok(locations) => completable.complete(Ok(locations)),
687+
Err(e) => completable.complete(Err(MethodError {
688+
code: 42069,
689+
message: format!("error finding definitions: {}", e),
690+
data: (),
691+
})),
692+
}
693+
});
690694
}
691695

692696
fn references(&mut self, _: ReferenceParams, completable: LSCompletable<Vec<Location>>) {

server/src/navigation.rs

Lines changed: 111 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,111 @@
1+
use std::fs::read_to_string;
2+
3+
use anyhow::Result;
4+
use rust_lsp::lsp_types::{Location, Position, Range};
5+
use slog_scope::{info, debug};
6+
use tree_sitter::{Node, Parser, Point, Tree, Query, QueryCursor};
7+
use url::Url;
8+
9+
macro_rules! find_function_str {
10+
() => {
11+
r#"
12+
(
13+
(function_declarator
14+
(identifier) @function)
15+
(#match? @function "{}")
16+
)
17+
"#
18+
};
19+
}
20+
pub struct ParserContext<'a> {
21+
source: String,
22+
tree: Tree,
23+
parser: &'a mut Parser,
24+
}
25+
26+
impl<'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())?;
29+
30+
let tree = parser.parse(&source, None).unwrap();
31+
32+
Ok(ParserContext { source, tree, parser })
33+
}
34+
35+
pub fn find_definitions(&self, document_uri: Url, point: Position) -> Result<Vec<Location>> {
36+
let current_node = match self.find_node_at_point(point) {
37+
Some(node) => node,
38+
None => return Ok(vec![]),
39+
};
40+
41+
let parent = match current_node.parent() {
42+
Some(parent) => parent,
43+
None => return Ok(vec![]),
44+
};
45+
46+
let query = match (current_node.kind(), parent.kind()) {
47+
(_, "call_expression") => {
48+
format!(find_function_str!(), current_node.utf8_text(self.source.as_bytes())?)
49+
}
50+
_ => return Ok(vec![]),
51+
};
52+
53+
let ts_query = Query::new(tree_sitter_glsl::language(), query.as_str())?;
54+
55+
let mut query_cursor = QueryCursor::new();
56+
57+
let mut locations = vec![];
58+
59+
for m in query_cursor.matches(&ts_query, self.tree.root_node(), self.source.as_bytes()) {
60+
for capture in m.captures {
61+
let start = capture.node.start_position();
62+
let end = capture.node.end_position();
63+
64+
locations.push(Location {
65+
uri: document_uri.clone(),
66+
range: Range {
67+
start: Position {
68+
line: start.row as u32,
69+
character: start.column as u32,
70+
},
71+
end: Position {
72+
line: end.row as u32,
73+
character: end.column as u32,
74+
},
75+
},
76+
});
77+
}
78+
}
79+
80+
info!("finished searching for definitions"; "definitions" => format!("{:?}", locations));
81+
82+
Ok(locations)
83+
}
84+
85+
pub fn find_references(&self) -> Result<Vec<Location>> {
86+
Ok(vec![])
87+
}
88+
89+
fn root_node(&self) -> Node {
90+
self.tree.root_node()
91+
}
92+
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+
) {
104+
Some(node) => {
105+
debug!("found a node"; "node" => format!("{:?}", node));
106+
Some(node)
107+
},
108+
None => None,
109+
}
110+
}
111+
}

0 commit comments

Comments
 (0)