1use crate::{ast::*, kind::JavaSyntaxKind, language::JavaLanguage, parser::JavaParser};
2use oak_core::{
3 GreenNode, Parser,
4 builder::{Builder, BuilderCache, BuildOutput},
5 source::{Source, TextEdit},
6 tree::red_tree::{RedNode, RedTree},
7};
8
9pub struct JavaBuilder<'config> {
10 language: &'config JavaLanguage,
11}
12
13impl<'config> JavaBuilder<'config> {
14 pub fn new(language: &'config JavaLanguage) -> Self {
15 Self { language }
16 }
17
18 fn build_root(&self, green: &GreenNode<JavaLanguage>, source: &str) -> JavaRoot {
19 let red = RedNode::new(green, 0);
20 let mut items = Vec::new();
21
22 for child in red.children() {
23 if let RedTree::Node(node) = child {
24 match node.green.kind {
25 JavaSyntaxKind::CompilationUnit => {
26 for sub_child in node.children() {
27 if let RedTree::Node(sub_node) = sub_child {
28 if let Some(item) = self.build_item(sub_node, source) {
29 items.push(item);
30 }
31 }
32 }
33 }
34 _ => {
35 if let Some(item) = self.build_item(node, source) {
36 items.push(item);
37 }
38 }
39 }
40 }
41 }
42
43 JavaRoot { items }
44 }
45
46 fn build_item(&self, node: RedNode<JavaLanguage>, source: &str) -> Option<Item> {
47 match node.green.kind {
48 JavaSyntaxKind::ClassDeclaration => Some(Item::Class(self.build_class(node, source))),
49 JavaSyntaxKind::InterfaceDeclaration => Some(Item::Interface(InterfaceDeclaration { name: self.extract_identifier(node, source), span: node.span() })),
50 JavaSyntaxKind::Package => Some(Item::Package(PackageDeclaration { name: self.extract_identifier(node, source), span: node.span() })),
51 JavaSyntaxKind::Import => Some(Item::Import(ImportDeclaration {
52 path: self.extract_identifier(node, source),
53 is_static: false, span: node.span(),
55 })),
56 _ => None,
57 }
58 }
59
60 fn get_text<'a>(&self, span: core::range::Range<usize>, source: &'a str) -> &'a str {
61 let start = span.start.min(source.len());
62 let end = span.end.min(source.len());
63 &source[start..end]
64 }
65
66 fn extract_identifier(&self, node: RedNode<JavaLanguage>, source: &str) -> String {
67 for child in node.children() {
68 match child {
69 RedTree::Leaf(leaf) => {
70 if leaf.kind == JavaSyntaxKind::Identifier {
71 let name = self.get_text(leaf.span, source).to_string();
72 eprintln!("DEBUG: Found identifier '{}' at {:?}", name, leaf.span);
73 return name;
74 }
75 }
76 RedTree::Node(sub_node) => {
77 let res = self.extract_identifier(sub_node, source);
78 if !res.is_empty() {
79 return res;
80 }
81 }
82 }
83 }
84 String::new()
85 }
86
87 fn build_class(&self, node: RedNode<JavaLanguage>, source: &str) -> ClassDeclaration {
88 let name = self.extract_identifier(node, source);
89 let mut members = Vec::new();
90
91 eprintln!("DEBUG: Building class '{}' with {} children", name, node.children().count());
92 for child in node.children() {
93 match child {
94 RedTree::Node(sub_node) => {
95 eprintln!("DEBUG: Child node kind: {:?}", sub_node.green.kind);
96 match sub_node.green.kind {
97 JavaSyntaxKind::MethodDeclaration => {
98 eprintln!("DEBUG: Found MethodDeclaration");
99 members.push(Member::Method(self.build_method(sub_node, source)));
100 }
101 JavaSyntaxKind::FieldDeclaration => {
102 eprintln!("DEBUG: Found FieldDeclaration");
103 members.push(Member::Field(self.build_field(sub_node, source)));
104 }
105 _ => {
106 self.collect_members(sub_node, source, &mut members);
108 }
109 }
110 }
111 RedTree::Leaf(leaf) => {
112 eprintln!("DEBUG: Child leaf kind: {:?}", leaf.kind);
113 }
114 }
115 }
116
117 ClassDeclaration { name, members, span: node.span() }
118 }
119
120 fn collect_members(&self, node: RedNode<JavaLanguage>, source: &str, members: &mut Vec<Member>) {
121 for child in node.children() {
122 if let RedTree::Node(sub_node) = child {
123 eprintln!("DEBUG: collect_members kind: {:?}", sub_node.green.kind);
124 match sub_node.green.kind {
125 JavaSyntaxKind::MethodDeclaration => {
126 eprintln!("DEBUG: collect_members Found MethodDeclaration");
127 members.push(Member::Method(self.build_method(sub_node, source)));
128 }
129 JavaSyntaxKind::FieldDeclaration => {
130 eprintln!("DEBUG: collect_members Found FieldDeclaration");
131 members.push(Member::Field(self.build_field(sub_node, source)));
132 }
133 _ => {
134 self.collect_members(sub_node, source, members);
135 }
136 }
137 }
138 }
139 }
140
141 fn build_method(&self, node: RedNode<JavaLanguage>, source: &str) -> MethodDeclaration {
142 let name_debug = self.extract_identifier(node, source);
143 eprintln!("DEBUG: Building method '{}'", name_debug);
144 let mut name = String::new();
145 let mut return_type = String::new();
146 let mut parameters = Vec::new();
147 let mut body = Vec::new();
148 let mut is_static = false;
149
150 for child in node.children() {
151 match child {
152 RedTree::Leaf(leaf) => match leaf.kind {
153 JavaSyntaxKind::Identifier => {
154 if return_type.is_empty() {
155 return_type = self.get_text(leaf.span, source).to_string();
156 }
157 else {
158 name = self.get_text(leaf.span, source).to_string();
159 }
160 }
161 JavaSyntaxKind::Static => is_static = true,
162 JavaSyntaxKind::Void | JavaSyntaxKind::Int | JavaSyntaxKind::Boolean => {
163 return_type = self.get_text(leaf.span, source).to_string();
164 }
165 _ => {}
166 },
167 RedTree::Node(sub_node) => match sub_node.green.kind {
168 JavaSyntaxKind::Parameter => {
169 parameters.push(self.build_parameter(sub_node, source));
170 }
171 JavaSyntaxKind::BlockStatement => {
172 eprintln!("DEBUG: Found block statement for method '{}'", name_debug);
173 body = self.build_block(sub_node, source);
174 }
175 _ => {}
176 },
177 }
178 }
179
180 if return_type.is_empty() {
181 return_type = "void".to_string();
182 }
183
184 eprintln!("DEBUG: Method '{}' has {} statements in body", name, body.len());
185 MethodDeclaration { name, return_type, parameters, body, is_static, span: node.span() }
186 }
187
188 fn build_parameter(&self, node: RedNode<JavaLanguage>, source: &str) -> Parameter {
189 let mut name = String::new();
190 let mut r#type = String::new();
191 let mut is_array = false;
192
193 for child in node.children() {
194 match child {
195 RedTree::Leaf(leaf) => match leaf.kind {
196 JavaSyntaxKind::Identifier => {
197 if r#type.is_empty() {
198 r#type = self.get_text(leaf.span, source).to_string();
199 }
200 else {
201 name = self.get_text(leaf.span, source).to_string();
202 }
203 }
204 JavaSyntaxKind::Int | JavaSyntaxKind::Boolean | JavaSyntaxKind::Void => {
205 r#type = self.get_text(leaf.span, source).to_string();
206 }
207 JavaSyntaxKind::LeftBracket => {
208 is_array = true;
209 }
210 _ => {}
211 },
212 _ => {}
213 }
214 }
215
216 if is_array {
217 r#type.push_str("[]");
218 }
219
220 Parameter { name, r#type }
221 }
222
223 fn build_field(&self, node: RedNode<JavaLanguage>, source: &str) -> FieldDeclaration {
224 let mut name = String::new();
225 let mut r#type = String::new();
226
227 for child in node.children() {
228 if let RedTree::Leaf(leaf) = child {
229 match leaf.kind {
230 JavaSyntaxKind::Identifier => {
231 if r#type.is_empty() {
232 r#type = self.get_text(leaf.span, source).to_string();
233 }
234 else {
235 name = self.get_text(leaf.span, source).to_string();
236 }
237 }
238 JavaSyntaxKind::Int | JavaSyntaxKind::Boolean | JavaSyntaxKind::Void => {
239 r#type = self.get_text(leaf.span, source).to_string();
240 }
241 _ => {}
242 }
243 }
244 }
245
246 FieldDeclaration { name, r#type, span: node.span() }
247 }
248
249 fn build_block(&self, node: RedNode<JavaLanguage>, source: &str) -> Vec<Statement> {
250 let mut statements = Vec::new();
251 for child in node.children() {
252 if let RedTree::Node(sub_node) = child {
253 statements.push(self.build_statement(sub_node, source));
254 }
255 }
256 statements
257 }
258
259 fn build_statement(&self, node: RedNode<JavaLanguage>, source: &str) -> Statement {
260 match node.green.kind {
261 JavaSyntaxKind::ExpressionStatement => {
262 eprintln!("DEBUG: ExpressionStatement children count: {}", node.children().count());
263 let mut last_expr_node = None;
264 for (i, child) in node.children().enumerate() {
265 match &child {
266 RedTree::Node(sub_node) => {
267 eprintln!(" Child {}: Node({:?})", i, sub_node.green.kind);
268 last_expr_node = Some(sub_node.clone());
269 }
270 RedTree::Leaf(leaf) => eprintln!(" Child {}: Leaf({:?})", i, leaf.kind),
271 }
272 }
273 if let Some(sub_node) = last_expr_node {
274 return Statement::Expression(self.build_expression(sub_node, source));
275 }
276 Statement::Block(vec![]) }
278 JavaSyntaxKind::BlockStatement => Statement::Block(self.build_block(node, source)),
279 JavaSyntaxKind::ReturnStatement => {
280 let mut expr = None;
281 for child in node.children() {
282 if let RedTree::Node(sub_node) = child {
283 expr = Some(self.build_expression(sub_node, source));
284 break;
285 }
286 }
287 Statement::Return(expr)
288 }
289 _ => Statement::Block(vec![]),
290 }
291 }
292
293 fn build_expression(&self, node: RedNode<JavaLanguage>, source: &str) -> Expression {
294 eprintln!("DEBUG: build_expression kind: {:?}", node.green.kind);
295 match node.green.kind {
296 JavaSyntaxKind::LiteralExpression => {
297 for child in node.children() {
298 if let RedTree::Leaf(leaf) = child {
299 match leaf.kind {
300 JavaSyntaxKind::IntegerLiteral => {
301 let val = self.get_text(leaf.span, source).parse().unwrap_or(0);
302 return Expression::Literal(Literal::Integer(val));
303 }
304 JavaSyntaxKind::StringLiteral => {
305 let text = self.get_text(leaf.span, source);
306 let content = if text.len() >= 2 { &text[1..text.len() - 1] } else { text };
307 return Expression::Literal(Literal::String(content.to_string()));
308 }
309 JavaSyntaxKind::BooleanLiteral => {
310 let val = self.get_text(leaf.span, source) == "true";
311 return Expression::Literal(Literal::Boolean(val));
312 }
313 _ => {}
314 }
315 }
316 }
317 Expression::Identifier("unknown".to_string())
318 }
319 JavaSyntaxKind::MethodCall => {
320 let mut target = None;
321 let mut name = String::new();
322 let mut arguments = Vec::new();
323 let mut first_node = true;
324
325 for child in node.children() {
326 match child {
327 RedTree::Node(sub_node) => {
328 if first_node {
329 first_node = false;
330 let expr = self.build_expression(sub_node.clone(), source);
331 match expr {
332 Expression::FieldAccess(fa) => {
333 target = Some(fa.target);
334 name = fa.name;
335 }
336 Expression::Identifier(id) => {
337 name = id;
338 }
339 _ => {
340 target = Some(Box::new(expr));
341 }
342 }
343 }
344 else {
345 arguments.push(self.build_expression(sub_node, source));
346 }
347 }
348 RedTree::Leaf(leaf) if leaf.kind == JavaSyntaxKind::Identifier => {
349 if name.is_empty() {
350 name = self.get_text(leaf.span, source).to_string();
351 }
352 }
353 _ => {}
354 }
355 }
356 eprintln!("DEBUG: Built MethodCall: name={}, args={}", name, arguments.len());
357 Expression::MethodCall(MethodCall { target, name, arguments })
358 }
359 JavaSyntaxKind::MemberSelect => {
360 let mut target = None;
361 let mut name = String::new();
362
363 for child in node.children() {
364 match child {
365 RedTree::Node(sub_node) => {
366 if target.is_none() {
367 target = Some(Box::new(self.build_expression(sub_node.clone(), source)));
368 }
369 else if sub_node.green.kind == JavaSyntaxKind::Identifier {
370 name = self.extract_identifier(sub_node.clone(), source);
371 }
372 }
373 RedTree::Leaf(leaf) if leaf.kind == JavaSyntaxKind::Identifier => {
374 name = self.get_text(leaf.span, source).to_string();
375 }
376 _ => {}
377 }
378 }
379 eprintln!("DEBUG: Built MemberSelect: name={}", name);
380 if let Some(target) = target { Expression::FieldAccess(FieldAccess { target, name }) } else { Expression::Identifier(name) }
381 }
382 _ => {
383 for child in node.children() {
385 if let RedTree::Leaf(leaf) = child {
386 if leaf.kind == JavaSyntaxKind::Identifier {
387 let name = self.get_text(leaf.span, source).to_string();
388 eprintln!("DEBUG: Built Identifier: {}", name);
389 return Expression::Identifier(name);
390 }
391 }
392 else if let RedTree::Node(sub_node) = child {
393 return self.build_expression(sub_node, source);
394 }
395 }
396 Expression::Identifier("unknown".to_string())
397 }
398 }
399 }
400}
401
402impl<'config> Builder<JavaLanguage> for JavaBuilder<'config> {
403 fn build<'a, S: Source + ?Sized>(&self, text: &S, edits: &[TextEdit], cache: &'a mut impl BuilderCache<JavaLanguage>) -> BuildOutput<JavaLanguage> {
404 let parser = JavaParser::new(self.language);
405 let output = parser.parse(text, edits, cache);
406 let result = output.result.map(|green| self.build_root(green, &text.get_text_in((0..text.length()).into())));
407 oak_core::errors::OakDiagnostics { result, diagnostics: output.diagnostics }
408 }
409}