use tree_sitter_graph::{functions::Function, ExecutionError, Identifier}; use crate::text_range; pub struct ScopeShorthand; #[allow(unused_must_use)] impl Function for ScopeShorthand { fn call( &self, graph: &mut tree_sitter_graph::graph::Graph, _source: &str, parameters: &mut dyn tree_sitter_graph::functions::Parameters, ) -> Result { let target_range = parameters.param()?; if target_range.as_list().is_err() { return Err(ExecutionError::ExpectedList(format!( "`scope` expects list" ))); } parameters.finish()?; let graph_node = graph.add_graph_node(); graph[graph_node] .attributes .add::(Identifier::from("kind"), "scope".into()); graph[graph_node] .attributes .add(Identifier::from("range"), target_range); Ok(tree_sitter_graph::graph::Value::GraphNode(graph_node)) } } pub struct DefShorthand; #[allow(unused_must_use)] impl Function for DefShorthand { fn call( &self, graph: &mut tree_sitter_graph::graph::Graph, source: &str, parameters: &mut dyn tree_sitter_graph::functions::Parameters, ) -> Result { let target_node = parameters.param()?.into_syntax_node_ref()?; let ts_node = graph[target_node]; let symbol = parameters .param() .and_then(|p| p.as_str().map(ToOwned::to_owned)) .ok(); parameters.finish()?; let graph_node = graph.add_graph_node(); graph[graph_node] .attributes .add::(Identifier::from("kind"), "def".into()); graph[graph_node] .attributes .add::(Identifier::from("scope"), "local".into()); if let Some(s) = symbol { graph[graph_node] .attributes .add::(Identifier::from("symbol"), s.into()); } graph[graph_node].attributes.add::( Identifier::from("text"), source[ts_node.byte_range()].to_string().into(), ); graph[graph_node].attributes.add( Identifier::from("range"), text_range::range_to_value(&ts_node.range()), ); graph[graph_node] .attributes .add::( Identifier::from("target"), target_node.into(), ); Ok(tree_sitter_graph::graph::Value::GraphNode(graph_node)) } } pub struct RefShortHand; #[allow(unused_must_use)] impl Function for RefShortHand { fn call( &self, graph: &mut tree_sitter_graph::graph::Graph, source: &str, parameters: &mut dyn tree_sitter_graph::functions::Parameters, ) -> Result { let target_node = parameters.param()?.into_syntax_node_ref()?; let ts_node = graph[target_node]; parameters.finish()?; let graph_node = graph.add_graph_node(); graph[graph_node] .attributes .add::(Identifier::from("kind"), "ref".into()); graph[graph_node].attributes.add::( Identifier::from("text"), source[ts_node.byte_range()].to_string().into(), ); graph[graph_node].attributes.add( Identifier::from("range"), text_range::range_to_value(&ts_node.range()), ); graph[graph_node] .attributes .add::( Identifier::from("target"), target_node.into(), ); Ok(tree_sitter_graph::graph::Value::GraphNode(graph_node)) } } pub struct CoverRanges; impl Function for CoverRanges { fn call( &self, graph: &mut tree_sitter_graph::graph::Graph, _source: &str, parameters: &mut dyn tree_sitter_graph::functions::Parameters, ) -> Result { let mut result = None; while let Ok(param) = parameters.param() { if !param.is_null() { let range = graph[param.into_syntax_node_ref()?].range(); result = match result { Some(r) => Some(cover(r, range)), None => Some(range), }; } } match result { Some(v) => Ok(text_range::range_to_value(&v)), None => panic!("all nulls"), } } } fn cover(a: tree_sitter::Range, b: tree_sitter::Range) -> tree_sitter::Range { let (start_byte, start_point) = if a.start_point < b.start_point { (a.start_byte, a.start_point) } else { (b.start_byte, b.start_point) }; let (end_byte, end_point) = if a.end_point > b.end_point { (a.end_byte, a.end_point) } else { (b.end_byte, b.end_point) }; tree_sitter::Range { start_byte, start_point, end_byte, end_point, } } pub struct NodeRange; impl Function for NodeRange { fn call( &self, graph: &mut tree_sitter_graph::graph::Graph, _source: &str, parameters: &mut dyn tree_sitter_graph::functions::Parameters, ) -> Result { let target_node = parameters.param()?.into_syntax_node_ref()?; let ts_node = graph[target_node]; Ok(text_range::range_to_value(&ts_node.range())) } }