Skip to main content

codanna/parsing/cpp/
parser.rs

1//! C++ language parser implementation
2
3use crate::parsing::context::ParserContext;
4use crate::parsing::method_call::MethodCall;
5use crate::parsing::parser::check_recursion_depth;
6use crate::parsing::{Import, Language, LanguageParser, NodeTracker, NodeTrackingState};
7use crate::types::{Range, SymbolCounter};
8use crate::{FileId, Symbol, SymbolKind, Visibility};
9use std::any::Any;
10use tree_sitter::{Node, Parser};
11
12pub struct CppParser {
13    parser: Parser,
14    context: ParserContext,
15    node_tracker: NodeTrackingState,
16}
17
18impl std::fmt::Debug for CppParser {
19    fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
20        f.debug_struct("CppParser")
21            .field("language", &"C++")
22            .finish()
23    }
24}
25
26impl CppParser {
27    pub fn new() -> Result<Self, String> {
28        let mut parser = Parser::new();
29        parser
30            .set_language(&tree_sitter_cpp::LANGUAGE.into())
31            .map_err(|e| format!("Failed to set C++ language: {e}"))?;
32
33        Ok(Self {
34            parser,
35            context: ParserContext::new(),
36            node_tracker: NodeTrackingState::new(),
37        })
38    }
39
40    /// Helper to create a symbol with all optional fields
41    fn create_symbol(
42        &self,
43        id: crate::types::SymbolId,
44        name: String,
45        kind: SymbolKind,
46        file_id: FileId,
47        range: Range,
48        signature: Option<String>,
49        doc_comment: Option<String>,
50        module_path: &str,
51        visibility: Visibility,
52    ) -> Symbol {
53        let mut symbol = Symbol::new(id, name, kind, file_id, range);
54
55        if let Some(sig) = signature {
56            symbol = symbol.with_signature(sig);
57        }
58        if let Some(doc) = doc_comment {
59            symbol = symbol.with_doc(doc);
60        }
61        if !module_path.is_empty() {
62            symbol = symbol.with_module_path(module_path);
63        }
64        symbol = symbol.with_visibility(visibility);
65
66        // Set scope context based on parser's current scope
67        symbol.scope_context = Some(self.context.current_scope_context());
68
69        symbol
70    }
71
72    /// Parse C++ code and extract symbols
73    ///
74    /// This is the main parsing method that can be called directly.
75    pub fn parse(
76        &mut self,
77        code: &str,
78        file_id: FileId,
79        symbol_counter: &mut SymbolCounter,
80    ) -> Vec<Symbol> {
81        // Delegate to the LanguageParser trait implementation
82        <Self as LanguageParser>::parse(self, code, file_id, symbol_counter)
83    }
84
85    /// Extract import statements from the code
86    fn extract_imports_from_node(
87        node: Node,
88        code: &str,
89        file_id: FileId,
90        imports: &mut Vec<Import>,
91    ) {
92        if node.kind() == "preproc_include" {
93            if let Some(path_node) = node.child_by_field_name("path") {
94                let path_text = &code[path_node.byte_range()];
95                // Remove quotes
96                let clean_path = path_text.trim_matches(|c| c == '"' || c == '<' || c == '>');
97                imports.push(Import {
98                    path: clean_path.to_string(),
99                    alias: None,
100                    file_id,
101                    is_glob: false,
102                    is_type_only: false,
103                });
104            }
105        }
106
107        // Recursively process children
108        for i in 0..node.child_count() {
109            if let Some(child) = node.child(i as u32) {
110                Self::extract_imports_from_node(child, code, file_id, imports);
111            }
112        }
113    }
114
115    fn extract_symbols_from_node(
116        &mut self,
117        node: Node,
118        code: &str,
119        file_id: FileId,
120        symbols: &mut Vec<Symbol>,
121        counter: &mut SymbolCounter,
122        depth: usize,
123    ) {
124        // Guard against stack overflow
125        if !check_recursion_depth(depth, node) {
126            return;
127        }
128
129        match node.kind() {
130            "function_definition" => {
131                self.register_handled_node(node.kind(), node.kind_id());
132                if let Some(declarator) = node.child_by_field_name("declarator") {
133                    // Check for qualified_identifier (ClassName::methodName)
134                    let mut is_method = self.context.current_class().is_some();
135                    let mut method_name = String::new();
136
137                    for i in 0..declarator.child_count() {
138                        if let Some(child) = declarator.child(i as u32) {
139                            if child.kind() == "qualified_identifier" {
140                                // This is a method implementation (Class::method)
141                                is_method = true;
142                                // Extract method name from qualified_identifier
143                                for j in 0..child.child_count() {
144                                    if let Some(id_node) = child.child(j as u32) {
145                                        if id_node.kind() == "identifier" {
146                                            method_name = code[id_node.byte_range()].to_string();
147                                            break;
148                                        }
149                                    }
150                                }
151                                break;
152                            }
153                        }
154                    }
155
156                    // Fallback: try to get declarator field
157                    if method_name.is_empty() {
158                        if let Some(name_node) = declarator.child_by_field_name("declarator") {
159                            method_name = code[name_node.byte_range()].to_string();
160                        }
161                    }
162
163                    if !method_name.is_empty() {
164                        let symbol_id = counter.next_id();
165                        let doc_comment = self.extract_doc_comment(&node, code);
166                        let range = Range::new(
167                            node.start_position().row as u32,
168                            node.start_position().column as u16,
169                            node.end_position().row as u32,
170                            node.end_position().column as u16,
171                        );
172
173                        let kind = if is_method {
174                            SymbolKind::Method
175                        } else {
176                            SymbolKind::Function
177                        };
178
179                        let symbol = self.create_symbol(
180                            symbol_id,
181                            method_name,
182                            kind,
183                            file_id,
184                            range,
185                            None, // signature
186                            doc_comment,
187                            "", // module_path
188                            Visibility::Public,
189                        );
190
191                        symbols.push(symbol);
192                    }
193                }
194            }
195            "class_specifier" => {
196                self.register_handled_node(node.kind(), node.kind_id());
197                if let Some(name_node) = node.child_by_field_name("name") {
198                    let class_name = &code[name_node.byte_range()];
199                    let symbol_id = counter.next_id();
200                    let doc_comment = self.extract_doc_comment(&node, code);
201                    let range = Range::new(
202                        node.start_position().row as u32,
203                        node.start_position().column as u16,
204                        node.end_position().row as u32,
205                        node.end_position().column as u16,
206                    );
207
208                    let symbol = self.create_symbol(
209                        symbol_id,
210                        class_name.to_string(),
211                        SymbolKind::Class,
212                        file_id,
213                        range,
214                        None, // signature
215                        doc_comment,
216                        "", // module_path
217                        Visibility::Public,
218                    );
219
220                    symbols.push(symbol);
221
222                    // Enter class scope to track methods
223                    self.context
224                        .enter_scope(crate::parsing::context::ScopeType::Class);
225
226                    // Save current context
227                    let saved_function = self.context.current_function().map(|s| s.to_string());
228                    let saved_class = self.context.current_class().map(|s| s.to_string());
229
230                    // Set current class for method tracking
231                    self.context.set_current_class(Some(class_name.to_string()));
232
233                    // Process children to extract methods
234                    for i in 0..node.child_count() {
235                        if let Some(child) = node.child(i as u32) {
236                            self.extract_symbols_from_node(
237                                child,
238                                code,
239                                file_id,
240                                symbols,
241                                counter,
242                                depth + 1,
243                            );
244                        }
245                    }
246
247                    // Exit scope first
248                    self.context.exit_scope();
249
250                    // Restore previous context
251                    self.context.set_current_function(saved_function);
252                    self.context.set_current_class(saved_class);
253
254                    // Return early since we already processed children
255                    return;
256                }
257            }
258            "struct_specifier" => {
259                self.register_handled_node(node.kind(), node.kind_id());
260                if let Some(name_node) = node.child_by_field_name("name") {
261                    let name = &code[name_node.byte_range()];
262                    let symbol_id = counter.next_id();
263                    let doc_comment = self.extract_doc_comment(&node, code);
264                    let range = Range::new(
265                        node.start_position().row as u32,
266                        node.start_position().column as u16,
267                        node.end_position().row as u32,
268                        node.end_position().column as u16,
269                    );
270
271                    let symbol = self.create_symbol(
272                        symbol_id,
273                        name.to_string(),
274                        SymbolKind::Struct,
275                        file_id,
276                        range,
277                        None, // signature
278                        doc_comment,
279                        "", // module_path
280                        Visibility::Public,
281                    );
282
283                    symbols.push(symbol);
284                }
285            }
286            "enum_specifier" => {
287                self.register_handled_node(node.kind(), node.kind_id());
288                if let Some(name_node) = node.child_by_field_name("name") {
289                    let name = &code[name_node.byte_range()];
290                    let symbol_id = counter.next_id();
291                    let doc_comment = self.extract_doc_comment(&node, code);
292                    let range = Range::new(
293                        node.start_position().row as u32,
294                        node.start_position().column as u16,
295                        node.end_position().row as u32,
296                        node.end_position().column as u16,
297                    );
298
299                    let symbol = self.create_symbol(
300                        symbol_id,
301                        name.to_string(),
302                        SymbolKind::Enum,
303                        file_id,
304                        range,
305                        None, // signature
306                        doc_comment,
307                        "", // module_path
308                        Visibility::Public,
309                    );
310
311                    symbols.push(symbol);
312                }
313            }
314            "field_declaration" => {
315                self.register_handled_node(node.kind(), node.kind_id());
316                // Check if this is a method declaration (has function_declarator child)
317                if self.context.current_class().is_some() {
318                    for i in 0..node.child_count() {
319                        if let Some(child) = node.child(i as u32) {
320                            if child.kind() == "function_declarator" {
321                                // This is a method declaration
322                                // Look for field_identifier child
323                                for j in 0..child.child_count() {
324                                    if let Some(name_node) = child.child(j as u32) {
325                                        if name_node.kind() == "field_identifier" {
326                                            let method_name = &code[name_node.byte_range()];
327                                            let symbol_id = counter.next_id();
328                                            let doc_comment = self.extract_doc_comment(&node, code);
329                                            let range = Range::new(
330                                                node.start_position().row as u32,
331                                                node.start_position().column as u16,
332                                                node.end_position().row as u32,
333                                                node.end_position().column as u16,
334                                            );
335
336                                            let symbol = self.create_symbol(
337                                                symbol_id,
338                                                method_name.to_string(),
339                                                SymbolKind::Method,
340                                                file_id,
341                                                range,
342                                                None, // signature
343                                                doc_comment,
344                                                "", // module_path
345                                                Visibility::Public,
346                                            );
347
348                                            symbols.push(symbol);
349                                            break;
350                                        }
351                                    }
352                                }
353                                break;
354                            }
355                        }
356                    }
357                }
358            }
359            _ => {
360                // Track all nodes we encounter, even if not extracting symbols
361                self.register_handled_node(node.kind(), node.kind_id());
362            }
363        }
364
365        // Process children
366        for i in 0..node.child_count() {
367            if let Some(child) = node.child(i as u32) {
368                self.extract_symbols_from_node(child, code, file_id, symbols, counter, depth + 1);
369            }
370        }
371    }
372
373    fn extract_calls_from_node(node: Node, code: &str, calls: &mut Vec<MethodCall>) {
374        if node.kind() == "call_expression" {
375            if let Some(function_node) = node.child_by_field_name("function") {
376                // Extract the actual function name from different call patterns
377                let function_name = match function_node.kind() {
378                    // Member function call: obj->method() or obj.method()
379                    "field_expression" => {
380                        // Get the field identifier (the actual method name)
381                        if let Some(field_node) = function_node.child_by_field_name("field") {
382                            &code[field_node.byte_range()]
383                        } else {
384                            &code[function_node.byte_range()]
385                        }
386                    }
387                    // Simple function call: function()
388                    _ => &code[function_node.byte_range()],
389                };
390
391                calls.push(MethodCall::new(
392                    "", // caller will be set by the indexer
393                    function_name,
394                    Range::new(
395                        node.start_position().row as u32,
396                        node.start_position().column as u16,
397                        node.end_position().row as u32,
398                        node.end_position().column as u16,
399                    ),
400                ));
401            }
402        }
403
404        // Process children
405        for i in 0..node.child_count() {
406            if let Some(child) = node.child(i as u32) {
407                Self::extract_calls_from_node(child, code, calls);
408            }
409        }
410    }
411
412    /// Find method implementations in AST nodes recursively
413    fn find_implementations_in_node<'a>(
414        node: Node,
415        code: &'a str,
416        implementations: &mut Vec<(&'a str, &'a str, Range)>,
417    ) {
418        // In C++, method implementations often have the form Class::method
419        if node.kind() == "function_definition" {
420            if let Some(declarator) = node.child_by_field_name("declarator") {
421                // Check if this is a method implementation (has :: in the name)
422                let declarator_text = &code[declarator.byte_range()];
423                if declarator_text.contains("::") {
424                    // This is likely a method implementation
425                    // Extract class name and method name
426                    if let Some(separator_pos) = declarator_text.find("::") {
427                        let class_name = &declarator_text[..separator_pos];
428                        let method_name = &declarator_text[separator_pos + 2..];
429                        let range = Range::new(
430                            node.start_position().row as u32,
431                            node.start_position().column as u16,
432                            node.end_position().row as u32,
433                            node.end_position().column as u16,
434                        );
435                        implementations.push((class_name, method_name, range));
436                    }
437                }
438            }
439        }
440
441        // Process children
442        for i in 0..node.child_count() {
443            if let Some(child) = node.child(i as u32) {
444                Self::find_implementations_in_node(child, code, implementations);
445            }
446        }
447    }
448
449    /// Find inheritance relationships in AST nodes recursively
450    fn find_extends_in_node<'a>(
451        node: Node,
452        code: &'a str,
453        extends: &mut Vec<(&'a str, &'a str, Range)>,
454    ) {
455        // In C++, inheritance is specified with : public BaseClass, : protected BaseClass, etc.
456        if node.kind() == "class_specifier" {
457            if let Some(name_node) = node.child_by_field_name("name") {
458                let derived_class = &code[name_node.byte_range()];
459
460                // Look for base class specifiers
461                for i in 0..node.child_count() {
462                    if let Some(child) = node.child(i as u32) {
463                        if child.kind() == "base_class_clause" {
464                            // Extract base class names
465                            Self::extract_base_classes_in_node(child, code, derived_class, extends);
466                        }
467                    }
468                }
469            }
470        }
471
472        // Process children
473        for i in 0..node.child_count() {
474            if let Some(child) = node.child(i as u32) {
475                Self::find_extends_in_node(child, code, extends);
476            }
477        }
478    }
479
480    /// Extract base classes from a base_class_clause node
481    fn extract_base_classes_in_node<'a>(
482        node: Node,
483        code: &'a str,
484        derived_class: &'a str,
485        extends: &mut Vec<(&'a str, &'a str, Range)>,
486    ) {
487        // Process children to find base class names
488        for i in 0..node.child_count() {
489            if let Some(child) = node.child(i as u32) {
490                if child.kind() == "type_identifier" {
491                    let base_class = &code[child.byte_range()];
492                    let range = Range::new(
493                        node.start_position().row as u32,
494                        node.start_position().column as u16,
495                        node.end_position().row as u32,
496                        node.end_position().column as u16,
497                    );
498                    extends.push((derived_class, base_class, range));
499                } else {
500                    // Recursively process children
501                    Self::extract_base_classes_in_node(child, code, derived_class, extends);
502                }
503            }
504        }
505    }
506
507    /// Find variable and function uses in AST nodes recursively
508    fn find_uses_in_node<'a>(node: Node, code: &'a str, uses: &mut Vec<(&'a str, &'a str, Range)>) {
509        // Identifier nodes represent variable/function uses
510        if node.kind() == "identifier" {
511            // We need context to determine what this identifier is used in
512            // For now, we'll just track the identifier name and its location
513            let identifier_name = &code[node.byte_range()];
514            let range = Range::new(
515                node.start_position().row as u32,
516                node.start_position().column as u16,
517                node.end_position().row as u32,
518                node.end_position().column as u16,
519            );
520            // Use empty string for context for now
521            uses.push(("", identifier_name, range));
522        }
523
524        // Process children
525        for i in 0..node.child_count() {
526            if let Some(child) = node.child(i as u32) {
527                Self::find_uses_in_node(child, code, uses);
528            }
529        }
530    }
531
532    /// Find variable and macro definitions in AST nodes recursively
533    fn find_defines_in_node<'a>(
534        node: Node,
535        code: &'a str,
536        defines: &mut Vec<(&'a str, &'a str, Range)>,
537    ) {
538        // Variable declarations
539        if node.kind() == "declaration" {
540            if let Some(declarator) = node.child_by_field_name("declarator") {
541                let declarator_text = &code[declarator.byte_range()];
542                // Extract variable name (before = if present)
543                if let Some(equals_pos) = declarator_text.find('=') {
544                    let var_name = declarator_text[..equals_pos].trim();
545                    let range = Range::new(
546                        node.start_position().row as u32,
547                        node.start_position().column as u16,
548                        node.end_position().row as u32,
549                        node.end_position().column as u16,
550                    );
551                    defines.push((var_name, "variable", range));
552                } else {
553                    let range = Range::new(
554                        node.start_position().row as u32,
555                        node.start_position().column as u16,
556                        node.end_position().row as u32,
557                        node.end_position().column as u16,
558                    );
559                    defines.push((declarator_text.trim(), "variable", range));
560                }
561            }
562        }
563        // Preprocessor definitions
564        else if node.kind() == "preproc_def" {
565            if let Some(name_node) = node.child_by_field_name("name") {
566                let macro_name = &code[name_node.byte_range()];
567                let range = Range::new(
568                    node.start_position().row as u32,
569                    node.start_position().column as u16,
570                    node.end_position().row as u32,
571                    node.end_position().column as u16,
572                );
573                defines.push((macro_name, "macro", range));
574            }
575        }
576
577        // Process children
578        for i in 0..node.child_count() {
579            if let Some(child) = node.child(i as u32) {
580                Self::find_defines_in_node(child, code, defines);
581            }
582        }
583    }
584
585    /// Find variable type relationships in AST nodes recursively
586    fn find_variable_types_in_node<'a>(
587        node: Node,
588        code: &'a str,
589        variable_types: &mut Vec<(&'a str, &'a str, Range)>,
590    ) {
591        // Variable declarations with explicit types
592        if node.kind() == "declaration" {
593            if let Some(type_node) = node.child_by_field_name("type") {
594                let type_name = &code[type_node.byte_range()];
595                if let Some(declarator) = node.child_by_field_name("declarator") {
596                    let declarator_text = &code[declarator.byte_range()];
597                    // Extract variable name (before = if present)
598                    let var_name = if let Some(equals_pos) = declarator_text.find('=') {
599                        declarator_text[..equals_pos].trim()
600                    } else {
601                        declarator_text.trim()
602                    };
603                    let range = Range::new(
604                        node.start_position().row as u32,
605                        node.start_position().column as u16,
606                        node.end_position().row as u32,
607                        node.end_position().column as u16,
608                    );
609                    variable_types.push((var_name, type_name, range));
610                }
611            }
612        }
613
614        // Process children
615        for i in 0..node.child_count() {
616            if let Some(child) = node.child(i as u32) {
617                Self::find_variable_types_in_node(child, code, variable_types);
618            }
619        }
620    }
621
622    /// Find class method definitions in AST nodes recursively
623    fn find_inherent_methods_in_node(
624        node: Node,
625        code: &str,
626        inherent_methods: &mut Vec<(String, String, Range)>,
627    ) {
628        // Method definitions inside class specifiers
629        if node.kind() == "class_specifier" {
630            if let Some(class_name_node) = node.child_by_field_name("name") {
631                let class_name = &code[class_name_node.byte_range()];
632
633                // Look for method definitions inside the class body
634                for i in 0..node.child_count() {
635                    if let Some(child) = node.child(i as u32) {
636                        if child.kind() == "field_declaration_list" {
637                            Self::extract_methods_from_class_body(
638                                child,
639                                code,
640                                class_name,
641                                inherent_methods,
642                            );
643                        }
644                    }
645                }
646            }
647        }
648
649        // Process children
650        for i in 0..node.child_count() {
651            if let Some(child) = node.child(i as u32) {
652                Self::find_inherent_methods_in_node(child, code, inherent_methods);
653            }
654        }
655    }
656
657    /// Extract methods from class body
658    fn extract_methods_from_class_body(
659        node: Node,
660        code: &str,
661        class_name: &str,
662        inherent_methods: &mut Vec<(String, String, Range)>,
663    ) {
664        for i in 0..node.child_count() {
665            if let Some(child) = node.child(i as u32) {
666                if child.kind() == "declaration" || child.kind() == "function_definition" {
667                    // Look for method names
668                    if let Some(declarator) = child.child_by_field_name("declarator") {
669                        let method_name = &code[declarator.byte_range()];
670                        // Extract just the method name (before parameters)
671                        if let Some(paren_pos) = method_name.find('(') {
672                            let clean_method_name = method_name[..paren_pos].trim();
673                            let range = Range::new(
674                                child.start_position().row as u32,
675                                child.start_position().column as u16,
676                                child.end_position().row as u32,
677                                child.end_position().column as u16,
678                            );
679                            inherent_methods.push((
680                                class_name.to_string(),
681                                clean_method_name.to_string(),
682                                range,
683                            ));
684                        } else {
685                            let range = Range::new(
686                                child.start_position().row as u32,
687                                child.start_position().column as u16,
688                                child.end_position().row as u32,
689                                child.end_position().column as u16,
690                            );
691                            inherent_methods.push((
692                                class_name.to_string(),
693                                method_name.trim().to_string(),
694                                range,
695                            ));
696                        }
697                    }
698                } else {
699                    // Recursively process children
700                    Self::extract_methods_from_class_body(
701                        child,
702                        code,
703                        class_name,
704                        inherent_methods,
705                    );
706                }
707            }
708        }
709    }
710}
711
712impl NodeTracker for CppParser {
713    fn get_handled_nodes(&self) -> &std::collections::HashSet<crate::parsing::HandledNode> {
714        self.node_tracker.get_handled_nodes()
715    }
716
717    fn register_handled_node(&mut self, node_kind: &str, node_id: u16) {
718        self.node_tracker.register_handled_node(node_kind, node_id);
719    }
720}
721
722impl LanguageParser for CppParser {
723    fn parse(
724        &mut self,
725        code: &str,
726        file_id: FileId,
727        symbol_counter: &mut SymbolCounter,
728    ) -> Vec<Symbol> {
729        let tree = match self.parser.parse(code, None) {
730            Some(tree) => tree,
731            None => return Vec::new(),
732        };
733
734        let root_node = tree.root_node();
735        let mut symbols = Vec::new();
736
737        self.extract_symbols_from_node(root_node, code, file_id, &mut symbols, symbol_counter, 0);
738
739        symbols
740    }
741
742    fn as_any(&self) -> &dyn Any {
743        self
744    }
745
746    fn extract_doc_comment(&self, node: &Node, code: &str) -> Option<String> {
747        // Look for Doxygen/JavaDoc style comments (/** ... */ or ///)
748        // Check previous sibling for doc comment
749        let prev = node.prev_sibling()?;
750
751        if prev.kind() == "comment" {
752            let comment = &code[prev.byte_range()];
753
754            // Handle block comments (/** ... */)
755            if comment.starts_with("/**") {
756                let cleaned = comment
757                    .trim_start_matches("/**")
758                    .trim_end_matches("*/")
759                    .lines()
760                    .map(|line| {
761                        // Remove leading " * " or " *" from each line
762                        line.trim_start_matches(" * ")
763                            .trim_start_matches(" *")
764                            .trim_start_matches("     * ") // Handle extra indentation
765                            .trim_start_matches("     *")
766                    })
767                    .collect::<Vec<_>>()
768                    .join("\n")
769                    .trim()
770                    .to_string();
771
772                if !cleaned.is_empty() {
773                    return Some(cleaned);
774                }
775            }
776            // Handle line comments (///)
777            else if comment.starts_with("///") {
778                let cleaned = comment.trim_start_matches("///").trim().to_string();
779                if !cleaned.is_empty() {
780                    return Some(cleaned);
781                }
782            }
783        }
784
785        None
786    }
787
788    fn find_calls<'a>(&mut self, code: &'a str) -> Vec<(&'a str, &'a str, Range)> {
789        let tree = match self.parser.parse(code, None) {
790            Some(tree) => tree,
791            None => return Vec::new(),
792        };
793
794        let root_node = tree.root_node();
795        let mut calls = Vec::new();
796
797        // Use recursive method with context tracking
798        Self::extract_calls_recursive(root_node, code, None, &mut calls);
799        calls
800    }
801
802    fn find_method_calls(&mut self, code: &str) -> Vec<MethodCall> {
803        let tree = match self.parser.parse(code, None) {
804            Some(tree) => tree,
805            None => return Vec::new(),
806        };
807
808        let root_node = tree.root_node();
809        let mut calls = Vec::new();
810
811        Self::extract_calls_from_node(root_node, code, &mut calls);
812
813        calls
814    }
815
816    fn find_implementations<'a>(&mut self, code: &'a str) -> Vec<(&'a str, &'a str, Range)> {
817        let tree = match self.parser.parse(code, None) {
818            Some(tree) => tree,
819            None => return Vec::new(),
820        };
821
822        let root_node = tree.root_node();
823        let mut implementations = Vec::new();
824
825        Self::find_implementations_in_node(root_node, code, &mut implementations);
826        implementations
827    }
828
829    fn find_extends<'a>(&mut self, code: &'a str) -> Vec<(&'a str, &'a str, Range)> {
830        let tree = match self.parser.parse(code, None) {
831            Some(tree) => tree,
832            None => return Vec::new(),
833        };
834
835        let root_node = tree.root_node();
836        let mut extends = Vec::new();
837
838        Self::find_extends_in_node(root_node, code, &mut extends);
839        extends
840    }
841
842    fn find_uses<'a>(&mut self, code: &'a str) -> Vec<(&'a str, &'a str, Range)> {
843        let tree = match self.parser.parse(code, None) {
844            Some(tree) => tree,
845            None => return Vec::new(),
846        };
847
848        let root_node = tree.root_node();
849        let mut uses = Vec::new();
850
851        Self::find_uses_in_node(root_node, code, &mut uses);
852        uses
853    }
854
855    fn find_defines<'a>(&mut self, code: &'a str) -> Vec<(&'a str, &'a str, Range)> {
856        let tree = match self.parser.parse(code, None) {
857            Some(tree) => tree,
858            None => return Vec::new(),
859        };
860
861        let root_node = tree.root_node();
862        let mut defines = Vec::new();
863
864        Self::find_defines_in_node(root_node, code, &mut defines);
865        defines
866    }
867
868    fn find_imports(&mut self, code: &str, file_id: FileId) -> Vec<Import> {
869        let tree = match self.parser.parse(code, None) {
870            Some(tree) => tree,
871            None => return Vec::new(),
872        };
873
874        let root_node = tree.root_node();
875        let mut imports = Vec::new();
876
877        Self::extract_imports_from_node(root_node, code, file_id, &mut imports);
878
879        imports
880    }
881
882    fn language(&self) -> Language {
883        Language::Cpp
884    }
885
886    fn find_variable_types<'a>(&mut self, code: &'a str) -> Vec<(&'a str, &'a str, Range)> {
887        let tree = match self.parser.parse(code, None) {
888            Some(tree) => tree,
889            None => return Vec::new(),
890        };
891
892        let root_node = tree.root_node();
893        let mut variable_types = Vec::new();
894
895        Self::find_variable_types_in_node(root_node, code, &mut variable_types);
896        variable_types
897    }
898
899    fn find_inherent_methods(&mut self, code: &str) -> Vec<(String, String, Range)> {
900        let tree = match self.parser.parse(code, None) {
901            Some(tree) => tree,
902            None => return Vec::new(),
903        };
904
905        let root_node = tree.root_node();
906        let mut inherent_methods = Vec::new();
907
908        Self::find_inherent_methods_in_node(root_node, code, &mut inherent_methods);
909        inherent_methods
910    }
911}
912
913impl CppParser {
914    /// Recursively extract function calls with context tracking
915    fn extract_calls_recursive<'a>(
916        node: Node,
917        code: &'a str,
918        current_function: Option<&'a str>,
919        calls: &mut Vec<(&'a str, &'a str, Range)>,
920    ) {
921        // Determine function context - track which function we're inside
922        let function_context = if node.kind() == "function_definition" {
923            // Extract function name
924            if let Some(declarator) = node.child_by_field_name("declarator") {
925                // Handle function_declarator (for both regular functions and methods)
926                if declarator.kind() == "function_declarator" {
927                    if let Some(inner_declarator) = declarator.child_by_field_name("declarator") {
928                        match inner_declarator.kind() {
929                            // Method: QWindow::setX
930                            "qualified_identifier" => {
931                                // Extract just the method name (after ::)
932                                if let Some(name_node) =
933                                    inner_declarator.child_by_field_name("name")
934                                {
935                                    Some(&code[name_node.byte_range()])
936                                } else {
937                                    Some(&code[inner_declarator.byte_range()])
938                                }
939                            }
940                            // Regular function or simple identifier
941                            _ => Some(&code[inner_declarator.byte_range()]),
942                        }
943                    } else {
944                        current_function
945                    }
946                } else if let Some(name_node) = declarator.child_by_field_name("declarator") {
947                    // Fallback for other declarator types
948                    Some(&code[name_node.byte_range()])
949                } else {
950                    current_function
951                }
952            } else {
953                current_function
954            }
955        } else {
956            // Not a function - inherit current context
957            current_function
958        };
959
960        // Check if this is a call expression
961        if node.kind() == "call_expression" {
962            if let Some(function_node) = node.child_by_field_name("function") {
963                // Extract the actual function name from different call patterns
964                let target_name = match function_node.kind() {
965                    // Member function call: obj->method() or obj.method()
966                    "field_expression" => {
967                        // Get the field identifier (the actual method name)
968                        if let Some(field_node) = function_node.child_by_field_name("field") {
969                            &code[field_node.byte_range()]
970                        } else {
971                            &code[function_node.byte_range()]
972                        }
973                    }
974                    // Simple function call: function()
975                    _ => &code[function_node.byte_range()],
976                };
977
978                let range = Range::new(
979                    node.start_position().row as u32,
980                    node.start_position().column as u16,
981                    node.end_position().row as u32,
982                    node.end_position().column as u16,
983                );
984
985                // Only record call if we have a function context
986                if let Some(context) = function_context {
987                    calls.push((context, target_name, range));
988                }
989            }
990        }
991
992        // Recurse to children with current context
993        let mut cursor = node.walk();
994        for child in node.children(&mut cursor) {
995            Self::extract_calls_recursive(child, code, function_context, calls);
996        }
997    }
998}