Cursor,底层到底是怎么理解你代码上下文的? (2)

张开发
2026/4/16 1:40:21 15 分钟阅读

分享文章

Cursor,底层到底是怎么理解你代码上下文的? (2)
Cursor底层到底是怎么理解你代码上下文的我刚开始用的时候也觉得很神奇。以前用 ESLint 或者正则匹配总是会误报或者漏报但 Cursor 就像是真的有一个资深同事在旁边看着你写代码一样。后来我专门去翻了翻它的底层逻辑和相关的 LSPLanguage Server Protocol协议规范才发现——其实并没有什么魔法它只是把我们平时写代码的“语法树”和“大模型”做了一次极其巧妙的结合。今天这篇咱们就剥开 Cursor 的外衣看看它底层到底是怎么理解你代码上下文的。1. 传统工具的痛点为什么正则和文本匹配不行在讲 Cursor 之前先回忆一下我们在 A 篇里提到的那个痛点找出嵌套过深函数里的未被使用的变量。如果让你自己写个脚本来找你可能会用正则表达式匹配let xxx 或者const yyy 然后再在后面的文本里搜索xxx或yyy有没有出现过。这种做法有两个致命缺陷作用域Scope盲区如果你在全局定义了let id 1然后在某个深层函数里又写了let id 2正则表达式根本分不清后面的id到底用的是哪一个。文本噪音如果你的注释里写了一句// 记得修改 id正则会以为这个变量被使用了。这就是为什么传统的纯文本检查工具在面对“屎山”时总是力不从心。它们看到的是“字符串”而不是“代码逻辑”。2. Cursor 的第一只眼AST抽象语法树要理解代码的逻辑结构就必须把字符串变成树状结构这就是ASTAbstract Syntax Tree抽象语法树。当你在 Cursor 里敲下代码时它底层的解析器通常基于语言服务器如 TypeScript 的 tsserver会瞬间把你的代码拆解成一棵树。比如你写了这样一段代码functioncalculate(a,b){letunusedVar10;returnab;}在 AST 的视角里它长这样简化版FunctionDeclaration (calculate) ├── Parameters │ ├── Identifier (a) │ └── Identifier (b) └── BlockStatement ├── VariableDeclaration (unusedVar 10) └── ReturnStatement └── BinaryExpression (a b)有了这棵树Cursor 就能清晰地知道unusedVar是一个变量声明。它存在于calculate函数的BlockStatement块级作用域内。在这个块级作用域内没有任何其他节点引用了unusedVar。这就是为什么在 A 篇里我们配置了no_unused_vars true后Cursor 能如此精准地把那些藏在深层嵌套里的无用变量揪出来。它根本不是在看文本而是在遍历这棵逻辑树。3. Cursor 的第二只眼LSP语言服务器协议与大模型的融合如果仅仅是 AST那 Cursor 也就是个高级版的 ESLint。它真正“神化”的地方在于它如何将本地的 LSP 上下文喂给云端的大模型LLM。我们在 A 篇里提到Cursor 能自动修正复杂的命名不规范甚至能根据上下文猜测你的意图。这是怎么做到的步骤一精准截取上下文Context Slicing大模型的上下文窗口是有限的不可能每次都把你整个几百 MB 的项目传给云端。当你光标停在某个函数上或者请求 Cursor 优化某段代码时Cursor 会利用 LSP 提取出与当前节点强相关的代码片段。它会提取当前函数的 AST 节点。该函数调用的其他函数的签名Signature。当前文件引入的依赖Imports。你的.cursorrules文件中的规则。步骤二构建 Prompt 喂给 LLMCursor 会把上述提取到的结构化信息拼装成一个极其复杂的 Prompt。打个比方它传给大模型的指令并不是简单的“帮我优化这段代码”而是类似于“当前开发者正在修改UserService.ts中的getUser函数。该函数依赖了Database接口定义如下…。项目根目录的.cursorrules要求变量必须用 camelCase最大嵌套不超过 3 层。请基于这些规则和上下文重构以下代码…”步骤三大模型推理与 AST 逆向还原云端大模型比如 Claude 3.5 Sonnet 或 GPT-4o收到这个超级 Prompt 后生成优化后的代码。Cursor 拿到返回结果后并不会直接盲目替换你的文本而是会再次进行 AST 校验确保大模型生成的代码没有破坏原有的语法结构最后才展示在你的编辑器里。4. 为什么有时候 Cursor 也会“犯傻”搞懂了底层原理你也就明白了为什么有时候 Cursor 会给出离谱的建议。场景跨文件的隐式依赖如果你的屎山代码里大量使用了全局变量比如挂载在window上的对象或者通过极其动态的方式如eval或动态反射调用函数LSP 就无法在静态分析阶段构建出正确的依赖树。这时候Cursor 提取给大模型的上下文就是残缺的。大模型就像一个被蒙住了一只眼睛的高手只能靠猜结果自然就容易翻车。这也是为什么我在 A 篇里强调一定要先用.cursorrules把基础的规范建立起来。你的代码结构越清晰、静态类型越严谨LSP 提取的上下文就越准确Cursor 背后的大模型发挥出的威力就越恐怖。尾声工具的本质是放大器说实话深挖完 Cursor 的底层逻辑后我反而不再觉得它“神”了。它不是什么魔法而是工程化做到极致的体现——把传统的静态代码分析AST/LSP作为精准的“导航仪”把大语言模型LLM作为强大的“发动机”。这也给我提了个醒AI 工具再强也只是开发者能力的放大器。如果你连基本的代码规范和作用域逻辑都不懂AI 给出的建议你也不敢放心合并。你平时用 Cursor 时遇到过什么它怎么都理解不了的“智障时刻”吗评论区聊聊看看是不是也是因为 AST 解析不到导致的。

更多文章