intelligent ctags powered by tree-sitter and lexical scope-graphs
at main 5.7 kB view raw
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}