程式碼定位、追蹤與修改操作筆記
這份筆記整理一套不用 AI 時也能照著做的工作流程:如何定位函式定義、找引用、追資料流、確認行為,並安全修改檔案。
核心原則
- 先用最快的工具縮小範圍,再用更精準的工具確認語意。
- 先找「定義」與「引用」,再讀上下文,不要只看單行。
- 修改前先確認資料流與呼叫順序,修改後用
git diff、build、test 驗證。 - 對 Xcode project 管理的 Swift 檔案,新增、刪除、搬移時要注意
.xcodeprojreference。
工具選擇
| 需求 | 優先工具 | 何時使用 |
|---|---|---|
| 快速找文字、函式、變數 | rg |
第一輪定位,速度最快 |
| 看檔案行號與上下文 |
nl -ba + sed
|
找到結果後閱讀附近程式 |
| 找 Swift 定義、引用、型別 | Xcode index / SourceKit-LSP | 同名函式、overload、protocol extension 較多時 |
| Swift 語法結構分析或安全改寫 | SwiftSyntax | 需要 AST/CST 等級分析或批次 rewrite |
| 通用語法樹查詢 | tree-sitter | 想找特定語法形狀,但不需要完整型別解析 |
| C/C++/Obj-C symbol index | ctags / cscope | 老專案或 C-family code 較多時 |
| 修改既有檔案內容 | apply_patch |
小到中型人工修改 |
| 新增 Xcode project 內 Swift 檔 | Xcode MCP XcodeWrite
|
需要加入 project structure / compile sources |
| 刪除 Xcode project 檔案 | Xcode MCP XcodeRM
|
避免只刪檔案但 project reference 還留著 |
| 搬移或 rename Xcode 檔案 | Xcode MCP XcodeMV
|
避免 Xcode project reference 壞掉 |
定位函式定義
假設要找 presentWebView 的定義:
rg -n 'func\s+presentWebView\b' AppPOS -g '*.swift'
說明:
-
func:找 Swift function declaration。 -
\s+:一個或多個空白,允許func presentWebView。 -
\b:單字邊界,避免誤中presentWebViewController。 -
-n:顯示行號。 -
-g '*.swift':只查 Swift 檔。
如果函式可能是 property、closure、protocol requirement,也可以放寬:
rg -n '\bpresentWebView\b' AppPOS -g '*.swift'
找函式引用
找呼叫點:
rg -n '\bpresentWebView\s*\(' AppPOS -g '*.swift'
說明:
-
\bpresentWebView:要求是完整名稱。 -
\s*:允許函式名和(中間有空白。 -
\(:找真正的左括號。
如果有 trailing closure 或不同語法,也可先放寬:
rg -n '\bpresentWebView\b' AppPOS -g '*.swift'
再人工排除不是呼叫的結果。
閱讀上下文
找到檔案與行號後,用 nl -ba 顯示行號,再用 sed 切範圍:
nl -ba AppPOS/Common/WebView/WebViewCoordinator.swift | sed -n '30,75p'
常見用法:
nl -ba path/to/File.swift | sed -n '起始行,結束行p'
例:
nl -ba AppPOS/Payment/Payment/QRScan/QRScanViewController.swift | sed -n '24,45p;190,225p;250,265p'
這可以一次看:
- property 宣告
- delegate callback
- setup camera
追資料流的方法
以 QR/barcode 掃描為例,確認是否支援 Code 128 時,追三段:
- 支援格式宣告
rg -n 'AVMetadataObject.ObjectType|vaildObjectTypes|code128' AppPOS -g '*.swift'
看到:
private let vaildObjectTypes: [AVMetadataObject.ObjectType] = [.qr, .code93, .code128]
- 是否真的套用到相機 output
rg -n 'metadataObjectTypes\s*=' AppPOS -g '*.swift'
看到:
output.metadataObjectTypes = vaildObjectTypes
- delegate 收到後是否放行
rg -n 'metadataOutput|contains\(data.type\)|scanCodeSubject.send' AppPOS -g '*.swift'
看到:
if vaildObjectTypes.contains(data.type) {
scanCodeSubject.send(symbolData)
}
這三段都成立時,才能說「相機掃描層支援 Code 128」。
接著要追後續業務是否接受:
rg -n 'scanCodeSubject|scanCode|paymentRequest|voucherScan|voucherInquiry|isFormatValid' AppPOS -g '*.swift'
例:
input.scanCode
.map {
self.useCase.paymentRequest(..., oneTimeKey: $0)
}
或:
if !VoucherCodeChecker.isFormatValid(text: $0) {
return ""
}
這代表掃描層支援不等於業務層一定接受。
Regex 常用片段
| Regex | 意思 |
|---|---|
\s |
空白字元,包含 space、tab、換行 |
\s+ |
一個或多個空白 |
\s* |
零個或多個空白 |
\b |
單字邊界 |
\( |
左括號 (
|
. |
任意字元 |
.* |
任意字元重複零次以上 |
| `foo | bar` |
建議 shell 裡用單引號包 regex:
rg -n 'func\s+presentWebView\b' AppPOS -g '*.swift'
比雙引號少處理一層 escape。
AST、LSP、rg 的差別
| 工具 | 解決問題 | 適合情境 |
|---|---|---|
rg |
找文字 pattern | 快速定位、第一輪搜尋 |
| AST/CST | 理解語法形狀 | 找所有 function declaration、assignment、call expression |
| LSP | 理解 symbol 語意 | go to definition、find references、hover type、diagnostics |
簡單判斷:
- 想找「文字在哪裡」:用
rg。 - 想找「這段 code 是什麼語法結構」:用 AST/CST。
- 想找「這個名字實際指的是哪個 symbol」:用 LSP / Xcode index。
Swift 專案裡:
- AST/CST:SwiftSyntax、
swiftc -dump-ast。 - LSP:SourceKit-LSP、Xcode index。
- 通用 CST:tree-sitter。
SourceKit-LSP 怎麼用
確認路徑:
xcrun --find sourcekit-lsp
通常會得到類似:
/Applications/Xcode.app/Contents/Developer/Toolchains/XcodeDefault.xctoolchain/usr/bin/sourcekit-lsp
實務上通常不手動呼叫 raw LSP JSON,而是透過 editor:
- Xcode:Jump to Definition、Find Call Hierarchy、Find References。
- VS Code / Neovim:設定 LSP server 為
xcrun sourcekit-lsp。
對 Xcode app 專案,先 build 過會讓 index 比較完整:
xcodebuild build \
-project AppPOS.xcodeproj \
-scheme "AppPOS Dev" \
-destination 'platform=iOS Simulator,name=iPhone 17,OS=26.5'
Xcode MCP 常用操作
如果在有 Xcode MCP 的環境,可以用:
| 指令 | 用途 |
|---|---|
XcodeGrep |
在 Xcode project structure 裡搜尋 |
XcodeRead |
讀 Xcode project 裡的檔案 |
XcodeGlob |
用 wildcard 找 project 檔案 |
XcodeGetCurrentFile |
讀目前 editor 開啟檔案 |
BuildProject |
build 目前 active scheme |
GetBuildLog |
讀 build log |
XcodeRefreshCodeIssuesInFile |
查單檔 compiler diagnostics |
GetTestList |
列出 tests |
RunSomeTests |
跑指定 tests |
XcodeWrite |
新增/覆寫檔案並加入 project |
XcodeUpdate |
用 old/new string 修改檔案 |
XcodeRM |
刪除 project 檔案 |
XcodeMV |
move / rename project 檔案 |
注意:Xcode MCP 看的是 Xcode project organization,不完全等同 filesystem。
修改檔案:apply_patch
修改既有檔案:
*** Begin Patch
*** Update File: AppPOS/Foo.swift
@@
- let title = "Old"
+ let title = "New"
*** End Patch
新增檔案:
*** Begin Patch
*** Add File: docs/example.md
+# Example
+
+This is a new file.
*** End Patch
刪除檔案:
*** Begin Patch
*** Delete File: docs/old.md
*** End Patch
使用原則:
- 小到中型人工修改:用
apply_patch。 - 新增 Swift 檔且要進 Xcode target:優先
XcodeWrite,或同步改.xcodeproj。 - 刪除/搬移 Xcode project 檔:優先
XcodeRM/XcodeMV。 - 修改完一定看
git diff。
修改後驗證
基本檢查:
git diff --stat
git diff
找是否有漏改:
rg -n 'OldName|NewName' AppPOS -g '*.swift'
跑測試或 build:
xcodebuild test \
-project AppPOS.xcodeproj \
-scheme "AppPOS Dev" \
-destination 'platform=iOS Simulator,name=iPhone 17,OS=26.5' \
-only-testing:AppPOSTests/SomeTests
如果只是確認 project schemes:
xcodebuild -list -project AppPOS.xcodeproj
實戰流程模板
- 先找入口:
rg -n '目標關鍵字|目標函式|目標型別' AppPOS -g '*.swift'
- 找定義:
rg -n 'func\s+函式名\b|class\s+型別名\b|struct\s+型別名\b|enum\s+型別名\b' AppPOS -g '*.swift'
- 找引用:
rg -n '\b函式名\s*\(|\b變數名\b|\b型別名\b' AppPOS -g '*.swift'
- 讀上下文:
nl -ba path/to/File.swift | sed -n 'start,endp'
- 追資料流:
- UI event / delegate callback
- Subject / publisher send
- ViewModel input
- UseCase
- API request
- Model / validation
- Output / navigation
- 修改:
- 既有內容:
apply_patch - Xcode 新增檔:
XcodeWrite - Xcode 刪除檔:
XcodeRM - Xcode 搬移檔:
XcodeMV
- 驗證:
git diff
xcodebuild build/test ...
常見陷阱
- 只看到
.code128宣告,不代表有套用到metadataObjectTypes。 - 掃描層支援格式,不代表業務層接受內容。
-
rg找到同名函式,不代表是同一個 overload。 - protocol extension / dynamic dispatch 需要 LSP 或人工確認型別。
- 新增 Swift 檔只放到 filesystem,不代表 Xcode target 會編譯。
- 刪檔只用
rm,可能留下.xcodeprojbroken reference。 - build/test 失敗要分清楚是本次修改造成,還是既有環境問題。
Top comments (0)