9.2 KiB
工程结构与源码搜索
除特别说明外,命令从 ShadowsocksX-NG2/ 执行,文中工程路径也相对于该目录。
工程结构
-
project.yml— XcodeGen 工程定义,唯一事实来源。.xcodeproj与App/Resources/Info.plist、*.entitlements、Tests/Info.plist都是生成物(已 gitignore),改工程结构一律改project.yml后重新生成。 -
App/— app target 源码(SwiftUI 菜单栏 app,LSUIElement)。目录即分层,层内按功能分组:Composition/— 组合根与进程生命周期:@main、依赖装配、应用形态与窗口激活策略。Application/— 应用层(无 SwiftUI 视图):*Workflow/工作流 module(UI-facing interface 与实现协作者)、ProxyRuntime/运行时控制器家族与事实投影、Services/LaunchAgent/登录项/helper/防火墙。Presentation/— 跨功能表现层:错误呈现、被多个界面共用的状态模型。UI/— 视图层,按子视图分目录(Workspace/、Home/、Servers/、Subscriptions/、Rules/、Settings/、Diagnostics/、StatusMenu/,Servers/Plugin/为插件管理子视图)。PlatformEffects/— 平台效应 seam(协议 + AppKit adapter;测试替身在Tests/Support/),系统框架访问集中于此。Resources/—Info.plist、entitlements(生成物)与Assets.xcassets、*.xcstrings(入库)。
分层边界由
Tests/Architecture/SkeletonTests.swift的正向圈定守卫断言:只扫描App/UI/,视图层不得引用运行时控制器、工作流实现协作者或原始目录/凭据存储类型;新增运行时适配器放进Application/即自动落在扫描范围外,无需登记豁免。注意App/下任何非源码文件都会被 XcodeGen 收进 Resources 阶段并封进签名后的 bundle,因此文档不放App/(project.yml已排除**/*.md)。分层与主题的组织方式、守卫为何取正面圈定、以及 XcodeGen 的上述约束见 ADR-0029。 -
Agent/— 独立的后台监管可执行文件,装入Contents/MacOS/,由 LaunchAgent 常驻。只读取非秘密agent-supervision.json,切换稳定配置与 ACL 链接,启动和监管 sslocal;不解析 sslocal 配置或 LAN 凭据。发布与失败处理见 ADR-0037、ADR-0038,GUI 单向配置输出见 ADR-0043。 -
LaunchAgent/—SMAppService.agent(plistName:)的注册清单,装入Contents/Library/LaunchAgents/;ProgramArguments用 bundle 相对路径,由 launchd 按注册 app 的 bundle 位置解析。 -
Domain/— 领域核心(配置目录树、凭据引用与持久化,spec #21 D3/D5),与 UI 无关。目录即主题,根下不留平铺文件,子目录口径取自 术语表 的章节划分:Catalog/— 配置目录树、结构不变量错误、目录文件存储、节点与凭据身份,以及ss://编解码SsUri。Subscription/— 订阅文档解析、抓取、订阅记录与刷新失败。Rules/— 代理模式、规则身份与匹配、内置规则快照、规则集合/浏览/分析、离线规则测试;Rules/Custom/为用户自定义规则的编辑草稿、校验与存储。Runtime/— 代理运行服务:运行时文档与监听设置、ACL 与部署收据、路径、原子写入、文件存储、日志与事件(统一日志发射单元SystemLog、统一日志行LogLine、sslocal 输出 intake)、端点/端口/socket 探针。Activation/— 激活候选校验、激活状态机与RuntimeConfiguration。Settings/— 代理监听配置文件、独立代理控制偏好、运行计算的内存快照与静默启动偏好。SystemProxy/— 系统代理 typed 配置、property list 映射、计划器、特权 helper 的 XPC 契约/请求引擎与 helper 侧日志事件。Plugin/— 托管插件、用户插件映射与插件安全校验。Credentials/、LegacyImport/、Diagnostics/— 主密钥存储与加密文件提交、旧版导入、诊断报告。
跨进程契约按文件编入其它 target:
Runtime/的 9 个文件和Settings/ApplicationSupportPaths.swift同时编入 wrapper(RuntimePaths、RuntimeSupervision、RuntimeLog、SystemLog、LogLine、SslocalOutputIntake等),SystemProxy/全部 7 个文件连同Runtime/SystemLog.swift编入特权 helper(helper 侧日志只进统一日志,ADR-0047)。project.yml里这 18 条是显式路径,在Domain/内移动文件必须同步,漏改会让xcodegen generate以缺文件直接失败。布局守卫(Tests/Architecture/SkeletonTests.swift的DomainLayoutTests)断言根下无平铺.swift、树下只有.swift(非源码文件会被 XcodeGen 收进 Resources 阶段并封进签名后的 bundle)。 -
Tests/— 单元测试 target,随ShadowsocksX-NG2scheme 运行。目录即主题,根下不留平铺测试文件:Architecture/— 跨切面工程约束守卫(分层与布局、平台效应 seam、开窗落点、清单完整性),扫源码或构建产物而不驱动行为。TestSupport/— 测试等待与清理 helper 的故障回归用例。Support/— 夹具、替身与 helper,不含用例(CatalogFixtures、ProxyRuntimeFixture、SystemProxyFakes、AppArtifact、TestSourceTree等)。Agent/、Activation/、Catalog/(工作流用例在Catalog/Workflow/)、Subscription/、Rules/(自定义规则在Rules/Custom/)、ProxyRuntime/、ProxyControl/、Runtime/、Settings/、SystemProxy/、Plugin/、Diagnostics/、Credentials/、Workspace/、Servers/— 按功能领域的用例,与生产代码的领域主题和*Workflow同名同界。Smoke/— 真实进程冒烟,独立 target 与 scheme(task test:smoke)。Fixtures/RuleSnapshots/— 生成的内置规则快照夹具,作为 folder resource 随测试 bundle 发布(GeneratedRuleSnapshotTests按subdirectory:读)。
断言需要读源码树(
Vendor/清单、App/、Domain/)时一律经Support/TestSourceTree.swift从#filePath沿父目录上溯定位ShadowsocksX-NG2/,不写死父目录层数——测试文件处于不同深度,写死层数会在文件移动后静默指错。布局守卫TestsLayoutTests只断言根层无平铺.swift(比Domain/那条弱一档:根层的Info.plist与Fixtures/下的 JSON 都必须在)。Tests/Support/AppArtifact.swift同时编入 Smoke target,是project.yml里的显式文件路径,移动需同步。 -
Vendor/<name>/manifest.json— 外部二进制的固定供应链清单(tag + 资产 URL + 资产 SHA-256 + bundle 内位置 + 签名 identifier);二进制本体与.fetched.sha256戳是构建缓存,不入库。 -
Vendor/rules/geolocation-cn/— 内置中国域名规则快照(issue #63):snapshot.json(规范化规则 + 元数据 + 损失报告)、manifest.json(上游版本与快照 SHA-256)、NOTICE(许可证与归属)。普通构建只读本地快照,绝不抓取或转换。 -
Vendor/rules/china-ipv4/— 内置中国 IPv4 CIDR 直连候选快照(issue #64):同上三件套,来源为 gaoyifan/china-operator-ipchina.txt固定 commit。规则模式的proxy_allACL 同时编入中国域名与 IPv4 CIDR 直连候选。 -
Vendor/rules/gfwlist/— 内置 GFWList 代理候选快照(issue #65):同上三件套,来源为 gfwlist/gfwlist 官方 Base64 AutoProxygfwlist.txt固定 commit。域名锚点转换为后缀匹配,满足条件的空路径或根路径 URL 前缀转换为精确域名匹配;「未匹配时直连」的bypass_allACL 编入这些代理候选。 -
Scripts/— 供应链脚本(见外部二进制供应链)与打包门槛断言;另有update-geolocation-cn.sh/update-china-ipv4.sh/update-gfwlist.sh(显式维护动作,抓取固定版上游并转换)与verify-rule-snapshots.sh(构建前离线校验快照完整性)。
源码搜索
先按上面的目录分层用 rg --files 定位,再限定目录或文件类型搜索内容;未找到时逐步扩大范围。以下命令从 ShadowsocksX-NG2/ 执行:
# 查外部二进制版本与来源,先定位对应清单
rg --files Vendor/sslocal -g 'manifest.json'
# 查运行职责,限定相关 Swift 源码
rg -n -g '*.swift' 'sslocal|reload' Agent Domain/Runtime App/Application/ProxyRuntime
# 查规则内容时先只列出命中文件
rg -l '关键词' Vendor/rules Tests/Fixtures/RuleSnapshots
# 需要显示匹配行时,省略超长行并保留命中提示
rg -n -M 300 '关键词' Vendor/rules
Vendor/rules/*/snapshot.json 与 Tests/Fixtures/RuleSnapshots/*.json 是生成的单行 JSON。-M 300 按字节限制长行显示,不限制总输出量;-m 和 head -n 只限制行数,不能防止单条长行撑大输出。需要完整规则时,定位具体快照后按 JSON 字段读取。清单与 NOTICE 也保留在各自的 Vendor 目录中,可按需单独搜索。