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
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        calls.into_iter().collect()
1090    }
1091
1092    /// Find the body node of a function/method
1093    fn find_body_node<'a>(&self, node: Node<'a>, language: Language) -> Option<Node<'a>> {
1094        match language {
1095            Language::Python => {
1096                // Python: function_definition > block
1097                for child in node.children(&mut node.walk()) {
1098                    if child.kind() == "block" {
1099                        return Some(child);
1100                    }
1101                }
1102            },
1103            Language::Rust => {
1104                // Rust: function_item > block
1105                for child in node.children(&mut node.walk()) {
1106                    if child.kind() == "block" {
1107                        return Some(child);
1108                    }
1109                }
1110            },
1111            Language::JavaScript | Language::TypeScript => {
1112                // JS/TS: various > statement_block
1113                for child in node.children(&mut node.walk()) {
1114                    if child.kind() == "statement_block" {
1115                        return Some(child);
1116                    }
1117                }
1118            },
1119            Language::Go => {
1120                // Go: function_declaration > block
1121                for child in node.children(&mut node.walk()) {
1122                    if child.kind() == "block" {
1123                        return Some(child);
1124                    }
1125                }
1126            },
1127            Language::Java => {
1128                // Java: method_declaration > block
1129                for child in node.children(&mut node.walk()) {
1130                    if child.kind() == "block" {
1131                        return Some(child);
1132                    }
1133                }
1134            },
1135            // C/C++ - compound_statement
1136            Language::C | Language::Cpp => {
1137                for child in node.children(&mut node.walk()) {
1138                    if child.kind() == "compound_statement" {
1139                        return Some(child);
1140                    }
1141                }
1142            },
1143            // Languages with block bodies (similar to Java)
1144            Language::CSharp
1145            | Language::Php
1146            | Language::Kotlin
1147            | Language::Swift
1148            | Language::Scala => {
1149                for child in node.children(&mut node.walk()) {
1150                    let kind = child.kind();
1151                    if kind == "block" || kind == "compound_statement" || kind == "function_body" {
1152                        return Some(child);
1153                    }
1154                }
1155            },
1156            // Ruby - uses do/end blocks
1157            Language::Ruby => {
1158                for child in node.children(&mut node.walk()) {
1159                    if child.kind() == "body_statement" || child.kind() == "do_block" {
1160                        return Some(child);
1161                    }
1162                }
1163            },
1164            // Bash - compound_statement
1165            Language::Bash => {
1166                for child in node.children(&mut node.walk()) {
1167                    if child.kind() == "compound_statement" {
1168                        return Some(child);
1169                    }
1170                }
1171            },
1172            // Functional languages - typically expression-based
1173            Language::Haskell
1174            | Language::Elixir
1175            | Language::Clojure
1176            | Language::OCaml
1177            | Language::FSharp
1178            | Language::R => {
1179                // Return the node itself as expressions are the body
1180                return Some(node);
1181            },
1182            // Lua - block body
1183            Language::Lua => {
1184                for child in node.children(&mut node.walk()) {
1185                    if child.kind() == "block" {
1186                        return Some(child);
1187                    }
1188                }
1189            },
1190        }
1191        None
1192    }
1193
1194    /// Recursively collect function calls from a node
1195    #[allow(clippy::only_used_in_recursion)]
1196    fn collect_calls_recursive(
1197        &self,
1198        node: Node<'_>,
1199        source_code: &str,
1200        language: Language,
1201        calls: &mut HashSet<String>,
1202    ) {
1203        let kind = node.kind();
1204
1205        // Check if this node is a call expression
1206        let call_name = match language {
1207            Language::Python => {
1208                if kind == "call" {
1209                    // Python: call > function (identifier or attribute)
1210                    node.child_by_field_name("function").and_then(|f| {
1211                        if f.kind() == "identifier" {
1212                            f.utf8_text(source_code.as_bytes()).ok().map(String::from)
1213                        } else if f.kind() == "attribute" {
1214                            // Get the attribute name (method name)
1215                            f.child_by_field_name("attribute")
1216                                .and_then(|a| a.utf8_text(source_code.as_bytes()).ok())
1217                                .map(String::from)
1218                        } else {
1219                            None
1220                        }
1221                    })
1222                } else {
1223                    None
1224                }
1225            },
1226            Language::Rust => {
1227                if kind == "call_expression" {
1228                    // Rust: call_expression > function
1229                    node.child_by_field_name("function").and_then(|f| {
1230                        if f.kind() == "identifier" {
1231                            f.utf8_text(source_code.as_bytes()).ok().map(String::from)
1232                        } else if f.kind() == "field_expression" {
1233                            // Method call: get the field name
1234                            f.child_by_field_name("field")
1235                                .and_then(|a| a.utf8_text(source_code.as_bytes()).ok())
1236                                .map(String::from)
1237                        } else if f.kind() == "scoped_identifier" {
1238                            // Path call like Module::function
1239                            f.utf8_text(source_code.as_bytes()).ok().map(String::from)
1240                        } else {
1241                            None
1242                        }
1243                    })
1244                } else if kind == "macro_invocation" {
1245                    // Rust macros
1246                    node.child_by_field_name("macro")
1247                        .and_then(|m| m.utf8_text(source_code.as_bytes()).ok())
1248                        .map(|s| format!("{}!", s))
1249                } else {
1250                    None
1251                }
1252            },
1253            Language::JavaScript | Language::TypeScript => {
1254                if kind == "call_expression" {
1255                    // JS/TS: call_expression > function
1256                    node.child_by_field_name("function").and_then(|f| {
1257                        if f.kind() == "identifier" {
1258                            f.utf8_text(source_code.as_bytes()).ok().map(String::from)
1259                        } else if f.kind() == "member_expression" {
1260                            // Method call: get the property
1261                            f.child_by_field_name("property")
1262                                .and_then(|p| p.utf8_text(source_code.as_bytes()).ok())
1263                                .map(String::from)
1264                        } else {
1265                            None
1266                        }
1267                    })
1268                } else {
1269                    None
1270                }
1271            },
1272            Language::Go => {
1273                if kind == "call_expression" {
1274                    // Go: call_expression > function
1275                    node.child_by_field_name("function").and_then(|f| {
1276                        if f.kind() == "identifier" {
1277                            f.utf8_text(source_code.as_bytes()).ok().map(String::from)
1278                        } else if f.kind() == "selector_expression" {
1279                            // Method call: get the field
1280                            f.child_by_field_name("field")
1281                                .and_then(|a| a.utf8_text(source_code.as_bytes()).ok())
1282                                .map(String::from)
1283                        } else {
1284                            None
1285                        }
1286                    })
1287                } else {
1288                    None
1289                }
1290            },
1291            Language::Java => {
1292                if kind == "method_invocation" {
1293                    // Java: method_invocation > name
1294                    node.child_by_field_name("name")
1295                        .and_then(|n| n.utf8_text(source_code.as_bytes()).ok())
1296                        .map(String::from)
1297                } else {
1298                    None
1299                }
1300            },
1301            // C/C++ - call_expression
1302            Language::C | Language::Cpp => {
1303                if kind == "call_expression" {
1304                    node.child_by_field_name("function").and_then(|f| {
1305                        if f.kind() == "identifier" {
1306                            f.utf8_text(source_code.as_bytes()).ok().map(String::from)
1307                        } else if f.kind() == "field_expression" {
1308                            f.child_by_field_name("field")
1309                                .and_then(|a| a.utf8_text(source_code.as_bytes()).ok())
1310                                .map(String::from)
1311                        } else {
1312                            None
1313                        }
1314                    })
1315                } else {
1316                    None
1317                }
1318            },
1319            // C#/Kotlin/Swift/Scala - invocation_expression or call_expression
1320            Language::CSharp | Language::Kotlin | Language::Swift | Language::Scala => {
1321                if kind == "invocation_expression"
1322                    || kind == "call_expression"
1323                    || kind == "method_invocation"
1324                {
1325                    node.child_by_field_name("function")
1326                        .or_else(|| node.child_by_field_name("name"))
1327                        .and_then(|f| {
1328                            if f.kind() == "identifier" || f.kind() == "simple_identifier" {
1329                                f.utf8_text(source_code.as_bytes()).ok().map(String::from)
1330                            } else if f.kind() == "member_access_expression"
1331                                || f.kind() == "member_expression"
1332                            {
1333                                f.child_by_field_name("name")
1334                                    .and_then(|n| n.utf8_text(source_code.as_bytes()).ok())
1335                                    .map(String::from)
1336                            } else {
1337                                None
1338                            }
1339                        })
1340                } else {
1341                    None
1342                }
1343            },
1344            // Ruby - method_call or call
1345            Language::Ruby => {
1346                if kind == "call" || kind == "method_call" {
1347                    node.child_by_field_name("method")
1348                        .and_then(|m| m.utf8_text(source_code.as_bytes()).ok())
1349                        .map(String::from)
1350                } else {
1351                    None
1352                }
1353            },
1354            // PHP - function_call_expression
1355            Language::Php => {
1356                if kind == "function_call_expression" || kind == "method_call_expression" {
1357                    node.child_by_field_name("function")
1358                        .or_else(|| node.child_by_field_name("name"))
1359                        .and_then(|f| f.utf8_text(source_code.as_bytes()).ok())
1360                        .map(String::from)
1361                } else {
1362                    None
1363                }
1364            },
1365            // Bash - command
1366            Language::Bash => {
1367                if kind == "command" {
1368                    node.child_by_field_name("name")
1369                        .and_then(|n| n.utf8_text(source_code.as_bytes()).ok())
1370                        .map(String::from)
1371                } else {
1372                    None
1373                }
1374            },
1375            // Functional languages - application or call nodes
1376            Language::Haskell
1377            | Language::Elixir
1378            | Language::Clojure
1379            | Language::OCaml
1380            | Language::FSharp
1381            | Language::Lua
1382            | Language::R => {
1383                if kind == "application" || kind == "call" || kind == "function_call" {
1384                    // Get first child as function name
1385                    node.child(0).and_then(|c| {
1386                        if c.kind() == "identifier" || c.kind() == "variable" {
1387                            c.utf8_text(source_code.as_bytes()).ok().map(String::from)
1388                        } else {
1389                            None
1390                        }
1391                    })
1392                } else {
1393                    None
1394                }
1395            },
1396        };
1397
1398        if let Some(name) = call_name {
1399            // Filter out common built-ins and very short names
1400            if name.len() > 1 && !Self::is_builtin(&name, language) {
1401                calls.insert(name);
1402            }
1403        }
1404
1405        // Recurse into children
1406        for child in node.children(&mut node.walk()) {
1407            self.collect_calls_recursive(child, source_code, language, calls);
1408        }
1409    }
1410
1411    /// Check if a function name is a common built-in (to filter noise)
1412    fn is_builtin(name: &str, language: Language) -> bool {
1413        match language {
1414            Language::Python => {
1415                matches!(
1416                    name,
1417                    "print"
1418                        | "len"
1419                        | "range"
1420                        | "str"
1421                        | "int"
1422                        | "float"
1423                        | "list"
1424                        | "dict"
1425                        | "set"
1426                        | "tuple"
1427                        | "bool"
1428                        | "type"
1429                        | "isinstance"
1430                        | "hasattr"
1431                        | "getattr"
1432                        | "setattr"
1433                        | "super"
1434                        | "iter"
1435                        | "next"
1436                        | "open"
1437                        | "input"
1438                        | "format"
1439                        | "enumerate"
1440                        | "zip"
1441                        | "map"
1442                        | "filter"
1443                        | "sorted"
1444                        | "reversed"
1445                        | "sum"
1446                        | "min"
1447                        | "max"
1448                        | "abs"
1449                        | "round"
1450                        | "ord"
1451                        | "chr"
1452                        | "hex"
1453                        | "bin"
1454                        | "oct"
1455                )
1456            },
1457            Language::JavaScript | Language::TypeScript => {
1458                matches!(
1459                    name,
1460                    "console"
1461                        | "log"
1462                        | "error"
1463                        | "warn"
1464                        | "parseInt"
1465                        | "parseFloat"
1466                        | "setTimeout"
1467                        | "setInterval"
1468                        | "clearTimeout"
1469                        | "clearInterval"
1470                        | "JSON"
1471                        | "stringify"
1472                        | "parse"
1473                        | "toString"
1474                        | "valueOf"
1475                        | "push"
1476                        | "pop"
1477                        | "shift"
1478                        | "unshift"
1479                        | "slice"
1480                        | "splice"
1481                        | "map"
1482                        | "filter"
1483                        | "reduce"
1484                        | "forEach"
1485                        | "find"
1486                        | "findIndex"
1487                        | "includes"
1488                        | "indexOf"
1489                        | "join"
1490                        | "split"
1491                        | "replace"
1492                )
1493            },
1494            Language::Rust => {
1495                matches!(
1496                    name,
1497                    "println!"
1498                        | "print!"
1499                        | "eprintln!"
1500                        | "eprint!"
1501                        | "format!"
1502                        | "vec!"
1503                        | "panic!"
1504                        | "assert!"
1505                        | "assert_eq!"
1506                        | "assert_ne!"
1507                        | "debug!"
1508                        | "info!"
1509                        | "warn!"
1510                        | "error!"
1511                        | "trace!"
1512                        | "unwrap"
1513                        | "expect"
1514                        | "ok"
1515                        | "err"
1516                        | "some"
1517                        | "none"
1518                        | "clone"
1519                        | "to_string"
1520                        | "into"
1521                        | "from"
1522                        | "default"
1523                        | "iter"
1524                        | "into_iter"
1525                        | "collect"
1526                        | "map"
1527                        | "filter"
1528                )
1529            },
1530            Language::Go => {
1531                matches!(
1532                    name,
1533                    "fmt"
1534                        | "Println"
1535                        | "Printf"
1536                        | "Sprintf"
1537                        | "Errorf"
1538                        | "make"
1539                        | "new"
1540                        | "len"
1541                        | "cap"
1542                        | "append"
1543                        | "copy"
1544                        | "delete"
1545                        | "close"
1546                        | "panic"
1547                        | "recover"
1548                        | "print"
1549                )
1550            },
1551            Language::Java => {
1552                matches!(
1553                    name,
1554                    "println"
1555                        | "print"
1556                        | "printf"
1557                        | "toString"
1558                        | "equals"
1559                        | "hashCode"
1560                        | "getClass"
1561                        | "clone"
1562                        | "notify"
1563                        | "wait"
1564                        | "get"
1565                        | "set"
1566                        | "add"
1567                        | "remove"
1568                        | "size"
1569                        | "isEmpty"
1570                        | "contains"
1571                        | "iterator"
1572                        | "valueOf"
1573                        | "parseInt"
1574                )
1575            },
1576            Language::C | Language::Cpp => {
1577                matches!(
1578                    name,
1579                    "printf"
1580                        | "scanf"
1581                        | "malloc"
1582                        | "free"
1583                        | "memcpy"
1584                        | "memset"
1585                        | "strlen"
1586                        | "strcpy"
1587                        | "strcmp"
1588                        | "strcat"
1589                        | "sizeof"
1590                        | "cout"
1591                        | "cin"
1592                        | "endl"
1593                        | "cerr"
1594                        | "clog"
1595                )
1596            },
1597            Language::CSharp => {
1598                matches!(
1599                    name,
1600                    "WriteLine"
1601                        | "Write"
1602                        | "ReadLine"
1603                        | "ToString"
1604                        | "Equals"
1605                        | "GetHashCode"
1606                        | "GetType"
1607                        | "Add"
1608                        | "Remove"
1609                        | "Contains"
1610                        | "Count"
1611                        | "Clear"
1612                        | "ToList"
1613                        | "ToArray"
1614                )
1615            },
1616            Language::Ruby => {
1617                matches!(
1618                    name,
1619                    "puts"
1620                        | "print"
1621                        | "p"
1622                        | "gets"
1623                        | "each"
1624                        | "map"
1625                        | "select"
1626                        | "reject"
1627                        | "reduce"
1628                        | "inject"
1629                        | "find"
1630                        | "any?"
1631                        | "all?"
1632                        | "include?"
1633                        | "empty?"
1634                        | "nil?"
1635                        | "length"
1636                        | "size"
1637                )
1638            },
1639            Language::Php => {
1640                matches!(
1641                    name,
1642                    "echo"
1643                        | "print"
1644                        | "var_dump"
1645                        | "print_r"
1646                        | "isset"
1647                        | "empty"
1648                        | "array"
1649                        | "count"
1650                        | "strlen"
1651                        | "strpos"
1652                        | "substr"
1653                        | "explode"
1654                        | "implode"
1655                        | "json_encode"
1656                        | "json_decode"
1657                )
1658            },
1659            Language::Kotlin => {
1660                matches!(
1661                    name,
1662                    "println"
1663                        | "print"
1664                        | "readLine"
1665                        | "toString"
1666                        | "equals"
1667                        | "hashCode"
1668                        | "map"
1669                        | "filter"
1670                        | "forEach"
1671                        | "let"
1672                        | "also"
1673                        | "apply"
1674                        | "run"
1675                        | "with"
1676                        | "listOf"
1677                        | "mapOf"
1678                        | "setOf"
1679                )
1680            },
1681            Language::Swift => {
1682                matches!(
1683                    name,
1684                    "print"
1685                        | "debugPrint"
1686                        | "dump"
1687                        | "map"
1688                        | "filter"
1689                        | "reduce"
1690                        | "forEach"
1691                        | "contains"
1692                        | "count"
1693                        | "isEmpty"
1694                        | "append"
1695                )
1696            },
1697            Language::Scala => {
1698                matches!(
1699                    name,
1700                    "println"
1701                        | "print"
1702                        | "map"
1703                        | "filter"
1704                        | "flatMap"
1705                        | "foreach"
1706                        | "reduce"
1707                        | "fold"
1708                        | "foldLeft"
1709                        | "foldRight"
1710                        | "collect"
1711                )
1712            },
1713            // Languages where builtins are less common or harder to filter
1714            Language::Bash
1715            | Language::Haskell
1716            | Language::Elixir
1717            | Language::Clojure
1718            | Language::OCaml
1719            | Language::FSharp
1720            | Language::Lua
1721            | Language::R => false,
1722        }
1723    }
1724
1725    /// Clean JSDoc comment
1726    fn clean_jsdoc(&self, text: &str) -> String {
1727        text.lines()
1728            .map(|line| {
1729                line.trim()
1730                    .trim_start_matches("/**")
1731                    .trim_start_matches("/*")
1732                    .trim_start_matches('*')
1733                    .trim_end_matches("*/")
1734                    .trim()
1735            })
1736            .filter(|line| !line.is_empty())
1737            .collect::<Vec<_>>()
1738            .join(" ")
1739    }
1740
1741    /// Clean JavaDoc comment
1742    fn clean_javadoc(&self, text: &str) -> String {
1743        self.clean_jsdoc(text) // Same format as JSDoc
1744    }
1745
1746    /// Extract class inheritance (extends) and interface implementations (implements)
1747    /// Returns (base_class, implemented_interfaces)
1748    fn extract_inheritance(
1749        &self,
1750        node: Node<'_>,
1751        source_code: &str,
1752        language: Language,
1753    ) -> (Option<String>, Vec<String>) {
1754        let mut extends = None;
1755        let mut implements = Vec::new();
1756
1757        match language {
1758            Language::Python => {
1759                // Python: class Foo(Bar, Baz): - first is base class, rest could be mixins
1760                if node.kind() == "class_definition" {
1761                    if let Some(args) = node.child_by_field_name("superclasses") {
1762                        let mut first = true;
1763                        for child in args.children(&mut args.walk()) {
1764                            if child.kind() == "identifier" || child.kind() == "attribute" {
1765                                if let Ok(name) = child.utf8_text(source_code.as_bytes()) {
1766                                    if first {
1767                                        extends = Some(name.to_owned());
1768                                        first = false;
1769                                    } else {
1770                                        implements.push(name.to_owned());
1771                                    }
1772                                }
1773                            }
1774                        }
1775                    }
1776                }
1777            },
1778            Language::JavaScript | Language::TypeScript => {
1779                // JS/TS: class Foo extends Bar implements IBaz, IQux
1780                if node.kind() == "class_declaration" {
1781                    // Look for heritage clause
1782                    for child in node.children(&mut node.walk()) {
1783                        if child.kind() == "class_heritage" {
1784                            for heritage in child.children(&mut child.walk()) {
1785                                if heritage.kind() == "extends_clause" {
1786                                    // Get the extended class
1787                                    for ext_child in heritage.children(&mut heritage.walk()) {
1788                                        if ext_child.kind() == "identifier"
1789                                            || ext_child.kind() == "type_identifier"
1790                                        {
1791                                            if let Ok(name) =
1792                                                ext_child.utf8_text(source_code.as_bytes())
1793                                            {
1794                                                extends = Some(name.to_owned());
1795                                            }
1796                                        }
1797                                    }
1798                                } else if heritage.kind() == "implements_clause" {
1799                                    // Get implemented interfaces
1800                                    for impl_child in heritage.children(&mut heritage.walk()) {
1801                                        if impl_child.kind() == "type_identifier"
1802                                            || impl_child.kind() == "identifier"
1803                                        {
1804                                            if let Ok(name) =
1805                                                impl_child.utf8_text(source_code.as_bytes())
1806                                            {
1807                                                implements.push(name.to_owned());
1808                                            }
1809                                        }
1810                                    }
1811                                }
1812                            }
1813                        }
1814                    }
1815                }
1816            },
1817            Language::Java => {
1818                // Java: class Foo extends Bar implements IBaz, IQux
1819                if node.kind() == "class_declaration" {
1820                    if let Some(superclass) = node.child_by_field_name("superclass") {
1821                        if let Ok(name) = superclass.utf8_text(source_code.as_bytes()) {
1822                            extends = Some(name.trim_start_matches("extends ").trim().to_owned());
1823                        }
1824                    }
1825                    if let Some(interfaces) = node.child_by_field_name("interfaces") {
1826                        for child in interfaces.children(&mut interfaces.walk()) {
1827                            if child.kind() == "type_identifier" {
1828                                if let Ok(name) = child.utf8_text(source_code.as_bytes()) {
1829                                    implements.push(name.to_owned());
1830                                }
1831                            }
1832                        }
1833                    }
1834                }
1835            },
1836            Language::Rust => {
1837                // Rust: impl Trait for Struct - captured differently
1838                // For structs, we don't have traditional inheritance
1839                // We could look at impl blocks separately if needed
1840            },
1841            Language::Go => {
1842                // Go: struct embedding (composition, not inheritance)
1843                // Go uses implicit interface implementation
1844                if node.kind() == "type_declaration" {
1845                    for child in node.children(&mut node.walk()) {
1846                        if child.kind() == "type_spec" {
1847                            // Look for embedded types in struct
1848                            for spec_child in child.children(&mut child.walk()) {
1849                                if spec_child.kind() == "struct_type" {
1850                                    for field in spec_child.children(&mut spec_child.walk()) {
1851                                        if field.kind() == "field_declaration" {
1852                                            // Embedded field has no name, just type
1853                                            let has_name =
1854                                                field.child_by_field_name("name").is_some();
1855                                            if !has_name {
1856                                                if let Some(type_node) =
1857                                                    field.child_by_field_name("type")
1858                                                {
1859                                                    if let Ok(name) =
1860                                                        type_node.utf8_text(source_code.as_bytes())
1861                                                    {
1862                                                        implements.push(name.to_owned());
1863                                                    }
1864                                                }
1865                                            }
1866                                        }
1867                                    }
1868                                }
1869                            }
1870                        }
1871                    }
1872                }
1873            },
1874            Language::Cpp => {
1875                // C++: class Foo : public Bar, public IBaz
1876                if node.kind() == "class_specifier" {
1877                    for child in node.children(&mut node.walk()) {
1878                        if child.kind() == "base_class_clause" {
1879                            let mut first = true;
1880                            for base in child.children(&mut child.walk()) {
1881                                if base.kind() == "type_identifier" {
1882                                    if let Ok(name) = base.utf8_text(source_code.as_bytes()) {
1883                                        if first {
1884                                            extends = Some(name.to_owned());
1885                                            first = false;
1886                                        } else {
1887                                            implements.push(name.to_owned());
1888                                        }
1889                                    }
1890                                }
1891                            }
1892                        }
1893                    }
1894                }
1895            },
1896            Language::CSharp => {
1897                // C#: class Foo : Bar, IFoo, IBar
1898                if node.kind() == "class_declaration" {
1899                    if let Some(base_list) = node.child_by_field_name("bases") {
1900                        let mut first = true;
1901                        for child in base_list.children(&mut base_list.walk()) {
1902                            if child.kind() == "identifier" || child.kind() == "generic_name" {
1903                                if let Ok(name) = child.utf8_text(source_code.as_bytes()) {
1904                                    // Convention: interfaces start with 'I'
1905                                    if first && !name.starts_with('I') {
1906                                        extends = Some(name.to_owned());
1907                                        first = false;
1908                                    } else {
1909                                        implements.push(name.to_owned());
1910                                    }
1911                                }
1912                            }
1913                        }
1914                    }
1915                }
1916            },
1917            Language::Ruby => {
1918                // Ruby: class Foo < Bar
1919                if node.kind() == "class" {
1920                    if let Some(superclass) = node.child_by_field_name("superclass") {
1921                        if let Ok(name) = superclass.utf8_text(source_code.as_bytes()) {
1922                            extends = Some(name.to_owned());
1923                        }
1924                    }
1925                }
1926            },
1927            Language::Kotlin => {
1928                // Kotlin: class Foo : Bar(), IBaz, IQux
1929                if node.kind() == "class_declaration" {
1930                    for child in node.children(&mut node.walk()) {
1931                        if child.kind() == "delegation_specifiers" {
1932                            let mut first = true;
1933                            for spec in child.children(&mut child.walk()) {
1934                                if spec.kind() == "delegation_specifier" {
1935                                    if let Ok(name) = spec.utf8_text(source_code.as_bytes()) {
1936                                        // Remove constructor call parentheses
1937                                        let clean_name =
1938                                            name.split('(').next().unwrap_or(name).trim();
1939                                        if first {
1940                                            extends = Some(clean_name.to_owned());
1941                                            first = false;
1942                                        } else {
1943                                            implements.push(clean_name.to_owned());
1944                                        }
1945                                    }
1946                                }
1947                            }
1948                        }
1949                    }
1950                }
1951            },
1952            Language::Swift => {
1953                // Swift: class Foo: Bar, Protocol1, Protocol2
1954                if node.kind() == "class_declaration" {
1955                    for child in node.children(&mut node.walk()) {
1956                        if child.kind() == "type_inheritance_clause" {
1957                            let mut first = true;
1958                            for type_child in child.children(&mut child.walk()) {
1959                                if type_child.kind() == "type_identifier" {
1960                                    if let Ok(name) = type_child.utf8_text(source_code.as_bytes()) {
1961                                        if first {
1962                                            extends = Some(name.to_owned());
1963                                            first = false;
1964                                        } else {
1965                                            implements.push(name.to_owned());
1966                                        }
1967                                    }
1968                                }
1969                            }
1970                        }
1971                    }
1972                }
1973            },
1974            Language::Scala => {
1975                // Scala: class Foo extends Bar with Trait1 with Trait2
1976                if node.kind() == "class_definition" {
1977                    for child in node.children(&mut node.walk()) {
1978                        if child.kind() == "extends_clause" {
1979                            if let Ok(name) = child.utf8_text(source_code.as_bytes()) {
1980                                // Parse "extends Bar with Trait1 with Trait2"
1981                                let text = name.trim_start_matches("extends").trim();
1982                                let parts: Vec<&str> = text.split(" with ").collect();
1983                                if let Some(base) = parts.first() {
1984                                    extends = Some(base.trim().to_owned());
1985                                }
1986                                for trait_name in parts.iter().skip(1) {
1987                                    implements.push(trait_name.trim().to_owned());
1988                                }
1989                            }
1990                        }
1991                    }
1992                }
1993            },
1994            // Languages without traditional class inheritance
1995            Language::C
1996            | Language::Bash
1997            | Language::Php
1998            | Language::Haskell
1999            | Language::Elixir
2000            | Language::Clojure
2001            | Language::OCaml
2002            | Language::FSharp
2003            | Language::Lua
2004            | Language::R => {},
2005        }
2006
2007        (extends, implements)
2008    }
2009
2010    // Language-specific parser initializers
2011
2012    fn init_python_parser() -> Result<TSParser, ParserError> {
2013        let mut parser = TSParser::new();
2014        parser
2015            .set_language(&tree_sitter_python::LANGUAGE.into())
2016            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2017        Ok(parser)
2018    }
2019
2020    fn init_javascript_parser() -> Result<TSParser, ParserError> {
2021        let mut parser = TSParser::new();
2022        parser
2023            .set_language(&tree_sitter_javascript::LANGUAGE.into())
2024            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2025        Ok(parser)
2026    }
2027
2028    fn init_typescript_parser() -> Result<TSParser, ParserError> {
2029        let mut parser = TSParser::new();
2030        parser
2031            .set_language(&tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into())
2032            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2033        Ok(parser)
2034    }
2035
2036    fn init_rust_parser() -> Result<TSParser, ParserError> {
2037        let mut parser = TSParser::new();
2038        parser
2039            .set_language(&tree_sitter_rust::LANGUAGE.into())
2040            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2041        Ok(parser)
2042    }
2043
2044    fn init_go_parser() -> Result<TSParser, ParserError> {
2045        let mut parser = TSParser::new();
2046        parser
2047            .set_language(&tree_sitter_go::LANGUAGE.into())
2048            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2049        Ok(parser)
2050    }
2051
2052    fn init_java_parser() -> Result<TSParser, ParserError> {
2053        let mut parser = TSParser::new();
2054        parser
2055            .set_language(&tree_sitter_java::LANGUAGE.into())
2056            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2057        Ok(parser)
2058    }
2059
2060    fn init_c_parser() -> Result<TSParser, ParserError> {
2061        let mut parser = TSParser::new();
2062        parser
2063            .set_language(&tree_sitter_c::LANGUAGE.into())
2064            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2065        Ok(parser)
2066    }
2067
2068    fn init_cpp_parser() -> Result<TSParser, ParserError> {
2069        let mut parser = TSParser::new();
2070        parser
2071            .set_language(&tree_sitter_cpp::LANGUAGE.into())
2072            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2073        Ok(parser)
2074    }
2075
2076    fn init_csharp_parser() -> Result<TSParser, ParserError> {
2077        let mut parser = TSParser::new();
2078        parser
2079            .set_language(&tree_sitter_c_sharp::LANGUAGE.into())
2080            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2081        Ok(parser)
2082    }
2083
2084    fn init_ruby_parser() -> Result<TSParser, ParserError> {
2085        let mut parser = TSParser::new();
2086        parser
2087            .set_language(&tree_sitter_ruby::LANGUAGE.into())
2088            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2089        Ok(parser)
2090    }
2091
2092    fn init_bash_parser() -> Result<TSParser, ParserError> {
2093        let mut parser = TSParser::new();
2094        parser
2095            .set_language(&tree_sitter_bash::LANGUAGE.into())
2096            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2097        Ok(parser)
2098    }
2099
2100    fn init_php_parser() -> Result<TSParser, ParserError> {
2101        let mut parser = TSParser::new();
2102        parser
2103            .set_language(&tree_sitter_php::LANGUAGE_PHP.into())
2104            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2105        Ok(parser)
2106    }
2107
2108    fn init_kotlin_parser() -> Result<TSParser, ParserError> {
2109        let mut parser = TSParser::new();
2110        parser
2111            .set_language(&tree_sitter_kotlin_ng::LANGUAGE.into())
2112            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2113        Ok(parser)
2114    }
2115
2116    fn init_swift_parser() -> Result<TSParser, ParserError> {
2117        let mut parser = TSParser::new();
2118        parser
2119            .set_language(&tree_sitter_swift::LANGUAGE.into())
2120            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2121        Ok(parser)
2122    }
2123
2124    fn init_scala_parser() -> Result<TSParser, ParserError> {
2125        let mut parser = TSParser::new();
2126        parser
2127            .set_language(&tree_sitter_scala::LANGUAGE.into())
2128            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2129        Ok(parser)
2130    }
2131
2132    fn init_haskell_parser() -> Result<TSParser, ParserError> {
2133        let mut parser = TSParser::new();
2134        parser
2135            .set_language(&tree_sitter_haskell::LANGUAGE.into())
2136            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2137        Ok(parser)
2138    }
2139
2140    fn init_elixir_parser() -> Result<TSParser, ParserError> {
2141        let mut parser = TSParser::new();
2142        parser
2143            .set_language(&tree_sitter_elixir::LANGUAGE.into())
2144            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2145        Ok(parser)
2146    }
2147
2148    fn init_clojure_parser() -> Result<TSParser, ParserError> {
2149        let mut parser = TSParser::new();
2150        parser
2151            .set_language(&tree_sitter_clojure::LANGUAGE.into())
2152            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2153        Ok(parser)
2154    }
2155
2156    fn init_ocaml_parser() -> Result<TSParser, ParserError> {
2157        let mut parser = TSParser::new();
2158        parser
2159            .set_language(&tree_sitter_ocaml::LANGUAGE_OCAML.into())
2160            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2161        Ok(parser)
2162    }
2163
2164    fn init_lua_parser() -> Result<TSParser, ParserError> {
2165        let mut parser = TSParser::new();
2166        parser
2167            .set_language(&tree_sitter_lua::LANGUAGE.into())
2168            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2169        Ok(parser)
2170    }
2171
2172    fn init_r_parser() -> Result<TSParser, ParserError> {
2173        let mut parser = TSParser::new();
2174        parser
2175            .set_language(&tree_sitter_r::LANGUAGE.into())
2176            .map_err(|e| ParserError::ParseError(e.to_string()))?;
2177        Ok(parser)
2178    }
2179
2180    // Language-specific queries
2181
2182    fn python_query() -> Result<Query, ParserError> {
2183        let query_string = r#"
2184            (function_definition
2185              name: (identifier) @name) @function
2186
2187            (class_definition
2188              name: (identifier) @name) @class
2189
2190            (class_definition
2191              body: (block
2192                (function_definition
2193                  name: (identifier) @name))) @method
2194        "#;
2195
2196        Query::new(&tree_sitter_python::LANGUAGE.into(), query_string)
2197            .map_err(|e| ParserError::QueryError(e.to_string()))
2198    }
2199
2200    fn javascript_query() -> Result<Query, ParserError> {
2201        let query_string = r#"
2202            (function_declaration
2203              name: (_) @name) @function
2204
2205            (class_declaration
2206              name: (_) @name) @class
2207
2208            (method_definition
2209              name: (property_identifier) @name) @method
2210
2211            (arrow_function) @function
2212
2213            (function_expression) @function
2214        "#;
2215
2216        Query::new(&tree_sitter_javascript::LANGUAGE.into(), query_string)
2217            .map_err(|e| ParserError::QueryError(e.to_string()))
2218    }
2219
2220    fn typescript_query() -> Result<Query, ParserError> {
2221        let query_string = r#"
2222            (function_declaration
2223              name: (identifier) @name) @function
2224
2225            (class_declaration
2226              name: (type_identifier) @name) @class
2227
2228            (interface_declaration
2229              name: (type_identifier) @name) @interface
2230
2231            (method_definition
2232              name: (property_identifier) @name) @method
2233
2234            (enum_declaration
2235              name: (identifier) @name) @enum
2236        "#;
2237
2238        Query::new(&tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(), query_string)
2239            .map_err(|e| ParserError::QueryError(e.to_string()))
2240    }
2241
2242    fn rust_query() -> Result<Query, ParserError> {
2243        let query_string = r#"
2244            (function_item
2245              name: (identifier) @name) @function
2246
2247            (struct_item
2248              name: (type_identifier) @name) @struct
2249
2250            (enum_item
2251              name: (type_identifier) @name) @enum
2252
2253            (trait_item
2254              name: (type_identifier) @name) @trait
2255        "#;
2256
2257        Query::new(&tree_sitter_rust::LANGUAGE.into(), query_string)
2258            .map_err(|e| ParserError::QueryError(e.to_string()))
2259    }
2260
2261    fn go_query() -> Result<Query, ParserError> {
2262        let query_string = r#"
2263            (function_declaration
2264              name: (identifier) @name) @function
2265
2266            (method_declaration
2267              name: (field_identifier) @name) @method
2268
2269            (type_declaration
2270              (type_spec
2271                name: (type_identifier) @name
2272                type: (struct_type))) @struct
2273
2274            (type_declaration
2275              (type_spec
2276                name: (type_identifier) @name
2277                type: (interface_type))) @interface
2278        "#;
2279
2280        Query::new(&tree_sitter_go::LANGUAGE.into(), query_string)
2281            .map_err(|e| ParserError::QueryError(e.to_string()))
2282    }
2283
2284    fn java_query() -> Result<Query, ParserError> {
2285        let query_string = r#"
2286            (method_declaration
2287              name: (identifier) @name) @method
2288
2289            (class_declaration
2290              name: (identifier) @name) @class
2291
2292            (interface_declaration
2293              name: (identifier) @name) @interface
2294
2295            (enum_declaration
2296              name: (identifier) @name) @enum
2297        "#;
2298
2299        Query::new(&tree_sitter_java::LANGUAGE.into(), query_string)
2300            .map_err(|e| ParserError::QueryError(e.to_string()))
2301    }
2302
2303    // ==========================================================================
2304    // Super-queries: combine symbols + imports in a single pass for performance
2305    // ==========================================================================
2306
2307    fn python_super_query() -> Result<Query, ParserError> {
2308        let query_string = r#"
2309            ; Functions
2310            (function_definition
2311              name: (identifier) @name) @function
2312
2313            ; Classes
2314            (class_definition
2315              name: (identifier) @name) @class
2316
2317            ; Methods inside classes
2318            (class_definition
2319              body: (block
2320                (function_definition
2321                  name: (identifier) @name))) @method
2322
2323            ; Imports
2324            (import_statement) @import
2325            (import_from_statement) @import
2326        "#;
2327
2328        Query::new(&tree_sitter_python::LANGUAGE.into(), query_string)
2329            .map_err(|e| ParserError::QueryError(e.to_string()))
2330    }
2331
2332    fn javascript_super_query() -> Result<Query, ParserError> {
2333        let query_string = r#"
2334            ; Functions
2335            (function_declaration
2336              name: (identifier) @name) @function
2337
2338            ; Classes
2339            (class_declaration
2340              name: (identifier) @name) @class
2341
2342            ; Methods
2343            (method_definition
2344              name: (property_identifier) @name) @method
2345
2346            ; Arrow functions (named via variable)
2347            (lexical_declaration
2348              (variable_declarator
2349                name: (identifier) @name
2350                value: (arrow_function))) @function
2351
2352            ; Imports
2353            (import_statement) @import
2354        "#;
2355
2356        Query::new(&tree_sitter_javascript::LANGUAGE.into(), query_string)
2357            .map_err(|e| ParserError::QueryError(e.to_string()))
2358    }
2359
2360    fn typescript_super_query() -> Result<Query, ParserError> {
2361        let query_string = r#"
2362            ; Functions
2363            (function_declaration
2364              name: (identifier) @name) @function
2365
2366            ; Classes
2367            (class_declaration
2368              name: (type_identifier) @name) @class
2369
2370            ; Interfaces
2371            (interface_declaration
2372              name: (type_identifier) @name) @interface
2373
2374            ; Methods
2375            (method_definition
2376              name: (property_identifier) @name) @method
2377
2378            ; Enums
2379            (enum_declaration
2380              name: (identifier) @name) @enum
2381
2382            ; Imports
2383            (import_statement) @import
2384        "#;
2385
2386        Query::new(&tree_sitter_typescript::LANGUAGE_TYPESCRIPT.into(), query_string)
2387            .map_err(|e| ParserError::QueryError(e.to_string()))
2388    }
2389
2390    fn rust_super_query() -> Result<Query, ParserError> {
2391        let query_string = r#"
2392            ; Functions
2393            (function_item
2394              name: (identifier) @name) @function
2395
2396            ; Structs
2397            (struct_item
2398              name: (type_identifier) @name) @struct
2399
2400            ; Enums
2401            (enum_item
2402              name: (type_identifier) @name) @enum
2403
2404            ; Traits
2405            (trait_item
2406              name: (type_identifier) @name) @trait
2407
2408            ; Use statements (imports)
2409            (use_declaration) @import
2410        "#;
2411
2412        Query::new(&tree_sitter_rust::LANGUAGE.into(), query_string)
2413            .map_err(|e| ParserError::QueryError(e.to_string()))
2414    }
2415
2416    fn go_super_query() -> Result<Query, ParserError> {
2417        let query_string = r#"
2418            ; Functions
2419            (function_declaration
2420              name: (identifier) @name) @function
2421
2422            ; Methods
2423            (method_declaration
2424              name: (field_identifier) @name) @method
2425
2426            ; Structs
2427            (type_declaration
2428              (type_spec
2429                name: (type_identifier) @name
2430                type: (struct_type))) @struct
2431
2432            ; Interfaces
2433            (type_declaration
2434              (type_spec
2435                name: (type_identifier) @name
2436                type: (interface_type))) @interface
2437
2438            ; Imports
2439            (import_declaration) @import
2440        "#;
2441
2442        Query::new(&tree_sitter_go::LANGUAGE.into(), query_string)
2443            .map_err(|e| ParserError::QueryError(e.to_string()))
2444    }
2445
2446    fn java_super_query() -> Result<Query, ParserError> {
2447        let query_string = r#"
2448            ; Methods
2449            (method_declaration
2450              name: (identifier) @name) @method
2451
2452            ; Classes
2453            (class_declaration
2454              name: (identifier) @name) @class
2455
2456            ; Interfaces
2457            (interface_declaration
2458              name: (identifier) @name) @interface
2459
2460            ; Enums
2461            (enum_declaration
2462              name: (identifier) @name) @enum
2463
2464            ; Imports
2465            (import_declaration) @import
2466        "#;
2467
2468        Query::new(&tree_sitter_java::LANGUAGE.into(), query_string)
2469            .map_err(|e| ParserError::QueryError(e.to_string()))
2470    }
2471
2472    // ==========================================================================
2473    // C language queries
2474    // ==========================================================================
2475
2476    fn c_query() -> Result<Query, ParserError> {
2477        let query_string = r#"
2478            (function_definition
2479              declarator: (function_declarator
2480                declarator: (identifier) @name)) @function
2481
2482            (struct_specifier
2483              name: (type_identifier) @name) @struct
2484
2485            (enum_specifier
2486              name: (type_identifier) @name) @enum
2487        "#;
2488
2489        Query::new(&tree_sitter_c::LANGUAGE.into(), query_string)
2490            .map_err(|e| ParserError::QueryError(e.to_string()))
2491    }
2492
2493    fn c_super_query() -> Result<Query, ParserError> {
2494        let query_string = r#"
2495            ; Functions
2496            (function_definition
2497              declarator: (function_declarator
2498                declarator: (identifier) @name)) @function
2499
2500            ; Structs
2501            (struct_specifier
2502              name: (type_identifier) @name) @struct
2503
2504            ; Enums
2505            (enum_specifier
2506              name: (type_identifier) @name) @enum
2507
2508            ; Includes (imports)
2509            (preproc_include) @import
2510        "#;
2511
2512        Query::new(&tree_sitter_c::LANGUAGE.into(), query_string)
2513            .map_err(|e| ParserError::QueryError(e.to_string()))
2514    }
2515
2516    // ==========================================================================
2517    // C++ language queries
2518    // ==========================================================================
2519
2520    fn cpp_query() -> Result<Query, ParserError> {
2521        let query_string = r#"
2522            (function_definition
2523              declarator: (function_declarator
2524                declarator: (identifier) @name)) @function
2525
2526            (class_specifier
2527              name: (type_identifier) @name) @class
2528
2529            (struct_specifier
2530              name: (type_identifier) @name) @struct
2531
2532            (enum_specifier
2533              name: (type_identifier) @name) @enum
2534        "#;
2535
2536        Query::new(&tree_sitter_cpp::LANGUAGE.into(), query_string)
2537            .map_err(|e| ParserError::QueryError(e.to_string()))
2538    }
2539
2540    fn cpp_super_query() -> Result<Query, ParserError> {
2541        let query_string = r#"
2542            ; Functions
2543            (function_definition
2544              declarator: (function_declarator
2545                declarator: (identifier) @name)) @function
2546
2547            ; Classes
2548            (class_specifier
2549              name: (type_identifier) @name) @class
2550
2551            ; Structs
2552            (struct_specifier
2553              name: (type_identifier) @name) @struct
2554
2555            ; Enums
2556            (enum_specifier
2557              name: (type_identifier) @name) @enum
2558
2559            ; Includes (imports)
2560            (preproc_include) @import
2561        "#;
2562
2563        Query::new(&tree_sitter_cpp::LANGUAGE.into(), query_string)
2564            .map_err(|e| ParserError::QueryError(e.to_string()))
2565    }
2566
2567    // ==========================================================================
2568    // C# language queries
2569    // ==========================================================================
2570
2571    fn csharp_query() -> Result<Query, ParserError> {
2572        let query_string = r#"
2573            (method_declaration
2574              name: (identifier) @name) @method
2575
2576            (class_declaration
2577              name: (identifier) @name) @class
2578
2579            (interface_declaration
2580              name: (identifier) @name) @interface
2581
2582            (struct_declaration
2583              name: (identifier) @name) @struct
2584
2585            (enum_declaration
2586              name: (identifier) @name) @enum
2587        "#;
2588
2589        Query::new(&tree_sitter_c_sharp::LANGUAGE.into(), query_string)
2590            .map_err(|e| ParserError::QueryError(e.to_string()))
2591    }
2592
2593    fn csharp_super_query() -> Result<Query, ParserError> {
2594        let query_string = r#"
2595            ; Methods
2596            (method_declaration
2597              name: (identifier) @name) @method
2598
2599            ; Classes
2600            (class_declaration
2601              name: (identifier) @name) @class
2602
2603            ; Interfaces
2604            (interface_declaration
2605              name: (identifier) @name) @interface
2606
2607            ; Structs
2608            (struct_declaration
2609              name: (identifier) @name) @struct
2610
2611            ; Enums
2612            (enum_declaration
2613              name: (identifier) @name) @enum
2614
2615            ; Imports (using directives)
2616            (using_directive) @import
2617        "#;
2618
2619        Query::new(&tree_sitter_c_sharp::LANGUAGE.into(), query_string)
2620            .map_err(|e| ParserError::QueryError(e.to_string()))
2621    }
2622
2623    // ==========================================================================
2624    // Ruby language queries
2625    // ==========================================================================
2626
2627    fn ruby_query() -> Result<Query, ParserError> {
2628        let query_string = r#"
2629            (method
2630              name: (identifier) @name) @function
2631
2632            (class
2633              name: (constant) @name) @class
2634
2635            (module
2636              name: (constant) @name) @class
2637        "#;
2638
2639        Query::new(&tree_sitter_ruby::LANGUAGE.into(), query_string)
2640            .map_err(|e| ParserError::QueryError(e.to_string()))
2641    }
2642
2643    fn ruby_super_query() -> Result<Query, ParserError> {
2644        let query_string = r#"
2645            ; Methods
2646            (method
2647              name: (identifier) @name) @function
2648
2649            ; Classes
2650            (class
2651              name: (constant) @name) @class
2652
2653            ; Modules
2654            (module
2655              name: (constant) @name) @class
2656
2657            ; Requires (imports)
2658            (call
2659              method: (identifier) @_method
2660              (#match? @_method "^require")
2661              arguments: (argument_list)) @import
2662        "#;
2663
2664        Query::new(&tree_sitter_ruby::LANGUAGE.into(), query_string)
2665            .map_err(|e| ParserError::QueryError(e.to_string()))
2666    }
2667
2668    // ==========================================================================
2669    // Bash language queries
2670    // ==========================================================================
2671
2672    fn bash_query() -> Result<Query, ParserError> {
2673        let query_string = r#"
2674            (function_definition
2675              name: (word) @name) @function
2676        "#;
2677
2678        Query::new(&tree_sitter_bash::LANGUAGE.into(), query_string)
2679            .map_err(|e| ParserError::QueryError(e.to_string()))
2680    }
2681
2682    fn bash_super_query() -> Result<Query, ParserError> {
2683        let query_string = r#"
2684            ; Functions
2685            (function_definition
2686              name: (word) @name) @function
2687
2688            ; Source commands (imports)
2689            (command
2690              name: (command_name) @_cmd
2691              (#match? @_cmd "^(source|\\.)$")
2692              argument: (word)) @import
2693        "#;
2694
2695        Query::new(&tree_sitter_bash::LANGUAGE.into(), query_string)
2696            .map_err(|e| ParserError::QueryError(e.to_string()))
2697    }
2698
2699    // ==========================================================================
2700    // PHP language queries
2701    // ==========================================================================
2702
2703    fn php_query() -> Result<Query, ParserError> {
2704        let query_string = r#"
2705            (function_definition
2706              name: (name) @name) @function
2707
2708            (method_declaration
2709              name: (name) @name) @method
2710
2711            (class_declaration
2712              name: (name) @name) @class
2713
2714            (interface_declaration
2715              name: (name) @name) @interface
2716
2717            (trait_declaration
2718              name: (name) @name) @trait
2719        "#;
2720
2721        Query::new(&tree_sitter_php::LANGUAGE_PHP.into(), query_string)
2722            .map_err(|e| ParserError::QueryError(e.to_string()))
2723    }
2724
2725    fn php_super_query() -> Result<Query, ParserError> {
2726        let query_string = r#"
2727            ; Functions
2728            (function_definition
2729              name: (name) @name) @function
2730
2731            ; Methods
2732            (method_declaration
2733              name: (name) @name) @method
2734
2735            ; Classes
2736            (class_declaration
2737              name: (name) @name) @class
2738
2739            ; Interfaces
2740            (interface_declaration
2741              name: (name) @name) @interface
2742
2743            ; Traits
2744            (trait_declaration
2745              name: (name) @name) @trait
2746
2747            ; Use statements (imports)
2748            (namespace_use_declaration) @import
2749        "#;
2750
2751        Query::new(&tree_sitter_php::LANGUAGE_PHP.into(), query_string)
2752            .map_err(|e| ParserError::QueryError(e.to_string()))
2753    }
2754
2755    // ==========================================================================
2756    // Kotlin language queries
2757    // ==========================================================================
2758
2759    fn kotlin_query() -> Result<Query, ParserError> {
2760        let query_string = r#"
2761            (function_declaration
2762              name: (_) @name) @function
2763
2764            (class_declaration
2765              name: (_) @name) @class
2766
2767            (object_declaration
2768              name: (_) @name) @class
2769        "#;
2770
2771        Query::new(&tree_sitter_kotlin_ng::LANGUAGE.into(), query_string)
2772            .map_err(|e| ParserError::QueryError(e.to_string()))
2773    }
2774
2775    fn kotlin_super_query() -> Result<Query, ParserError> {
2776        let query_string = r#"
2777            ; Functions
2778            (function_declaration
2779              name: (_) @name) @function
2780
2781            ; Classes
2782            (class_declaration
2783              name: (_) @name) @class
2784
2785            ; Objects
2786            (object_declaration
2787              name: (_) @name) @class
2788
2789            ; Imports
2790            (import) @import
2791        "#;
2792
2793        Query::new(&tree_sitter_kotlin_ng::LANGUAGE.into(), query_string)
2794            .map_err(|e| ParserError::QueryError(e.to_string()))
2795    }
2796
2797    // ==========================================================================
2798    // Swift language queries
2799    // ==========================================================================
2800
2801    fn swift_query() -> Result<Query, ParserError> {
2802        let query_string = r#"
2803            (function_declaration
2804              name: (simple_identifier) @name) @function
2805
2806            (class_declaration
2807              declaration_kind: "class"
2808              name: (type_identifier) @name) @class
2809
2810            (protocol_declaration
2811              name: (type_identifier) @name) @interface
2812
2813            (class_declaration
2814              declaration_kind: "struct"
2815              name: (type_identifier) @name) @struct
2816
2817            (class_declaration
2818              declaration_kind: "enum"
2819              name: (type_identifier) @name) @enum
2820        "#;
2821
2822        Query::new(&tree_sitter_swift::LANGUAGE.into(), query_string)
2823            .map_err(|e| ParserError::QueryError(e.to_string()))
2824    }
2825
2826    fn swift_super_query() -> Result<Query, ParserError> {
2827        let query_string = r#"
2828            ; Functions
2829            (function_declaration
2830              name: (simple_identifier) @name) @function
2831
2832            ; Classes
2833            (class_declaration
2834              declaration_kind: "class"
2835              name: (type_identifier) @name) @class
2836
2837            ; Protocols (interfaces)
2838            (protocol_declaration
2839              name: (type_identifier) @name) @interface
2840
2841            ; Structs
2842            (class_declaration
2843              declaration_kind: "struct"
2844              name: (type_identifier) @name) @struct
2845
2846            ; Enums
2847            (class_declaration
2848              declaration_kind: "enum"
2849              name: (type_identifier) @name) @enum
2850
2851            ; Imports
2852            (import_declaration) @import
2853        "#;
2854
2855        Query::new(&tree_sitter_swift::LANGUAGE.into(), query_string)
2856            .map_err(|e| ParserError::QueryError(e.to_string()))
2857    }
2858
2859    // ==========================================================================
2860    // Scala language queries
2861    // ==========================================================================
2862
2863    fn scala_query() -> Result<Query, ParserError> {
2864        let query_string = r#"
2865            (function_definition
2866              name: (identifier) @name) @function
2867
2868            (class_definition
2869              name: (identifier) @name) @class
2870
2871            (object_definition
2872              name: (identifier) @name) @class
2873
2874            (trait_definition
2875              name: (identifier) @name) @trait
2876        "#;
2877
2878        Query::new(&tree_sitter_scala::LANGUAGE.into(), query_string)
2879            .map_err(|e| ParserError::QueryError(e.to_string()))
2880    }
2881
2882    fn scala_super_query() -> Result<Query, ParserError> {
2883        let query_string = r#"
2884            ; Functions
2885            (function_definition
2886              name: (identifier) @name) @function
2887
2888            ; Classes
2889            (class_definition
2890              name: (identifier) @name) @class
2891
2892            ; Objects
2893            (object_definition
2894              name: (identifier) @name) @class
2895
2896            ; Traits
2897            (trait_definition
2898              name: (identifier) @name) @trait
2899
2900            ; Imports
2901            (import_declaration) @import
2902        "#;
2903
2904        Query::new(&tree_sitter_scala::LANGUAGE.into(), query_string)
2905            .map_err(|e| ParserError::QueryError(e.to_string()))
2906    }
2907
2908    // ==========================================================================
2909    // Haskell language queries
2910    // ==========================================================================
2911
2912    fn haskell_query() -> Result<Query, ParserError> {
2913        let query_string = r#"
2914            (function
2915              name: (variable) @name) @function
2916
2917            (signature
2918              name: (variable) @name) @function
2919
2920            (function
2921              name: (prefix_id) @name) @function
2922
2923            (signature
2924              name: (prefix_id) @name) @function
2925
2926            (newtype
2927              name: (name) @name) @struct
2928
2929            (type_synomym
2930              name: (name) @name) @struct
2931
2932            (data_type
2933              name: (name) @name) @enum
2934        "#;
2935
2936        Query::new(&tree_sitter_haskell::LANGUAGE.into(), query_string)
2937            .map_err(|e| ParserError::QueryError(e.to_string()))
2938    }
2939
2940    fn haskell_super_query() -> Result<Query, ParserError> {
2941        let query_string = r#"
2942            ; Functions
2943            (function
2944              name: (variable) @name) @function
2945
2946            ; Type signatures
2947            (signature
2948              name: (variable) @name) @function
2949
2950            ; Type aliases
2951            (function
2952              name: (prefix_id) @name) @function
2953
2954            (signature
2955              name: (prefix_id) @name) @function
2956
2957            ; Newtypes
2958            (newtype
2959              name: (name) @name) @struct
2960
2961            ; ADTs (data declarations)
2962            (type_synomym
2963              name: (name) @name) @struct
2964
2965            (data_type
2966              name: (name) @name) @enum
2967
2968            ; Imports
2969            (import) @import
2970        "#;
2971
2972        Query::new(&tree_sitter_haskell::LANGUAGE.into(), query_string)
2973            .map_err(|e| ParserError::QueryError(e.to_string()))
2974    }
2975
2976    // ==========================================================================
2977    // Elixir language queries
2978    // ==========================================================================
2979
2980    fn elixir_query() -> Result<Query, ParserError> {
2981        let query_string = r#"
2982            (call
2983              target: (identifier) @_type
2984              (#match? @_type "^(def|defp|defmacro|defmacrop)$")
2985              (arguments
2986                (call
2987                  target: (identifier) @name))) @function
2988
2989            (call
2990              target: (identifier) @_type
2991              (#match? @_type "^defmodule$")
2992              (arguments
2993                (alias) @name)) @class
2994        "#;
2995
2996        Query::new(&tree_sitter_elixir::LANGUAGE.into(), query_string)
2997            .map_err(|e| ParserError::QueryError(e.to_string()))
2998    }
2999
3000    fn elixir_super_query() -> Result<Query, ParserError> {
3001        let query_string = r#"
3002            ; Functions (def, defp, defmacro)
3003            (call
3004              target: (identifier) @_type
3005              (#match? @_type "^(def|defp|defmacro|defmacrop)$")
3006              (arguments
3007                (call
3008                  target: (identifier) @name))) @function
3009
3010            ; Modules
3011            (call
3012              target: (identifier) @_type
3013              (#match? @_type "^defmodule$")
3014              (arguments
3015                (alias) @name)) @class
3016
3017            ; Imports (alias, import, use, require)
3018            (call
3019              target: (identifier) @_type
3020              (#match? @_type "^(alias|import|use|require)$")) @import
3021        "#;
3022
3023        Query::new(&tree_sitter_elixir::LANGUAGE.into(), query_string)
3024            .map_err(|e| ParserError::QueryError(e.to_string()))
3025    }
3026
3027    // ==========================================================================
3028    // Clojure language queries
3029    // ==========================================================================
3030
3031    fn clojure_query() -> Result<Query, ParserError> {
3032        let query_string = r#"
3033            (list_lit
3034              (sym_lit) @_type
3035              (#match? @_type "^(defn|defn-|defmacro)$")
3036              (sym_lit) @name) @function
3037
3038            (list_lit
3039              (sym_lit) @_type
3040              (#match? @_type "^(defrecord|deftype|defprotocol)$")
3041              (sym_lit) @name) @class
3042        "#;
3043
3044        Query::new(&tree_sitter_clojure::LANGUAGE.into(), query_string)
3045            .map_err(|e| ParserError::QueryError(e.to_string()))
3046    }
3047
3048    fn clojure_super_query() -> Result<Query, ParserError> {
3049        let query_string = r#"
3050            ; Functions
3051            (list_lit
3052              (sym_lit) @_type
3053              (#match? @_type "^(defn|defn-|defmacro)$")
3054              (sym_lit) @name) @function
3055
3056            ; Records/Types/Protocols
3057            (list_lit
3058              (sym_lit) @_type
3059              (#match? @_type "^(defrecord|deftype|defprotocol)$")
3060              (sym_lit) @name) @class
3061
3062            ; Namespace (imports)
3063            (list_lit
3064              (sym_lit) @_type
3065              (#match? @_type "^(ns|require|use|import)$")) @import
3066        "#;
3067
3068        Query::new(&tree_sitter_clojure::LANGUAGE.into(), query_string)
3069            .map_err(|e| ParserError::QueryError(e.to_string()))
3070    }
3071
3072    // ==========================================================================
3073    // OCaml language queries
3074    // ==========================================================================
3075
3076    fn ocaml_query() -> Result<Query, ParserError> {
3077        let query_string = r#"
3078            (value_definition
3079              (let_binding
3080                pattern: (value_name) @name)) @function
3081
3082            (type_definition
3083              (type_binding
3084                name: (type_constructor) @name)) @struct
3085
3086            (module_definition
3087              (module_binding
3088                name: (module_name) @name)) @class
3089        "#;
3090
3091        Query::new(&tree_sitter_ocaml::LANGUAGE_OCAML.into(), query_string)
3092            .map_err(|e| ParserError::QueryError(e.to_string()))
3093    }
3094
3095    fn ocaml_super_query() -> Result<Query, ParserError> {
3096        let query_string = r#"
3097            ; Functions (let bindings)
3098            (value_definition
3099              (let_binding
3100                pattern: (value_name) @name)) @function
3101
3102            ; Types
3103            (type_definition
3104              (type_binding
3105                name: (type_constructor) @name)) @struct
3106
3107            ; Modules
3108            (module_definition
3109              (module_binding
3110                name: (module_name) @name)) @class
3111
3112            ; Opens (imports)
3113            (open_module) @import
3114        "#;
3115
3116        Query::new(&tree_sitter_ocaml::LANGUAGE_OCAML.into(), query_string)
3117            .map_err(|e| ParserError::QueryError(e.to_string()))
3118    }
3119
3120    // ==========================================================================
3121    // Lua language queries
3122    // ==========================================================================
3123
3124    fn lua_query() -> Result<Query, ParserError> {
3125        let query_string = r#"
3126            (function_declaration
3127              name: (identifier) @name) @function
3128
3129            (function_declaration
3130              name: (dot_index_expression) @name) @method
3131
3132            (function_declaration
3133              name: (method_index_expression) @name) @method
3134        "#;
3135
3136        Query::new(&tree_sitter_lua::LANGUAGE.into(), query_string)
3137            .map_err(|e| ParserError::QueryError(e.to_string()))
3138    }
3139
3140    fn lua_super_query() -> Result<Query, ParserError> {
3141        let query_string = r#"
3142            ; Global functions
3143            (function_declaration
3144              name: (identifier) @name) @function
3145
3146            ; Method-like functions
3147            (function_declaration
3148              name: (dot_index_expression) @name) @method
3149
3150            (function_declaration
3151              name: (method_index_expression) @name) @method
3152
3153            ; Requires (imports)
3154            (function_call
3155              name: (variable
3156                (identifier) @_func)
3157              (#eq? @_func "require")
3158              arguments: (arguments)) @import
3159        "#;
3160
3161        Query::new(&tree_sitter_lua::LANGUAGE.into(), query_string)
3162            .map_err(|e| ParserError::QueryError(e.to_string()))
3163    }
3164
3165    // ==========================================================================
3166    // R language queries
3167    // ==========================================================================
3168
3169    fn r_query() -> Result<Query, ParserError> {
3170        let query_string = r#"
3171            (binary_operator
3172              lhs: (identifier) @name
3173              operator: "<-"
3174              rhs: (function_definition)) @function
3175
3176            (binary_operator
3177              lhs: (identifier) @name
3178              operator: "="
3179              rhs: (function_definition)) @function
3180        "#;
3181
3182        Query::new(&tree_sitter_r::LANGUAGE.into(), query_string)
3183            .map_err(|e| ParserError::QueryError(e.to_string()))
3184    }
3185
3186    fn r_super_query() -> Result<Query, ParserError> {
3187        let query_string = r#"
3188            ; Functions (left assignment)
3189            (binary_operator
3190              lhs: (identifier) @name
3191              operator: "<-"
3192              rhs: (function_definition)) @function
3193
3194            ; Functions (equals assignment)
3195            (binary_operator
3196              lhs: (identifier) @name
3197              operator: "="
3198              rhs: (function_definition)) @function
3199
3200            ; Library/require calls (imports)
3201            (call
3202              function: (identifier) @_func
3203              (#match? @_func "^(library|require|source)$")) @import
3204        "#;
3205
3206        Query::new(&tree_sitter_r::LANGUAGE.into(), query_string)
3207            .map_err(|e| ParserError::QueryError(e.to_string()))
3208    }
3209}
3210
3211impl Default for Parser {
3212    fn default() -> Self {
3213        Self::new()
3214    }
3215}
3216
3217#[cfg(test)]
3218mod tests {
3219    use super::*;
3220
3221    #[test]
3222    fn test_language_from_extension() {
3223        assert_eq!(Language::from_extension("py"), Some(Language::Python));
3224        assert_eq!(Language::from_extension("js"), Some(Language::JavaScript));
3225        assert_eq!(Language::from_extension("ts"), Some(Language::TypeScript));
3226        assert_eq!(Language::from_extension("rs"), Some(Language::Rust));
3227        assert_eq!(Language::from_extension("go"), Some(Language::Go));
3228        assert_eq!(Language::from_extension("java"), Some(Language::Java));
3229        assert_eq!(Language::from_extension("unknown"), None);
3230    }
3231
3232    #[test]
3233    fn test_parse_python() {
3234        let mut parser = Parser::new();
3235        let source = r#"
3236def hello_world():
3237    """This is a docstring"""
3238    print("Hello, World!")
3239
3240class MyClass:
3241    def method(self, x):
3242        return x * 2
3243"#;
3244
3245        let symbols = parser.parse(source, Language::Python).unwrap();
3246        assert!(!symbols.is_empty());
3247
3248        // Find function
3249        let func = symbols
3250            .iter()
3251            .find(|s| s.name == "hello_world" && s.kind == SymbolKind::Function);
3252        assert!(func.is_some());
3253
3254        // Find class
3255        let class = symbols
3256            .iter()
3257            .find(|s| s.name == "MyClass" && s.kind == SymbolKind::Class);
3258        assert!(class.is_some());
3259
3260        // Find method
3261        let method = symbols
3262            .iter()
3263            .find(|s| s.name == "method" && s.kind == SymbolKind::Method);
3264        assert!(method.is_some());
3265    }
3266
3267    #[test]
3268    fn test_parse_rust() {
3269        let mut parser = Parser::new();
3270        let source = r#"
3271/// A test function
3272fn test_function() -> i32 {
3273    42
3274}
3275
3276struct MyStruct {
3277    field: i32,
3278}
3279
3280enum MyEnum {
3281    Variant1,
3282    Variant2,
3283}
3284"#;
3285
3286        let symbols = parser.parse(source, Language::Rust).unwrap();
3287        assert!(!symbols.is_empty());
3288
3289        // Find function
3290        let func = symbols
3291            .iter()
3292            .find(|s| s.name == "test_function" && s.kind == SymbolKind::Function);
3293        assert!(func.is_some());
3294
3295        // Find struct
3296        let struct_sym = symbols
3297            .iter()
3298            .find(|s| s.name == "MyStruct" && s.kind == SymbolKind::Struct);
3299        assert!(struct_sym.is_some());
3300
3301        // Find enum
3302        let enum_sym = symbols
3303            .iter()
3304            .find(|s| s.name == "MyEnum" && s.kind == SymbolKind::Enum);
3305        assert!(enum_sym.is_some());
3306    }
3307
3308    #[test]
3309    fn test_parse_javascript() {
3310        let mut parser = Parser::new();
3311        let source = r#"
3312function testFunction() {
3313    return 42;
3314}
3315
3316class TestClass {
3317    testMethod() {
3318        return "test";
3319    }
3320}
3321
3322const arrowFunc = () => {
3323    console.log("arrow");
3324};
3325"#;
3326
3327        let symbols = parser.parse(source, Language::JavaScript).unwrap();
3328        assert!(!symbols.is_empty());
3329
3330        // Find function
3331        let func = symbols
3332            .iter()
3333            .find(|s| s.name == "testFunction" && s.kind == SymbolKind::Function);
3334        assert!(func.is_some());
3335
3336        // Find class
3337        let class = symbols
3338            .iter()
3339            .find(|s| s.name == "TestClass" && s.kind == SymbolKind::Class);
3340        assert!(class.is_some());
3341    }
3342
3343    #[test]
3344    fn test_parse_typescript() {
3345        let mut parser = Parser::new();
3346        let source = r#"
3347interface TestInterface {
3348    method(): void;
3349}
3350
3351enum TestEnum {
3352    Value1,
3353    Value2
3354}
3355
3356class TestClass implements TestInterface {
3357    method(): void {
3358        console.log("test");
3359    }
3360}
3361"#;
3362
3363        let symbols = parser.parse(source, Language::TypeScript).unwrap();
3364        assert!(!symbols.is_empty());
3365
3366        // Find interface
3367        let interface = symbols
3368            .iter()
3369            .find(|s| s.name == "TestInterface" && s.kind == SymbolKind::Interface);
3370        assert!(interface.is_some());
3371
3372        // Find enum
3373        let enum_sym = symbols
3374            .iter()
3375            .find(|s| s.name == "TestEnum" && s.kind == SymbolKind::Enum);
3376        assert!(enum_sym.is_some());
3377    }
3378
3379    #[test]
3380    fn test_symbol_metadata() {
3381        let mut parser = Parser::new();
3382        let source = r#"
3383def test_func(x, y):
3384    """A test function with params"""
3385    return x + y
3386"#;
3387
3388        let symbols = parser.parse(source, Language::Python).unwrap();
3389        let func = symbols
3390            .iter()
3391            .find(|s| s.name == "test_func")
3392            .expect("Function not found");
3393
3394        assert!(func.start_line > 0);
3395        assert!(func.end_line >= func.start_line);
3396        assert!(func.signature.is_some());
3397        assert!(func.docstring.is_some());
3398    }
3399}