Understand-Anything 的 Swift 支持:语言提示片段如何与 tree-sitter 结构抽取协作,把 Swift 代码变成知识图谱
在 Understand-Anything 项目中,understand-anything-plugin/skills/understand/languages/swift.md 是 /understand 技能内置的 Swift 语言提示片段(Language Prompt Snippet):它汇总了 Swift 的关键语言概念、导入模式、文件模式、常见框架与示例语言笔记,在项目被识别为包含 Swift 代码时,整段注入架构分析子代理的提示词中。读完本文,你能理解这份片段在整个分析流水线中的注入时机与作用,并通过 Swift 语言配置 与 SwiftExtractor 结构抽取器 的源码,看清"提示词侧"与"确定性解析侧"是如何对同一套 Swift 知识达成一致的。
一、这份文档是什么:/understand 技能的 Swift 语言上下文
这份片段与 SKILL.md 位于同一技能目录的 languages/ 子目录下,是 /understand 技能按需加载的提示词素材。它的加载契约在 SKILL.md 的 Phase 4(ARCHITECTURE)中写明(见 Phase 4 语言上下文注入步骤):
对 Phase 1 检测到的每一种语言,读取
./languages/<language-id>.md(例如./languages/python.md),将其内容附加到基础模板之后,位于## Language Context标题之下;如果该语言对应的文件不存在,则静默跳过并继续。包括非代码语言片段 —— 它们为这些非代码文件提供边模式和摘要风格。
也就是说:Phase 1 的扫描(SCAN)阶段先确定项目的语言集合;一旦检测出 Swift,架构分析子代理(定义见 architecture-analyzer.md)的提示词就会带上这份 swift.md 全文,用来指导 LLM 在划分架构层、撰写摘要与标签时遵循 Swift 的惯用结构(例如把 Package.swift 视为配置、App.swift 视为入口、Tests/ 视为测试目录)。下面完整继承原文档的全部技术要素。
1.1 Key Concepts(关键概念清单)
原文档列出 10 个核心 Swift 概念,它们同时也是 LLM 判读 Swift 文件时的"概念词汇表":
| 概念 | 原文档表述 |
|---|---|
| Optionals 与可选链 | Type? 包裹可能为 nil 的值;?. 安全链式调用 |
| Protocols 与协议扩展 | 用扩展为协议提供默认实现,形成契约 |
| 值类型 vs 引用类型 | struct 与 enum 是值类型;class 是引用类型 |
| Closures 闭包 | 自包含的功能块,可捕获周围上下文 |
| Property Wrappers 属性包装器 | @State、@Binding、@Published 封装属性存储逻辑 |
| Result Builders 结果构建器 | @ViewBuilder、@resultBuilder 支持声明式 DSL 语法 |
| Actors 与结构化并发 | actor 类型实现数据隔离;async let、TaskGroup |
| Generics 泛型 | 带 where 子句的泛型参数与关联类型约束 |
| 带关联值的枚举 | 每个 case 可携带类型各异的有效载荷 |
| Extensions 扩展 | 为已有类型追加方法、计算属性与协议一致性 |
值得注意:这 10 条并不是孤立的提示词素材。与它们一一对应的是 swiftConfig 中的 concepts 字段(optionals、protocols、extensions、generics、closures、property wrappers、result builders、actors、structured concurrency、value types vs reference types)。从源码结构看,这份 concepts 列表会被 language-lesson 模块用于基于节点的 tags、summary 与 languageNotes 检测节点是否命中某个语言概念,为图谱节点生成"学习"内容——提示词侧的概念清单与确定性侧的概念表是刻意保持同源的。
1.2 Import Patterns(导入模式)
原文档归纳了 4 种 Swift 导入形态:
import Foundation—— 核心库,提供数据类型、集合与网络能力;import UIKit—— 传统 view controller 架构的 iOS UI 框架;import SwiftUI—— 带响应式状态管理的声明式 UI 框架;@testable import ModuleName—— 以 internal 访问级别导入,用于单元测试。
这四种模式与提取器的测试用例逐条吻合:swift-extractor.test.ts 中有专门用例验证 @testable import MyApp 能被正确解析为 source: "MyApp"(见 测试用例),并且 #if canImport(UIKit) 条件导入块内的 import UIKit 也能被带正确行号地提取出来(见 测试用例)。
1.3 File Patterns(文件模式)
原文档列出 5 类 Swift 项目的标志性文件:
| 文件/目录 | 含义 |
|---|---|
Package.swift |
Swift Package Manager 清单,定义 target 与依赖 |
*.xcodeproj / *.xcworkspace |
Xcode 工程与工作区配置 |
AppDelegate.swift |
UIKit 应用生命周期入口 |
App.swift |
使用 @main 的 SwiftUI 应用入口 |
Tests/ |
遵循 SPM 或 Xcode 惯例的测试 target 目录 |
这些"文档知识"在确定性侧有精确映射,见 swiftConfig.filePatterns:
filePatterns: {
entryPoints: ["Sources/*/main.swift", "App.swift", "AppDelegate.swift"],
barrels: [],
tests: ["*Tests.swift", "Tests/**/*.swift"],
config: ["Package.swift"],
},
即文档中的 App.swift/AppDelegate.swift 被注册为入口点模式,Tests/ 目录被细化为 *Tests.swift 与 Tests/**/*.swift 两个测试模式,Package.swift 被归类为配置文件。文件到语言的判定则由 LanguageRegistry.getForFile 按扩展名(.swift)或文件名完成;swiftConfig 通过 builtinLanguageConfigs 注册进默认注册表。
1.4 Common Frameworks(常见框架)
原文档列出 5 个在 Swift 代码库中最常见的框架:
- SwiftUI —— 声明式 UI 框架,响应式数据流;
- UIKit —— 命令式 UI 框架,使用 view controller 与 Auto Layout;
- Vapor —— 支持 async 的服务器端 Swift Web 框架;
- Combine —— 处理时间序列值流的响应式框架;
- Core Data —— 对象图与持久化框架。
这份框架清单的作用是在框架检测命中后,与 frameworks/ 子目录下的框架补充说明一起进入架构分析提示词;Swift 项目若使用 Vapor 等 Web 框架做服务器端开发,层划分时也能据此区分 UI 层与服务器层。
1.5 Example Language Notes(示例语言笔记)
原文档给出两条 languageNotes 写作示例,定义了 LLM 为该技能图谱节点撰写语言笔记时的"语气与深度标准":
Uses
@Publishedproperty wrapper to automatically notify SwiftUI views of state changes. When the wrapped value mutates, the property wrapper triggersobjectWillChangeon the enclosingObservableObject, causing dependent views to re-render.Protocol extensions provide default implementations, allowing types to conform by simply declaring conformance — no method body needed if defaults suffice.
两条示例的共同点:不只描述"用了什么语法",而是解释状态如何流转、机制如何触发(@Published → objectWillChange → 视图重渲染;协议扩展默认实现 → 仅需声明一致性)。languageNotes 是图谱节点 schema 中的可选字符串字段(见 types.ts 与 schema.ts),在仪表盘的 NodeInfo 组件 中展示给探索者。
二、确定性侧如何兑现这些 Swift 知识:SwiftExtractor
提示词片段负责"教 LLM 看懂 Swift",而 SwiftExtractor 负责"机器精确地拆解 Swift"。它基于 tree-sitter 语法运行,实现 extractStructure(结构分析)与 extractCallGraph(调用图)两个能力。以下实现细节均可在源码中逐条核对。
2.1 类型容器折叠:class/struct/enum/actor/extension 统一进 classes[]
TYPE_DECLARATION_KINDS 定义了 class、struct、enum、actor、extension 五种类型声明。源码注释说明了设计取舍:Swift 拥有比共享 StructuralAnalysis schema 直接表达的更多"类容器",因此沿用 Dart/Kotlin/Rust 的惯例,把 class、struct、enum、actor、protocol、extension 全部折叠进 classes[],而其中的可调用成员同时出现在 functions[] 里。
几个与原文档概念直接呼应的处理:
- 带关联值的枚举:
enum LoadState { case idle; case failed(Error); case loaded(User) }会被解析为类条目LoadState,且idle/failed/loaded三个 case 进入properties(见 测试用例); - Actors:
actor Cache { ... }被提取为Cache类型条目,属性store与方法get(返回类型Data?)均被记录(见 测试用例); - 扩展:扩展以
extension <Name>的复合名作为独立条目,避免与原类型撞名,例如struct User {}+extension User: Codable产生["User", "extension User"]两个类条目(见 classLikeName 实现 与 测试用例); - 协议与关联类型:
protocol Repository中的associatedtype Item、var id: String { get }、func load(id:) async throws -> Item、init(seed:)分别落到 properties 与 methods,且Repository.init作为独立函数条目携带参数["seed"](见 extractProtocol 实现 与 测试用例)。
2.2 成员命名约定:init/deinit/subscript 与外部标签
init 与 deinit 被记为成员方法,并以 容器名.init / 容器名.deinit 的函数名进入 functions[](如 Box.init、Box.deinit);subscript 记为成员 subscript,并提取其参数与返回类型。参数提取刻意使用本地参数名而非外部标签:func update(_ value: Int = 0, forKey key: String) 得到 ["value", "key"](见 extractParams 实现 与 测试用例)。
2.3 可见性规则决定 exports
Swift 的可见性是图谱"导出面"的关键。isExported 判定 的逻辑是:继承父级导出状态,且声明不是 private/fileprivate。测试覆盖了完整的可见性矩阵:默认与 internal 导出;public/open/package 导出;private/fileprivate 不导出;public private(set) 属性仍导出;private extension 的成员不导出;@objc public func 这种"属性在前、修饰符在后"的排列也能识别(见 visibility 测试组)。
2.4 import 解析:source 取首段、specifier 取末段
extractImport 把导入标识符按 . 拆分:source 取第一段(模块名),specifier 取最后一段(具体符号)。这正好覆盖了原文档 Import Patterns 的粒度——import struct Foundation.Date 解析为 source: "Foundation"、specifiers: ["Date"];import class UIKit.UIView 与 import protocol Combine.Publisher 则分别得到 UIView、Publisher(见 测试用例)。带导入种类限定符(class/protocol/struct)的行也能正确处理,因为这些 token 在 tree-sitter 树中不是 identifier 类型的命名子节点。
2.5 调用图:调用者栈与可选链归一化
extractCallGraph 维护一个调用者栈:进入 function_declaration、init(记为 容器名.init)、deinit 时压栈,离开时弹栈;计算属性与 willset/didset 观察块内发生的调用归属到属性名本身(例如 var value: Int { didSet { notify() } } 产生 value → notify)。对 call_expression 与 constructor_expression 两类被调表达式分别提取名称,其中导航表达式的归一化规则在 extractNavigationName 中实现:先剥离 ?. 与 !.(对应原文档 Key Concepts 里的可选链),再按接收者判断——super 保留全限定(super.init)、self 只取末段(self.fetch → fetch)、大写开头的接收者保留限定名(Logger.info 保持 Logger.info)、小写接收者只取末段(service.fetch → fetch)。
测试用例印证了这套规则的边界情况:
- SwiftUI 结果构建器:
struct AppView { var body: some View { VStack { Text("Hi") } } }产生body → VStack与body → Text(对应原文档 Key Concepts 的 Result Builders,见 测试用例); - 构造器形态的调用:
User(name: "A")记录为make → User; - 闭包内的调用归属外层函数:
items.map { transform($0) }中的map/transform都归属build(对应原文档的 Closures); - 顶层无外层可调用的语句不产生调用边:
let booted = bootstrap()记录为空。
三、WASM 语法与运行链路
SwiftExtractor 依赖的 Swift 语法是项目自托管的 WASM 包 @understand-anything/tree-sitter-swift-wasm:
Vendored tree-sitter-swift WASM grammar built with the modern dylink.0 ABI for use with web-tree-sitter@^0.26.
swiftConfig.treeSitter 声明了 wasmPackage 与 wasmFile(tree-sitter-swift.wasm)两个字段;语法包的构建细节记录在 BUILD.md。整个链路是:TreeSitterPlugin 加载 wasm 语法 → 按扩展名把 .swift 文件分派给 SwiftExtractor(languageIds = ["swift"])→ 产出 functions/classes/imports/exports 与调用图 → 汇入 knowledge-graph.json 的节点与边。插件集成测试 用一个最小 SwiftUI App(@main struct MyApp: App { ... WindowGroup { ContentView() } })验证了全链路:import SwiftUI 被识别、MyApp 与 body 被提取为类条目、WindowGroup 与 ContentView 进入调用图。
四、小结:一份提示词素材的双重角色
回到 swift.md 本身。它只有几十行,但在 Understand-Anything 中承担了两个相互咬合的角色:
- 提示词角色:Phase 4 中被整体注入 architecture-analyzer 的
## Language Context,让 LLM 用 Swift 的惯用语言(可选值、协议、入口点、Package.swift配置、Tests/目录)去划分架构层、撰写摘要与languageNotes; - 知识基线角色:其中的关键概念、文件模式与导入模式,在 swiftConfig 的
concepts/filePatterns与 SwiftExtractor 的解析规则中有确定性的对应实现,并有 完整测试套件 逐条锁定行为。
这种"LLM 侧语义 + 解析器侧结构"的双轨设计,正是 Understand-Anything 把任意 Swift 代码库变成可探索、可搜索、可提问的知识图谱的底层机制之一。
atomcodeClaude Code 的开源替代方案。连接任意大模型,编辑代码,运行命令,自动验证 — 全自动执行。用 Rust 构建,极致性能。 | An open-source alternative to Claude Code. Connect any LLM, edit code, run commands, and verify changes — autonomously. Built in Rust for speed. Get StartedRust0624
Hy4-previewHy4 preview 是由腾讯混元团队研发的新一代混合专家(MoE)旗舰模型。模型总参数量 770B,每个 token 激活 49B,主干共包含78层,第一层采用标准 FFN,其余 77 层均为 MoE 结构,每层包含 256 个路由专家与 1 个共享专家,每个 token 激活 top-8 路由专家及共享专家。主干之外原生内置 1 层 MTP(总参数量 10B,激活 0.7B)以支持投机解码。Python00
GLM-5.3GLM-5.3 与 GLM-5.2 使用相同的基座模型——所有提升均来自后训练。与 GLM-5.2 相比,它在复杂编程和长程任务上的表现显著提升。Jinja00
GLM-5.3-FlashGLM-5.3-Flash (320B-A18B),是GLM-5系列的首个原生多模态模型。320B总参数,能力超过GLM-5.2Jinja00
Spark-X2.5-4BSpark-X2.5-4B 旨在让强大的 AI 更实用、更高效、更易获得。在广泛日常任务中表现强劲,涵盖对话、写作、翻译、推理、编码、工具调用以及智能体工作流,并在同等规模的开源模型中取得领先成绩。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00
Spark-X2.5-1.7BSpark-X2.5-1.7B 旨在让强大的 AI 更加实用、高效且易于获取。这些模型在广泛的日常任务中表现出色,涵盖对话、写作、翻译、推理、编程、工具调用和智能体工作流,并在同等规模的开源模型中取得领先结果。Spark-X2.5 将面向效率的架构与最高 1M tokens 的原生上下文窗口相结合,并支持 200 多种语言。Python00