Skip to main content

oak_java/builder/
mod.rs

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, // TODO: Check for static keyword
54                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                            // Recursively look for members in case they are wrapped in a block
107                            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![]) // Should not happen
277            }
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                    // Check for Identifier leaf directly
384                    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}