1use tree_sitter_graph::{functions::Function, ExecutionError, Identifier};
2
3use crate::text_range;
4
5pub struct ScopeShorthand;
6
7#[allow(unused_must_use)]
8impl Function for ScopeShorthand {
9 fn call(
10 &self,
11 graph: &mut tree_sitter_graph::graph::Graph,
12 _source: &str,
13 parameters: &mut dyn tree_sitter_graph::functions::Parameters,
14 ) -> Result<tree_sitter_graph::graph::Value, ExecutionError> {
15 let target_range = parameters.param()?;
16 if target_range.as_list().is_err() {
17 return Err(ExecutionError::ExpectedList(format!(
18 "`scope` expects list"
19 )));
20 }
21 parameters.finish()?;
22
23 let graph_node = graph.add_graph_node();
24 graph[graph_node]
25 .attributes
26 .add::<String>(Identifier::from("kind"), "scope".into());
27 graph[graph_node]
28 .attributes
29 .add(Identifier::from("range"), target_range);
30
31 Ok(tree_sitter_graph::graph::Value::GraphNode(graph_node))
32 }
33}
34
35pub struct DefShorthand;
36
37#[allow(unused_must_use)]
38impl Function for DefShorthand {
39 fn call(
40 &self,
41 graph: &mut tree_sitter_graph::graph::Graph,
42 source: &str,
43 parameters: &mut dyn tree_sitter_graph::functions::Parameters,
44 ) -> Result<tree_sitter_graph::graph::Value, ExecutionError> {
45 let target_node = parameters.param()?.into_syntax_node_ref()?;
46 let ts_node = graph[target_node];
47 let symbol = parameters
48 .param()
49 .and_then(|p| p.as_str().map(ToOwned::to_owned))
50 .ok();
51 parameters.finish()?;
52
53 let graph_node = graph.add_graph_node();
54 graph[graph_node]
55 .attributes
56 .add::<String>(Identifier::from("kind"), "def".into());
57 graph[graph_node]
58 .attributes
59 .add::<String>(Identifier::from("scope"), "local".into());
60
61 if let Some(s) = symbol {
62 graph[graph_node]
63 .attributes
64 .add::<String>(Identifier::from("symbol"), s.into());
65 }
66 graph[graph_node].attributes.add::<String>(
67 Identifier::from("text"),
68 source[ts_node.byte_range()].to_string().into(),
69 );
70 graph[graph_node].attributes.add(
71 Identifier::from("range"),
72 text_range::range_to_value(&ts_node.range()),
73 );
74 graph[graph_node]
75 .attributes
76 .add::<tree_sitter_graph::graph::SyntaxNodeRef>(
77 Identifier::from("target"),
78 target_node.into(),
79 );
80
81 Ok(tree_sitter_graph::graph::Value::GraphNode(graph_node))
82 }
83}
84
85pub struct RefShortHand;
86
87#[allow(unused_must_use)]
88impl Function for RefShortHand {
89 fn call(
90 &self,
91 graph: &mut tree_sitter_graph::graph::Graph,
92 source: &str,
93 parameters: &mut dyn tree_sitter_graph::functions::Parameters,
94 ) -> Result<tree_sitter_graph::graph::Value, ExecutionError> {
95 let target_node = parameters.param()?.into_syntax_node_ref()?;
96 let ts_node = graph[target_node];
97 parameters.finish()?;
98
99 let graph_node = graph.add_graph_node();
100 graph[graph_node]
101 .attributes
102 .add::<String>(Identifier::from("kind"), "ref".into());
103 graph[graph_node].attributes.add::<String>(
104 Identifier::from("text"),
105 source[ts_node.byte_range()].to_string().into(),
106 );
107 graph[graph_node].attributes.add(
108 Identifier::from("range"),
109 text_range::range_to_value(&ts_node.range()),
110 );
111 graph[graph_node]
112 .attributes
113 .add::<tree_sitter_graph::graph::SyntaxNodeRef>(
114 Identifier::from("target"),
115 target_node.into(),
116 );
117
118 Ok(tree_sitter_graph::graph::Value::GraphNode(graph_node))
119 }
120}
121
122pub struct CoverRanges;
123
124impl Function for CoverRanges {
125 fn call(
126 &self,
127 graph: &mut tree_sitter_graph::graph::Graph,
128 _source: &str,
129 parameters: &mut dyn tree_sitter_graph::functions::Parameters,
130 ) -> Result<tree_sitter_graph::graph::Value, ExecutionError> {
131 let mut result = None;
132 while let Ok(param) = parameters.param() {
133 if !param.is_null() {
134 let range = graph[param.into_syntax_node_ref()?].range();
135 result = match result {
136 Some(r) => Some(cover(r, range)),
137 None => Some(range),
138 };
139 }
140 }
141
142 match result {
143 Some(v) => Ok(text_range::range_to_value(&v)),
144 None => panic!("all nulls"),
145 }
146 }
147}
148
149fn cover(a: tree_sitter::Range, b: tree_sitter::Range) -> tree_sitter::Range {
150 let (start_byte, start_point) = if a.start_point < b.start_point {
151 (a.start_byte, a.start_point)
152 } else {
153 (b.start_byte, b.start_point)
154 };
155 let (end_byte, end_point) = if a.end_point > b.end_point {
156 (a.end_byte, a.end_point)
157 } else {
158 (b.end_byte, b.end_point)
159 };
160 tree_sitter::Range {
161 start_byte,
162 start_point,
163 end_byte,
164 end_point,
165 }
166}
167
168pub struct NodeRange;
169
170impl Function for NodeRange {
171 fn call(
172 &self,
173 graph: &mut tree_sitter_graph::graph::Graph,
174 _source: &str,
175 parameters: &mut dyn tree_sitter_graph::functions::Parameters,
176 ) -> Result<tree_sitter_graph::graph::Value, ExecutionError> {
177 let target_node = parameters.param()?.into_syntax_node_ref()?;
178 let ts_node = graph[target_node];
179 Ok(text_range::range_to_value(&ts_node.range()))
180 }
181}