eslint 和 sonar 不应拦截 yield 语句,因其是合法语法且广泛用于 redux-saga、koa 等生产场景;“无生产理由”属主观判断,静态工具无法判定;应聚焦可量化问题,如未调用 generator 或类型不匹配,并通过白名单、封装 api 和 ci 曝光等工程化手段管理。

ESLint 和 Sonar(包括 eslint-plugin-sonarjs)**均不支持、也不应强行拦截 yield 语句**——因为 yield 本身不是缺陷,而是 JavaScript 中合法且关键的语法特性,用于生成器函数(function*)和 async 函数内部的 await 实现机制。
为什么不能、也不该“拦截无生产理由的 yield()”
所谓“无生产理由”属于主观业务判断,静态分析工具无法也不应承担该职责:
-
yield是语言原生能力,出现在 Redux-Saga、Koa 中间件、自定义异步流控制、测试 mock 工具(如 jest 的jest.genMockFn)等大量生产级场景中 - ESLint 的规则必须基于 AST 可判定、语义明确、无歧义。而“是否有生产理由”依赖上下文、架构设计、团队约定,无法通过语法树推断
- SonarQube /
eslint-plugin-sonarjs聚焦可量化的代码质量维度:空指针、重复逻辑、认知复杂度、安全漏洞等,不审计开发者的“意图合理性”
如果你真正想约束的是“不必要或误用的 generator 函数”
那应转向可静态识别的具体问题,例如:
-
废弃的 generator 函数未被调用:可用
@typescript-eslint/no-unused-vars(配合ignoreRestSiblings: false)+ 自定义 AST 脚本扫描未被引用的function*声明 -
generator 函数被当作普通函数调用(忘加
next()或for...of):这类错误会在运行时返回Generator对象而非预期值,ESLint 无法直接捕获,但可通过 JSDoc 标注 +sonarjs/no-null-dereference配合类型流分析间接预警(例如标注返回值为string却实际返回Generator) -
滥用
yield替代简单同步逻辑(如yield 42无意义):这属于代码审查范畴,建议纳入 PR checklist,或用自定义 ESLint 规则匹配yield Literal | Identifier且父作用域无for...of/next()调用的模式(需谨慎启用,避免误伤)
更务实的替代方案:用工程化手段管理 generator 使用边界
若团队确有统一收敛 generator 用法的需求(如仅允许在 saga 层出现),推荐以下三步落地:
-
定义白名单路径:在
.eslintignore或自定义规则中,仅对src/sagas/**启用 generator 相关检查,其他目录报错 -
封装受控 API:提供
createSaga工厂函数替代裸function*,并在其内部做参数校验与调用约束,ESLint 可配合no-restricted-syntax禁止直接写function* -
CI 阶段补充语义检查:用
jscodeshift脚本统计全量yield出现位置,输出报告供 TL 审阅;不阻断,但强曝光
把“是否该用 yield”交给人判断,把“是否写错 yield”交给工具卡点——这才是静态检查的合理分工。










