Skip to main content

dk_engine/parser/langs/
swift.rs

1//! Swift language configuration for the query-driven parser.
2
3use crate::parser::lang_config::{CommentStyle, LanguageConfig};
4use dk_core::{Symbol, SymbolKind, Visibility};
5use tree_sitter::Language;
6
7/// Swift language configuration for [`QueryDrivenParser`](crate::parser::engine::QueryDrivenParser).
8pub struct SwiftConfig;
9
10impl LanguageConfig for SwiftConfig {
11    fn language(&self) -> Language {
12        tree_sitter_swift::LANGUAGE.into()
13    }
14
15    fn extensions(&self) -> &'static [&'static str] {
16        &["swift"]
17    }
18
19    fn symbols_query(&self) -> &'static str {
20        include_str!("../queries/swift_symbols.scm")
21    }
22
23    fn calls_query(&self) -> &'static str {
24        include_str!("../queries/swift_calls.scm")
25    }
26
27    fn imports_query(&self) -> &'static str {
28        include_str!("../queries/swift_imports.scm")
29    }
30
31    fn comment_style(&self) -> CommentStyle {
32        CommentStyle::SlashSlash
33    }
34
35    fn resolve_visibility(&self, modifiers: Option<&str>, _name: &str) -> Visibility {
36        match modifiers {
37            Some(m) if m.contains("public") => Visibility::Public,
38            Some(m) if m.contains("open") => Visibility::Public,
39            // Check fileprivate BEFORE private — "fileprivate".contains("private")
40            // is true, so the more specific match must come first.
41            Some(m) if m.contains("fileprivate") => Visibility::Private,
42            Some(m) if m.contains("private") => Visibility::Private,
43            // internal (explicit or implicit) → Private
44            _ => Visibility::Private,
45        }
46    }
47
48    fn adjust_symbol(&self, sym: &mut Symbol, node: &tree_sitter::Node, _source: &[u8]) {
49        // tree-sitter-swift 0.6 represents enums, structs, and classes all
50        // as `class_declaration`. Distinguish by the body child type:
51        //   - `enum_class_body` → Enum
52        //   - `class_body` with struct keyword in source → Struct
53        //   - `class_body` otherwise → Class (default)
54        if node.kind() == "class_declaration" && sym.kind == SymbolKind::Class {
55            let mut cursor = node.walk();
56            for child in node.children(&mut cursor) {
57                if child.kind() == "enum_class_body" {
58                    sym.kind = SymbolKind::Enum;
59                    break;
60                }
61            }
62
63            // Check if the declaration starts with "struct" keyword
64            if sym.kind == SymbolKind::Class {
65                let mut cursor = node.walk();
66                for child in node.children(&mut cursor) {
67                    if child.kind() == "struct" {
68                        sym.kind = SymbolKind::Struct;
69                        break;
70                    }
71                }
72            }
73        }
74    }
75
76    fn is_external_import(&self, _module_path: &str) -> bool {
77        // Swift imports are module-based. Without SPM/Xcode context
78        // we can't distinguish internal vs external, so treat all as external.
79        true
80    }
81}