infiniloom_engine/
parser.rs

1//! Tree-sitter based code parser for extracting symbols from source files
2//!
3//! This module provides a unified interface for parsing source code across
4//! multiple programming languages and extracting symbols (functions, classes,
5//! methods, structs, enums, etc.) with their metadata.
6//!
7//! # Supported Languages
8//!
9//! Full symbol extraction support (with tree-sitter queries):
10//! - Python
11//! - JavaScript
12//! - TypeScript
13//! - Rust
14//! - Go
15//! - Java
16//! - C
17//! - C++
18//! - C#
19//! - Ruby
20//! - Bash
21//! - PHP
22//! - Kotlin
23//! - Swift
24//! - Scala
25//! - Haskell
26//! - Elixir
27//! - Clojure
28//! - OCaml
29//! - Lua
30//! - R
31//!
32//! Note: F# is recognized by file extension but tree-sitter parser support
33//! is not yet implemented.
34//!
35//! # Example
36//!
37//! ```rust,ignore
38//! use infiniloom_engine::parser::{Parser, Language};
39//!
40//! let parser = Parser::new();
41//! let source_code = std::fs::read_to_string("example.py")?;
42//! let symbols = parser.parse(&source_code, Language::Python)?;
43//!
44//! for symbol in symbols {
45//!     println!("{}: {} (lines {}-{})",
46//!         symbol.kind.name(),
47//!         symbol.name,
48//!         symbol.start_line,
49//!         symbol.end_line
50//!     );
51//! }
52//! ```
53
54use crate::types::{Symbol, SymbolKind, Visibility};
55use std::collections::{HashMap, HashSet};
56use thiserror::Error;
57use tree_sitter::{Node, Parser as TSParser, Query, QueryCursor, StreamingIterator, Tree};
58
59/// Parser errors
60#[derive(Debug, Error)]
61pub enum ParserError {
62    #[error("Unsupported language: {0}")]
63    UnsupportedLanguage(String),
64
65    #[error("Parse error: {0}")]
66    ParseError(String),
67
68    #[error("Query error: {0}")]
69    QueryError(String),
70
71    #[error("Invalid UTF-8 in source code")]
72    InvalidUtf8,
73}
74
75/// Supported programming languages
76#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
77pub enum Language {
78    Python,
79    JavaScript,
80    TypeScript,
81    Rust,
82    Go,
83    Java,
84    C,
85    Cpp,
86    CSharp,
87    Ruby,
88    Bash,
89    Php,
90    Kotlin,
91    Swift,
92    Scala,
93    Haskell,
94    Elixir,
95    Clojure,
96    OCaml,
97    FSharp,
98    Lua,
99    R,
100}
101
102impl Language {
103    /// Detect language from file extension
104    pub fn from_extension(ext: &str) -> Option<Self> {
105        match ext.to_lowercase().as_str() {
106            "py" | "pyw" => Some(Self::Python),
107            "js" | "jsx" | "mjs" | "cjs" => Some(Self::JavaScript),
108            "ts" | "tsx" => Some(Self::TypeScript),
109            "rs" => Some(Self::Rust),
110            "go" => Some(Self::Go),
111            "java" => Some(Self::Java),
112            "c" | "h" => Some(Self::C),
113            "cpp" | "cc" | "cxx" | "hpp" | "hxx" | "hh" => Some(Self::Cpp),
114            "cs" => Some(Self::CSharp),
115            "rb" | "rake" | "gemspec" => Some(Self::Ruby),
116            "sh" | "bash" | "zsh" | "fish" => Some(Self::Bash),
117            "php" | "phtml" | "php3" | "php4" | "php5" | "phps" => Some(Self::Php),
118            "kt" | "kts" => Some(Self::Kotlin),
119            "swift" => Some(Self::Swift),
120            "scala" | "sc" => Some(Self::Scala),
121            "hs" | "lhs" => Some(Self::Haskell),
122            "ex" | "exs" | "eex" | "heex" | "leex" => Some(Self::Elixir),
123            "clj" | "cljs" | "cljc" | "edn" => Some(Self::Clojure),
124            "ml" | "mli" => Some(Self::OCaml),
125            "fs" | "fsi" | "fsx" | "fsscript" => Some(Self::FSharp),
126            "lua" => Some(Self::Lua),
127            "r" | "rmd" => Some(Self::R),
128            _ => None,
129        }
130    }
131
132    /// Get language name as string
133    pub fn name(&self) -> &'static str {
134        match self {
135            Self::Python => "python",
136            Self::JavaScript => "javascript",
137            Self::TypeScript => "typescript",
138            Self::Rust => "rust",
139            Self::Go => "go",
140            Self::Java => "java",
141            Self::C => "c",
142            Self::Cpp => "cpp",
143            Self::CSharp => "csharp",
144            Self::Ruby => "ruby",
145            Self::Bash => "bash",
146            Self::Php => "php",
147            Self::Kotlin => "kotlin",
148            Self::Swift => "swift",
149            Self::Scala => "scala",
150            Self::Haskell => "haskell",
151            Self::Elixir => "elixir",
152            Self::Clojure => "clojure",
153            Self::OCaml => "ocaml",
154            Self::FSharp => "fsharp",
155            Self::Lua => "lua",
156            Self::R => "r",
157        }
158    }
159}
160
161/// Main parser struct for extracting code symbols
162/// Uses lazy initialization - parsers are only created when first needed
163///
164/// # Performance
165///
166/// The parser uses "super-queries" that combine symbol extraction, imports, and call
167/// expressions into a single tree traversal per file. This is more efficient than
168/// running multiple separate queries.
169pub struct Parser {
170    parsers: HashMap<Language, TSParser>,
171    queries: HashMap<Language, Query>,
172    /// Super-queries that combine symbols + imports in one pass
173    super_queries: HashMap<Language, Query>,
174}
175
176impl Parser {
177    /// Create a new parser instance with lazy initialization
178    /// Parsers and queries are created on-demand when parse() is called
179    pub fn new() -> Self {
180        Self { parsers: HashMap::new(), queries: HashMap::new(), super_queries: HashMap::new() }
181    }
182
183    /// Ensure parser and query are initialized for a language
184    fn ensure_initialized(&mut self, language: Language) -> Result<(), ParserError> {
185        use std::collections::hash_map::Entry;
186        if let Entry::Vacant(parser_entry) = self.parsers.entry(language) {
187            let (parser, query, super_query) = match language {
188                Language::Python => (
189                    Self::init_python_parser()?,
190                    Self::python_query()?,
191                    Self::python_super_query()?,
192                ),
193                Language::JavaScript => (
194                    Self::init_javascript_parser()?,
195                    Self::javascript_query()?,
196                    Self::javascript_super_query()?,
197                ),
198                Language::TypeScript => (
199                    Self::init_typescript_parser()?,
200                    Self::typescript_query()?,
201                    Self::typescript_super_query()?,
202                ),
203                Language::Rust => {
204                    (Self::init_rust_parser()?, Self::rust_query()?, Self::rust_super_query()?)
205                },
206                Language::Go => {
207                    (Self::init_go_parser()?, Self::go_query()?, Self::go_super_query()?)
208                },
209                Language::Java => {
210                    (Self::init_java_parser()?, Self::java_query()?, Self::java_super_query()?)
211                },
212                Language::C => (Self::init_c_parser()?, Self::c_query()?, Self::c_super_query()?),
213                Language::Cpp => {
214                    (Self::init_cpp_parser()?, Self::cpp_query()?, Self::cpp_super_query()?)
215                },
216                Language::CSharp => (
217                    Self::init_csharp_parser()?,
218                    Self::csharp_query()?,
219                    Self::csharp_super_query()?,
220                ),
221                Language::Ruby => {
222                    (Self::init_ruby_parser()?, Self::ruby_query()?, Self::ruby_super_query()?)
223                },
224                Language::Bash => {
225                    (Self::init_bash_parser()?, Self::bash_query()?, Self::bash_super_query()?)
226                },
227                Language::Php => {
228                    (Self::init_php_parser()?, Self::php_query()?, Self::php_super_query()?)
229                },
230                Language::Kotlin => (
231                    Self::init_kotlin_parser()?,
232                    Self::kotlin_query()?,
233                    Self::kotlin_super_query()?,
234                ),
235                Language::Swift => {
236                    (Self::init_swift_parser()?, Self::swift_query()?, Self::swift_super_query()?)
237                },
238                Language::Scala => {
239                    (Self::init_scala_parser()?, Self::scala_query()?, Self::scala_super_query()?)
240                },
241                Language::Haskell => (
242                    Self::init_haskell_parser()?,
243                    Self::haskell_query()?,
244                    Self::haskell_super_query()?,
245                ),
246                Language::Elixir => (
247                    Self::init_elixir_parser()?,
248                    Self::elixir_query()?,
249                    Self::elixir_super_query()?,
250                ),
251                Language::Clojure => (
252                    Self::init_clojure_parser()?,
253                    Self::clojure_query()?,
254                    Self::clojure_super_query()?,
255                ),
256                Language::OCaml => {
257                    (Self::init_ocaml_parser()?, Self::ocaml_query()?, Self::ocaml_super_query()?)
258                },
259                Language::FSharp => {
260                    return Err(ParserError::UnsupportedLanguage(
261                        "F# not yet supported (no tree-sitter grammar available)".to_owned(),
262                    ));
263                },
264                Language::Lua => {
265                    (Self::init_lua_parser()?, Self::lua_query()?, Self::lua_super_query()?)
266                },
267                Language::R => (Self::init_r_parser()?, Self::r_query()?, Self::r_super_query()?),
268            };
269            parser_entry.insert(parser);
270            self.queries.insert(language, query);
271            self.super_queries.insert(language, super_query);
272        }
273        Ok(())
274    }
275
276    /// Parse source code and extract symbols
277    ///
278    /// This method now uses "super-queries" that combine symbol extraction and imports
279    /// into a single AST traversal for better performance.
280    pub fn parse(
281        &mut self,
282        source_code: &str,
283        language: Language,
284    ) -> Result<Vec<Symbol>, ParserError> {
285        // Lazy initialization - only init parser for this language
286        self.ensure_initialized(language)?;
287
288        let parser = self
289            .parsers
290            .get_mut(&language)
291            .ok_or_else(|| ParserError::UnsupportedLanguage(language.name().to_owned()))?;
292
293        let tree = parser
294            .parse(source_code, None)
295            .ok_or_else(|| ParserError::ParseError("Failed to parse source code".to_owned()))?;
296
297        // Use super-query for single-pass extraction (symbols + imports)
298        let super_query = self
299            .super_queries
300            .get(&language)
301            .ok_or_else(|| ParserError::QueryError("No super-query available".to_owned()))?;
302
303        self.extract_symbols_single_pass(&tree, source_code, super_query, language)
304    }
305
306    /// Extract symbols using single-pass super-query (combines symbols + imports)
307    fn extract_symbols_single_pass(
308        &self,
309        tree: &Tree,
310        source_code: &str,
311        query: &Query,
312        language: Language,
313    ) -> Result<Vec<Symbol>, ParserError> {
314        let mut symbols = Vec::new();
315        let mut cursor = QueryCursor::new();
316        let root_node = tree.root_node();
317
318        let mut matches = cursor.matches(query, root_node, source_code.as_bytes());
319        let capture_names: Vec<&str> = query.capture_names().to_vec();
320
321        while let Some(m) = matches.next() {
322            // Process imports (captured with @import)
323            if let Some(import_symbol) = self.process_import_match(m, source_code, &capture_names) {
324                symbols.push(import_symbol);
325                continue;
326            }
327
328            // Process regular symbols (functions, classes, etc.)
329            if let Some(symbol) =
330                self.process_match_single_pass(m, source_code, &capture_names, language)
331            {
332                symbols.push(symbol);
333            }
334        }
335
336        Ok(symbols)
337    }
338
339    /// Process an import match from super-query
340    fn process_import_match(
341        &self,
342        m: &tree_sitter::QueryMatch<'_, '_>,
343        source_code: &str,
344        capture_names: &[&str],
345    ) -> Option<Symbol> {
346        let captures = &m.captures;
347
348        // Look for import capture
349        let import_capture = captures.iter().find(|c| {
350            capture_names
351                .get(c.index as usize)
352                .map(|n| *n == "import")
353                .unwrap_or(false)
354        })?;
355
356        let node = import_capture.node;
357        let text = node.utf8_text(source_code.as_bytes()).ok()?;
358
359        let mut symbol = Symbol::new(text.trim(), SymbolKind::Import);
360        symbol.start_line = node.start_position().row as u32 + 1;
361        symbol.end_line = node.end_position().row as u32 + 1;
362
363        Some(symbol)
364    }
365
366    /// Process a symbol match from super-query (single-pass version)
367    fn process_match_single_pass(
368        &self,
369        m: &tree_sitter::QueryMatch<'_, '_>,
370        source_code: &str,
371        capture_names: &[&str],
372        language: Language,
373    ) -> Option<Symbol> {
374        let captures = &m.captures;
375
376        // Find name capture
377        let name_node = captures
378            .iter()
379            .find(|c| {
380                capture_names
381                    .get(c.index as usize)
382                    .map(|n| *n == "name")
383                    .unwrap_or(false)
384            })?
385            .node;
386
387        // Find kind capture (function, class, method, etc.)
388        let kind_capture = captures.iter().find(|c| {
389            capture_names
390                .get(c.index as usize)
391                .map(|n| {
392                    ["function", "class", "method", "struct", "enum", "interface", "trait"]
393                        .contains(n)
394                })
395                .unwrap_or(false)
396        })?;
397
398        let kind_name = capture_names.get(kind_capture.index as usize)?;
399        let mut symbol_kind = self.map_symbol_kind(kind_name);
400
401        let name = name_node.utf8_text(source_code.as_bytes()).ok()?;
402
403        // Find the definition node (usually the largest capture)
404        let def_node = captures
405            .iter()
406            .max_by_key(|c| c.node.byte_range().len())
407            .map(|c| c.node)
408            .unwrap_or(name_node);
409
410        if language == Language::Kotlin && def_node.kind() == "class_declaration" {
411            let mut cursor = def_node.walk();
412            for child in def_node.children(&mut cursor) {
413                if child.kind() == "interface" {
414                    symbol_kind = SymbolKind::Interface;
415                    break;
416                }
417            }
418        }
419
420        let start_line = def_node.start_position().row as u32 + 1;
421        let end_line = def_node.end_position().row as u32 + 1;
422
423        // Extract signature, docstring, parent, visibility, calls
424        let signature = self.extract_signature(def_node, source_code, language);
425        let docstring = self.extract_docstring(def_node, source_code, language);
426        let parent = if symbol_kind == SymbolKind::Method {
427            self.extract_parent(def_node, source_code)
428        } else {
429            None
430        };
431        let visibility = self.extract_visibility(def_node, source_code, language);
432        let calls = if matches!(symbol_kind, SymbolKind::Function | SymbolKind::Method) {
433            self.extract_calls(def_node, source_code, language)
434        } else {
435            Vec::new()
436        };
437
438        // Extract inheritance info for classes, structs, interfaces
439        let (extends, implements) = if matches!(
440            symbol_kind,
441            SymbolKind::Class | SymbolKind::Struct | SymbolKind::Interface
442        ) {
443            self.extract_inheritance(def_node, source_code, language)
444        } else {
445            (None, Vec::new())
446        };
447
448        let mut symbol = Symbol::new(name, symbol_kind);
449        symbol.start_line = start_line;
450        symbol.end_line = end_line;
451        symbol.signature = signature;
452        symbol.docstring = docstring;
453        symbol.parent = parent;
454        symbol.visibility = visibility;
455        symbol.calls = calls;
456        symbol.extends = extends;
457        symbol.implements = implements;
458
459        Some(symbol)
460    }
461
462    /// Map query capture name to SymbolKind
463    fn map_symbol_kind(&self, capture_name: &str) -> SymbolKind {
464        match capture_name {
465            "function" => SymbolKind::Function,
466            "class" => SymbolKind::Class,
467            "method" => SymbolKind::Method,
468            "struct" => SymbolKind::Struct,
469            "enum" => SymbolKind::Enum,
470            "interface" => SymbolKind::Interface,
471            "trait" => SymbolKind::Trait,
472            _ => SymbolKind::Function,
473        }
474    }
475
476    /// Extract function/method signature
477    fn extract_signature(
478        &self,
479        node: Node<'_>,
480        source_code: &str,
481        language: Language,
482    ) -> Option<String> {
483        // Find the signature node based on language
484        let sig_node = match language {
485            Language::Python => {
486                // For Python, find function_definition and get first line
487                if node.kind() == "function_definition" {
488                    // Get the line from 'def' to ':'
489                    let start = node.start_byte();
490                    let mut end = start;
491                    for byte in &source_code.as_bytes()[start..] {
492                        end += 1;
493                        if *byte == b':' {
494                            break;
495                        }
496                        if *byte == b'\n' {
497                            break;
498                        }
499                    }
500                    return Some(source_code[start..end].trim().to_owned().replace('\n', " "));
501                }
502                None
503            },
504            Language::JavaScript | Language::TypeScript => {
505                // For JS/TS, try to find the function declaration
506                if node.kind().contains("function") || node.kind().contains("method") {
507                    // Get first line up to opening brace
508                    let start = node.start_byte();
509                    let mut end = start;
510                    let mut brace_count = 0;
511                    for byte in &source_code.as_bytes()[start..] {
512                        if *byte == b'{' {
513                            brace_count += 1;
514                            if brace_count == 1 {
515                                break;
516                            }
517                        }
518                        end += 1;
519                    }
520                    return Some(source_code[start..end].trim().to_owned().replace('\n', " "));
521                }
522                None
523            },
524            Language::Rust => {
525                // For Rust, get the function signature
526                if node.kind() == "function_item" {
527                    // Get everything before the body
528                    for child in node.children(&mut node.walk()) {
529                        if child.kind() == "block" {
530                            let start = node.start_byte();
531                            let end = child.start_byte();
532                            return Some(
533                                source_code[start..end].trim().to_owned().replace('\n', " "),
534                            );
535                        }
536                    }
537                }
538                None
539            },
540            Language::Go => {
541                // For Go, get function declaration
542                if node.kind() == "function_declaration" || node.kind() == "method_declaration" {
543                    for child in node.children(&mut node.walk()) {
544                        if child.kind() == "block" {
545                            let start = node.start_byte();
546                            let end = child.start_byte();
547                            return Some(
548                                source_code[start..end].trim().to_owned().replace('\n', " "),
549                            );
550                        }
551                    }
552                }
553                None
554            },
555            Language::Java => {
556                // For Java, get method declaration
557                if node.kind() == "method_declaration" {
558                    for child in node.children(&mut node.walk()) {
559                        if child.kind() == "block" {
560                            let start = node.start_byte();
561                            let end = child.start_byte();
562                            return Some(
563                                source_code[start..end].trim().to_owned().replace('\n', " "),
564                            );
565                        }
566                    }
567                }
568                None
569            },
570            // Languages with block-based bodies (similar to Java/Go)
571            Language::C
572            | Language::Cpp
573            | Language::CSharp
574            | Language::Php
575            | Language::Kotlin
576            | Language::Swift
577            | Language::Scala => {
578                // Get everything before the body block
579                for child in node.children(&mut node.walk()) {
580                    if child.kind() == "block"
581                        || child.kind() == "compound_statement"
582                        || child.kind() == "function_body"
583                    {
584                        let start = node.start_byte();
585                        let end = child.start_byte();
586                        return Some(source_code[start..end].trim().to_owned().replace('\n', " "));
587                    }
588                }
589                None
590            },
591            // Ruby uses 'end' keyword, get first line
592            Language::Ruby | Language::Lua => {
593                let start = node.start_byte();
594                let mut end = start;
595                for byte in &source_code.as_bytes()[start..] {
596                    end += 1;
597                    if *byte == b'\n' {
598                        break;
599                    }
600                }
601                Some(source_code[start..end].trim().to_owned())
602            },
603            // Bash functions
604            Language::Bash => {
605                let start = node.start_byte();
606                let mut end = start;
607                for byte in &source_code.as_bytes()[start..] {
608                    if *byte == b'{' {
609                        break;
610                    }
611                    end += 1;
612                }
613                Some(source_code[start..end].trim().to_owned())
614            },
615            // Functional languages - get first line or up to '='
616            Language::Haskell
617            | Language::OCaml
618            | Language::FSharp
619            | Language::Elixir
620            | Language::Clojure
621            | Language::R => {
622                let start = node.start_byte();
623                let mut end = start;
624                for byte in &source_code.as_bytes()[start..] {
625                    end += 1;
626                    if *byte == b'\n' || *byte == b'=' {
627                        break;
628                    }
629                }
630                Some(source_code[start..end].trim().to_owned())
631            },
632        };
633
634        sig_node.or_else(|| {
635            // Fallback: get first line of the node
636            let start = node.start_byte();
637            let end = std::cmp::min(start + 200, source_code.len());
638            let text = &source_code[start..end];
639            text.lines().next().map(|s| s.trim().to_owned())
640        })
641    }
642
643    /// Extract docstring/documentation comment
644    fn extract_docstring(
645        &self,
646        node: Node<'_>,
647        source_code: &str,
648        language: Language,
649    ) -> Option<String> {
650        match language {
651            Language::Python => {
652                // Look for string literal as first child of function body
653                let mut cursor = node.walk();
654                for child in node.children(&mut cursor) {
655                    if child.kind() == "block" {
656                        // Look for first expression_statement with string
657                        for stmt in child.children(&mut child.walk()) {
658                            if stmt.kind() == "expression_statement" {
659                                for expr in stmt.children(&mut stmt.walk()) {
660                                    if expr.kind() == "string" {
661                                        if let Ok(text) = expr.utf8_text(source_code.as_bytes()) {
662                                            // Remove quotes and clean up
663                                            return Some(
664                                                text.trim_matches(|c| c == '"' || c == '\'')
665                                                    .trim()
666                                                    .to_owned(),
667                                            );
668                                        }
669                                    }
670                                }
671                            }
672                        }
673                    }
674                }
675                None
676            },
677            Language::JavaScript | Language::TypeScript => {
678                // Look for JSDoc comment immediately before the node
679                if let Some(prev_sibling) = node.prev_sibling() {
680                    if prev_sibling.kind() == "comment" {
681                        if let Ok(text) = prev_sibling.utf8_text(source_code.as_bytes()) {
682                            if text.starts_with("/**") {
683                                return Some(self.clean_jsdoc(text));
684                            }
685                        }
686                    }
687                }
688                None
689            },
690            Language::Rust => {
691                // Look for doc comment (///) above the node
692                let start_byte = node.start_byte();
693                let lines_before: Vec<_> = source_code[..start_byte]
694                    .lines()
695                    .rev()
696                    .take_while(|line| line.trim().starts_with("///") || line.trim().is_empty())
697                    .collect();
698
699                if !lines_before.is_empty() {
700                    let doc: Vec<String> = lines_before
701                        .into_iter()
702                        .rev()
703                        .filter_map(|line| {
704                            let trimmed = line.trim();
705                            trimmed.strip_prefix("///").map(|s| s.trim().to_owned())
706                        })
707                        .collect();
708
709                    if !doc.is_empty() {
710                        return Some(doc.join(" "));
711                    }
712                }
713                None
714            },
715            Language::Go => {
716                // Look for comment immediately before
717                if let Some(prev_sibling) = node.prev_sibling() {
718                    if prev_sibling.kind() == "comment" {
719                        if let Ok(text) = prev_sibling.utf8_text(source_code.as_bytes()) {
720                            return Some(text.trim_start_matches("//").trim().to_owned());
721                        }
722                    }
723                }
724                None
725            },
726            Language::Java => {
727                // Look for JavaDoc comment
728                if let Some(prev_sibling) = node.prev_sibling() {
729                    if prev_sibling.kind() == "block_comment" {
730                        if let Ok(text) = prev_sibling.utf8_text(source_code.as_bytes()) {
731                            if text.starts_with("/**") {
732                                return Some(self.clean_javadoc(text));
733                            }
734                        }
735                    }
736                }
737                None
738            },
739            // C/C++ - look for /* */ or // comments
740            Language::C | Language::Cpp => {
741                if let Some(prev_sibling) = node.prev_sibling() {
742                    if prev_sibling.kind() == "comment" {
743                        if let Ok(text) = prev_sibling.utf8_text(source_code.as_bytes()) {
744                            if text.starts_with("/**") || text.starts_with("/*") {
745                                return Some(self.clean_jsdoc(text));
746                            }
747                            return Some(text.trim_start_matches("//").trim().to_owned());
748                        }
749                    }
750                }
751                None
752            },
753            // C# - XML doc comments (///)
754            Language::CSharp => {
755                let start_byte = node.start_byte();
756                let lines_before: Vec<_> = source_code[..start_byte]
757                    .lines()
758                    .rev()
759                    .take_while(|line| line.trim().starts_with("///") || line.trim().is_empty())
760                    .collect();
761
762                if !lines_before.is_empty() {
763                    let doc: Vec<String> = lines_before
764                        .into_iter()
765                        .rev()
766                        .filter_map(|line| {
767                            let trimmed = line.trim();
768                            trimmed.strip_prefix("///").map(|s| s.trim().to_owned())
769                        })
770                        .collect();
771
772                    if !doc.is_empty() {
773                        return Some(doc.join(" "));
774                    }
775                }
776                None
777            },
778            // Ruby - look for # comments
779            Language::Ruby => {
780                if let Some(prev_sibling) = node.prev_sibling() {
781                    if prev_sibling.kind() == "comment" {
782                        if let Ok(text) = prev_sibling.utf8_text(source_code.as_bytes()) {
783                            return Some(text.trim_start_matches('#').trim().to_owned());
784                        }
785                    }
786                }
787                None
788            },
789            // PHP - look for /** */ comments
790            Language::Php | Language::Kotlin | Language::Swift | Language::Scala => {
791                if let Some(prev_sibling) = node.prev_sibling() {
792                    let kind = prev_sibling.kind();
793                    if kind == "comment" || kind == "multiline_comment" || kind == "block_comment" {
794                        if let Ok(text) = prev_sibling.utf8_text(source_code.as_bytes()) {
795                            if text.starts_with("/**") {
796                                return Some(self.clean_jsdoc(text));
797                            }
798                        }
799                    }
800                }
801                None
802            },
803            // Bash - look for # comments
804            Language::Bash => {
805                if let Some(prev_sibling) = node.prev_sibling() {
806                    if prev_sibling.kind() == "comment" {
807                        if let Ok(text) = prev_sibling.utf8_text(source_code.as_bytes()) {
808                            return Some(text.trim_start_matches('#').trim().to_owned());
809                        }
810                    }
811                }
812                None
813            },
814            // Haskell - look for {- -} or -- comments
815            Language::Haskell => {
816                if let Some(prev_sibling) = node.prev_sibling() {
817                    if prev_sibling.kind() == "comment" {
818                        if let Ok(text) = prev_sibling.utf8_text(source_code.as_bytes()) {
819                            let cleaned = text
820                                .trim_start_matches("{-")
821                                .trim_end_matches("-}")
822                                .trim_start_matches("--")
823                                .trim();
824                            return Some(cleaned.to_owned());
825                        }
826                    }
827                }
828                None
829            },
830            // Elixir - look for @doc or @moduledoc
831            Language::Elixir => {
832                // Simplified: just look for preceding comment
833                if let Some(prev_sibling) = node.prev_sibling() {
834                    if prev_sibling.kind() == "comment" {
835                        if let Ok(text) = prev_sibling.utf8_text(source_code.as_bytes()) {
836                            return Some(text.trim_start_matches('#').trim().to_owned());
837                        }
838                    }
839                }
840                None
841            },
842            // Clojure - look for docstring in defn
843            Language::Clojure => {
844                // Docstrings are typically the second element in defn forms
845                None
846            },
847            // OCaml - look for (** *) comments
848            Language::OCaml | Language::FSharp => {
849                if let Some(prev_sibling) = node.prev_sibling() {
850                    if prev_sibling.kind() == "comment" {
851                        if let Ok(text) = prev_sibling.utf8_text(source_code.as_bytes()) {
852                            let cleaned = text
853                                .trim_start_matches("(**")
854                                .trim_start_matches("(*")
855                                .trim_end_matches("*)")
856                                .trim();
857                            return Some(cleaned.to_owned());
858                        }
859                    }
860                }
861                None
862            },
863            // Lua - look for -- or --[[ ]] comments
864            Language::Lua => {
865                if let Some(prev_sibling) = node.prev_sibling() {
866                    if prev_sibling.kind() == "comment" {
867                        if let Ok(text) = prev_sibling.utf8_text(source_code.as_bytes()) {
868                            let cleaned = text
869                                .trim_start_matches("--[[")
870                                .trim_end_matches("]]")
871                                .trim_start_matches("--")
872                                .trim();
873                            return Some(cleaned.to_owned());
874                        }
875                    }
876                }
877                None
878            },
879            // R - look for # comments
880            Language::R => {
881                if let Some(prev_sibling) = node.prev_sibling() {
882                    if prev_sibling.kind() == "comment" {
883                        if let Ok(text) = prev_sibling.utf8_text(source_code.as_bytes()) {
884                            return Some(text.trim_start_matches('#').trim().to_owned());
885                        }
886                    }
887                }
888                None
889            },
890        }
891    }
892
893    /// Extract parent class/struct name for methods
894    fn extract_parent(&self, node: Node<'_>, source_code: &str) -> Option<String> {
895        let mut current = node.parent()?;
896
897        while let Some(parent) = current.parent() {
898            if ["class_definition", "class_declaration", "struct_item", "impl_item"]
899                .contains(&parent.kind())
900            {
901                // Find the name node
902                for child in parent.children(&mut parent.walk()) {
903                    if child.kind() == "identifier" || child.kind() == "type_identifier" {
904                        if let Ok(name) = child.utf8_text(source_code.as_bytes()) {
905                            return Some(name.to_owned());
906                        }
907                    }
908                }
909            }
910            current = parent;
911        }
912
913        None
914    }
915
916    /// Extract visibility modifier from a node
917    fn extract_visibility(
918        &self,
919        node: Node<'_>,
920        source_code: &str,
921        language: Language,
922    ) -> Visibility {
923        match language {
924            Language::Python => {
925                // Python uses naming convention: _private, __dunder__
926                if let Some(name_node) = node.child_by_field_name("name") {
927                    if let Ok(name) = name_node.utf8_text(source_code.as_bytes()) {
928                        if name.starts_with("__") && !name.ends_with("__") {
929                            return Visibility::Private;
930                        } else if name.starts_with('_') {
931                            return Visibility::Protected; // Convention for "internal"
932                        }
933                    }
934                }
935                Visibility::Public
936            },
937            Language::Rust => {
938                // Check for pub keyword
939                for child in node.children(&mut node.walk()) {
940                    if child.kind() == "visibility_modifier" {
941                        if let Ok(text) = child.utf8_text(source_code.as_bytes()) {
942                            if text.contains("pub(crate)") || text.contains("pub(super)") {
943                                return Visibility::Internal;
944                            } else if text.starts_with("pub") {
945                                return Visibility::Public;
946                            }
947                        }
948                    }
949                }
950                Visibility::Private // Rust default is private
951            },
952            Language::JavaScript | Language::TypeScript => {
953                // Check for private/protected keywords (TypeScript/ES2022)
954                for child in node.children(&mut node.walk()) {
955                    let kind = child.kind();
956                    if kind == "private" || kind == "accessibility_modifier" {
957                        if let Ok(text) = child.utf8_text(source_code.as_bytes()) {
958                            return match text {
959                                "private" => Visibility::Private,
960                                "protected" => Visibility::Protected,
961                                _ => Visibility::Public,
962                            };
963                        }
964                    }
965                }
966                // Check for # prefix (private fields in JS)
967                if let Some(name_node) = node.child_by_field_name("name") {
968                    if let Ok(name) = name_node.utf8_text(source_code.as_bytes()) {
969                        if name.starts_with('#') {
970                            return Visibility::Private;
971                        }
972                    }
973                }
974                Visibility::Public
975            },
976            Language::Go => {
977                // Go uses capitalization: Exported vs unexported
978                if let Some(name_node) = node.child_by_field_name("name") {
979                    if let Ok(name) = name_node.utf8_text(source_code.as_bytes()) {
980                        if let Some(first_char) = name.chars().next() {
981                            if first_char.is_lowercase() {
982                                return Visibility::Private;
983                            }
984                        }
985                    }
986                }
987                Visibility::Public
988            },
989            Language::Java => {
990                // Check for visibility modifiers
991                for child in node.children(&mut node.walk()) {
992                    if child.kind() == "modifiers" {
993                        if let Ok(text) = child.utf8_text(source_code.as_bytes()) {
994                            if text.contains("private") {
995                                return Visibility::Private;
996                            } else if text.contains("protected") {
997                                return Visibility::Protected;
998                            } else if text.contains("public") {
999                                return Visibility::Public;
1000                            }
1001                        }
1002                    }
1003                }
1004                Visibility::Internal // Java default is package-private
1005            },
1006            // C/C++ - check for static keyword (file-local)
1007            Language::C | Language::Cpp => {
1008                for child in node.children(&mut node.walk()) {
1009                    if child.kind() == "storage_class_specifier" {
1010                        if let Ok(text) = child.utf8_text(source_code.as_bytes()) {
1011                            if text == "static" {
1012                                return Visibility::Private;
1013                            }
1014                        }
1015                    }
1016                }
1017                Visibility::Public
1018            },
1019            // C# - check for access modifiers
1020            Language::CSharp | Language::Kotlin | Language::Swift | Language::Scala => {
1021                for child in node.children(&mut node.walk()) {
1022                    let kind = child.kind();
1023                    if kind == "modifier" || kind == "modifiers" || kind == "visibility_modifier" {
1024                        if let Ok(text) = child.utf8_text(source_code.as_bytes()) {
1025                            if text.contains("private") {
1026                                return Visibility::Private;
1027                            } else if text.contains("protected") {
1028                                return Visibility::Protected;
1029                            } else if text.contains("internal") {
1030                                return Visibility::Internal;
1031                            } else if text.contains("public") {
1032                                return Visibility::Public;
1033                            }
1034                        }
1035                    }
1036                }
1037                Visibility::Internal
1038            },
1039            // Ruby - uses naming convention like Python
1040            Language::Ruby => {
1041                if let Some(name_node) = node.child_by_field_name("name") {
1042                    if let Ok(name) = name_node.utf8_text(source_code.as_bytes()) {
1043                        if name.starts_with("_") {
1044                            return Visibility::Private;
1045                        }
1046                    }
1047                }
1048                Visibility::Public
1049            },
1050            // PHP - check for visibility keywords
1051            Language::Php => {
1052                for child in node.children(&mut node.walk()) {
1053                    if child.kind() == "visibility_modifier" {
1054                        if let Ok(text) = child.utf8_text(source_code.as_bytes()) {
1055                            return match text {
1056                                "private" => Visibility::Private,
1057                                "protected" => Visibility::Protected,
1058                                "public" => Visibility::Public,
1059                                _ => Visibility::Public,
1060                            };
1061                        }
1062                    }
1063                }
1064                Visibility::Public
1065            },
1066            // Bash - all functions are effectively public (no visibility concept)
1067            Language::Bash => Visibility::Public,
1068            // Functional languages - generally public by default
1069            Language::Haskell
1070            | Language::Elixir
1071            | Language::Clojure
1072            | Language::OCaml
1073            | Language::FSharp
1074            | Language::Lua
1075            | Language::R => Visibility::Public,
1076        }
1077    }
1078
1079    /// Extract function calls from a function/method body (Bug #1 fix - improved extraction)
1080    fn extract_calls(&self, node: Node<'_>, source_code: &str, language: Language) -> Vec<String> {
1081        let mut calls = HashSet::new();
1082
1083        // Find the function body
1084        let body_node = self.find_body_node(node, language);
1085        if let Some(body) = body_node {
1086            self.collect_calls_recursive(body, source_code, language, &mut calls);
1087        }
1088
1089        // Fallback: If no calls found and we have a body, scan the entire node
1090        // This handles cases where body detection might miss some patterns
1091        if calls.is_empty() {
1092            self.collect_calls_recursive(node, source_code, language, &mut calls);
1093        }
1094
1095        calls.into_iter().collect()
1096    }
1097
1098    /// Find the body node of a function/method
1099    fn find_body_node<'a>(&self, node: Node<'a>, language: Language) -> Option<Node<'a>> {
1100        match language {
1101            Language::Python => {
1102                // Python: function_definition > block
1103                for child in node.children(&mut node.walk()) {
1104                    if child.kind() == "block" {
1105                        return Some(child);
1106                    }
1107                }
1108            },
1109            Language::Rust => {
1110                // Rust: function_item > block
1111                for child in node.children(&mut node.walk()) {
1112                    if child.kind() == "block" {
1113                        return Some(child);
1114                    }
1115                }
1116            },
1117            Language::JavaScript | Language::TypeScript => {
1118                // JS/TS: various function forms - statement_block, arrow body, or expression body
1119                for child in node.children(&mut node.walk()) {
1120                    let kind = child.kind();
1121                    if kind == "statement_block" {
1122                        return Some(child);
1123                    }
1124                    // Arrow functions can have expression bodies
1125                    if kind == "arrow_function" {
1126                        // Recursively find body in arrow function
1127                        if let Some(body) = self.find_body_node(child, language) {
1128                            return Some(body);
1129                        }
1130                        // Or the arrow function itself has the calls
1131                        return Some(child);
1132                    }
1133                }
1134                // Fallback: for arrow functions without block body, return the node itself
1135                // This handles cases like: const fn = () => doSomething()
1136                if node.kind() == "arrow_function" {
1137                    for child in node.children(&mut node.walk()) {
1138                        // Skip parameter list and arrow
1139                        let kind = child.kind();
1140                        if kind != "formal_parameters"
1141                            && kind != "identifier"
1142                            && kind != "=>"
1143                            && kind != "("
1144                            && kind != ")"
1145                            && kind != ","
1146                        {
1147                            return Some(child);
1148                        }
1149                    }
1150                    return Some(node);
1151                }
1152            },
1153            Language::Go => {
1154                // Go: function_declaration > block
1155                for child in node.children(&mut node.walk()) {
1156                    if child.kind() == "block" {
1157                        return Some(child);
1158                    }
1159                }
1160            },
1161            Language::Java => {
1162                // Java: method_declaration > block
1163                for child in node.children(&mut node.walk()) {
1164                    if child.kind() == "block" {
1165                        return Some(child);
1166                    }
1167                }
1168            },
1169            // C/C++ - compound_statement
1170            Language::C | Language::Cpp => {
1171                for child in node.children(&mut node.walk()) {
1172                    if child.kind() == "compound_statement" {
1173                        return Some(child);
1174                    }
1175                }
1176            },
1177            // Languages with block bodies (similar to Java)
1178            Language::CSharp
1179            | Language::Php
1180            | Language::Kotlin
1181            | Language::Swift
1182            | Language::Scala => {
1183                for child in node.children(&mut node.walk()) {
1184                    let kind = child.kind();
1185                    if kind == "block" || kind == "compound_statement" || kind == "function_body" {
1186                        return Some(child);
1187                    }
1188                }
1189            },
1190            // Ruby - uses do/end blocks
1191            Language::Ruby => {
1192                for child in node.children(&mut node.walk()) {
1193                    if child.kind() == "body_statement" || child.kind() == "do_block" {
1194                        return Some(child);
1195                    }
1196                }
1197            },
1198            // Bash - compound_statement
1199            Language::Bash => {
1200                for child in node.children(&mut node.walk()) {
1201                    if child.kind() == "compound_statement" {
1202                        return Some(child);
1203                    }
1204                }
1205            },
1206            // Functional languages - typically expression-based
1207            Language::Haskell
1208            | Language::Elixir
1209            | Language::Clojure
1210            | Language::OCaml
1211            | Language::FSharp
1212            | Language::R => {
1213                // Return the node itself as expressions are the body
1214                return Some(node);
1215            },
1216            // Lua - block body
1217            Language::Lua => {
1218                for child in node.children(&mut node.walk()) {
1219                    if child.kind() == "block" {
1220                        return Some(child);
1221                    }
1222                }
1223            },
1224        }
1225        None
1226    }
1227
1228    /// Recursively collect function calls from a node
1229    #[allow(clippy::only_used_in_recursion)]
1230    fn collect_calls_recursive(
1231        &self,
1232        node: Node<'_>,
1233        source_code: &str,
1234        language: Language,
1235        calls: &mut HashSet<String>,
1236    ) {
1237        let kind = node.kind();
1238
1239        // Check if this node is a call expression
1240        let call_name = match language {
1241            Language::Python => {
1242                if kind == "call" {
1243                    // Python: call > function (identifier or attribute)
1244                    node.child_by_field_name("function").and_then(|f| {
1245                        if f.kind() == "identifier" {
1246                            f.utf8_text(source_code.as_bytes()).ok().map(String::from)
1247                        } else if f.kind() == "attribute" {
1248                            // Get the attribute name (method name)
1249                            f.child_by_field_name("attribute")
1250                                .and_then(|a| a.utf8_text(source_code.as_bytes()).ok())
1251                                .map(String::from)
1252                        } else {
1253                            None
1254                        }
1255                    })
1256                } else {
1257                    None
1258                }
1259            },
1260            Language::Rust => {
1261                if kind == "call_expression" {
1262                    // Rust: call_expression > function
1263                    node.child_by_field_name("function").and_then(|f| {
1264                        if f.kind() == "identifier" {
1265                            f.utf8_text(source_code.as_bytes()).ok().map(String::from)
1266                        } else if f.kind() == "field_expression" {
1267                            // Method call: get the field name
1268                            f.child_by_field_name("field")
1269                                .and_then(|a| a.utf8_text(source_code.as_bytes()).ok())
1270                                .map(String::from)
1271                        } else if f.kind() == "scoped_identifier" {
1272                            // Path call like Module::function
1273                            f.utf8_text(source_code.as_bytes()).ok().map(String::from)
1274                        } else {
1275                            None
1276                        }
1277                    })
1278                } else if kind == "macro_invocation" {
1279                    // Rust macros
1280                    node.child_by_field_name("macro")
1281                        .and_then(|m| m.utf8_text(source_code.as_bytes()).ok())
1282                        .map(|s| format!("{}!", s))
1283                } else {
1284                    None
1285                }
1286            },
1287            Language::JavaScript | Language::TypeScript => {
1288                if kind == "call_expression" {
1289                    // JS/TS: call_expression > function
1290                    node.child_by_field_name("function").and_then(|f| {
1291                        if f.kind() == "identifier" {
1292                            f.utf8_text(source_code.as_bytes()).ok().map(String::from)
1293                        } else if f.kind() == "member_expression" {
1294                            // Method call: get the property
1295                            f.child_by_field_name("property")
1296                                .and_then(|p| p.utf8_text(source_code.as_bytes()).ok())
1297                                .map(String::from)
1298                        } else {
1299                            None
1300                        }
1301                    })
1302                } else {
1303                    None
1304                }
1305            },
1306            Language::Go => {
1307                if kind == "call_expression" {
1308                    // Go: call_expression > function
1309                    node.child_by_field_name("function").and_then(|f| {
1310                        if f.kind() == "identifier" {
1311                            f.utf8_text(source_code.as_bytes()).ok().map(String::from)
1312                        } else if f.kind() == "selector_expression" {
1313                            // Method call: get the field
1314                            f.child_by_field_name("field")
1315                                .and_then(|a| a.utf8_text(source_code.as_bytes()).ok())
1316                                .map(String::from)
1317                        } else {
1318                            None
1319                        }
1320                    })
1321                } else {
1322                    None
1323                }
1324            },
1325            Language::Java => {
1326                if kind == "method_invocation" {
1327                    // Java: method_invocation > name
1328                    node.child_by_field_name("name")
1329                        .and_then(|n| n.utf8_text(source_code.as_bytes()).ok())
1330                        .map(String::from)
1331                } else {
1332                    None
1333                }
1334            },
1335            // C/C++ - call_expression
1336            Language::C | Language::Cpp => {
1337                if kind == "call_expression" {
1338                    node.child_by_field_name("function").and_then(|f| {
1339                        if f.kind() == "identifier" {
1340                            f.utf8_text(source_code.as_bytes()).ok().map(String::from)
1341                        } else if f.kind() == "field_expression" {
1342                            f.child_by_field_name("field")
1343                                .and_then(|a| a.utf8_text(source_code.as_bytes()).ok())
1344                                .map(String::from)
1345                        } else {
1346                            None
1347                        }
1348                    })
1349                } else {
1350                    None
1351                }
1352            },
1353            // C#/Kotlin/Swift/Scala - invocation_expression or call_expression
1354            Language::CSharp | Language::Kotlin | Language::Swift | Language::Scala => {
1355                if kind == "invocation_expression"
1356                    || kind == "call_expression"
1357                    || kind == "method_invocation"
1358                {
1359                    node.child_by_field_name("function")
1360                        .or_else(|| node.child_by_field_name("name"))
1361                        .and_then(|f| {
1362                            if f.kind() == "identifier" || f.kind() == "simple_identifier" {
1363                                f.utf8_text(source_code.as_bytes()).ok().map(String::from)
1364                            } else if f.kind() == "member_access_expression"
1365                                || f.kind() == "member_expression"
1366                            {
1367                                f.child_by_field_name("name")
1368                                    .and_then(|n| n.utf8_text(source_code.as_bytes()).ok())
1369                                    .map(String::from)
1370                            } else {
1371                                None
1372                            }
1373                        })
1374                } else {
1375                    None
1376                }
1377            },
1378            // Ruby - method_call or call
1379            Language::Ruby => {
1380                if kind == "call" || kind == "method_call" {
1381                    node.child_by_field_name("method")
1382                        .and_then(|m| m.utf8_text(source_code.as_bytes()).ok())
1383                        .map(String::from)
1384                } else {
1385                    None
1386                }
1387            },
1388            // PHP - function_call_expression
1389            Language::Php => {
1390                if kind == "function_call_expression" || kind == "method_call_expression" {
1391                    node.child_by_field_name("function")
1392                        .or_else(|| node.child_by_field_name("name"))
1393                        .and_then(|f| f.utf8_text(source_code.as_bytes()).ok())
1394                        .map(String::from)
1395                } else {
1396                    None
1397                }
1398            },
1399            // Bash - command
1400            Language::Bash => {
1401                if kind == "command" {
1402                    node.child_by_field_name("name")
1403                        .and_then(|n| n.utf8_text(source_code.as_bytes()).ok())
1404                        .map(String::from)
1405                } else {
1406                    None
1407                }
1408            },
1409            // Functional languages - application or call nodes
1410            Language::Haskell
1411            | Language::Elixir
1412            | Language::Clojure
1413            | Language::OCaml
1414            | Language::FSharp
1415            | Language::Lua
1416            | Language::R => {
1417                if kind == "application" || kind == "call" || kind == "function_call" {
1418                    // Get first child as function name
1419                    node.child(0).and_then(|c| {
1420                        if c.kind() == "identifier" || c.kind() == "variable" {
1421                            c.utf8_text(source_code.as_bytes()).ok().map(String::from)
1422                        } else {
1423                            None
1424                        }
1425                    })
1426                } else {
1427                    None
1428                }
1429            },
1430        };
1431
1432        if let Some(name) = call_name {
1433            // Filter out common built-ins and very short names
1434            if name.len() > 1 && !Self::is_builtin(&name, language) {
1435                calls.insert(name);
1436            }
1437        }
1438
1439        // Recurse into children
1440        for child in node.children(&mut node.walk()) {
1441            self.collect_calls_recursive(child, source_code, language, calls);
1442        }
1443    }
1444
1445    /// Check if a function name is a common built-in (to filter noise)
1446    fn is_builtin(name: &str, language: Language) -> bool {
1447        match language {
1448            Language::Python => {
1449                matches!(
1450                    name,
1451                    "print"
1452                        | "len"
1453                        | "range"
1454                        | "str"
1455                        | "int"
1456                        | "float"
1457                        | "list"
1458                        | "dict"
1459                        | "set"
1460                        | "tuple"
1461                        | "bool"
1462                        | "type"
1463                        | "isinstance"
1464                        | "hasattr"
1465                        | "getattr"
1466                        | "setattr"
1467                        | "super"
1468                        | "iter"
1469                        | "next"
1470                        | "open"
1471                        | "input"
1472                        | "format"
1473                        | "enumerate"
1474                        | "zip"
1475                        | "map"
1476                        | "filter"
1477                        | "sorted"
1478                        | "reversed"
1479                        | "sum"
1480                        | "min"
1481                        | "max"
1482                        | "abs"
1483                        | "round"
1484                        | "ord"
1485                        | "chr"
1486                        | "hex"
1487                        | "bin"
1488                        | "oct"
1489                )
1490            },
1491            Language::JavaScript | Language::TypeScript => {
1492                matches!(
1493                    name,
1494                    "console"
1495                        | "log"
1496                        | "error"
1497                        | "warn"
1498                        | "parseInt"
1499                        | "parseFloat"
1500                        | "setTimeout"
1501                        | "setInterval"
1502                        | "clearTimeout"
1503                        | "clearInterval"
1504                        | "JSON"
1505                        | "stringify"
1506                        | "parse"
1507                        | "toString"
1508                        | "valueOf"
1509                        | "push"
1510                        | "pop"
1511                        | "shift"
1512                        | "unshift"
1513                        | "slice"
1514                        | "splice"
1515                        | "map"
1516                        | "filter"
1517                        | "reduce"
1518                        | "forEach"
1519                        | "find"
1520                        | "findIndex"
1521                        | "includes"
1522                        | "indexOf"
1523                        | "join"
1524                        | "split"
1525                        | "replace"
1526                )
1527            },
1528            Language::Rust => {
1529                matches!(
1530                    name,
1531                    "println!"
1532                        | "print!"
1533                        | "eprintln!"
1534                        | "eprint!"
1535                        | "format!"
1536                        | "vec!"
1537                        | "panic!"
1538                        | "assert!"
1539                        | "assert_eq!"
1540                        | "assert_ne!"
1541                        | "debug!"
1542                        | "info!"
1543                        | "warn!"
1544                        | "error!"
1545                        | "trace!"
1546                        | "unwrap"
1547                        | "expect"
1548                        | "ok"
1549                        | "err"
1550                        | "some"
1551                        | "none"
1552                        | "clone"
1553                        | "to_string"
1554                        | "into"
1555                        | "from"
1556                        | "default"
1557                        | "iter"
1558                        | "into_iter"
1559                        | "collect"
1560                        | "map"
1561                        | "filter"
1562                )
1563            },
1564            Language::Go => {
1565                matches!(
1566                    name,
1567                    "fmt"
1568                        | "Println"
1569                        | "Printf"
1570                        | "Sprintf"
1571                        | "Errorf"
1572                        | "make"
1573                        | "new"
1574                        | "len"
1575                        | "cap"
1576                        | "append"
1577                        | "copy"
1578                        | "delete"
1579                        | "close"
1580                        | "panic"
1581                        | "recover"
1582                        | "print"
1583                )
1584            },
1585            Language::Java => {
1586                matches!(
1587                    name,
1588                    "println"
1589                        | "print"
1590                        | "printf"
1591                        | "toString"
1592                        | "equals"
1593                        | "hashCode"
1594                        | "getClass"
1595                        | "clone"
1596                        | "notify"
1597                        | "wait"
1598                        | "get"
1599                        | "set"
1600                        | "add"
1601                        | "remove"
1602                        | "size"
1603                        | "isEmpty"
1604                        | "contains"
1605                        | "iterator"
1606                        | "valueOf"
1607                        | "parseInt"
1608                )
1609            },
1610            Language::C | Language::Cpp => {
1611                matches!(
1612                    name,
1613                    "printf"
1614                        | "scanf"
1615                        | "malloc"
1616                        | "free"
1617                        | "memcpy"
1618                        | "memset"
1619                        | "strlen"
1620                        | "strcpy"
1621                        | "strcmp"
1622                        | "strcat"
1623                        | "sizeof"
1624                        | "cout"
1625                        | "cin"
1626                        | "endl"
1627                        | "cerr"
1628                        | "clog"
1629                )
1630            },
1631            Language::CSharp => {
1632                matches!(
1633                    name,
1634                    "WriteLine"
1635                        | "Write"
1636                        | "ReadLine"
1637                        | "ToString"
1638                        | "Equals"
1639                        | "GetHashCode"
1640                        | "GetType"
1641                        | "Add"
1642                        | "Remove"
1643                        | "Contains"
1644                        | "Count"
1645                        | "Clear"
1646                        | "ToList"
1647                        | "ToArray"
1648                )
1649            },
1650            Language::Ruby => {
1651                matches!(
1652                    name,
1653                    "puts"
1654                        | "print"
1655                        | "p"
1656                        | "gets"
1657                        | "each"
1658                        | "map"
1659                        | "select"
1660                        | "reject"
1661                        | "reduce"
1662                        | "inject"
1663                        | "find"
1664                        | "any?"
1665                        | "all?"
1666                        | "include?"
1667                        | "empty?"
1668                        | "nil?"
1669                        | "length"
1670                        | "size"
1671                )
1672            },
1673            Language::Php => {
1674                matches!(
1675                    name,
1676                    "echo"
1677                        | "print"
1678                        | "var_dump"
1679                        | "print_r"
1680                        | "isset"
1681                        | "empty"
1682                        | "array"
1683                        | "count"
1684                        | "strlen"
1685                        | "strpos"
1686                        | "substr"
1687                        | "explode"
1688                        | "implode"
1689                        | "json_encode"
1690                        | "json_decode"
1691                )
1692            },
1693            Language::Kotlin => {
1694                matches!(
1695                    name,
1696                    "println"
1697                        | "print"
1698                        | "readLine"
1699                        | "toString"
1700                        | "equals"
1701                        | "hashCode"
1702                        | "map"
1703                        | "filter"
1704                        | "forEach"
1705                        | "let"
1706                        | "also"
1707                        | "apply"
1708                        | "run"
1709                        | "with"
1710                        | "listOf"
1711                        | "mapOf"
1712                        | "setOf"
1713                )
1714            },
1715            Language::Swift => {
1716                matches!(
1717                    name,
1718                    "print"
1719                        | "debugPrint"
1720                        | "dump"
1721                        | "map"
1722                        | "filter"
1723                        | "reduce"
1724                        | "forEach"
1725                        | "contains"
1726                        | "count"
1727                        | "isEmpty"
1728                        | "append"
1729                )
1730            },
1731            Language::Scala => {
1732                matches!(
1733                    name,
1734                    "println"
1735                        | "print"
1736                        | "map"
1737                        | "filter"
1738                        | "flatMap"
1739                        | "foreach"
1740                        | "reduce"
1741                        | "fold"
1742                        | "foldLeft"
1743                        | "foldRight"
1744                        | "collect"
1745                )
1746            },
1747            // Languages where builtins are less common or harder to filter
1748            Language::Bash
1749            | Language::Haskell
1750            | Language::Elixir
1751            | Language::Clojure
1752            | Language::OCaml
1753            | Language::FSharp
1754            | Language::Lua
1755            | Language::R => false,
1756        }
1757    }
1758
1759    /// Clean JSDoc comment
1760    fn clean_jsdoc(&self, text: &str) -> String {
1761        text.lines()
1762            .map(|line| {
1763                line.trim()
1764                    .trim_start_matches("/**")
1765                    .trim_start_matches("/*")
1766                    .trim_start_matches('*')
1767                    .trim_end_matches("*/")
1768                    .trim()
1769            })
1770            .filter(|line| !line.is_empty())
1771            .collect::<Vec<_>>()
1772            .join(" ")
1773    }
1774
1775    /// Clean JavaDoc comment
1776    fn clean_javadoc(&self, text: &str) -> String {
1777        self.clean_jsdoc(text) // Same format as JSDoc
1778    }
1779
1780    /// Extract class inheritance (extends) and interface implementations (implements)
1781    /// Returns (base_class, implemented_interfaces)
1782    fn extract_inheritance(
1783        &self,
1784        node: Node<'_>,
1785        source_code: &str,
1786        language: Language,
1787    ) -> (Option<String>, Vec<String>) {
1788        let mut extends = None;
1789        let mut implements = Vec::new();
1790
1791        match language {
1792            Language::Python => {
1793                // Python: class Foo(Bar, Baz): - first is base class, rest could be mixins
1794                if node.kind() == "class_definition" {
1795                    if let Some(args) = node.child_by_field_name("superclasses") {
1796                        let mut first = true;
1797                        for child in args.children(&mut args.walk()) {
1798                            if child.kind() == "identifier" || child.kind() == "attribute" {
1799                                if let Ok(name) = child.utf8_text(source_code.as_bytes()) {
1800                                    if first {
1801                                        extends = Some(name.to_owned());
1802                                        first = false;
1803                                    } else {
1804                                        implements.push(name.to_owned());
1805                                    }
1806                                }
1807                            }
1808                        }
1809                    }
1810                }
1811            },
1812            Language::JavaScript | Language::TypeScript => {
1813                // JS/TS: class Foo extends Bar implements IBaz, IQux
1814                if node.kind() == "class_declaration" {
1815                    // Look for heritage clause
1816                    for child in node.children(&mut node.walk()) {
1817                        if child.kind() == "class_heritage" {
1818                            for heritage in child.children(&mut child.walk()) {
1819                                if heritage.kind() == "extends_clause" {
1820                                    // Get the extended class
1821                                    for ext_child in heritage.children(&mut heritage.walk()) {
1822                                        if ext_child.kind() == "identifier"
1823                                            || ext_child.kind() == "type_identifier"
1824                                        {
1825                                            if let Ok(name) =
1826                                                ext_child.utf8_text(source_code.as_bytes())
1827                                            {
1828                                                extends = Some(name.to_owned());
1829                                            }
1830                                        }
1831                                    }
1832                                } else if heritage.kind() == "implements_clause" {
1833                                    // Get implemented interfaces
1834                                    for impl_child in heritage.children(&mut heritage.walk()) {
1835                                        if impl_child.kind() == "type_identifier"
1836                                            || impl_child.kind() == "identifier"
1837                                        {
1838                                            if let Ok(name) =
1839                                                impl_child.utf8_text(source_code.as_bytes())
1840                                            {
1841                                                implements.push(name.to_owned());
1842                                            }
1843                                        }
1844                                    }
1845                                }
1846                            }
1847                        }
1848                    }
1849                }
1850            },
1851            Language::Java => {
1852                // Java: class Foo extends Bar implements IBaz, IQux
1853                if node.kind() == "class_declaration" {
1854                    if let Some(superclass) = node.child_by_field_name("superclass") {
1855                        if let Ok(name) = superclass.utf8_text(source_code.as_bytes()) {
1856                            extends = Some(name.trim_start_matches("extends ").trim().to_owned());
1857                        }
1858                    }
1859                    if let Some(interfaces) = node.child_by_field_name("interfaces") {
1860                        for child in interfaces.children(&mut interfaces.walk()) {
1861                            if child.kind() == "type_identifier" {
1862                                if let Ok(name) = child.utf8_text(source_code.as_bytes()) {
1863                                    implements.push(name.to_owned());
1864                                }
1865                            }
1866                        }
1867                    }
1868                }
1869            },
1870            Language::Rust => {
1871                // Rust: impl Trait for Struct - captured differently
1872                // For structs, we don't have traditional inheritance
1873                // We could look at impl blocks separately if needed
1874            },
1875            Language::Go => {
1876                // Go: struct embedding (composition, not inheritance)
1877                // Go uses implicit interface implementation
1878                if node.kind() == "type_declaration" {
1879                    for child in node.children(&mut node.walk()) {
1880                        if child.kind() == "type_spec" {
1881                            // Look for embedded types in struct
1882                            for spec_child in child.children(&mut child.walk()) {
1883                                if spec_child.kind() == "struct_type" {
1884                                    for field in spec_child.children(&mut spec_child.walk()) {
1885                                        if field.kind() == "field_declaration" {
1886                                            // Embedded field has no name, just type
1887                                            let has_name =
1888                                                field.child_by_field_name("name").is_some();
1889                                            if !has_name {
1890                                                if let Some(type_node) =
1891                                                    field.child_by_field_name("type")
1892                                                {
1893                                                    if let Ok(name) =
1894                                                        type_node.utf8_text(source_code.as_bytes())
1895                                                    {
1896                                                        implements.push(name.to_owned());
1897                                                    }
1898                                                }
1899                                            }
1900                                        }
1901                                    }
1902                                }
1903                            }
1904                        }
1905                    }
1906                }
1907            },
1908            Language::Cpp => {
1909                // C++: class Foo : public Bar, public IBaz
1910                if node.kind() == "class_specifier" {
1911                    for child in node.children(&mut node.walk()) {
1912                        if child.kind() == "base_class_clause" {
1913                            let mut first = true;
1914                            for base in child.children(&mut child.walk()) {
1915                                if base.kind() == "type_identifier" {
1916                                    if let Ok(name) = base.utf8_text(source_code.as_bytes()) {
1917                                        if first {
1918                                            extends = Some(name.to_owned());
1919                                            first = false;
1920                                        } else {
1921                                            implements.push(name.to_owned());
1922                                        }
1923                                    }
1924                                }
1925                            }
1926                        }
1927                    }
1928                }
1929            },
1930            Language::CSharp => {
1931                // C#: class Foo : Bar, IFoo, IBar
1932                if node.kind() == "class_declaration" {
1933                    if let Some(base_list) = node.child_by_field_name("bases") {
1934                        let mut first = true;
1935                        for child in base_list.children(&mut base_list.walk()) {
1936                            if child.kind() == "identifier" || child.kind() == "generic_name" {
1937                                if let Ok(name) = child.utf8_text(source_code.as_bytes()) {
1938                                    // Convention: interfaces start with 'I'
1939                                    if first && !name.starts_with('I') {
1940                                        extends = Some(name.to_owned());
1941                                        first = false;
1942                                    } else {
1943                                        implements.push(name.to_owned());
1944                                    }
1945                                }
1946                            }
1947                        }
1948                    }
1949                }
1950            },
1951            Language::Ruby => {
1952                // Ruby: class Foo < Bar
1953                if node.kind() == "class" {
1954                    if let Some(superclass) = node.child_by_field_name("superclass") {
1955                        if let Ok(name) = superclass.utf8_text(source_code.as_bytes()) {
1956                            extends = Some(name.to_owned());
1957                        }
1958                    }
1959                }
1960            },
1961            Language::Kotlin => {
1962                // Kotlin: class Foo : Bar(), IBaz, IQux
1963                if node.kind() == "class_declaration" {
1964                    for child in node.children(&mut node.walk()) {
1965                        if child.kind() == "delegation_specifiers" {
1966                            let mut first = true;
1967                            for spec in child.children(&mut child.walk()) {
1968                                if spec.kind() == "delegation_specifier" {
1969                                    if let Ok(name) = spec.utf8_text(source_code.as_bytes()) {
1970                                        // Remove constructor call parentheses
1971                                        let clean_name =
1972                                            name.split('(').next().unwrap_or(name).trim();
1973                                        if first {
1974                                            extends = Some(clean_name.to_owned());
1975                                            first = false;
1976                                        } else {
1977                                            implements.push(clean_name.to_owned());
1978                                        }
1979                                    }
1980                                }
1981                            }
1982                        }
1983                    }
1984                }
1985            },
1986            Language::Swift => {
1987                // Swift: class Foo: Bar, Protocol1, Protocol2
1988                if node.kind() == "class_declaration" {
1989                    for child in node.children(&mut node.walk()) {
1990                        if child.kind() == "type_inheritance_clause" {
1991                            let mut first = true;
1992                            for type_child in child.children(&mut child.walk()) {
1993                                if type_child.kind() == "type_identifier" {
1994                                    if let Ok(name) = type_child.utf8_text(source_code.as_bytes()) {
1995                                        if first {
1996                                            extends = Some(name.to_owned());
1997                                            first = false;
1998                                        } else {
1999                                            implements.push(name.to_owned());
2000                                        }
2001                                    }
2002                                }
2003                            }
2004                        }
2005                    }
2006                }
2007            },
2008            Language::Scala => {
2009                // Scala: class Foo extends Bar with Trait1 with Trait2
2010                if node.kind() == "class_definition" {
2011                    for child in node.children(&mut node.walk()) {
2012                        if child.kind() == "extends_clause" {
2013                            if let Ok(name) = child.utf8_text(source_code.as_bytes()) {
2014                                // Parse "extends Bar with Trait1 with Trait2"
2015                                let text = name.trim_start_matches("extends").trim();
2016                                let parts: Vec<&str> = text.split(" with ").collect();
2017                                if let Some(base) = parts.first() {
2018                                    extends = Some(base.trim().to_owned());
2019                                }
2020                                for trait_name in parts.iter().skip(1) {
2021                                    implements.push(trait_name.trim().to_owned());
2022                                }
2023                            }
2024                        }
2025                    }
2026                }
2027            },
2028            // Languages without traditional class inheritance
2029            Language::C
2030            | Language::Bash
2031            | Language::Php
2032            | Language::Haskell
2033            | Language::Elixir
2034            | Language::Clojure
2035            | Language::OCaml
2036            | Language::FSharp
2037            | Language::Lua
2038            | Language::R => {},
2039        }
2040
2041        (extends, implements)
2042    }
2043
2044    // Language-specific parser initializers
2045
2046    fn init_python_parser() -> Result<TSParser, ParserError> {
2047        let mut parser = TSParser::new();
2048        parser
2049            .set_language(&tree_sitter_python::LANGUAGE.into())
2050            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2051        Ok(parser)
2052    }
2053
2054    fn init_javascript_parser() -> Result<TSParser, ParserError> {
2055        let mut parser = TSParser::new();
2056        parser
2057            .set_language(&tree_sitter_javascript::LANGUAGE.into())
2058            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2059        Ok(parser)
2060    }
2061
2062    fn init_typescript_parser() -> Result<TSParser, ParserError> {
2063        let mut parser = TSParser::new();
2064        parser
2065            .set_language(&tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into())
2066            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2067        Ok(parser)
2068    }
2069
2070    fn init_rust_parser() -> Result<TSParser, ParserError> {
2071        let mut parser = TSParser::new();
2072        parser
2073            .set_language(&tree_sitter_rust::LANGUAGE.into())
2074            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2075        Ok(parser)
2076    }
2077
2078    fn init_go_parser() -> Result<TSParser, ParserError> {
2079        let mut parser = TSParser::new();
2080        parser
2081            .set_language(&tree_sitter_go::LANGUAGE.into())
2082            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2083        Ok(parser)
2084    }
2085
2086    fn init_java_parser() -> Result<TSParser, ParserError> {
2087        let mut parser = TSParser::new();
2088        parser
2089            .set_language(&tree_sitter_java::LANGUAGE.into())
2090            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2091        Ok(parser)
2092    }
2093
2094    fn init_c_parser() -> Result<TSParser, ParserError> {
2095        let mut parser = TSParser::new();
2096        parser
2097            .set_language(&tree_sitter_c::LANGUAGE.into())
2098            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2099        Ok(parser)
2100    }
2101
2102    fn init_cpp_parser() -> Result<TSParser, ParserError> {
2103        let mut parser = TSParser::new();
2104        parser
2105            .set_language(&tree_sitter_cpp::LANGUAGE.into())
2106            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2107        Ok(parser)
2108    }
2109
2110    fn init_csharp_parser() -> Result<TSParser, ParserError> {
2111        let mut parser = TSParser::new();
2112        parser
2113            .set_language(&tree_sitter_c_sharp::LANGUAGE.into())
2114            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2115        Ok(parser)
2116    }
2117
2118    fn init_ruby_parser() -> Result<TSParser, ParserError> {
2119        let mut parser = TSParser::new();
2120        parser
2121            .set_language(&tree_sitter_ruby::LANGUAGE.into())
2122            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2123        Ok(parser)
2124    }
2125
2126    fn init_bash_parser() -> Result<TSParser, ParserError> {
2127        let mut parser = TSParser::new();
2128        parser
2129            .set_language(&tree_sitter_bash::LANGUAGE.into())
2130            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2131        Ok(parser)
2132    }
2133
2134    fn init_php_parser() -> Result<TSParser, ParserError> {
2135        let mut parser = TSParser::new();
2136        parser
2137            .set_language(&tree_sitter_php::LANGUAGE_PHP.into())
2138            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2139        Ok(parser)
2140    }
2141
2142    fn init_kotlin_parser() -> Result<TSParser, ParserError> {
2143        let mut parser = TSParser::new();
2144        parser
2145            .set_language(&tree_sitter_kotlin_ng::LANGUAGE.into())
2146            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2147        Ok(parser)
2148    }
2149
2150    fn init_swift_parser() -> Result<TSParser, ParserError> {
2151        let mut parser = TSParser::new();
2152        parser
2153            .set_language(&tree_sitter_swift::LANGUAGE.into())
2154            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2155        Ok(parser)
2156    }
2157
2158    fn init_scala_parser() -> Result<TSParser, ParserError> {
2159        let mut parser = TSParser::new();
2160        parser
2161            .set_language(&tree_sitter_scala::LANGUAGE.into())
2162            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2163        Ok(parser)
2164    }
2165
2166    fn init_haskell_parser() -> Result<TSParser, ParserError> {
2167        let mut parser = TSParser::new();
2168        parser
2169            .set_language(&tree_sitter_haskell::LANGUAGE.into())
2170            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2171        Ok(parser)
2172    }
2173
2174    fn init_elixir_parser() -> Result<TSParser, ParserError> {
2175        let mut parser = TSParser::new();
2176        parser
2177            .set_language(&tree_sitter_elixir::LANGUAGE.into())
2178            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2179        Ok(parser)
2180    }
2181
2182    fn init_clojure_parser() -> Result<TSParser, ParserError> {
2183        let mut parser = TSParser::new();
2184        parser
2185            .set_language(&tree_sitter_clojure::LANGUAGE.into())
2186            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2187        Ok(parser)
2188    }
2189
2190    fn init_ocaml_parser() -> Result<TSParser, ParserError> {
2191        let mut parser = TSParser::new();
2192        parser
2193            .set_language(&tree_sitter_ocaml::LANGUAGE_OCAML.into())
2194            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2195        Ok(parser)
2196    }
2197
2198    fn init_lua_parser() -> Result<TSParser, ParserError> {
2199        let mut parser = TSParser::new();
2200        parser
2201            .set_language(&tree_sitter_lua::LANGUAGE.into())
2202            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2203        Ok(parser)
2204    }
2205
2206    fn init_r_parser() -> Result<TSParser, ParserError> {
2207        let mut parser = TSParser::new();
2208        parser
2209            .set_language(&tree_sitter_r::LANGUAGE.into())
2210            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2211        Ok(parser)
2212    }
2213
2214    // Language-specific queries
2215
2216    fn python_query() -> Result<Query, ParserError> {
2217        let query_string = r#"
2218            (function_definition
2219              name: (identifier) @name) @function
2220
2221            (class_definition
2222              name: (identifier) @name) @class
2223
2224            (class_definition
2225              body: (block
2226                (function_definition
2227                  name: (identifier) @name))) @method
2228        "#;
2229
2230        Query::new(&tree_sitter_python::LANGUAGE.into(), query_string)
2231            .map_err(|e| ParserError::QueryError(e.to_string()))
2232    }
2233
2234    fn javascript_query() -> Result<Query, ParserError> {
2235        let query_string = r#"
2236            (function_declaration
2237              name: (_) @name) @function
2238
2239            (class_declaration
2240              name: (_) @name) @class
2241
2242            (method_definition
2243              name: (property_identifier) @name) @method
2244
2245            (arrow_function) @function
2246
2247            (function_expression) @function
2248        "#;
2249
2250        Query::new(&tree_sitter_javascript::LANGUAGE.into(), query_string)
2251            .map_err(|e| ParserError::QueryError(e.to_string()))
2252    }
2253
2254    fn typescript_query() -> Result<Query, ParserError> {
2255        let query_string = r#"
2256            (function_declaration
2257              name: (identifier) @name) @function
2258
2259            (class_declaration
2260              name: (type_identifier) @name) @class
2261
2262            (interface_declaration
2263              name: (type_identifier) @name) @interface
2264
2265            (method_definition
2266              name: (property_identifier) @name) @method
2267
2268            (enum_declaration
2269              name: (identifier) @name) @enum
2270
2271            ; Arrow functions (named via variable) - Bug #1 fix
2272            (lexical_declaration
2273              (variable_declarator
2274                name: (identifier) @name
2275                value: (arrow_function))) @function
2276        "#;
2277
2278        Query::new(&tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(), query_string)
2279            .map_err(|e| ParserError::QueryError(e.to_string()))
2280    }
2281
2282    fn rust_query() -> Result<Query, ParserError> {
2283        let query_string = r#"
2284            (function_item
2285              name: (identifier) @name) @function
2286
2287            (struct_item
2288              name: (type_identifier) @name) @struct
2289
2290            (enum_item
2291              name: (type_identifier) @name) @enum
2292
2293            (trait_item
2294              name: (type_identifier) @name) @trait
2295        "#;
2296
2297        Query::new(&tree_sitter_rust::LANGUAGE.into(), query_string)
2298            .map_err(|e| ParserError::QueryError(e.to_string()))
2299    }
2300
2301    fn go_query() -> Result<Query, ParserError> {
2302        let query_string = r#"
2303            (function_declaration
2304              name: (identifier) @name) @function
2305
2306            (method_declaration
2307              name: (field_identifier) @name) @method
2308
2309            (type_declaration
2310              (type_spec
2311                name: (type_identifier) @name
2312                type: (struct_type))) @struct
2313
2314            (type_declaration
2315              (type_spec
2316                name: (type_identifier) @name
2317                type: (interface_type))) @interface
2318        "#;
2319
2320        Query::new(&tree_sitter_go::LANGUAGE.into(), query_string)
2321            .map_err(|e| ParserError::QueryError(e.to_string()))
2322    }
2323
2324    fn java_query() -> Result<Query, ParserError> {
2325        let query_string = r#"
2326            (method_declaration
2327              name: (identifier) @name) @method
2328
2329            (class_declaration
2330              name: (identifier) @name) @class
2331
2332            (interface_declaration
2333              name: (identifier) @name) @interface
2334
2335            (enum_declaration
2336              name: (identifier) @name) @enum
2337        "#;
2338
2339        Query::new(&tree_sitter_java::LANGUAGE.into(), query_string)
2340            .map_err(|e| ParserError::QueryError(e.to_string()))
2341    }
2342
2343    // ==========================================================================
2344    // Super-queries: combine symbols + imports in a single pass for performance
2345    // ==========================================================================
2346
2347    fn python_super_query() -> Result<Query, ParserError> {
2348        let query_string = r#"
2349            ; Functions
2350            (function_definition
2351              name: (identifier) @name) @function
2352
2353            ; Classes
2354            (class_definition
2355              name: (identifier) @name) @class
2356
2357            ; Methods inside classes
2358            (class_definition
2359              body: (block
2360                (function_definition
2361                  name: (identifier) @name))) @method
2362
2363            ; Imports
2364            (import_statement) @import
2365            (import_from_statement) @import
2366        "#;
2367
2368        Query::new(&tree_sitter_python::LANGUAGE.into(), query_string)
2369            .map_err(|e| ParserError::QueryError(e.to_string()))
2370    }
2371
2372    fn javascript_super_query() -> Result<Query, ParserError> {
2373        let query_string = r#"
2374            ; Functions
2375            (function_declaration
2376              name: (identifier) @name) @function
2377
2378            ; Classes
2379            (class_declaration
2380              name: (identifier) @name) @class
2381
2382            ; Methods
2383            (method_definition
2384              name: (property_identifier) @name) @method
2385
2386            ; Arrow functions (named via variable)
2387            (lexical_declaration
2388              (variable_declarator
2389                name: (identifier) @name
2390                value: (arrow_function))) @function
2391
2392            ; Imports
2393            (import_statement) @import
2394        "#;
2395
2396        Query::new(&tree_sitter_javascript::LANGUAGE.into(), query_string)
2397            .map_err(|e| ParserError::QueryError(e.to_string()))
2398    }
2399
2400    fn typescript_super_query() -> Result<Query, ParserError> {
2401        let query_string = r#"
2402            ; Functions
2403            (function_declaration
2404              name: (identifier) @name) @function
2405
2406            ; Classes
2407            (class_declaration
2408              name: (type_identifier) @name) @class
2409
2410            ; Interfaces
2411            (interface_declaration
2412              name: (type_identifier) @name) @interface
2413
2414            ; Methods
2415            (method_definition
2416              name: (property_identifier) @name) @method
2417
2418            ; Enums
2419            (enum_declaration
2420              name: (identifier) @name) @enum
2421
2422            ; Arrow functions (named via variable) - Bug #1 fix
2423            (lexical_declaration
2424              (variable_declarator
2425                name: (identifier) @name
2426                value: (arrow_function))) @function
2427
2428            ; Arrow functions (exported)
2429            (export_statement
2430              declaration: (lexical_declaration
2431                (variable_declarator
2432                  name: (identifier) @name
2433                  value: (arrow_function)))) @function
2434
2435            ; Type aliases
2436            (type_alias_declaration
2437              name: (type_identifier) @name) @struct
2438
2439            ; Imports
2440            (import_statement) @import
2441
2442            ; Exports (re-exports)
2443            (export_statement) @export
2444        "#;
2445
2446        Query::new(&tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(), query_string)
2447            .map_err(|e| ParserError::QueryError(e.to_string()))
2448    }
2449
2450    fn rust_super_query() -> Result<Query, ParserError> {
2451        let query_string = r#"
2452            ; Functions
2453            (function_item
2454              name: (identifier) @name) @function
2455
2456            ; Structs
2457            (struct_item
2458              name: (type_identifier) @name) @struct
2459
2460            ; Enums
2461            (enum_item
2462              name: (type_identifier) @name) @enum
2463
2464            ; Traits
2465            (trait_item
2466              name: (type_identifier) @name) @trait
2467
2468            ; Use statements (imports)
2469            (use_declaration) @import
2470        "#;
2471
2472        Query::new(&tree_sitter_rust::LANGUAGE.into(), query_string)
2473            .map_err(|e| ParserError::QueryError(e.to_string()))
2474    }
2475
2476    fn go_super_query() -> Result<Query, ParserError> {
2477        let query_string = r#"
2478            ; Functions
2479            (function_declaration
2480              name: (identifier) @name) @function
2481
2482            ; Methods
2483            (method_declaration
2484              name: (field_identifier) @name) @method
2485
2486            ; Structs
2487            (type_declaration
2488              (type_spec
2489                name: (type_identifier) @name
2490                type: (struct_type))) @struct
2491
2492            ; Interfaces
2493            (type_declaration
2494              (type_spec
2495                name: (type_identifier) @name
2496                type: (interface_type))) @interface
2497
2498            ; Imports
2499            (import_declaration) @import
2500        "#;
2501
2502        Query::new(&tree_sitter_go::LANGUAGE.into(), query_string)
2503            .map_err(|e| ParserError::QueryError(e.to_string()))
2504    }
2505
2506    fn java_super_query() -> Result<Query, ParserError> {
2507        let query_string = r#"
2508            ; Methods
2509            (method_declaration
2510              name: (identifier) @name) @method
2511
2512            ; Classes
2513            (class_declaration
2514              name: (identifier) @name) @class
2515
2516            ; Interfaces
2517            (interface_declaration
2518              name: (identifier) @name) @interface
2519
2520            ; Enums
2521            (enum_declaration
2522              name: (identifier) @name) @enum
2523
2524            ; Imports
2525            (import_declaration) @import
2526        "#;
2527
2528        Query::new(&tree_sitter_java::LANGUAGE.into(), query_string)
2529            .map_err(|e| ParserError::QueryError(e.to_string()))
2530    }
2531
2532    // ==========================================================================
2533    // C language queries
2534    // ==========================================================================
2535
2536    fn c_query() -> Result<Query, ParserError> {
2537        let query_string = r#"
2538            (function_definition
2539              declarator: (function_declarator
2540                declarator: (identifier) @name)) @function
2541
2542            (struct_specifier
2543              name: (type_identifier) @name) @struct
2544
2545            (enum_specifier
2546              name: (type_identifier) @name) @enum
2547        "#;
2548
2549        Query::new(&tree_sitter_c::LANGUAGE.into(), query_string)
2550            .map_err(|e| ParserError::QueryError(e.to_string()))
2551    }
2552
2553    fn c_super_query() -> Result<Query, ParserError> {
2554        let query_string = r#"
2555            ; Functions
2556            (function_definition
2557              declarator: (function_declarator
2558                declarator: (identifier) @name)) @function
2559
2560            ; Structs
2561            (struct_specifier
2562              name: (type_identifier) @name) @struct
2563
2564            ; Enums
2565            (enum_specifier
2566              name: (type_identifier) @name) @enum
2567
2568            ; Includes (imports)
2569            (preproc_include) @import
2570        "#;
2571
2572        Query::new(&tree_sitter_c::LANGUAGE.into(), query_string)
2573            .map_err(|e| ParserError::QueryError(e.to_string()))
2574    }
2575
2576    // ==========================================================================
2577    // C++ language queries
2578    // ==========================================================================
2579
2580    fn cpp_query() -> Result<Query, ParserError> {
2581        let query_string = r#"
2582            (function_definition
2583              declarator: (function_declarator
2584                declarator: (identifier) @name)) @function
2585
2586            (class_specifier
2587              name: (type_identifier) @name) @class
2588
2589            (struct_specifier
2590              name: (type_identifier) @name) @struct
2591
2592            (enum_specifier
2593              name: (type_identifier) @name) @enum
2594        "#;
2595
2596        Query::new(&tree_sitter_cpp::LANGUAGE.into(), query_string)
2597            .map_err(|e| ParserError::QueryError(e.to_string()))
2598    }
2599
2600    fn cpp_super_query() -> Result<Query, ParserError> {
2601        let query_string = r#"
2602            ; Functions
2603            (function_definition
2604              declarator: (function_declarator
2605                declarator: (identifier) @name)) @function
2606
2607            ; Classes
2608            (class_specifier
2609              name: (type_identifier) @name) @class
2610
2611            ; Structs
2612            (struct_specifier
2613              name: (type_identifier) @name) @struct
2614
2615            ; Enums
2616            (enum_specifier
2617              name: (type_identifier) @name) @enum
2618
2619            ; Includes (imports)
2620            (preproc_include) @import
2621        "#;
2622
2623        Query::new(&tree_sitter_cpp::LANGUAGE.into(), query_string)
2624            .map_err(|e| ParserError::QueryError(e.to_string()))
2625    }
2626
2627    // ==========================================================================
2628    // C# language queries
2629    // ==========================================================================
2630
2631    fn csharp_query() -> Result<Query, ParserError> {
2632        let query_string = r#"
2633            (method_declaration
2634              name: (identifier) @name) @method
2635
2636            (class_declaration
2637              name: (identifier) @name) @class
2638
2639            (interface_declaration
2640              name: (identifier) @name) @interface
2641
2642            (struct_declaration
2643              name: (identifier) @name) @struct
2644
2645            (enum_declaration
2646              name: (identifier) @name) @enum
2647        "#;
2648
2649        Query::new(&tree_sitter_c_sharp::LANGUAGE.into(), query_string)
2650            .map_err(|e| ParserError::QueryError(e.to_string()))
2651    }
2652
2653    fn csharp_super_query() -> Result<Query, ParserError> {
2654        let query_string = r#"
2655            ; Methods
2656            (method_declaration
2657              name: (identifier) @name) @method
2658
2659            ; Classes
2660            (class_declaration
2661              name: (identifier) @name) @class
2662
2663            ; Interfaces
2664            (interface_declaration
2665              name: (identifier) @name) @interface
2666
2667            ; Structs
2668            (struct_declaration
2669              name: (identifier) @name) @struct
2670
2671            ; Enums
2672            (enum_declaration
2673              name: (identifier) @name) @enum
2674
2675            ; Imports (using directives)
2676            (using_directive) @import
2677        "#;
2678
2679        Query::new(&tree_sitter_c_sharp::LANGUAGE.into(), query_string)
2680            .map_err(|e| ParserError::QueryError(e.to_string()))
2681    }
2682
2683    // ==========================================================================
2684    // Ruby language queries
2685    // ==========================================================================
2686
2687    fn ruby_query() -> Result<Query, ParserError> {
2688        let query_string = r#"
2689            (method
2690              name: (identifier) @name) @function
2691
2692            (class
2693              name: (constant) @name) @class
2694
2695            (module
2696              name: (constant) @name) @class
2697        "#;
2698
2699        Query::new(&tree_sitter_ruby::LANGUAGE.into(), query_string)
2700            .map_err(|e| ParserError::QueryError(e.to_string()))
2701    }
2702
2703    fn ruby_super_query() -> Result<Query, ParserError> {
2704        let query_string = r#"
2705            ; Methods
2706            (method
2707              name: (identifier) @name) @function
2708
2709            ; Classes
2710            (class
2711              name: (constant) @name) @class
2712
2713            ; Modules
2714            (module
2715              name: (constant) @name) @class
2716
2717            ; Requires (imports)
2718            (call
2719              method: (identifier) @_method
2720              (#match? @_method "^require")
2721              arguments: (argument_list)) @import
2722        "#;
2723
2724        Query::new(&tree_sitter_ruby::LANGUAGE.into(), query_string)
2725            .map_err(|e| ParserError::QueryError(e.to_string()))
2726    }
2727
2728    // ==========================================================================
2729    // Bash language queries
2730    // ==========================================================================
2731
2732    fn bash_query() -> Result<Query, ParserError> {
2733        let query_string = r#"
2734            (function_definition
2735              name: (word) @name) @function
2736        "#;
2737
2738        Query::new(&tree_sitter_bash::LANGUAGE.into(), query_string)
2739            .map_err(|e| ParserError::QueryError(e.to_string()))
2740    }
2741
2742    fn bash_super_query() -> Result<Query, ParserError> {
2743        let query_string = r#"
2744            ; Functions
2745            (function_definition
2746              name: (word) @name) @function
2747
2748            ; Source commands (imports)
2749            (command
2750              name: (command_name) @_cmd
2751              (#match? @_cmd "^(source|\\.)$")
2752              argument: (word)) @import
2753        "#;
2754
2755        Query::new(&tree_sitter_bash::LANGUAGE.into(), query_string)
2756            .map_err(|e| ParserError::QueryError(e.to_string()))
2757    }
2758
2759    // ==========================================================================
2760    // PHP language queries
2761    // ==========================================================================
2762
2763    fn php_query() -> Result<Query, ParserError> {
2764        let query_string = r#"
2765            (function_definition
2766              name: (name) @name) @function
2767
2768            (method_declaration
2769              name: (name) @name) @method
2770
2771            (class_declaration
2772              name: (name) @name) @class
2773
2774            (interface_declaration
2775              name: (name) @name) @interface
2776
2777            (trait_declaration
2778              name: (name) @name) @trait
2779        "#;
2780
2781        Query::new(&tree_sitter_php::LANGUAGE_PHP.into(), query_string)
2782            .map_err(|e| ParserError::QueryError(e.to_string()))
2783    }
2784
2785    fn php_super_query() -> Result<Query, ParserError> {
2786        let query_string = r#"
2787            ; Functions
2788            (function_definition
2789              name: (name) @name) @function
2790
2791            ; Methods
2792            (method_declaration
2793              name: (name) @name) @method
2794
2795            ; Classes
2796            (class_declaration
2797              name: (name) @name) @class
2798
2799            ; Interfaces
2800            (interface_declaration
2801              name: (name) @name) @interface
2802
2803            ; Traits
2804            (trait_declaration
2805              name: (name) @name) @trait
2806
2807            ; Use statements (imports)
2808            (namespace_use_declaration) @import
2809        "#;
2810
2811        Query::new(&tree_sitter_php::LANGUAGE_PHP.into(), query_string)
2812            .map_err(|e| ParserError::QueryError(e.to_string()))
2813    }
2814
2815    // ==========================================================================
2816    // Kotlin language queries
2817    // ==========================================================================
2818
2819    fn kotlin_query() -> Result<Query, ParserError> {
2820        let query_string = r#"
2821            (function_declaration
2822              name: (_) @name) @function
2823
2824            (class_declaration
2825              name: (_) @name) @class
2826
2827            (object_declaration
2828              name: (_) @name) @class
2829        "#;
2830
2831        Query::new(&tree_sitter_kotlin_ng::LANGUAGE.into(), query_string)
2832            .map_err(|e| ParserError::QueryError(e.to_string()))
2833    }
2834
2835    fn kotlin_super_query() -> Result<Query, ParserError> {
2836        let query_string = r#"
2837            ; Functions
2838            (function_declaration
2839              name: (_) @name) @function
2840
2841            ; Classes
2842            (class_declaration
2843              name: (_) @name) @class
2844
2845            ; Objects
2846            (object_declaration
2847              name: (_) @name) @class
2848
2849            ; Imports
2850            (import) @import
2851        "#;
2852
2853        Query::new(&tree_sitter_kotlin_ng::LANGUAGE.into(), query_string)
2854            .map_err(|e| ParserError::QueryError(e.to_string()))
2855    }
2856
2857    // ==========================================================================
2858    // Swift language queries
2859    // ==========================================================================
2860
2861    fn swift_query() -> Result<Query, ParserError> {
2862        let query_string = r#"
2863            (function_declaration
2864              name: (simple_identifier) @name) @function
2865
2866            (class_declaration
2867              declaration_kind: "class"
2868              name: (type_identifier) @name) @class
2869
2870            (protocol_declaration
2871              name: (type_identifier) @name) @interface
2872
2873            (class_declaration
2874              declaration_kind: "struct"
2875              name: (type_identifier) @name) @struct
2876
2877            (class_declaration
2878              declaration_kind: "enum"
2879              name: (type_identifier) @name) @enum
2880        "#;
2881
2882        Query::new(&tree_sitter_swift::LANGUAGE.into(), query_string)
2883            .map_err(|e| ParserError::QueryError(e.to_string()))
2884    }
2885
2886    fn swift_super_query() -> Result<Query, ParserError> {
2887        let query_string = r#"
2888            ; Functions
2889            (function_declaration
2890              name: (simple_identifier) @name) @function
2891
2892            ; Classes
2893            (class_declaration
2894              declaration_kind: "class"
2895              name: (type_identifier) @name) @class
2896
2897            ; Protocols (interfaces)
2898            (protocol_declaration
2899              name: (type_identifier) @name) @interface
2900
2901            ; Structs
2902            (class_declaration
2903              declaration_kind: "struct"
2904              name: (type_identifier) @name) @struct
2905
2906            ; Enums
2907            (class_declaration
2908              declaration_kind: "enum"
2909              name: (type_identifier) @name) @enum
2910
2911            ; Imports
2912            (import_declaration) @import
2913        "#;
2914
2915        Query::new(&tree_sitter_swift::LANGUAGE.into(), query_string)
2916            .map_err(|e| ParserError::QueryError(e.to_string()))
2917    }
2918
2919    // ==========================================================================
2920    // Scala language queries
2921    // ==========================================================================
2922
2923    fn scala_query() -> Result<Query, ParserError> {
2924        let query_string = r#"
2925            (function_definition
2926              name: (identifier) @name) @function
2927
2928            (class_definition
2929              name: (identifier) @name) @class
2930
2931            (object_definition
2932              name: (identifier) @name) @class
2933
2934            (trait_definition
2935              name: (identifier) @name) @trait
2936        "#;
2937
2938        Query::new(&tree_sitter_scala::LANGUAGE.into(), query_string)
2939            .map_err(|e| ParserError::QueryError(e.to_string()))
2940    }
2941
2942    fn scala_super_query() -> Result<Query, ParserError> {
2943        let query_string = r#"
2944            ; Functions
2945            (function_definition
2946              name: (identifier) @name) @function
2947
2948            ; Classes
2949            (class_definition
2950              name: (identifier) @name) @class
2951
2952            ; Objects
2953            (object_definition
2954              name: (identifier) @name) @class
2955
2956            ; Traits
2957            (trait_definition
2958              name: (identifier) @name) @trait
2959
2960            ; Imports
2961            (import_declaration) @import
2962        "#;
2963
2964        Query::new(&tree_sitter_scala::LANGUAGE.into(), query_string)
2965            .map_err(|e| ParserError::QueryError(e.to_string()))
2966    }
2967
2968    // ==========================================================================
2969    // Haskell language queries
2970    // ==========================================================================
2971
2972    fn haskell_query() -> Result<Query, ParserError> {
2973        let query_string = r#"
2974            (function
2975              name: (variable) @name) @function
2976
2977            (signature
2978              name: (variable) @name) @function
2979
2980            (function
2981              name: (prefix_id) @name) @function
2982
2983            (signature
2984              name: (prefix_id) @name) @function
2985
2986            (newtype
2987              name: (name) @name) @struct
2988
2989            (type_synomym
2990              name: (name) @name) @struct
2991
2992            (data_type
2993              name: (name) @name) @enum
2994        "#;
2995
2996        Query::new(&tree_sitter_haskell::LANGUAGE.into(), query_string)
2997            .map_err(|e| ParserError::QueryError(e.to_string()))
2998    }
2999
3000    fn haskell_super_query() -> Result<Query, ParserError> {
3001        let query_string = r#"
3002            ; Functions
3003            (function
3004              name: (variable) @name) @function
3005
3006            ; Type signatures
3007            (signature
3008              name: (variable) @name) @function
3009
3010            ; Type aliases
3011            (function
3012              name: (prefix_id) @name) @function
3013
3014            (signature
3015              name: (prefix_id) @name) @function
3016
3017            ; Newtypes
3018            (newtype
3019              name: (name) @name) @struct
3020
3021            ; ADTs (data declarations)
3022            (type_synomym
3023              name: (name) @name) @struct
3024
3025            (data_type
3026              name: (name) @name) @enum
3027
3028            ; Imports
3029            (import) @import
3030        "#;
3031
3032        Query::new(&tree_sitter_haskell::LANGUAGE.into(), query_string)
3033            .map_err(|e| ParserError::QueryError(e.to_string()))
3034    }
3035
3036    // ==========================================================================
3037    // Elixir language queries
3038    // ==========================================================================
3039
3040    fn elixir_query() -> Result<Query, ParserError> {
3041        let query_string = r#"
3042            (call
3043              target: (identifier) @_type
3044              (#match? @_type "^(def|defp|defmacro|defmacrop)$")
3045              (arguments
3046                (call
3047                  target: (identifier) @name))) @function
3048
3049            (call
3050              target: (identifier) @_type
3051              (#match? @_type "^defmodule$")
3052              (arguments
3053                (alias) @name)) @class
3054        "#;
3055
3056        Query::new(&tree_sitter_elixir::LANGUAGE.into(), query_string)
3057            .map_err(|e| ParserError::QueryError(e.to_string()))
3058    }
3059
3060    fn elixir_super_query() -> Result<Query, ParserError> {
3061        let query_string = r#"
3062            ; Functions (def, defp, defmacro)
3063            (call
3064              target: (identifier) @_type
3065              (#match? @_type "^(def|defp|defmacro|defmacrop)$")
3066              (arguments
3067                (call
3068                  target: (identifier) @name))) @function
3069
3070            ; Modules
3071            (call
3072              target: (identifier) @_type
3073              (#match? @_type "^defmodule$")
3074              (arguments
3075                (alias) @name)) @class
3076
3077            ; Imports (alias, import, use, require)
3078            (call
3079              target: (identifier) @_type
3080              (#match? @_type "^(alias|import|use|require)$")) @import
3081        "#;
3082
3083        Query::new(&tree_sitter_elixir::LANGUAGE.into(), query_string)
3084            .map_err(|e| ParserError::QueryError(e.to_string()))
3085    }
3086
3087    // ==========================================================================
3088    // Clojure language queries
3089    // ==========================================================================
3090
3091    fn clojure_query() -> Result<Query, ParserError> {
3092        let query_string = r#"
3093            (list_lit
3094              (sym_lit) @_type
3095              (#match? @_type "^(defn|defn-|defmacro)$")
3096              (sym_lit) @name) @function
3097
3098            (list_lit
3099              (sym_lit) @_type
3100              (#match? @_type "^(defrecord|deftype|defprotocol)$")
3101              (sym_lit) @name) @class
3102        "#;
3103
3104        Query::new(&tree_sitter_clojure::LANGUAGE.into(), query_string)
3105            .map_err(|e| ParserError::QueryError(e.to_string()))
3106    }
3107
3108    fn clojure_super_query() -> Result<Query, ParserError> {
3109        let query_string = r#"
3110            ; Functions
3111            (list_lit
3112              (sym_lit) @_type
3113              (#match? @_type "^(defn|defn-|defmacro)$")
3114              (sym_lit) @name) @function
3115
3116            ; Records/Types/Protocols
3117            (list_lit
3118              (sym_lit) @_type
3119              (#match? @_type "^(defrecord|deftype|defprotocol)$")
3120              (sym_lit) @name) @class
3121
3122            ; Namespace (imports)
3123            (list_lit
3124              (sym_lit) @_type
3125              (#match? @_type "^(ns|require|use|import)$")) @import
3126        "#;
3127
3128        Query::new(&tree_sitter_clojure::LANGUAGE.into(), query_string)
3129            .map_err(|e| ParserError::QueryError(e.to_string()))
3130    }
3131
3132    // ==========================================================================
3133    // OCaml language queries
3134    // ==========================================================================
3135
3136    fn ocaml_query() -> Result<Query, ParserError> {
3137        let query_string = r#"
3138            (value_definition
3139              (let_binding
3140                pattern: (value_name) @name)) @function
3141
3142            (type_definition
3143              (type_binding
3144                name: (type_constructor) @name)) @struct
3145
3146            (module_definition
3147              (module_binding
3148                name: (module_name) @name)) @class
3149        "#;
3150
3151        Query::new(&tree_sitter_ocaml::LANGUAGE_OCAML.into(), query_string)
3152            .map_err(|e| ParserError::QueryError(e.to_string()))
3153    }
3154
3155    fn ocaml_super_query() -> Result<Query, ParserError> {
3156        let query_string = r#"
3157            ; Functions (let bindings)
3158            (value_definition
3159              (let_binding
3160                pattern: (value_name) @name)) @function
3161
3162            ; Types
3163            (type_definition
3164              (type_binding
3165                name: (type_constructor) @name)) @struct
3166
3167            ; Modules
3168            (module_definition
3169              (module_binding
3170                name: (module_name) @name)) @class
3171
3172            ; Opens (imports)
3173            (open_module) @import
3174        "#;
3175
3176        Query::new(&tree_sitter_ocaml::LANGUAGE_OCAML.into(), query_string)
3177            .map_err(|e| ParserError::QueryError(e.to_string()))
3178    }
3179
3180    // ==========================================================================
3181    // Lua language queries
3182    // ==========================================================================
3183
3184    fn lua_query() -> Result<Query, ParserError> {
3185        let query_string = r#"
3186            (function_declaration
3187              name: (identifier) @name) @function
3188
3189            (function_declaration
3190              name: (dot_index_expression) @name) @method
3191
3192            (function_declaration
3193              name: (method_index_expression) @name) @method
3194        "#;
3195
3196        Query::new(&tree_sitter_lua::LANGUAGE.into(), query_string)
3197            .map_err(|e| ParserError::QueryError(e.to_string()))
3198    }
3199
3200    fn lua_super_query() -> Result<Query, ParserError> {
3201        let query_string = r#"
3202            ; Global functions
3203            (function_declaration
3204              name: (identifier) @name) @function
3205
3206            ; Method-like functions
3207            (function_declaration
3208              name: (dot_index_expression) @name) @method
3209
3210            (function_declaration
3211              name: (method_index_expression) @name) @method
3212
3213            ; Requires (imports)
3214            (function_call
3215              name: (variable
3216                (identifier) @_func)
3217              (#eq? @_func "require")
3218              arguments: (arguments)) @import
3219        "#;
3220
3221        Query::new(&tree_sitter_lua::LANGUAGE.into(), query_string)
3222            .map_err(|e| ParserError::QueryError(e.to_string()))
3223    }
3224
3225    // ==========================================================================
3226    // R language queries
3227    // ==========================================================================
3228
3229    fn r_query() -> Result<Query, ParserError> {
3230        let query_string = r#"
3231            (binary_operator
3232              lhs: (identifier) @name
3233              operator: "<-"
3234              rhs: (function_definition)) @function
3235
3236            (binary_operator
3237              lhs: (identifier) @name
3238              operator: "="
3239              rhs: (function_definition)) @function
3240        "#;
3241
3242        Query::new(&tree_sitter_r::LANGUAGE.into(), query_string)
3243            .map_err(|e| ParserError::QueryError(e.to_string()))
3244    }
3245
3246    fn r_super_query() -> Result<Query, ParserError> {
3247        let query_string = r#"
3248            ; Functions (left assignment)
3249            (binary_operator
3250              lhs: (identifier) @name
3251              operator: "<-"
3252              rhs: (function_definition)) @function
3253
3254            ; Functions (equals assignment)
3255            (binary_operator
3256              lhs: (identifier) @name
3257              operator: "="
3258              rhs: (function_definition)) @function
3259
3260            ; Library/require calls (imports)
3261            (call
3262              function: (identifier) @_func
3263              (#match? @_func "^(library|require|source)$")) @import
3264        "#;
3265
3266        Query::new(&tree_sitter_r::LANGUAGE.into(), query_string)
3267            .map_err(|e| ParserError::QueryError(e.to_string()))
3268    }
3269}
3270
3271impl Default for Parser {
3272    fn default() -> Self {
3273        Self::new()
3274    }
3275}
3276
3277#[cfg(test)]
3278mod tests {
3279    use super::*;
3280
3281    #[test]
3282    fn test_language_from_extension() {
3283        assert_eq!(Language::from_extension("py"), Some(Language::Python));
3284        assert_eq!(Language::from_extension("js"), Some(Language::JavaScript));
3285        assert_eq!(Language::from_extension("ts"), Some(Language::TypeScript));
3286        assert_eq!(Language::from_extension("rs"), Some(Language::Rust));
3287        assert_eq!(Language::from_extension("go"), Some(Language::Go));
3288        assert_eq!(Language::from_extension("java"), Some(Language::Java));
3289        assert_eq!(Language::from_extension("unknown"), None);
3290    }
3291
3292    #[test]
3293    fn test_parse_python() {
3294        let mut parser = Parser::new();
3295        let source = r#"
3296def hello_world():
3297    """This is a docstring"""
3298    print("Hello, World!")
3299
3300class MyClass:
3301    def method(self, x):
3302        return x * 2
3303"#;
3304
3305        let symbols = parser.parse(source, Language::Python).unwrap();
3306        assert!(!symbols.is_empty());
3307
3308        // Find function
3309        let func = symbols
3310            .iter()
3311            .find(|s| s.name == "hello_world" && s.kind == SymbolKind::Function);
3312        assert!(func.is_some());
3313
3314        // Find class
3315        let class = symbols
3316            .iter()
3317            .find(|s| s.name == "MyClass" && s.kind == SymbolKind::Class);
3318        assert!(class.is_some());
3319
3320        // Find method
3321        let method = symbols
3322            .iter()
3323            .find(|s| s.name == "method" && s.kind == SymbolKind::Method);
3324        assert!(method.is_some());
3325    }
3326
3327    #[test]
3328    fn test_parse_rust() {
3329        let mut parser = Parser::new();
3330        let source = r#"
3331/// A test function
3332fn test_function() -> i32 {
3333    42
3334}
3335
3336struct MyStruct {
3337    field: i32,
3338}
3339
3340enum MyEnum {
3341    Variant1,
3342    Variant2,
3343}
3344"#;
3345
3346        let symbols = parser.parse(source, Language::Rust).unwrap();
3347        assert!(!symbols.is_empty());
3348
3349        // Find function
3350        let func = symbols
3351            .iter()
3352            .find(|s| s.name == "test_function" && s.kind == SymbolKind::Function);
3353        assert!(func.is_some());
3354
3355        // Find struct
3356        let struct_sym = symbols
3357            .iter()
3358            .find(|s| s.name == "MyStruct" && s.kind == SymbolKind::Struct);
3359        assert!(struct_sym.is_some());
3360
3361        // Find enum
3362        let enum_sym = symbols
3363            .iter()
3364            .find(|s| s.name == "MyEnum" && s.kind == SymbolKind::Enum);
3365        assert!(enum_sym.is_some());
3366    }
3367
3368    #[test]
3369    fn test_parse_javascript() {
3370        let mut parser = Parser::new();
3371        let source = r#"
3372function testFunction() {
3373    return 42;
3374}
3375
3376class TestClass {
3377    testMethod() {
3378        return "test";
3379    }
3380}
3381
3382const arrowFunc = () => {
3383    console.log("arrow");
3384};
3385"#;
3386
3387        let symbols = parser.parse(source, Language::JavaScript).unwrap();
3388        assert!(!symbols.is_empty());
3389
3390        // Find function
3391        let func = symbols
3392            .iter()
3393            .find(|s| s.name == "testFunction" && s.kind == SymbolKind::Function);
3394        assert!(func.is_some());
3395
3396        // Find class
3397        let class = symbols
3398            .iter()
3399            .find(|s| s.name == "TestClass" && s.kind == SymbolKind::Class);
3400        assert!(class.is_some());
3401    }
3402
3403    #[test]
3404    fn test_parse_typescript() {
3405        let mut parser = Parser::new();
3406        let source = r#"
3407interface TestInterface {
3408    method(): void;
3409}
3410
3411enum TestEnum {
3412    Value1,
3413    Value2
3414}
3415
3416class TestClass implements TestInterface {
3417    method(): void {
3418        console.log("test");
3419    }
3420}
3421"#;
3422
3423        let symbols = parser.parse(source, Language::TypeScript).unwrap();
3424        assert!(!symbols.is_empty());
3425
3426        // Find interface
3427        let interface = symbols
3428            .iter()
3429            .find(|s| s.name == "TestInterface" && s.kind == SymbolKind::Interface);
3430        assert!(interface.is_some());
3431
3432        // Find enum
3433        let enum_sym = symbols
3434            .iter()
3435            .find(|s| s.name == "TestEnum" && s.kind == SymbolKind::Enum);
3436        assert!(enum_sym.is_some());
3437    }
3438
3439    #[test]
3440    fn test_symbol_metadata() {
3441        let mut parser = Parser::new();
3442        let source = r#"
3443def test_func(x, y):
3444    """A test function with params"""
3445    return x + y
3446"#;
3447
3448        let symbols = parser.parse(source, Language::Python).unwrap();
3449        let func = symbols
3450            .iter()
3451            .find(|s| s.name == "test_func")
3452            .expect("Function not found");
3453
3454        assert!(func.start_line > 0);
3455        assert!(func.end_line >= func.start_line);
3456        assert!(func.signature.is_some());
3457        assert!(func.docstring.is_some());
3458    }
3459}