mirror of
https://github.com/Strum355/mcshader-lsp.git
synced 2025-08-03 16:39:16 +00:00
go-to-def for same-file functions from function calls working
This commit is contained in:
parent
616b7cef74
commit
3957eaed17
2 changed files with 133 additions and 18 deletions
|
@ -7,7 +7,7 @@ use petgraph::stable_graph::NodeIndex;
|
|||
use serde::Deserialize;
|
||||
use serde_json::{from_value, Value};
|
||||
|
||||
use tree_sitter::{Parser, Point};
|
||||
use tree_sitter::Parser;
|
||||
use url_norm::FromUrl;
|
||||
|
||||
use walkdir::WalkDir;
|
||||
|
@ -48,6 +48,7 @@ mod logging;
|
|||
mod lsp_ext;
|
||||
mod merge_views;
|
||||
mod opengl;
|
||||
mod navigation;
|
||||
mod url_norm;
|
||||
|
||||
#[cfg(test)]
|
||||
|
@ -670,23 +671,26 @@ impl LanguageServerHandling for MinecraftShaderLanguageServer {
|
|||
}
|
||||
|
||||
fn goto_definition(&mut self, params: TextDocumentPositionParams, completable: LSCompletable<Vec<Location>>) {
|
||||
let source = fs::read_to_string(params.text_document.uri.path()).unwrap();
|
||||
let tree = self.tree_sitter.borrow_mut().parse(source, None).unwrap();
|
||||
|
||||
let node_at_pos = tree.root_node().named_descendant_for_point_range(
|
||||
Point {
|
||||
row: params.position.line as usize,
|
||||
column: params.position.character as usize,
|
||||
},
|
||||
Point {
|
||||
row: params.position.line as usize,
|
||||
column: (params.position.character + 1) as usize,
|
||||
},
|
||||
);
|
||||
|
||||
info!("found a node"; "node" => format!("{:?}", node_at_pos));
|
||||
|
||||
completable.complete(Err(Self::error_not_available(())));
|
||||
logging::slog_with_trace_id(|| {
|
||||
let parser = &mut self.tree_sitter.borrow_mut();
|
||||
let parser_ctx = match navigation::ParserContext::new(parser, params.text_document.uri.clone()) {
|
||||
Ok(ctx) => ctx,
|
||||
Err(e) => return completable.complete(Err(MethodError{
|
||||
code: 42069,
|
||||
message: format!("error building parser context: {}", e),
|
||||
data: (),
|
||||
})),
|
||||
};
|
||||
|
||||
match parser_ctx.find_definitions(params.text_document.uri, params.position) {
|
||||
Ok(locations) => completable.complete(Ok(locations)),
|
||||
Err(e) => completable.complete(Err(MethodError {
|
||||
code: 42069,
|
||||
message: format!("error finding definitions: {}", e),
|
||||
data: (),
|
||||
})),
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
fn references(&mut self, _: ReferenceParams, completable: LSCompletable<Vec<Location>>) {
|
||||
|
|
111
server/src/navigation.rs
Normal file
111
server/src/navigation.rs
Normal file
|
@ -0,0 +1,111 @@
|
|||
use std::fs::read_to_string;
|
||||
|
||||
use anyhow::Result;
|
||||
use rust_lsp::lsp_types::{Location, Position, Range};
|
||||
use slog_scope::{info, debug};
|
||||
use tree_sitter::{Node, Parser, Point, Tree, Query, QueryCursor};
|
||||
use url::Url;
|
||||
|
||||
macro_rules! find_function_str {
|
||||
() => {
|
||||
r#"
|
||||
(
|
||||
(function_declarator
|
||||
(identifier) @function)
|
||||
(#match? @function "{}")
|
||||
)
|
||||
"#
|
||||
};
|
||||
}
|
||||
pub struct ParserContext<'a> {
|
||||
source: String,
|
||||
tree: Tree,
|
||||
parser: &'a mut Parser,
|
||||
}
|
||||
|
||||
impl<'a> ParserContext<'a> {
|
||||
pub fn new(parser: &'a mut Parser, document_uri: Url) -> Result<Self> {
|
||||
let source = read_to_string(document_uri.path())?;
|
||||
|
||||
let tree = parser.parse(&source, None).unwrap();
|
||||
|
||||
Ok(ParserContext { source, tree, parser })
|
||||
}
|
||||
|
||||
pub fn find_definitions(&self, document_uri: Url, point: Position) -> Result<Vec<Location>> {
|
||||
let current_node = match self.find_node_at_point(point) {
|
||||
Some(node) => node,
|
||||
None => return Ok(vec![]),
|
||||
};
|
||||
|
||||
let parent = match current_node.parent() {
|
||||
Some(parent) => parent,
|
||||
None => return Ok(vec![]),
|
||||
};
|
||||
|
||||
let query = match (current_node.kind(), parent.kind()) {
|
||||
(_, "call_expression") => {
|
||||
format!(find_function_str!(), current_node.utf8_text(self.source.as_bytes())?)
|
||||
}
|
||||
_ => return Ok(vec![]),
|
||||
};
|
||||
|
||||
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.tree.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: document_uri.clone(),
|
||||
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));
|
||||
|
||||
Ok(locations)
|
||||
}
|
||||
|
||||
pub fn find_references(&self) -> Result<Vec<Location>> {
|
||||
Ok(vec![])
|
||||
}
|
||||
|
||||
fn root_node(&self) -> Node {
|
||||
self.tree.root_node()
|
||||
}
|
||||
|
||||
fn find_node_at_point(&self, point: Position) -> Option<Node> {
|
||||
match self.root_node().named_descendant_for_point_range(
|
||||
Point {
|
||||
row: point.line as usize,
|
||||
column: (point.character - 1) as usize,
|
||||
},
|
||||
Point {
|
||||
row: point.line as usize,
|
||||
column: point.character as usize,
|
||||
},
|
||||
) {
|
||||
Some(node) => {
|
||||
debug!("found a node"; "node" => format!("{:?}", node));
|
||||
Some(node)
|
||||
},
|
||||
None => None,
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue