Skip to content

feat(lint): 引入 ESLint flat config 并接入 CI 与 Makefile - #536

Merged
Menghuan1918 merged 3 commits into
mainfrom
feat/eslint
Sep 3, 2026
Merged

feat(lint): 引入 ESLint flat config 并接入 CI 与 Makefile#536
Menghuan1918 merged 3 commits into
mainfrom
feat/eslint

Conversation

@Menghuan1918

Copy link
Copy Markdown
Collaborator

规则集选择与理由

eslint.config.js(flat config,~90 行):

  • 基础@eslint/js recommended + typescript-eslint recommended(非 type-checked 档——全量 type-checked 需要项目服务且更慢,当前收益不足以引入)。
  • react-hooks:v7 的 recommendedconfigs.flat.recommended)。⚠️ v7 起 recommended 捆绑了 React Compiler 语义规则(purity / immutability / refs / set-state-in-effect 等),对本仓库 CodeMirror / xterm 命令式集成的大量既有模式(render 期读 ref、effect 内同步 setState)报出 57 处错误,均为噪音级误报——该档整体关闭(config 内有注释),只保留经典 rules-of-hooks + exhaustive-deps 双规则;后者消费代码里带理由的既有豁免注释。
  • globals 分域src/client/** → browser;src/*.ts / scripts/** / 根级 *.config.ts → node;tests/** → node+browser(jsdom 组件测试)。eslint.config.js 自身不 ignore,走 js recommended + node globals 正常通过。
  • linterOptions.reportUnusedDisableDirectives: 'error' 自动揪孤儿豁免;no-unused-vars^_ 前缀忽略以对齐仓库既有占位约定(36 处 _fn / _ns / _locale mock 桩)。
  • 依赖:eslint@^10 + typescript-eslint@^8.69 + eslint-plugin-react-hooks@^7 + globals@^17 + @eslint/js@^10(ESLint 10 起 @eslint/js 不再随 eslint 自带,pnpm 严格模式下需显式安装)。均为 devDependencies,不触市场安装约束(market-manifest.spec.ts 5/5 绿)。

孤儿 disable 清理清单(实报为准)

位置 规则 处理
src/client/SideChatView.tsx:577 exhaustive-deps 删除(多行理由注释把 disable-next-line 顶离实报行,规则本就不报)
src/client/Sidebar.tsx:421 exhaustive-deps 删除(同上,理由注释保留)
src/client/selection-popup.ts:151 exhaustive-deps 提取 popupOpen 标志 + 注释合并,真修复(两处 warning 消失)
tests/chunk-artifact.spec.ts:39 no-new-func 删除(no-new-func 已不在 @eslint/js 10 recommended 中)

保留且被使用:SideChatView:532TextEditor:363/431 的 exhaustive-deps 豁免与 service.spec.ts / editor-refresh.spec.tsx 的豁免(lint 实证「被使用」)。

存量零告警的证据(lint 输出摘要)

  • 首跑(清零前):141 errors / 21 warnings / 162 problems —— 60 no-unused-vars(36 个 _ 前缀桩 + 24 个真实死代码)、57 个 React Compiler 档 hooks 规则、21 exhaustive-deps、4 孤儿 disable、以及 preserve-caught-error×3 / prefer-const×3 / no-require-imports×3 / no-useless-assignment×2 / no-control-regex×2 / no-unused-expressions×2 / no-explicit-any×2 / rules-of-hooks×1 / no-useless-escape×1 / no-irregular-whitespace×1。
  • 清零后pnpm lint 零输出、exit 0make lint 同绿。
  • 真实修复样例:agent-opens.ts 三处 throw 补 { cause }lazy-chunk.tsx ComponentType<any>ComponentType<P>P extends object);SubagentView catalogs 空兜底改 useMemo(修复「?? {} 每渲染新对象使下游 memo 失效」的真问题);terminal-links 字符类多余转义;pty-helpers.spec 内联 require 提升为静态导入;editor-host.spec 内联 viewer 提出为大写 FakeViewer(rules-of-hooks 识别);panel-host-css.spec 注释中的零宽空格改为可见写法;死代码(未用导入×15、死累加器 total、死助手函数×2)删除。
  • 依赖数组:ctx(挂载期恒定)直接入 deps(Sidebar×3);幂等 effect 补 scope(TextEditor previewScroll);其余 12 处为带理由豁免(granular scope 字段 ×5、job.status 粒度 ×2、清理期读 ref、mount-only 注册等)。

接入点清单

  • package.json"lint": "eslint ." + devDependencies。
  • Makefilelint 目标(typecheck 旁);check 聚合补 pnpm lint(保持「对齐 CI」注释语义成立);移除「lint 目标留给后续 PR」占位注释;.PHONY 同步。
  • .github/workflows/ci.ymlcici-windows 两 job 在 Typecheck 后加 - name: Lint / run: pnpm lint(plugin-mount job 不加,ci job 已覆盖)。
  • .github/workflows/release.yml:Typecheck 后加 Lint,「release 与 PR 同门禁」注释的顺序说明同步为 typecheck → lint → test → build。
  • README.md / README_EN.md:「开发与构建」命令清单各补一行 pnpm lint(双语镜像)。

验证(全实跑)

  • pnpm lint → 零输出 exit 0;pnpm typecheck → 0;pnpm build → complete;pnpm test118/118 files,1241 passed | 9 skipped(含 market-manifest.spec.ts 5/5);pnpm check:consumer-types → OK;make lint → 0;ci.yml / release.ymlnpx js-yaml 校验通过。

- devDependencies: eslint 10 / typescript-eslint 8 / eslint-plugin-react-hooks 7 / globals / @eslint/js(ESLint 10 起 @eslint/js 不再随 eslint 自带,需显式安装)
- eslint.config.js:@eslint/js recommended + typescript-eslint recommended(非 type-checked)+ react-hooks recommended(v7 的 React Compiler 语义规则档整体关闭——57 处存量误报,保留经典 rules-of-hooks / exhaustive-deps 双规则)
- globals 分域:src/client → browser;src 根 / scripts / 根级 config → node;tests → node+browser
- reportUnusedDisableDirectives: error 揪孤儿豁免;no-unused-vars 对齐仓库既有 _ 前缀占位约定
- package.json 增加 lint script(eslint .)
存量清理(首跑 141 errors / 21 warnings → 0 / 0):
- 删除孤儿 disable:SideChatView / Sidebar / selection-popup 三处 exhaustive-deps 豁免与 chunk-artifact 的 no-new-func 豁免(多行理由注释把 disable-next-line 顶离了实报行;selection-popup 改为提取 popupOpen 标志真修复)
- 死代码:未用导入(Sidebar×7、TextEditor、SideCardSection、config、fs-operations 及 6 个 spec)、sidechat-core 死累加器 total、chunk-loader.spec 死助手 registry、sidechat-seed-validation 死助手 toolResultMessage
- 真实小修:agent-opens 三处 throw 补 cause;lazy-chunk any → ComponentType<P>(P extends object);service.ts claimed 初值改定值赋值;chunk-loader task / spec 内 etag / pendingLoad / snapshot 改 const;terminal-links 去掉字符类内多余转义;SubagentView catalogs 空兜底 useMemo 稳定标识;editor-host.spec 组件提出大写 FakeViewer(rules-of-hooks);pty-helpers.spec 内联 require 提升为静态导入;panel-host-css 注释里的零宽空格改为可见写法
- 依赖数组豁免(均带理由):granular scope 字段(EditorHost / PdfView / ChangesTab / GitLens×2)、job.status 粒度(SubagentView×2)、清理期读 ref、mount-only 注册等;ctx(挂载期恒定)直接入 deps(Sidebar×3)、TextEditor previewScroll 补 scope(幂等)
- 刻意控制字符正则(conversation-draft / markdown-images)与宿主槽位 any 签名(context-types)以带理由豁免保留

接入:
- Makefile:lint 目标(typecheck 旁),check 聚合补 lint 保持「对齐 CI」语义
- ci.yml ci / ci-windows 两 job 与 release.yml 在 Typecheck 后加 Lint 步骤(release 注释同步顺序)
@Menghuan1918
Menghuan1918 merged commit 7b5c7dd into main Sep 3, 2026
7 of 9 checks passed
@Menghuan1918
Menghuan1918 deleted the feat/eslint branch September 3, 2026 12:18
LiarCoder pushed a commit to LiarCoder/DSH-better-sidebar that referenced this pull request Sep 3, 2026
omdsh-dev#535(i18n catalog names)给 tests/add-plugin-modal.spec.tsx 新增
sentinelEntry 行时漏了 import;omdsh-dev#535 自身 CI run 被 cancel,omdsh-dev#536 带病
合入,main HEAD 7b5c7dd 的 typecheck/test 双红(本地 stash 复现一致:
TS2304 / ReferenceError: builtinTabPlugins is not defined,CI run
33754439466 failure)。补上与 plugin-list.spec.ts 同源的 import。

与本 PR 主题无关,仅为本流验证门(typecheck/test 全绿)所需的最小
main 修复,独立成 commit 便于 review 剔除。
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant