Skip to content

Commit

Permalink
implemented file-local go-to-def for variables
Browse files Browse the repository at this point in the history
  • Loading branch information
Strum355 committed Apr 10, 2022
1 parent d8cb046 commit f66f566
Showing 1 changed file with 101 additions and 36 deletions.
137 changes: 101 additions & 36 deletions server/main/src/navigation.rs
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@ macro_rules! find_function_def_str {
(
(function_declarator
(identifier) @function)
(#match? @function "{}")
(#match? @function "^{}$")
)
"#
};
Expand All @@ -26,11 +26,33 @@ macro_rules! find_function_refs_str {
(
(call_expression
(identifier) @call)
(#match? @call "{}")
(#match? @call "^{}$")
)
"#
};
}

macro_rules! find_variable_def_str {
() => {
r#"
(
[
(init_declarator
(identifier) @variable)
(parameter_declaration
(identifier) @variable)
(declaration
(identifier) @variable)
(#match? @variable "^{}$")
]
)
"#
};
}

pub struct ParserContext<'a> {
source: String,
tree: Tree,
Expand Down Expand Up @@ -65,40 +87,23 @@ impl<'a> ParserContext<'a> {
None => return Ok(None),
};

let query = match (current_node.kind(), parent.kind()) {
debug!("matching location lookup method for parent-child tuple"; "parent" => parent.kind(), "child" => current_node.kind());

let locations = match (current_node.kind(), parent.kind()) {
(_, "call_expression") => {
format!(find_function_def_str!(), current_node.utf8_text(self.source.as_bytes())?)
let query_str = format!(find_function_def_str!(), current_node.utf8_text(self.source.as_bytes())?);
self.simple_global_search(path, &query_str)?
}
("identifier", "argument_list") |
("identifier", "field_expression") |
("identifier", "binary_expression") |
("identifier", "assignment_expression") => {
self.tree_climbing_search(path, current_node)?
}
_ => return Ok(None),
};

let ts_query = Query::new(tree_sitter_glsl::language(), query.as_str())?;
let mut query_cursor = QueryCursor::new();

let mut locations = vec![];

for m in query_cursor.matches(&ts_query, self.root_node(), self.source.as_bytes()) {
for capture in m.captures {
let start = capture.node.start_position();
let end = capture.node.end_position();

locations.push(Location {
uri: Url::from_file_path(path).unwrap(),
range: Range {
start: Position {
line: start.row as u32,
character: start.column as u32,
},
end: Position {
line: end.row as u32,
character: end.column as u32,
},
},
});
}
}

info!("finished searching for definitions"; "definitions" => format!("{:?}", locations));
info!("finished searching for definitions"; "count" => locations.len(), "definitions" => format!("{:?}", locations));

Ok(Some(locations))
}
Expand All @@ -114,19 +119,79 @@ impl<'a> ParserContext<'a> {
None => return Ok(None),
};

let query = match (current_node.kind(), parent.kind()) {
let locations = match (current_node.kind(), parent.kind()) {
(_, "function_declarator") => {
format!(find_function_refs_str!(), current_node.utf8_text(self.source.as_bytes())?)
let query_str = format!(find_function_refs_str!(), current_node.utf8_text(self.source.as_bytes())?);
self.simple_global_search(path, &query_str)?
}
_ => return Ok(None),
};

let ts_query = Query::new(tree_sitter_glsl::language(), query.as_str())?;
info!("finished searching for references"; "count" => locations.len(), "references" => format!("{:?}", locations));

Ok(Some(locations))
}

fn tree_climbing_search(&self, path: &Path, start_node: Node) -> Result<Vec<Location>> {
let mut locations = vec![];

let node_text = start_node.utf8_text(self.source.as_bytes())?;

let query_str = format!(find_variable_def_str!(), node_text);

debug!("built query string"; "query" => &query_str);

let mut parent = start_node.parent();

loop {
if parent.is_none() {
trace!("no more parent left, found nothing");
break;
}

let query = Query::new(tree_sitter_glsl::language(), &query_str)?;
let mut query_cursor = QueryCursor::new();

trace!("running tree-sitter query for node"; "node" => format!("{:?}", parent.unwrap()), "node_text" => parent.unwrap().utf8_text(self.source.as_bytes()).unwrap());

for m in query_cursor.matches(&query, parent.unwrap(), self.source.as_bytes()) {
for capture in m.captures {
let start = capture.node.start_position();
let end = capture.node.end_position();

locations.push(Location {
uri: Url::from_file_path(path).unwrap(),
range: Range {
start: Position {
line: start.row as u32,
character: start.column as u32,
},
end: Position {
line: end.row as u32,
character: end.column as u32,
},
},
});
}
}

if !locations.is_empty() {
break;
}

parent = parent.unwrap().parent();
}

Ok(locations)
}

fn simple_global_search(&self, path: &Path, query_str: &str) -> Result<Vec<Location>> {
let query = Query::new(tree_sitter_glsl::language(), query_str)?;
let mut query_cursor = QueryCursor::new();

let mut locations = vec![];

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

Ok(Some(locations))
Ok(locations)
}

fn root_node(&self) -> Node {
Expand Down

0 comments on commit f66f566

Please sign in to comment.