"""Swift language parser using tree-sitter.
Extracts functions, classes, structs, enums, protocols, methods, imports,
calls, type annotations, and inheritance relationships from Swift source code.
"""
from __future__ import annotations
import tree_sitter_swift as tsswift
from tree_sitter import Language, Node, Parser
from axon.core.parsers.base import (
CallInfo,
ImportInfo,
LanguageParser,
ParseResult,
SymbolInfo,
TypeRef,
)
SWIFT_LANGUAGE = Language(tsswift.language())
_BUILTIN_TYPES: frozenset[str] = frozenset(
{
"Int", "Int8", "Int16", "Int32", "Int64",
"UInt", "UInt8", "UInt16", "UInt32", "UInt64",
"Float", "Double", "Bool", "String", "Character",
"Void", "Any", "AnyObject", "Never",
"Optional", "Array", "Dictionary", "Set",
}
)
class SwiftParser(LanguageParser):
"""Parses Swift source code using tree-sitter."""
def __init__(self) -> None:
self._parser = Parser(SWIFT_LANGUAGE)
def parse(self, content: str, file_path: str) -> ParseResult:
tree = self._parser.parse(content.encode("utf-8"))
result = ParseResult()
self._walk(tree.root_node, content, result, class_name="")
return result
def _walk(self, node, content, result, class_name):
for child in node.children:
ntype = child.type
if ntype == "function_declaration":
self._extract_function(child, content, result, class_name)
elif ntype == "class_declaration":
self._extract_class_like(child, content, result)
elif ntype == "protocol_declaration":
self._extract_protocol(child, content, result)
elif ntype == "typealias_declaration":
self._extract_typealias(child, content, result)
elif ntype == "import_declaration":
self._extract_import(child, result)
elif ntype == "call_expression":
self._extract_call(child, result)
elif ntype == "init_declaration":
self._extract_init(child, content, result, class_name)
elif ntype == "protocol_function_declaration":
self._extract_protocol_function(child, content, result, class_name)
else:
self._walk(child, content, result, class_name)
# ... (full implementation in the linked file above)
Summary
Three items bundled in this issue for discussion — happy to split into separate PRs if preferred.
1. Swift Language Support (feat)
I added Swift parsing support to Axon. Tested on a ~350-file Swift iOS project — successfully indexes 2988 symbols and 8351 relationships.
Constructs extracted:
init), classes, structs, enums, protocols (→interface), typealiases (→type_alias), extensions (walked for methods, no separate symbol emitted)import Foundation,import UIKit, etc.MyClass(name:)) and method calls (someObj.method())Files changed:
pyproject.toml— addedtree-sitter-swift>=0.0.1dependencysrc/axon/config/languages.py— added.swift→"swift"extension mappingsrc/axon/core/ingestion/parser_phase.py— registeredSwiftParserin_PARSER_FACTORIESsrc/axon/core/parsers/swift.py— new file, full parser implementation (~400 lines)tree-sitter-swift AST notes (useful for reviewers):
class_declarationis reused forclass,struct,enum, andextension— distinguished by the first keyword childprotocol_declarationis separate fromclass_declarationsimple_identifierchildren (not anamefield)navigation_expression→navigation_suffix(notmember_expression)protocol_function_declarationis distinct fromfunction_declaration2. Bug fix:
max_workerscrash on empty repos (fix)process_imports()insrc/axon/core/ingestion/imports.pycrashes withValueError: max_workers must be greater than 0whenparse_datais empty (e.g., a repo with no supported files).3. Frontend build needed for
axon ui(docs)After a fresh
pip install -e .,axon uiserves{"detail":"Not Found"}because the frontend hasn't been built. Thedist/directory is listed inpyproject.tomlartifacts but isn't included in the repo or built during install.Fix is to run:
This could be documented in the README or automated in the build process.
Code Changes
Diff of existing files
New file: src/axon/core/parsers/swift.py (~400 lines)
Full file is ~400 lines following the same
_extract_*pattern as the Python and TypeScript parsers. Handles Swift-specific AST quirks likeclass_declarationreuse andnavigation_expressionfor method calls.Happy to split these into separate issues/PRs, add tests in
tests/core/test_parser_swift.py, or adjust scope based on your feedback.