Cursor 使用 Claude Sonnet 4 (Thinking) 排查 eslint 问题全流程记录。
背景
问题:一个微信小程序项目的 wxml 文件,某个自定义 rules 规则不希望被检查,但添加 eslint-disable 后依旧被检查出 error。
我:对 eslint 了解甚微,完全无思路。
1 | import wxml from 'eslint-plugin-wxml'; |
看了下使用了 eslint-plugin-wxml 和 @wxml/parser ,github 上也没看到相关问题。
寄托于 AI 了。
Demo1 eslint-test
尝试复现问题。

现在创建项目 AI 会主动先创建一些测试文件保证功能正常:

然后自己测试:

先学到一个知识点禁用整个文件 eslint 检查不能用 // eslint-disable ,应该用 /* eslint-disable */。

写 demo 前和 ai 聊了下(聊天记录不知道为啥没了),当时以为是自定义规则有问题导致 eslint-disable 不生效,所以思路是看自定义规则是不是执行来推导是否符合预期。
先问了下 ai 哪个函数执行。


得出了结论各个生命周期都还会执行,只是 context.report 调用被过滤了,继续追问怎么观察出是否被过滤:

AI 列了个表格分析了一波:


还是只是说了会被丢弃,但没有讲细节。先不追问了,让他写个 wxml 看能不能复现现场。

三下五除二搞完了:

再让他搞个自定义规则:

执行过程中自己发现了一个问题,只检测了 wxs:

然后自己又写了写代码修复了:


但我此时在文件添加了 <!-- eslint-disable --> 后,生效了,错误不再检查,复现失败。
看了下不同之处,demo 用的 eslint 8 ,但项目是 9,让 AI 升级下:


升级的很顺利,但是 <!-- eslint-disable --> 依旧生效了。
现在的不同之处就是 wxml 的那两个库了,让 AI 换下库:

然后 <!-- eslint-disable --> 就不生效了,复现成功。
询问 AI 原因:

AI 思考了很多,尝试了很多,最后给出了结论,

还顺带翻 node_modules 源码发现刚自定义的规则可以用自带的,不需要自己写:

就是说是这个插件 eslint-plugin-wxml 的锅。那能绕过吗?

通过自定义 processor 还真解决了:

但我看了下它写的代码,只考虑了 <abc> 这一种情况,让他生成个通用方案

一顿操作还真给写出来了,但懒得去读代码了,直接问他实现的原理是什么:



一句话说明就是在 preprocess 阶段将不需要检查的代码注释掉了。虽然解决了,但还是怪怪的,想知道 eslint 原生是怎么处理 eslint-disable 的。


列了一个图,但依旧是表象,还是没说出 eslint 是怎么干的。
Demo2 eslint-wxml-test
Demo1 项目代码比较乱了,再写一个纯粹的项目来二次确认是 eslint-plugin-wxml 出了问题。

忘记指定版本了,让他升级下

成功复现,可以确认是 plugin 的问题了,顺便问问怎么解决:


让我们忽略掉 相应的文件,当然不是我们想要的。
还记得 html 的 plugin 生效,问他为什么:


又回到 插件的 postprocess 了,再问问他刚没明白的原生的:


说的有道理,但不涉及细节。
目前排除了自定义规则的问题,聚焦到 eslint-plugin-wxml 这个 node 包,可以通过 preprocess(检查前)注释代码或者 postprocess(检查后) 过滤错误来解决。
Demo3 eslint-html-test
一开始使用的 html 的 plugin 是正常的,让 AI 再创建一个 html 的 demo 研究下。

测试文件加一个 eslint-disable ,然后直入主题:


AI 猜测了一下说是 postprocess 处理的,移除了禁用的错误。
直觉上不太像,让他去 node_modules 里翻翻源码:



破案了,不是 eslint-plugin-wxml postprocess 阶段做的,而是 @wxml/parser 做的,解析过程中收集了 comment,有了 comment 之后 Eslint 会自己判断。
有了方案了,可以回到 demo2 了。
最终方案


告诉它方案之后,也直接解决了。但代码看上去非常啰嗦。
原库导出了两个方法 parse 和 parseForESLint 。
1 | import { parse as cstParse } from "./cst"; |
parse 相对底层,它基于 parse 来重写了 parseForEslint 。但直觉上应该直接基于 parseForEslint 重写 parseForEslint 就行。


整体思路上清晰了很多。
1 | import wxmlParser from '@wxml/parser'; |
但看起来还是很多细节冗余,一点点的 review 代码让它优化:
1
1 | // 确保 AST 符合 ESLint 要求 |


2


3


4


5


6
1 | traverseAST(node, callback, visited = new Set()) { |
看到遍历是写死了几个标签名,让他优化下:


变成了更通用的方法:
1 | traverseAST(node, callback, visited = new Set()) { |
当然也不是每次质疑都成功:
7
看到它返回 parse 也调用了 parserInstance.parseForESLint,想着是不是不应该重写 parse 就可以。
parse: (code, options) => parserInstance.parseForESLint(code, options).ast


8
尝试引导它加一些兜底


但过于谨慎了,超时都整上了,最终没有采用。
最终版本:
1 | import wxmlParser from '@wxml/parser'; |
从怀疑自定义 eslint 规则,到 eslint-plugin-wxml 这个 node 包通过 preprocess(检查前)或者 postprocess(检查后) 解决,之后转到了一个更优的方案 @wxml/parser 解析过程中收集 comment,最终一步一步再优化代码解决了这个问题。
总
一些感受:
- AI 目前可以完成事情,但需要人为的引导可以把事情做的更好。未来如何让 Cursor 一次就写好是个值得探索的方向,除了等 ai 模型更强,另一个就是从 Cursor rules 入手了。
目前看来过去积累的编程直觉还是有一定作用的,不然无法引导 ai。也就是常说的解决问题的能力,原来是思路 + 执行,现在思路我们来引导,执行交给 ai 就可以了。
有问题都先尝试着去问一下 AI,不断的熟悉 AI 的能力边界。
AI 写 demo 现在就是一句话的事,找 bug 完全可以先构造一个最小场景复现后继续排查。
当下试错成本非常低,有想法直接让 AI 实现即可,大不了就是推翻重来。
解决问题的流程变了,以往是先学习 -> 再尝试解决,现在变成了问题解决了 -> 再去学习了解。