1use crate::code::{node_source, File};
2use core::fmt;
3use std::sync::Arc;
4use tree_sitter::{Node, Parser, Query};
5
6mod go;
7mod java;
8mod javascript;
9mod kotlin;
10mod php;
11mod python;
12mod ruby;
13mod rust;
14mod tsx;
15mod typescript;
16mod typescript_common;
17
18pub use {
19 go::*, java::*, javascript::*, kotlin::*, php::*, python::*, ruby::*, rust::*, tsx::*,
20 typescript::*,
21};
22
23#[allow(clippy::borrowed_box)]
24pub fn from_str(name: &str) -> Option<&Box<dyn Language + Sync>> {
25 ALL_LANGS.iter().find(|language| language.name() == name)
26}
27
28use lazy_static::lazy_static;
29
30lazy_static! {
31 pub static ref ALL_LANGS: Vec<Box<dyn Language + Sync>> = {
32 vec![
33 Box::<php::Php>::default(),
34 Box::<kotlin::Kotlin>::default(),
35 Box::<go::Go>::default(),
36 Box::<java::Java>::default(),
37 Box::<javascript::JavaScript>::default(),
38 Box::<python::Python>::default(),
39 Box::<ruby::Ruby>::default(),
40 Box::<rust::Rust>::default(),
41 Box::<typescript::TypeScript>::default(),
42 Box::<tsx::TSX>::default(),
43 ]
44 };
45}
46
47pub trait Language {
48 fn name(&self) -> &str;
49
50 fn self_keyword(&self) -> Option<&str>;
51
52 fn invisible_container_nodes(&self) -> Vec<&str> {
53 vec![]
54 }
55 fn if_nodes(&self) -> Vec<&str>;
56 fn elsif_nodes(&self) -> Vec<&str> {
57 vec![]
58 }
59 fn else_nodes(&self) -> Vec<&str> {
60 vec![]
61 }
62 fn ternary_nodes(&self) -> Vec<&str> {
63 vec![]
64 }
65 fn switch_nodes(&self) -> Vec<&str>;
66 fn case_nodes(&self) -> Vec<&str>;
67 fn loop_nodes(&self) -> Vec<&str>;
68 fn except_nodes(&self) -> Vec<&str> {
69 vec![]
70 }
71 fn try_expression_nodes(&self) -> Vec<&str> {
72 vec![]
73 }
74 fn conditional_assignment_nodes(&self) -> Vec<&str> {
75 vec![]
76 }
77 fn jump_nodes(&self) -> Vec<&str>;
78 fn return_nodes(&self) -> Vec<&str>;
79 fn binary_nodes(&self) -> Vec<&str>;
80 fn field_nodes(&self) -> Vec<&str>;
81 fn call_nodes(&self) -> Vec<&str>;
82 fn function_nodes(&self) -> Vec<&str>;
83 fn closure_nodes(&self) -> Vec<&str>;
84 fn comment_nodes(&self) -> Vec<&str>;
85 fn string_nodes(&self) -> Vec<&str>;
86 fn block_nodes(&self) -> Vec<&str> {
87 vec![]
88 }
89
90 fn boolean_operator_nodes(&self) -> Vec<&str>;
91
92 fn constructor_names(&self) -> Vec<&str> {
93 vec![]
94 }
95
96 fn destructor_names(&self) -> Vec<&str> {
97 vec![]
98 }
99
100 fn is_decorator_function(&self, _node: &Node) -> bool {
101 false
102 }
103
104 fn is_instance_method(&self, _file: &File, _node: &Node) -> bool {
105 true
106 }
107
108 fn is_jump_label(&self, _node: &Node) -> bool {
109 false
110 }
111
112 fn all_operators(&self) -> Vec<&str> {
113 vec![]
114 }
115
116 fn all_operands(&self) -> Vec<&str> {
117 vec![]
118 }
119
120 fn iterator_method_identifiers(&self) -> Vec<&str> {
121 vec![]
122 }
123
124 fn call_identifiers(&self, source_file: &File, node: &Node) -> (Option<String>, String);
125 fn field_identifiers(&self, source_file: &File, node: &Node) -> (String, String);
126
127 fn tree_sitter_language(&self) -> tree_sitter::Language;
128
129 fn class_query(&self) -> &Query;
130 fn function_declaration_query(&self) -> &Query;
131 fn field_query(&self) -> &Query;
132 fn implementation_query(&self) -> Option<&Query> {
133 None
134 }
135
136 fn has_labeled_jumps(&self) -> bool {
137 false
138 }
139
140 fn query(&self, query_source: &str) -> Query {
141 Query::new(&self.tree_sitter_language(), query_source).unwrap()
142 }
143
144 fn parser(&self) -> Parser {
145 let mut parser = Parser::new();
146 parser
147 .set_language(&self.tree_sitter_language())
148 .expect("Error loading grammar");
149 parser
150 }
151
152 fn has_field_names(&self) -> bool {
153 false
154 }
155
156 fn sanitize_parameter_name(&self, parameter_name: String) -> Option<String> {
157 if let Some(self_keyword) = self.self_keyword() {
158 if parameter_name != self_keyword
159 && parameter_name != format!("&{}", self_keyword)
160 && parameter_name != format!("&mut {}", self_keyword)
161 {
162 return Some(parameter_name);
163 }
164 }
165 None
166 }
167
168 fn get_parameter_names(
169 &self,
170 parameters_node: tree_sitter::Node,
171 source_file: &Arc<File>,
172 ) -> Vec<String> {
173 let mut parameter_names = vec![];
174 let cursor = &mut parameters_node.walk();
175
176 for parameter_node in parameters_node.named_children(cursor) {
177 let parameter_name = node_source(¶meter_node, &source_file);
178
179 let sanitized_parameter_name = self.sanitize_parameter_name(parameter_name);
180 match sanitized_parameter_name {
181 Some(sanitized_parameter_name) => parameter_names.push(sanitized_parameter_name),
182 _ => {}
183 };
184 }
185 parameter_names
186 }
187
188 fn function_name_node<'a>(&'a self, node: &'a Node) -> Node<'a> {
189 node.child_by_field_name("name").unwrap()
190 }
191}
192
193impl fmt::Display for dyn Language {
194 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
195 write!(f, "Language[{}]", self.name())
196 }
197}
198
199impl fmt::Debug for dyn Language {
200 fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
201 write!(f, "Language[{}]", self.name())
202 }
203}
204
205#[cfg(test)]
206mod test {
207 use super::*;
208
209 #[test]
210 fn language_names() {
211 let variant = crate::lang::from_str("rust").unwrap();
212 assert_eq!("rust", variant.name());
213
214 let rust = crate::lang::Rust::default();
215 assert_eq!(rust.name(), "rust");
216 }
217
218 #[test]
219 fn language_parser() {
220 crate::lang::Rust::default().parser();
221 }
222}