feat: 根目录文档、脚本、gitignore
This commit is contained in:
@@ -0,0 +1,880 @@
|
||||
# sourcekit-lsp 使用指南
|
||||
|
||||
> 通过 Serena MCP 工具调用 sourcekit-lsp 进行 Swift/iOS 代码分析
|
||||
|
||||
## 前置条件
|
||||
|
||||
### 1. 确保 sourcekit-lsp 已安装
|
||||
|
||||
sourcekit-lsp 随 Xcode 一起安装,位于 Xcode 工具链中:
|
||||
|
||||
```bash
|
||||
# 验证 sourcekit-lsp 是否可用
|
||||
xcrun sourcekit-lsp --version
|
||||
|
||||
# 或者直接定位
|
||||
xcrun --find sourcekit-lsp
|
||||
|
||||
# 输出示例:
|
||||
# /Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/sourcekit-lsp
|
||||
```
|
||||
|
||||
### 2. 项目结构要求
|
||||
|
||||
sourcekit-lsp 需要以下文件来识别 iOS/Swift 项目:
|
||||
|
||||
- Xcode 项目: `*.xcodeproj` 或 `*.xcworkspace`
|
||||
- Swift Package: `Package.swift`
|
||||
- CocoaPods: `Podfile` + `*.xcworkspace`
|
||||
- Carthage: `Cartfile`
|
||||
|
||||
**注意**: 对于使用 CocoaPods 的项目,必须先执行 `pod install` 生成 workspace。
|
||||
|
||||
---
|
||||
|
||||
## 通过 Serena 使用 sourcekit-lsp
|
||||
|
||||
### 激活项目
|
||||
|
||||
```yaml
|
||||
# Step 1: 激活 Swift/iOS 项目
|
||||
tool: mcp__serena__activate_project
|
||||
params:
|
||||
project: "/path/to/ios/project"
|
||||
|
||||
# 返回: 项目已激活,sourcekit-lsp 已初始化
|
||||
```
|
||||
|
||||
### 验证配置
|
||||
|
||||
```yaml
|
||||
# 检查当前配置
|
||||
tool: mcp__serena__get_current_config
|
||||
|
||||
# 确认输出包含:
|
||||
# - active_project: /path/to/ios/project
|
||||
# - language_server: sourcekit-lsp
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 符号提取操作
|
||||
|
||||
### 获取文件符号概览
|
||||
|
||||
```yaml
|
||||
# 获取单个文件的符号列表(不含代码体)
|
||||
tool: mcp__serena__get_symbols_overview
|
||||
params:
|
||||
relative_path: "MyApp/ViewModels/HomeViewModel.swift"
|
||||
depth: 1 # 0=仅顶层, 1=含直接成员, 2=含嵌套成员
|
||||
|
||||
# 返回示例:
|
||||
# Classes:
|
||||
# - HomeViewModel (class) [12-187]
|
||||
# Structs:
|
||||
# - Input (struct) [15-25]
|
||||
# - Output (struct) [27-40]
|
||||
# Properties:
|
||||
# - disposeBag (property) [14-14]
|
||||
# - userService (property) [13-13]
|
||||
# Methods:
|
||||
# - transform(input:) (method) [42-120]
|
||||
# - fetchUserData() (method) [122-150]
|
||||
```
|
||||
|
||||
### 查找符号
|
||||
|
||||
```yaml
|
||||
# 按名称模式查找符号
|
||||
tool: mcp__serena__find_symbol
|
||||
params:
|
||||
name_path_pattern: "HomeViewModel"
|
||||
relative_path: "MyApp/ViewModels/"
|
||||
include_body: false
|
||||
include_info: true
|
||||
depth: 1
|
||||
|
||||
# 名称模式规则:
|
||||
# - "HomeViewModel" -> 匹配任何包含此名称的符号
|
||||
# - "ViewModels/HomeViewModel" -> 匹配此路径后缀
|
||||
# - "/MyApp.HomeViewModel" -> 精确匹配完整路径
|
||||
# - "HomeViewModel/transform" -> 匹配类中的方法
|
||||
```
|
||||
|
||||
### 获取符号详情(含代码体)
|
||||
|
||||
```yaml
|
||||
# 获取完整的符号定义(含代码)
|
||||
tool: mcp__serena__find_symbol
|
||||
params:
|
||||
name_path_pattern: "HomeViewModel/fetchUserData"
|
||||
relative_path: "MyApp/ViewModels/HomeViewModel.swift"
|
||||
include_body: true
|
||||
depth: 0
|
||||
|
||||
# 返回包含:
|
||||
# - 方法签名
|
||||
# - 文档注释
|
||||
# - 完整方法体
|
||||
# - 行号范围
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 引用分析操作
|
||||
|
||||
### 查找符号引用
|
||||
|
||||
```yaml
|
||||
# 查找某个符号被哪些地方引用
|
||||
tool: mcp__serena__find_referencing_symbols
|
||||
params:
|
||||
name_path: "UserService/fetchUser"
|
||||
relative_path: "MyApp/Services/UserService.swift"
|
||||
include_info: true
|
||||
|
||||
# 返回示例:
|
||||
# References (3 found):
|
||||
# - HomeViewModel.fetchUserData [45:12-45:35]
|
||||
# snippet: "userService.fetchUser()"
|
||||
# - ProfileViewModel.loadProfile [67:8-67:31]
|
||||
# snippet: "userService.fetchUser()"
|
||||
```
|
||||
|
||||
### 模式搜索(补充 LSP)
|
||||
|
||||
```yaml
|
||||
# 当 LSP 无法找到时,使用模式搜索
|
||||
tool: mcp__serena__search_for_pattern
|
||||
params:
|
||||
substring_pattern: "\.subscribe\(onNext:"
|
||||
paths_include_glob: "**/*.swift"
|
||||
restrict_search_to_code_files: true
|
||||
context_lines_before: 2
|
||||
context_lines_after: 2
|
||||
|
||||
# 适用场景:
|
||||
# - RxSwift 订阅链
|
||||
# - Protocol extension 方法
|
||||
# - 动态类型调用
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Swift 特有处理
|
||||
|
||||
### Swift 特有关键字与结构
|
||||
|
||||
```yaml
|
||||
# Swift 特有符号类型
|
||||
struct:
|
||||
pattern: "struct \\w+"
|
||||
description: "Swift 结构体,值类型"
|
||||
|
||||
class:
|
||||
pattern: "class \\w+"
|
||||
description: "Swift 类,引用类型"
|
||||
|
||||
enum:
|
||||
pattern: "enum \\w+"
|
||||
description: "Swift 枚举,支持关联值"
|
||||
|
||||
protocol:
|
||||
pattern: "protocol \\w+"
|
||||
description: "Swift 协议,类似接口"
|
||||
|
||||
extension:
|
||||
pattern: "extension \\w+"
|
||||
description: "Swift 扩展,为类型添加功能"
|
||||
|
||||
typealias:
|
||||
pattern: "typealias \\w+"
|
||||
description: "类型别名"
|
||||
|
||||
@propertyWrapper:
|
||||
pattern: "@\\w+\\s+(var|let)"
|
||||
description: "属性包装器"
|
||||
|
||||
computed_property:
|
||||
pattern: "var \\w+: \\w+ \\{"
|
||||
description: "计算属性"
|
||||
|
||||
lazy_property:
|
||||
pattern: "lazy var \\w+"
|
||||
description: "延迟初始化属性"
|
||||
```
|
||||
|
||||
### iOS MVVM 架构层识别
|
||||
|
||||
```yaml
|
||||
# 根据命名约定和基类识别架构层
|
||||
|
||||
ViewController 层:
|
||||
naming: "*ViewController.swift", "*VC.swift"
|
||||
base_classes:
|
||||
- "UIViewController"
|
||||
- "BaseViewController"
|
||||
- "UITableViewController"
|
||||
- "UICollectionViewController"
|
||||
key_elements:
|
||||
- "viewDidLoad()"
|
||||
- "viewWillAppear(_:)"
|
||||
- "IBOutlet"
|
||||
- "IBAction"
|
||||
|
||||
ViewModel 层:
|
||||
naming: "*ViewModel.swift", "*VM.swift"
|
||||
protocols:
|
||||
- "ViewModelProtocol"
|
||||
- "ViewModelType"
|
||||
key_elements:
|
||||
- "struct Input"
|
||||
- "struct Output"
|
||||
- "func transform(input:)"
|
||||
- "DisposeBag"
|
||||
|
||||
Service 层:
|
||||
naming: "*Service.swift", "*Manager.swift"
|
||||
patterns:
|
||||
- "static let shared"
|
||||
- "func fetch"
|
||||
- "func request"
|
||||
key_elements:
|
||||
- "Observable<"
|
||||
- "Single<"
|
||||
- "Completable"
|
||||
|
||||
Model 层:
|
||||
naming: "*Model.swift", "*Entity.swift", "*Response.swift"
|
||||
markers:
|
||||
- ": Codable"
|
||||
- ": Decodable"
|
||||
- ": Encodable"
|
||||
key_elements:
|
||||
- "enum CodingKeys"
|
||||
- "init(from decoder:)"
|
||||
|
||||
Network 层:
|
||||
naming: "*API.swift", "*Router.swift", "*Target.swift"
|
||||
protocols:
|
||||
- "TargetType"
|
||||
- "URLRequestConvertible"
|
||||
key_elements:
|
||||
- "var baseURL: URL"
|
||||
- "var path: String"
|
||||
- "var method: Moya.Method"
|
||||
|
||||
Coordinator 层:
|
||||
naming: "*Coordinator.swift", "*Navigator.swift"
|
||||
protocols:
|
||||
- "Coordinator"
|
||||
- "CoordinatorType"
|
||||
key_elements:
|
||||
- "var childCoordinators"
|
||||
- "func start()"
|
||||
- "weak var parentCoordinator"
|
||||
|
||||
Extension 层:
|
||||
naming: "*+*.swift"
|
||||
description: "Swift extension 文件 (e.g., String+Extensions.swift)"
|
||||
patterns:
|
||||
- "extension \\w+ \\{"
|
||||
- "extension \\w+: \\w+ \\{"
|
||||
```
|
||||
|
||||
### Moya API 识别
|
||||
|
||||
```yaml
|
||||
# Moya TargetType 枚举识别
|
||||
|
||||
TargetType 协议:
|
||||
description: "Moya 网络请求定义协议"
|
||||
required_properties:
|
||||
- "baseURL: URL"
|
||||
- "path: String"
|
||||
- "method: Moya.Method"
|
||||
- "task: Task"
|
||||
- "headers: [String: String]?"
|
||||
|
||||
# 提取示例
|
||||
tool: mcp__serena__search_for_pattern
|
||||
params:
|
||||
substring_pattern: "case\\s+\\w+.*\\n.*var path"
|
||||
paths_include_glob: "**/*API.swift"
|
||||
multiline: true
|
||||
|
||||
# 解析 Moya Target
|
||||
# enum UserAPI: TargetType {
|
||||
# case login(phone: String, code: String)
|
||||
# case fetchProfile(userId: Int)
|
||||
#
|
||||
# var path: String {
|
||||
# switch self {
|
||||
# case .login:
|
||||
# return "/api/v1/user/login"
|
||||
# case .fetchProfile(let userId):
|
||||
# return "/api/v1/user/\(userId)"
|
||||
# }
|
||||
# }
|
||||
# }
|
||||
#
|
||||
# 提取:
|
||||
# - case: login
|
||||
# path: /api/v1/user/login
|
||||
# method: POST (从 method 属性推断)
|
||||
# params: [phone: String, code: String]
|
||||
#
|
||||
# - case: fetchProfile
|
||||
# path: /api/v1/user/{userId}
|
||||
# method: GET
|
||||
# params: [userId: Int]
|
||||
```
|
||||
|
||||
### Alamofire 请求识别
|
||||
|
||||
```yaml
|
||||
# Alamofire 请求模式
|
||||
|
||||
AF.request:
|
||||
description: "Alamofire 5.x 请求"
|
||||
pattern: "AF\\.request\\("
|
||||
example: |
|
||||
AF.request("https://api.example.com/users",
|
||||
method: .get,
|
||||
parameters: params,
|
||||
encoding: URLEncoding.default)
|
||||
.responseDecodable(of: UserResponse.self) { response in
|
||||
// handle response
|
||||
}
|
||||
|
||||
session.request:
|
||||
description: "Session 实例请求"
|
||||
pattern: "session\\.request\\("
|
||||
|
||||
URLRequestConvertible:
|
||||
description: "自定义请求构建器"
|
||||
protocol: "URLRequestConvertible"
|
||||
method: "asURLRequest() throws -> URLRequest"
|
||||
```
|
||||
|
||||
### RxSwift/RxCocoa 模式
|
||||
|
||||
```yaml
|
||||
# RxSwift 核心类型
|
||||
rx_types:
|
||||
Observable:
|
||||
description: "可观察序列,核心类型"
|
||||
operators: ["map", "flatMap", "filter", "subscribe"]
|
||||
|
||||
Single:
|
||||
description: "单值序列,成功或失败"
|
||||
operators: ["subscribe", "map", "flatMap"]
|
||||
|
||||
Completable:
|
||||
description: "无值序列,仅完成或失败"
|
||||
operators: ["subscribe", "andThen"]
|
||||
|
||||
Maybe:
|
||||
description: "可选单值序列"
|
||||
operators: ["subscribe", "map"]
|
||||
|
||||
Driver:
|
||||
description: "UI 绑定专用,主线程、无错误、共享"
|
||||
from: "asDriver()"
|
||||
|
||||
Signal:
|
||||
description: "类似 Driver,但不重放"
|
||||
from: "asSignal()"
|
||||
|
||||
# RxSwift Subject 类型
|
||||
rx_subjects:
|
||||
PublishSubject:
|
||||
description: "无初始值,只发送新事件"
|
||||
usage: "事件总线"
|
||||
|
||||
BehaviorSubject:
|
||||
description: "有初始值,发送最新值"
|
||||
usage: "状态管理"
|
||||
|
||||
ReplaySubject:
|
||||
description: "缓存指定数量事件"
|
||||
usage: "历史事件回放"
|
||||
|
||||
PublishRelay:
|
||||
description: "PublishSubject 无 error/complete"
|
||||
usage: "UI 事件转发"
|
||||
|
||||
BehaviorRelay:
|
||||
description: "BehaviorSubject 无 error/complete"
|
||||
usage: "状态绑定"
|
||||
|
||||
# 常用操作符
|
||||
rx_operators:
|
||||
transformation:
|
||||
- "map"
|
||||
- "flatMap"
|
||||
- "flatMapLatest"
|
||||
- "compactMap"
|
||||
- "scan"
|
||||
|
||||
filtering:
|
||||
- "filter"
|
||||
- "distinctUntilChanged"
|
||||
- "debounce"
|
||||
- "throttle"
|
||||
- "skip"
|
||||
- "take"
|
||||
|
||||
combining:
|
||||
- "merge"
|
||||
- "combineLatest"
|
||||
- "zip"
|
||||
- "withLatestFrom"
|
||||
- "concat"
|
||||
|
||||
error_handling:
|
||||
- "catchError"
|
||||
- "catchErrorJustReturn"
|
||||
- "retry"
|
||||
- "retryWhen"
|
||||
|
||||
utility:
|
||||
- "do(onNext:)"
|
||||
- "delay"
|
||||
- "observeOn"
|
||||
- "subscribeOn"
|
||||
- "share"
|
||||
- "replay"
|
||||
|
||||
# 提取 RxSwift 模式
|
||||
tool: mcp__serena__search_for_pattern
|
||||
params:
|
||||
substring_pattern: "\\.(map|flatMap|filter|subscribe)\\s*\\{"
|
||||
paths_include_glob: "**/*.swift"
|
||||
```
|
||||
|
||||
### Combine 模式(Swift 原生响应式)
|
||||
|
||||
```yaml
|
||||
# Combine 核心类型
|
||||
combine_types:
|
||||
Publisher:
|
||||
description: "发布者协议"
|
||||
operators: ["map", "flatMap", "sink", "assign"]
|
||||
|
||||
AnyPublisher:
|
||||
description: "类型擦除发布者"
|
||||
usage: "API 返回类型"
|
||||
|
||||
PassthroughSubject:
|
||||
description: "类似 PublishSubject"
|
||||
usage: "事件发送"
|
||||
|
||||
CurrentValueSubject:
|
||||
description: "类似 BehaviorSubject"
|
||||
usage: "状态管理"
|
||||
|
||||
@Published:
|
||||
description: "属性包装器,自动发布变化"
|
||||
usage: "SwiftUI/Combine 状态"
|
||||
|
||||
AnyCancellable:
|
||||
description: "订阅句柄"
|
||||
usage: "生命周期管理"
|
||||
|
||||
# 识别 Combine 使用
|
||||
tool: mcp__serena__search_for_pattern
|
||||
params:
|
||||
substring_pattern: "@Published|PassthroughSubject|CurrentValueSubject|\\.sink\\("
|
||||
paths_include_glob: "**/*.swift"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## LSP SymbolKind 映射
|
||||
|
||||
```yaml
|
||||
# sourcekit-lsp 返回的 SymbolKind 数值对照
|
||||
|
||||
1: File
|
||||
2: Module
|
||||
3: Namespace # extension
|
||||
4: Package
|
||||
5: Class # class
|
||||
6: Method # func (instance)
|
||||
7: Property # var/let (instance)
|
||||
8: Field
|
||||
9: Constructor # init
|
||||
10: Enum # enum
|
||||
11: Interface # protocol
|
||||
12: Function # func (top-level/static)
|
||||
13: Variable # var/let (local)
|
||||
14: Constant # let (constant)
|
||||
15: String
|
||||
16: Number
|
||||
17: Boolean
|
||||
18: Array
|
||||
19: Object
|
||||
20: Key
|
||||
21: Null
|
||||
22: EnumMember # enum case
|
||||
23: Struct # struct
|
||||
24: Event
|
||||
25: Operator
|
||||
26: TypeParameter # associated type / generic
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 调用链构建
|
||||
|
||||
### ViewController -> ViewModel 调用链
|
||||
|
||||
```python
|
||||
# 伪代码: 构建 MVVM 调用链
|
||||
|
||||
def build_mvvm_chain(viewcontroller_path):
|
||||
# Step 1: 获取 ViewController 符号
|
||||
vc_symbols = get_symbols_overview(viewcontroller_path, depth=2)
|
||||
|
||||
# Step 2: 识别 ViewModel 依赖
|
||||
# 查找类似: private let viewModel = HomeViewModel()
|
||||
# 或: private var viewModel: HomeViewModelType!
|
||||
vm_deps = extract_viewmodel_deps(vc_symbols)
|
||||
|
||||
# Step 3: 追踪 ViewModel 绑定
|
||||
for vm in vm_deps:
|
||||
# 获取 ViewModel 定义
|
||||
vm_symbols = get_symbols_overview(vm.file_path, depth=2)
|
||||
|
||||
# 查找 Input/Output 模式
|
||||
if has_input_output_pattern(vm_symbols):
|
||||
input_struct = find_symbol("Input", vm.file_path)
|
||||
output_struct = find_symbol("Output", vm.file_path)
|
||||
transform_method = find_symbol("transform", vm.file_path, include_body=True)
|
||||
|
||||
# 追踪 Service 调用
|
||||
service_calls = extract_service_calls(transform_method.body)
|
||||
|
||||
return chain
|
||||
```
|
||||
|
||||
### ViewModel -> Service -> API 调用链
|
||||
|
||||
```yaml
|
||||
# 实际操作步骤
|
||||
|
||||
# 1. 获取 ViewModel 方法
|
||||
tool: mcp__serena__find_symbol
|
||||
params:
|
||||
name_path_pattern: "HomeViewModel/fetchUserData"
|
||||
relative_path: "MyApp/ViewModels/"
|
||||
include_body: true
|
||||
|
||||
# 2. 分析方法体中的 Service 调用
|
||||
# 从返回的 body 中提取: userService.fetchUser()
|
||||
|
||||
# 3. 定位 Service 方法
|
||||
tool: mcp__serena__find_symbol
|
||||
params:
|
||||
name_path_pattern: "UserService/fetchUser"
|
||||
relative_path: "MyApp/Services/"
|
||||
include_body: true
|
||||
|
||||
# 4. 分析 Service 中的 API 调用
|
||||
# 从返回的 body 中提取: provider.request(.fetchProfile(userId))
|
||||
|
||||
# 5. 定位 Moya Target
|
||||
tool: mcp__serena__search_for_pattern
|
||||
params:
|
||||
substring_pattern: "case fetchProfile"
|
||||
paths_include_glob: "**/*API.swift"
|
||||
context_lines_after: 10
|
||||
|
||||
# 6. 提取端点信息
|
||||
# case fetchProfile(userId: Int)
|
||||
# path: "/api/v1/user/\(userId)"
|
||||
# method: .get
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 大规模项目处理
|
||||
|
||||
### 项目规模评估
|
||||
|
||||
```bash
|
||||
# 评估 Swift 项目规模
|
||||
find /path/to/project -name "*.swift" -not -path "*/Pods/*" -not -path "*/Carthage/*" | wc -l
|
||||
# 输出: 3602 (文件数)
|
||||
|
||||
find /path/to/project -name "*.swift" -not -path "*/Pods/*" -not -path "*/Carthage/*" -exec wc -l {} + | tail -1
|
||||
# 输出: 424000 (总行数)
|
||||
```
|
||||
|
||||
### 分批处理策略
|
||||
|
||||
```yaml
|
||||
# 大规模项目(424K 行)处理策略
|
||||
|
||||
batch_processing:
|
||||
description: "按模块分批处理,避免内存溢出"
|
||||
|
||||
# Step 1: 按目录分组
|
||||
grouping:
|
||||
- "AppDelegate.swift" # 入口点优先
|
||||
- "**/Coordinator/**/*.swift" # 导航层
|
||||
- "**/ViewModel/**/*.swift" # ViewModel 层
|
||||
- "**/Service/**/*.swift" # Service 层
|
||||
- "**/Network/**/*.swift" # Network 层
|
||||
- "**/Model/**/*.swift" # Model 层
|
||||
- "**/View/**/*.swift" # View 层
|
||||
- "**/Extension/**/*.swift" # Extension 层
|
||||
- "**/*.swift" # 其他
|
||||
|
||||
# Step 2: 批次配置
|
||||
batch_config:
|
||||
batch_size: 100 # 每批 100 个文件
|
||||
parallel_batches: 3 # 最多 3 个并行批次
|
||||
checkpoint_interval: 50 # 每 50 个文件保存检查点
|
||||
|
||||
# Step 3: 内存管理
|
||||
memory_management:
|
||||
release_after_batch: true # 每批处理后释放内存
|
||||
stream_output: true # 流式写入输出文件
|
||||
|
||||
# 处理流程
|
||||
procedure:
|
||||
- step: "scan_and_group"
|
||||
description: "扫描文件并按层分组"
|
||||
|
||||
- step: "process_core_first"
|
||||
description: "优先处理核心文件"
|
||||
files:
|
||||
- "AppDelegate.swift"
|
||||
- "SceneDelegate.swift"
|
||||
- "*Coordinator.swift"
|
||||
|
||||
- step: "batch_process"
|
||||
description: "分批处理各层"
|
||||
for_each_batch: "grouped_files | batch(100)"
|
||||
actions:
|
||||
- "extract_symbols"
|
||||
- "analyze_layer"
|
||||
- "save_checkpoint"
|
||||
|
||||
- step: "merge_results"
|
||||
description: "合并所有批次结果"
|
||||
```
|
||||
|
||||
### Pod 模块边界识别
|
||||
|
||||
```yaml
|
||||
# 分析 Podfile 识别模块边界
|
||||
|
||||
# Step 1: 读取 Podfile
|
||||
tool: Read
|
||||
params:
|
||||
file_path: "/path/to/project/Podfile"
|
||||
|
||||
# Step 2: 提取 Pod 依赖
|
||||
patterns:
|
||||
- "pod '([^']+)'(?:,\\s*'([^']+)')?"
|
||||
- "pod \"([^\"]+)\"(?:,\\s*\"([^\"]+)\")?"
|
||||
|
||||
# Step 3: 分类 Pod
|
||||
categories:
|
||||
networking:
|
||||
- "Alamofire"
|
||||
- "Moya"
|
||||
- "AFNetworking"
|
||||
- "Kingfisher"
|
||||
- "SDWebImage"
|
||||
|
||||
reactive:
|
||||
- "RxSwift"
|
||||
- "RxCocoa"
|
||||
- "RxRelay"
|
||||
- "RxDataSources"
|
||||
- "RxGesture"
|
||||
|
||||
ui:
|
||||
- "SnapKit"
|
||||
- "Masonry"
|
||||
- "MBProgressHUD"
|
||||
- "SVProgressHUD"
|
||||
- "MJRefresh"
|
||||
|
||||
database:
|
||||
- "Realm"
|
||||
- "FMDB"
|
||||
- "GRDB"
|
||||
- "CoreStore"
|
||||
|
||||
analytics:
|
||||
- "Firebase"
|
||||
- "Bugly"
|
||||
- "UMAnalytics"
|
||||
|
||||
testing:
|
||||
- "Quick"
|
||||
- "Nimble"
|
||||
- "RxTest"
|
||||
- "RxBlocking"
|
||||
|
||||
# Step 4: 分析模块边界
|
||||
module_boundaries:
|
||||
description: "识别 Pod 模块边界"
|
||||
analysis:
|
||||
- "哪些模块依赖 RxSwift"
|
||||
- "网络层使用哪个库"
|
||||
- "UI 组件库选型"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 常见问题
|
||||
|
||||
### Q: sourcekit-lsp 启动慢
|
||||
|
||||
```
|
||||
A: sourcekit-lsp 首次索引项目可能较慢:
|
||||
- 大型项目(3600+ 文件)可能需要几分钟
|
||||
- 确保 Xcode 和 Command Line Tools 已安装
|
||||
建议: 先执行 xcodebuild 构建项目预热索引
|
||||
|
||||
# 预热命令
|
||||
xcodebuild -workspace MyApp.xcworkspace -scheme MyApp -configuration Debug build
|
||||
```
|
||||
|
||||
### Q: 找不到 Swift 符号
|
||||
|
||||
```
|
||||
A: 可能原因:
|
||||
1. 项目未正确配置(缺少 xcworkspace)
|
||||
2. CocoaPods 未安装(先执行 pod install)
|
||||
3. 符号在 Pods 目录中(被排除)
|
||||
4. Swift Package 未解析
|
||||
|
||||
解决:
|
||||
1. 确保使用 .xcworkspace 而非 .xcodeproj
|
||||
2. 执行 pod install 生成 workspace
|
||||
3. 使用 search_for_pattern 作为备选
|
||||
4. 对于 SPM 项目,确保 Package.resolved 存在
|
||||
```
|
||||
|
||||
### Q: RxSwift 调用追踪不完整
|
||||
|
||||
```
|
||||
A: RxSwift 的链式调用使得静态分析困难:
|
||||
1. 操作符链可能跨越多行
|
||||
2. 闭包中的调用难以追踪
|
||||
3. 协议扩展方法无法直接定位
|
||||
|
||||
解决:
|
||||
使用 search_for_pattern 搜索特定操作符模式
|
||||
结合 Input/Output 模式分析 ViewModel
|
||||
追踪 DisposeBag 的使用位置
|
||||
```
|
||||
|
||||
### Q: Extension 方法找不到
|
||||
|
||||
```
|
||||
A: Swift extension 方法分散在多个文件中:
|
||||
1. extension 文件通常命名为 Type+Category.swift
|
||||
2. 同一类型可能有多个 extension 文件
|
||||
3. Protocol extension 更难追踪
|
||||
|
||||
解决:
|
||||
1. 先搜索 extension TypeName 识别所有扩展
|
||||
2. 使用 Glob 匹配 *+*.swift 文件
|
||||
3. 分析 Protocol extension 时搜索协议名
|
||||
```
|
||||
|
||||
### Q: Moya Target 解析
|
||||
|
||||
```
|
||||
A: Moya TargetType 是 enum,需要特殊处理:
|
||||
1. case 定义了 API 端点
|
||||
2. path/method/task 等属性需要配合分析
|
||||
3. switch self 模式匹配需要解析
|
||||
|
||||
解决:
|
||||
1. 先提取所有 case 定义
|
||||
2. 分析 path 属性的 switch 语句
|
||||
3. 匹配 case 与 path 的对应关系
|
||||
|
||||
# 示例搜索
|
||||
mcp__serena__search_for_pattern(
|
||||
substring_pattern="case \\w+.*\\n.*path:",
|
||||
paths_include_glob="**/*API.swift",
|
||||
multiline=True,
|
||||
context_lines_after=5
|
||||
)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 最佳实践
|
||||
|
||||
1. **按架构层分析** - 先识别 MVVM 各层文件,再逐层深入
|
||||
2. **ViewModel 是关键** - ViewModel 层连接 ViewController 和 Service,是分析重点
|
||||
3. **Input/Output 模式** - 识别 RxSwift MVVM 的标准模式
|
||||
4. **Pod 依赖优先** - 通过 Podfile 快速了解项目技术栈
|
||||
5. **Extension 归类** - 将 extension 文件与原类型关联
|
||||
6. **分批处理大项目** - 424K 行项目必须分批处理
|
||||
|
||||
---
|
||||
|
||||
## 项目特定模式(示例:chefu_driver_app_ios)
|
||||
|
||||
该项目使用的技术栈和模式:
|
||||
|
||||
```yaml
|
||||
架构模式: MVVM + Coordinator
|
||||
ViewController: *ViewController.swift
|
||||
ViewModel: *ViewModel.swift (Input/Output 模式)
|
||||
Service: *Service.swift (单例模式)
|
||||
Coordinator: *Coordinator.swift
|
||||
|
||||
网络层: Moya + RxSwift
|
||||
API 定义: *API.swift (TargetType enum)
|
||||
Provider: MoyaProvider<API>
|
||||
响应类型: Observable<Response>
|
||||
|
||||
响应式框架: RxSwift + RxCocoa
|
||||
ViewModel: Observable/Driver
|
||||
ViewController: DisposeBag, bind/drive
|
||||
|
||||
UI 框架:
|
||||
布局: SnapKit
|
||||
图片: Kingfisher
|
||||
刷新: MJRefresh
|
||||
|
||||
项目规模:
|
||||
文件数: 3,602 Swift 文件
|
||||
代码行数: 约 424,000 行
|
||||
Pod 依赖: 50+ 个 Pod
|
||||
|
||||
目录结构:
|
||||
MyApp/
|
||||
AppDelegate.swift
|
||||
Coordinator/ # 导航协调器
|
||||
Modules/ # 按功能模块划分
|
||||
Home/
|
||||
ViewController/
|
||||
ViewModel/
|
||||
View/
|
||||
Model/
|
||||
Order/
|
||||
...
|
||||
Services/ # 业务服务
|
||||
Network/ # 网络层
|
||||
API/
|
||||
Model/
|
||||
Common/ # 公共组件
|
||||
Base/
|
||||
Extension/
|
||||
Utils/
|
||||
```
|
||||
Reference in New Issue
Block a user