leindex 1.6.0

LeIndex MCP and semantic code search engine for AI tools and large codebases
// Swift language parser implementation

use crate::parse::traits::{CodeIntelligence, ComplexityMetrics, Error, Graph, Result, SignatureInfo};
use crate::parse::traits::{Block, Edge, EdgeType, Parameter, Visibility};
use tree_sitter::Parser;

pub struct SwiftParser;

impl Default for SwiftParser {
    fn default() -> Self { Self::new() }
}

impl SwiftParser {
    pub fn new() -> Self { Self }
}

impl CodeIntelligence for SwiftParser {
    fn get_signatures(&self, source: &[u8]) -> Result<Vec<SignatureInfo>> {
        let mut parser = Parser::new();
        parser.set_language(&crate::parse::traits::languages::swift::language())
            .map_err(|e| Error::ParseFailed(e.to_string()))?;
        let tree = parser.parse(source, None)
            .ok_or_else(|| Error::ParseFailed("Failed to parse Swift source".to_string()))?;
        let mut signatures = Vec::new();
        fn visit(node: &tree_sitter::Node, source: &[u8], sigs: &mut Vec<SignatureInfo>) {
            match node.kind() {
                "function_declaration" | "method_declaration" => {
                    if let Some(name) = node.child_by_field_name("name").and_then(|n| n.utf8_text(source).ok()) {
                        sigs.push(SignatureInfo {
                            name: name.to_string(),
                            qualified_name: name.to_string(),
                            parameters: vec![],
                            return_type: node.child_by_field_name("return_type").and_then(|r| r.utf8_text(source).ok()).map(|s| s.trim().to_string()),
                            visibility: Visibility::Public,
                            is_async: node.children(&mut node.walk()).any(|c| c.utf8_text(source).ok().map_or(false, |t| t.contains("async"))),
                            is_method: node.kind() == "method_declaration",
                            docstring: None,
                            calls: vec![],
                            imports: vec![],
                            byte_range: (0, 0),
                            cyclomatic_complexity: 0,
                            });
                    }
                }
                _ => { let mut c = node.walk(); for ch in node.children(&mut c) { visit(&ch, source, sigs); } }
            }
        }
        visit(&tree.root_node(), source, &mut signatures);
        Ok(signatures)
    }

    fn compute_cfg(&self, source: &[u8], _node_id: usize) -> Result<Graph<Block, Edge>> {
        let mut parser = Parser::new();
        parser.set_language(&crate::parse::traits::languages::swift::language())
            .map_err(|e| Error::ParseFailed(e.to_string()))?;
        parser.parse(source, None).ok_or_else(|| Error::ParseFailed("Failed to parse".to_string()))?;
        Ok(Graph { blocks: vec![], edges: vec![], entry_block: 0, exit_blocks: vec![] })
    }

    fn extract_complexity(&self, node: &tree_sitter::Node) -> ComplexityMetrics {
        ComplexityMetrics { cyclomatic: 1, nesting_depth: 0, line_count: 1, token_count: node.child_count() }
    }
}

#[cfg(test)]
mod tests {
    use super::*;

    #[test]
    fn test_swift_function() {
        let source = b"func greet(_ name: String) -> String { \"Hello, \\(name)\" }";
        let parser = SwiftParser::new();
        assert!(parser.get_signatures(source).unwrap().len() > 0);
    }
}