查找文件、跟随符号、核对源码引用
什么时候用找文件、全文搜索或语言服务导航,以及结果缺失时该检查什么。
知道文件大概在哪,用找文件;知道它写了什么,用全文搜索;想沿着符号往下读,用语言服务导航。三种方式换着用,通常比反复修改一个宽泛的搜索词更快。
选对搜索方式
| 已知线索 | 用什么 | 例子 |
|---|---|---|
| 文件名或路径的一部分 | Command-P(找文件…) | SettingsStore、src/config |
| 一段消息、配置名或代码片段 | 文件栏里的全文搜索 | 完整的报错信息、配置 key |
| 当前文件里的某个符号 | 跳到定义、查找引用 | 函数的实现、调用方 |
找文件只匹配文件名和路径,不搜文件内容。要找程序打印的报错信息,就用全文搜索,而且尽量搜有辨识度的字符串,别搜 data、result 这种词。
文件或结果找不到时,先看项目根目录对不对,再看隐藏文件和被 Git 忽略的文件有没有显示。默认值在设置 → 通用 → 文件里,同时作用于文件栏、找文件和全文搜索;每个项目还可以在文件栏的状态栏里单独调整。
从报错信息找到触发它的分支
报错信息能提供一个起点,但打印它的那一行,也可能只是在包装别处传来的失败。
- 搜固定的部分。 点文件栏的放大镜打开全文搜索,去掉运行时插入的时间戳、请求 ID 和路径。先关闭正则和整词;不确定大小写时,在 Aa 菜单里选不区分。
- 检查搜索范围。 打开筛选范围,先清掉上次留下的目录或文件匹配规则,再扩大搜索。确定大概在哪个模块后,可以缩小目录,或用
*.rs这样的规则限定文件。出现最相关提示,说明列表不完整;先缩小搜索,再判断某个位置是否没有匹配。 - 读匹配位置的上下文。 打开结果,找到走到这里的条件。这条消息是在这里创建的,还是 catch 或日志层给另一个错误补充了上下文?如果是后者,继续追那个失败的操作。
- 往回追输入。 找包含这段逻辑的函数由谁调用,以及哪个值选中了这个分支。语言服务器支持时用查找引用;否则搜索函数名、配置名,再逐处核对使用位置的上下文。
- 核对解释。 用已有的针对性测试,或同一代码版本的运行日志,对照推测的输入和分支。记清证据确认了什么、还有什么没确认;只找到报错文本,还不能确定原因。
全文搜索针对当前工作区,也包括已打开文件中尚未保存的文本,不会遍历所有 Git 历史版本。如果报错来自旧构建,先比较对应版本,再判断当前源码能否解释它。
语言服务器
跳转到定义、查找引用、实现和调用层级,都由语言服务器提供:
| 语言 | 服务器 |
|---|---|
| Swift | SourceKit-LSP |
| Rust | rust-analyzer |
| C、C++、Objective-C、Objective-C++ | clangd |
| Python | Pyright |
| JavaScript、JSX、TypeScript、TSX | TypeScript Language Server |
| Go | gopls |
rust-analyzer 可以在设置 → 代码导航里由 Yenpo 安装。SourceKit-LSP 和 clangd 来自当前选择的 Xcode 工具链;Pyright、TypeScript Language Server 和 gopls 需要你自己安装,并且能在 PATH 里找到。不同服务器支持的功能不一样,有些项目还要额外配置,导航才能正常工作。
确定存在的符号却跳不过去时,检查三件事:打开的是不是项目根目录,服务器装好了没有,项目依赖和构建配置是否齐全。(没有语言服务器时,语法高亮也照样正常。)
没有语言服务器,文本搜索也能解决大部分问题:搜出声明和使用位置,再根据类型和 import 区分同名符号。
跟着行为读,别丢了起点
去别处看定义时,把最开始的文件留在标签页里。每遇到一个重要调用,记下输入是什么,以及由什么决定下一步走哪条路:配置、类型、注册表里的 key,还是当前状态。
查找引用显示的是语言服务器返回的使用位置,不是执行轨迹。服务器支持情况、项目配置和结果数量限制,都可能让列表不完整。如果一个注册表里同时有本地和远程两种实现,要找到选中其中一个的那个值。遇到异步调用,还要看结果返回之前哪些状态可能变了。
追一个配置值时,笔记可以这样记:
命令行输入 → 配置选择 → 校验 → 请求构造
实际来源:环境变量覆盖
失败时:非法值在构造请求前就被拒绝
未确认:哪个父进程设置了这个环境变量
给真正核对过的步骤补上文件和行号。配置追踪案例用可运行的测试完整走了一遍。
核对 AI 回答里的源码引用
点击 AI 回答中的源码引用,会在快速查看里打开对应的几行代码。片段太短看不明白时,点打开文件在标签页里打开整个文件。
依赖回答之前,先看看周围的条件和调用方。比如一行删除缓存条目的代码,可能只有在条目仍属于当前请求时才安全。引用告诉你该看哪里,周围的代码才决定结论站不站得住。
文档和历史版本
Markdown 文件默认以阅读模式打开,也可以切换到编辑源码。把 README 或测试放在实现旁边对照着读,两者说法不一致时记下来。
Git 历史版本的文件可以和当前文件同时打开。跟随引用或动手修改之前,先确认标签页显示的是哪个版本:对旧提交的解释,未必适用于你现在的代码。如何选择版本,见比较提交与分支。