Skip to content

Commit f66f566

Browse files
committed
implemented file-local go-to-def for variables
1 parent d8cb046 commit f66f566

File tree

1 file changed

+101
-36
lines changed

1 file changed

+101
-36
lines changed

server/main/src/navigation.rs

Lines changed: 101 additions & 36 deletions
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ macro_rules! find_function_def_str {
1414
(
1515
(function_declarator
1616
(identifier) @function)
17-
(#match? @function "{}")
17+
(#match? @function "^{}$")
1818
)
1919
"#
2020
};
@@ -26,11 +26,33 @@ macro_rules! find_function_refs_str {
2626
(
2727
(call_expression
2828
(identifier) @call)
29-
(#match? @call "{}")
29+
(#match? @call "^{}$")
3030
)
3131
"#
3232
};
3333
}
34+
35+
macro_rules! find_variable_def_str {
36+
() => {
37+
r#"
38+
(
39+
[
40+
(init_declarator
41+
(identifier) @variable)
42+
43+
(parameter_declaration
44+
(identifier) @variable)
45+
46+
(declaration
47+
(identifier) @variable)
48+
49+
(#match? @variable "^{}$")
50+
]
51+
)
52+
"#
53+
};
54+
}
55+
3456
pub struct ParserContext<'a> {
3557
source: String,
3658
tree: Tree,
@@ -65,40 +87,23 @@ impl<'a> ParserContext<'a> {
6587
None => return Ok(None),
6688
};
6789

68-
let query = match (current_node.kind(), parent.kind()) {
90+
debug!("matching location lookup method for parent-child tuple"; "parent" => parent.kind(), "child" => current_node.kind());
91+
92+
let locations = match (current_node.kind(), parent.kind()) {
6993
(_, "call_expression") => {
70-
format!(find_function_def_str!(), current_node.utf8_text(self.source.as_bytes())?)
94+
let query_str = format!(find_function_def_str!(), current_node.utf8_text(self.source.as_bytes())?);
95+
self.simple_global_search(path, &query_str)?
96+
}
97+
("identifier", "argument_list") |
98+
("identifier", "field_expression") |
99+
("identifier", "binary_expression") |
100+
("identifier", "assignment_expression") => {
101+
self.tree_climbing_search(path, current_node)?
71102
}
72103
_ => return Ok(None),
73104
};
74105

75-
let ts_query = Query::new(tree_sitter_glsl::language(), query.as_str())?;
76-
let mut query_cursor = QueryCursor::new();
77-
78-
let mut locations = vec![];
79-
80-
for m in query_cursor.matches(&ts_query, self.root_node(), self.source.as_bytes()) {
81-
for capture in m.captures {
82-
let start = capture.node.start_position();
83-
let end = capture.node.end_position();
84-
85-
locations.push(Location {
86-
uri: Url::from_file_path(path).unwrap(),
87-
range: Range {
88-
start: Position {
89-
line: start.row as u32,
90-
character: start.column as u32,
91-
},
92-
end: Position {
93-
line: end.row as u32,
94-
character: end.column as u32,
95-
},
96-
},
97-
});
98-
}
99-
}
100-
101-
info!("finished searching for definitions"; "definitions" => format!("{:?}", locations));
106+
info!("finished searching for definitions"; "count" => locations.len(), "definitions" => format!("{:?}", locations));
102107

103108
Ok(Some(locations))
104109
}
@@ -114,19 +119,79 @@ impl<'a> ParserContext<'a> {
114119
None => return Ok(None),
115120
};
116121

117-
let query = match (current_node.kind(), parent.kind()) {
122+
let locations = match (current_node.kind(), parent.kind()) {
118123
(_, "function_declarator") => {
119-
format!(find_function_refs_str!(), current_node.utf8_text(self.source.as_bytes())?)
124+
let query_str = format!(find_function_refs_str!(), current_node.utf8_text(self.source.as_bytes())?);
125+
self.simple_global_search(path, &query_str)?
120126
}
121127
_ => return Ok(None),
122128
};
123129

124-
let ts_query = Query::new(tree_sitter_glsl::language(), query.as_str())?;
130+
info!("finished searching for references"; "count" => locations.len(), "references" => format!("{:?}", locations));
131+
132+
Ok(Some(locations))
133+
}
134+
135+
fn tree_climbing_search(&self, path: &Path, start_node: Node) -> Result<Vec<Location>> {
136+
let mut locations = vec![];
137+
138+
let node_text = start_node.utf8_text(self.source.as_bytes())?;
139+
140+
let query_str = format!(find_variable_def_str!(), node_text);
141+
142+
debug!("built query string"; "query" => &query_str);
143+
144+
let mut parent = start_node.parent();
145+
146+
loop {
147+
if parent.is_none() {
148+
trace!("no more parent left, found nothing");
149+
break;
150+
}
151+
152+
let query = Query::new(tree_sitter_glsl::language(), &query_str)?;
153+
let mut query_cursor = QueryCursor::new();
154+
155+
trace!("running tree-sitter query for node"; "node" => format!("{:?}", parent.unwrap()), "node_text" => parent.unwrap().utf8_text(self.source.as_bytes()).unwrap());
156+
157+
for m in query_cursor.matches(&query, parent.unwrap(), self.source.as_bytes()) {
158+
for capture in m.captures {
159+
let start = capture.node.start_position();
160+
let end = capture.node.end_position();
161+
162+
locations.push(Location {
163+
uri: Url::from_file_path(path).unwrap(),
164+
range: Range {
165+
start: Position {
166+
line: start.row as u32,
167+
character: start.column as u32,
168+
},
169+
end: Position {
170+
line: end.row as u32,
171+
character: end.column as u32,
172+
},
173+
},
174+
});
175+
}
176+
}
177+
178+
if !locations.is_empty() {
179+
break;
180+
}
181+
182+
parent = parent.unwrap().parent();
183+
}
184+
185+
Ok(locations)
186+
}
187+
188+
fn simple_global_search(&self, path: &Path, query_str: &str) -> Result<Vec<Location>> {
189+
let query = Query::new(tree_sitter_glsl::language(), query_str)?;
125190
let mut query_cursor = QueryCursor::new();
126191

127192
let mut locations = vec![];
128193

129-
for m in query_cursor.matches(&ts_query, self.root_node(), self.source.as_bytes()) {
194+
for m in query_cursor.matches(&query, self.root_node(), self.source.as_bytes()) {
130195
for capture in m.captures {
131196
let start = capture.node.start_position();
132197
let end = capture.node.end_position();
@@ -147,7 +212,7 @@ impl<'a> ParserContext<'a> {
147212
}
148213
}
149214

150-
Ok(Some(locations))
215+
Ok(locations)
151216
}
152217

153218
fn root_node(&self) -> Node {

0 commit comments

Comments
 (0)