You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Add Swift language support to aptu-coder using the tree-sitter-swift grammar. This enables the four core MCP tools (analyze_directory, analyze_file, analyze_symbol, analyze_module) to parse and analyze Swift source files.
Context
Swift is the primary language for iOS, macOS, watchOS, and tvOS development, and has grown in adoption for server-side applications. Adding Swift support extends aptu-coder's reach into the Apple ecosystem and complements existing support for Go, Java, Rust, and other languages.
Acceptance Criteria
Cargo dependency:tree-sitter-swift = "0.7.2" added to [workspace.dependencies] in root Cargo.toml
Feature flag:lang-swift feature created in crates/aptu-coder-core/Cargo.toml and added to default feature set; dependency declared as optional under [features]
Query module:crates/aptu-coder-core/src/languages/swift.rs created with:
ELEMENT_QUERY (function declarations, class/struct/actor/enum/extension/protocol type declarations, extraction of both name field and declaration_kind field where relevant)
CALL_QUERY (call expressions)
REFERENCE_QUERY (simple identifier references)
IMPORT_QUERY (import declarations)
DEFUSE_QUERY (definition and use sites for variables and assignments)
extract_inheritance handler function (walks inheritance_specifier children via inherits_from field to collect superclass and protocol names)
SPDX header (Apache-2.0) on the file
Extension registry:.swift extension registered in EXTENSION_MAP in lang.rs behind #[cfg(feature = "lang-swift")]; "swift" added to supported_languages()
Language info:"swift" arm added in get_language_info() in languages/mod.rs (behind feature gate):
name, language (via tree_sitter_swift::LANGUAGE.into()), element_query, call_query, reference_query, import_query, defuse_query fields set
impl_query, impl_trait_query, extract_function_name, find_method_for_receiver, find_receiver_type set to None
extract_inheritance set to Some(swift::extract_inheritance)
Module registration:mod swift; added to languages/mod.rs behind #[cfg(feature = "lang-swift")]
Unit tests: Created in swift.rs under #[cfg(all(test, feature = "lang-swift"))] with parse_swift(source) helper:
Enum declaration (class_declaration with declaration_kind = "enum")
Extension declaration (class_declaration with declaration_kind = "extension")
Function call symbol extraction
Import statement parsing
Single superclass inheritance
Multiple protocol conformance
Mixed superclass and protocol inheritance
All tests pass:cargo test --features lang-swift
Linting passes:cargo clippy -- -D warnings with lang-swift feature
Implementation Notes
Grammar crate:tree-sitter-swift 0.7.2 (alex-pinkus/tree-sitter-swift). Its normal (non-dev) dependency is tree-sitter-language ^0.1.0 only; tree-sitter itself is a dev-only dependency. This means adding tree-sitter-swift introduces no version conflict with the workspace tree-sitter = "0.26.6".
Entry point:tree_sitter_swift::LANGUAGE.into() -- same pattern as all other languages in mod.rs.
There is no get_ts_language() function: The grammar entry point is the language field inside LanguageInfo, set inline in the get_language_info() match arm.
defuse_query is required:LanguageInfo.defuse_query is a mandatory struct field (typed Option<&'static str>). Every language in the registry sets it. Define a DEFUSE_QUERY constant in swift.rs covering local variable/constant declarations, assignments, and identifier reads. Model after java.rs.
Reference handler: Model after java.rs -- Swift shares JVM-inspired structural patterns (named method/function declarations, type inheritance, imports).
Key node kinds (from grammar.js and node-types.json):
function_declaration -- free functions and methods; name field holds the identifier
class_declaration -- covers class, struct, actor, enum, and extension via the declaration_kind field (literal string: "class", "struct", "actor", "enum", "extension"); name field holds a type_identifier
protocol_declaration -- separate node from class_declaration; name field holds a type_identifier
import_declaration -- module imports; no named fields; child identifier holds the module path
call_expression -- function and method calls
simple_identifier -- symbol references
inheritance_specifier -- one base type per node; has inherits_from field pointing to a user_type node; multiple specifiers are siblings under _inheritance_specifiers (comma-separated in source)
ELEMENT_QUERY guidance: Capture function_declaration with its name field as @function/@method_name. Capture class_declaration with its name field as @class/@class_name. Capture protocol_declaration similarly. A single pattern per node kind is sufficient; the declaration_kind field distinguishes struct/enum/extension at runtime if needed.
Inheritance walking: Walk inheritance_specifier descendants; for each, read the inherits_from field, then find the type_identifier or user_type text to get the name. There is no constructor-call vs. interface distinction in Swift inheritance syntax (superclass and protocols both appear the same way in _inheritance_specifiers).
Extension declarations:extension TypeName { ... } is represented as class_declaration with declaration_kind = "extension". The name field contains the extended type identifier, making it work automatically with the same ELEMENT_QUERY pattern used for class/struct.
No impl blocks: Swift has no separate impl block construct; set impl_query and impl_trait_query to None.
No struct_declaration or extension_declaration node types exist in this grammar -- both are represented via class_declaration with different declaration_kind values. The issue's earlier reference to struct_declaration and extension_declaration as separate node kinds was incorrect.
Not In Scope
Extraction of async/await or throws modifiers
Property wrappers (@State, @Published, etc.)
SwiftUI view body parsing or DSL-aware analysis
Macro expansion or custom operator definitions
actor isolation and concurrency annotation extraction
Summary
Add Swift language support to aptu-coder using the
tree-sitter-swiftgrammar. This enables the four core MCP tools (analyze_directory,analyze_file,analyze_symbol,analyze_module) to parse and analyze Swift source files.Context
Swift is the primary language for iOS, macOS, watchOS, and tvOS development, and has grown in adoption for server-side applications. Adding Swift support extends aptu-coder's reach into the Apple ecosystem and complements existing support for Go, Java, Rust, and other languages.
Acceptance Criteria
tree-sitter-swift = "0.7.2"added to[workspace.dependencies]in rootCargo.tomllang-swiftfeature created incrates/aptu-coder-core/Cargo.tomland added todefaultfeature set; dependency declared as optional under[features]crates/aptu-coder-core/src/languages/swift.rscreated with:ELEMENT_QUERY(function declarations, class/struct/actor/enum/extension/protocol type declarations, extraction of bothnamefield anddeclaration_kindfield where relevant)CALL_QUERY(call expressions)REFERENCE_QUERY(simple identifier references)IMPORT_QUERY(import declarations)DEFUSE_QUERY(definition and use sites for variables and assignments)extract_inheritancehandler function (walksinheritance_specifierchildren viainherits_fromfield to collect superclass and protocol names).swiftextension registered inEXTENSION_MAPinlang.rsbehind#[cfg(feature = "lang-swift")];"swift"added tosupported_languages()"swift"arm added inget_language_info()inlanguages/mod.rs(behind feature gate):name,language(viatree_sitter_swift::LANGUAGE.into()),element_query,call_query,reference_query,import_query,defuse_queryfields setimpl_query,impl_trait_query,extract_function_name,find_method_for_receiver,find_receiver_typeset toNoneextract_inheritanceset toSome(swift::extract_inheritance)mod swift;added tolanguages/mod.rsbehind#[cfg(feature = "lang-swift")]swift.rsunder#[cfg(all(test, feature = "lang-swift"))]withparse_swift(source)helper:class_declarationnode,declaration_kind = "struct")protocol_declarationnode)class_declarationwithdeclaration_kind = "enum")class_declarationwithdeclaration_kind = "extension")cargo test --features lang-swiftcargo clippy -- -D warningswithlang-swiftfeatureImplementation Notes
Grammar crate:
tree-sitter-swift0.7.2 (alex-pinkus/tree-sitter-swift). Its normal (non-dev) dependency istree-sitter-language ^0.1.0only;tree-sitteritself is a dev-only dependency. This means addingtree-sitter-swiftintroduces no version conflict with the workspacetree-sitter = "0.26.6".Entry point:
tree_sitter_swift::LANGUAGE.into()-- same pattern as all other languages inmod.rs.There is no
get_ts_language()function: The grammar entry point is thelanguagefield insideLanguageInfo, set inline in theget_language_info()match arm.defuse_queryis required:LanguageInfo.defuse_queryis a mandatory struct field (typedOption<&'static str>). Every language in the registry sets it. Define aDEFUSE_QUERYconstant inswift.rscovering local variable/constant declarations, assignments, and identifier reads. Model afterjava.rs.Reference handler: Model after
java.rs-- Swift shares JVM-inspired structural patterns (named method/function declarations, type inheritance, imports).Key node kinds (from grammar.js and node-types.json):
function_declaration-- free functions and methods;namefield holds the identifierclass_declaration-- covers class, struct, actor, enum, and extension via thedeclaration_kindfield (literal string:"class","struct","actor","enum","extension");namefield holds atype_identifierprotocol_declaration-- separate node fromclass_declaration;namefield holds atype_identifierimport_declaration-- module imports; no named fields; childidentifierholds the module pathcall_expression-- function and method callssimple_identifier-- symbol referencesinheritance_specifier-- one base type per node; hasinherits_fromfield pointing to auser_typenode; multiple specifiers are siblings under_inheritance_specifiers(comma-separated in source)ELEMENT_QUERYguidance: Capturefunction_declarationwith itsnamefield as@function/@method_name. Captureclass_declarationwith itsnamefield as@class/@class_name. Captureprotocol_declarationsimilarly. A single pattern per node kind is sufficient; thedeclaration_kindfield distinguishes struct/enum/extension at runtime if needed.Inheritance walking: Walk
inheritance_specifierdescendants; for each, read theinherits_fromfield, then find thetype_identifieroruser_typetext to get the name. There is no constructor-call vs. interface distinction in Swift inheritance syntax (superclass and protocols both appear the same way in_inheritance_specifiers).Extension declarations:
extension TypeName { ... }is represented asclass_declarationwithdeclaration_kind = "extension". Thenamefield contains the extended type identifier, making it work automatically with the sameELEMENT_QUERYpattern used for class/struct.No
implblocks: Swift has no separateimplblock construct; setimpl_queryandimpl_trait_querytoNone.No struct_declaration or extension_declaration node types exist in this grammar -- both are represented via
class_declarationwith differentdeclaration_kindvalues. The issue's earlier reference tostruct_declarationandextension_declarationas separate node kinds was incorrect.Not In Scope
async/awaitorthrowsmodifiers@State,@Published, etc.)actorisolation and concurrency annotation extraction