1use 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 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 symbol.scope_context = Some(self.context.current_scope_context());
68
69 symbol
70 }
71
72 pub fn parse(
76 &mut self,
77 code: &str,
78 file_id: FileId,
79 symbol_counter: &mut SymbolCounter,
80 ) -> Vec<Symbol> {
81 <Self as LanguageParser>::parse(self, code, file_id, symbol_counter)
83 }
84
85 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 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 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 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 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 is_method = true;
142 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 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, doc_comment,
187 "", 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, doc_comment,
216 "", Visibility::Public,
218 );
219
220 symbols.push(symbol);
221
222 self.context
224 .enter_scope(crate::parsing::context::ScopeType::Class);
225
226 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 self.context.set_current_class(Some(class_name.to_string()));
232
233 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 self.context.exit_scope();
249
250 self.context.set_current_function(saved_function);
252 self.context.set_current_class(saved_class);
253
254 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, doc_comment,
279 "", 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, doc_comment,
307 "", Visibility::Public,
309 );
310
311 symbols.push(symbol);
312 }
313 }
314 "field_declaration" => {
315 self.register_handled_node(node.kind(), node.kind_id());
316 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 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, doc_comment,
344 "", Visibility::Public,
346 );
347
348 symbols.push(symbol);
349 break;
350 }
351 }
352 }
353 break;
354 }
355 }
356 }
357 }
358 }
359 _ => {
360 self.register_handled_node(node.kind(), node.kind_id());
362 }
363 }
364
365 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 let function_name = match function_node.kind() {
378 "field_expression" => {
380 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 _ => &code[function_node.byte_range()],
389 };
390
391 calls.push(MethodCall::new(
392 "", 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 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 fn find_implementations_in_node<'a>(
414 node: Node,
415 code: &'a str,
416 implementations: &mut Vec<(&'a str, &'a str, Range)>,
417 ) {
418 if node.kind() == "function_definition" {
420 if let Some(declarator) = node.child_by_field_name("declarator") {
421 let declarator_text = &code[declarator.byte_range()];
423 if declarator_text.contains("::") {
424 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 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 fn find_extends_in_node<'a>(
451 node: Node,
452 code: &'a str,
453 extends: &mut Vec<(&'a str, &'a str, Range)>,
454 ) {
455 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 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 Self::extract_base_classes_in_node(child, code, derived_class, extends);
466 }
467 }
468 }
469 }
470 }
471
472 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 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 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 Self::extract_base_classes_in_node(child, code, derived_class, extends);
502 }
503 }
504 }
505 }
506
507 fn find_uses_in_node<'a>(node: Node, code: &'a str, uses: &mut Vec<(&'a str, &'a str, Range)>) {
509 if node.kind() == "identifier" {
511 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 uses.push(("", identifier_name, range));
522 }
523
524 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 fn find_defines_in_node<'a>(
534 node: Node,
535 code: &'a str,
536 defines: &mut Vec<(&'a str, &'a str, Range)>,
537 ) {
538 if node.kind() == "declaration" {
540 if let Some(declarator) = node.child_by_field_name("declarator") {
541 let declarator_text = &code[declarator.byte_range()];
542 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 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 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 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 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 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 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 fn find_inherent_methods_in_node(
624 node: Node,
625 code: &str,
626 inherent_methods: &mut Vec<(String, String, Range)>,
627 ) {
628 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 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 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 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 if let Some(declarator) = child.child_by_field_name("declarator") {
669 let method_name = &code[declarator.byte_range()];
670 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 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 let prev = node.prev_sibling()?;
750
751 if prev.kind() == "comment" {
752 let comment = &code[prev.byte_range()];
753
754 if comment.starts_with("/**") {
756 let cleaned = comment
757 .trim_start_matches("/**")
758 .trim_end_matches("*/")
759 .lines()
760 .map(|line| {
761 line.trim_start_matches(" * ")
763 .trim_start_matches(" *")
764 .trim_start_matches(" * ") .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 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 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 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 let function_context = if node.kind() == "function_definition" {
923 if let Some(declarator) = node.child_by_field_name("declarator") {
925 if declarator.kind() == "function_declarator" {
927 if let Some(inner_declarator) = declarator.child_by_field_name("declarator") {
928 match inner_declarator.kind() {
929 "qualified_identifier" => {
931 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 _ => 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 Some(&code[name_node.byte_range()])
949 } else {
950 current_function
951 }
952 } else {
953 current_function
954 }
955 } else {
956 current_function
958 };
959
960 if node.kind() == "call_expression" {
962 if let Some(function_node) = node.child_by_field_name("function") {
963 let target_name = match function_node.kind() {
965 "field_expression" => {
967 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 _ => &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 if let Some(context) = function_context {
987 calls.push((context, target_name, range));
988 }
989 }
990 }
991
992 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}