probe_code/language/
swift.rs

1use super::language_trait::LanguageImpl;
2use tree_sitter::{Language as TSLanguage, Node};
3
4/// Implementation of LanguageImpl for Swift
5pub struct SwiftLanguage;
6
7impl Default for SwiftLanguage {
8    fn default() -> Self {
9        Self::new()
10    }
11}
12
13impl SwiftLanguage {
14    pub fn new() -> Self {
15        SwiftLanguage
16    }
17}
18
19impl LanguageImpl for SwiftLanguage {
20    fn get_tree_sitter_language(&self) -> TSLanguage {
21        // Create a new instance of the Language type from the current tree-sitter version
22        unsafe { std::mem::transmute(tree_sitter_swift::LANGUAGE) }
23    }
24
25    fn get_extension(&self) -> &'static str {
26        "swift"
27    }
28
29    fn is_acceptable_parent(&self, node: &Node) -> bool {
30        matches!(
31            node.kind(),
32            "function_declaration"
33                | "class_declaration"
34                | "struct_declaration"
35                | "enum_declaration"
36                | "protocol_declaration"
37                | "extension_declaration"
38                | "typealias_declaration"
39                | "variable_declaration"
40                | "constant_declaration"
41        )
42    }
43
44    fn is_test_node(&self, node: &Node, source: &[u8]) -> bool {
45        let debug_mode = std::env::var("DEBUG").unwrap_or_default() == "1";
46        let node_type = node.kind();
47
48        // Swift: Check for test functions in XCTest
49        if node_type == "function_declaration" {
50            let mut cursor = node.walk();
51
52            // Look for function name starting with "test"
53            for child in node.children(&mut cursor) {
54                if child.kind() == "simple_identifier" {
55                    let name = child.utf8_text(source).unwrap_or("");
56                    if name.starts_with("test") {
57                        if debug_mode {
58                            println!("DEBUG: Test node detected (Swift): test function");
59                        }
60                        return true;
61                    }
62                }
63            }
64
65            // Also check for @Test attribute
66            for child in node.children(&mut cursor) {
67                if child.kind() == "attribute" {
68                    let attr_text = child.utf8_text(source).unwrap_or("");
69                    if attr_text.contains("@Test") {
70                        if debug_mode {
71                            println!("DEBUG: Test node detected (Swift): @Test attribute");
72                        }
73                        return true;
74                    }
75                }
76            }
77        }
78
79        // Also check for XCTestCase class declarations
80        if node_type == "class_declaration" {
81            let mut cursor = node.walk();
82
83            // Check if class inherits from XCTestCase
84            for child in node.children(&mut cursor) {
85                if child.kind() == "type_inheritance_clause" {
86                    let inheritance_text = child.utf8_text(source).unwrap_or("");
87                    if inheritance_text.contains("XCTestCase") {
88                        if debug_mode {
89                            println!("DEBUG: Test node detected (Swift): XCTestCase class");
90                        }
91                        return true;
92                    }
93                }
94            }
95        }
96
97        false
98    }
99
100    fn find_parent_function<'a>(&self, node: Node<'a>) -> Option<Node<'a>> {
101        let mut current = node;
102
103        while let Some(parent) = current.parent() {
104            if parent.kind() == "function_declaration" {
105                return Some(parent);
106            }
107            current = parent;
108        }
109
110        None
111    }
112}