Hacktoberfest 2026:维护者为十月标记出来的 issue,仍然开放、适合新手。 浏览 Hacktoberfest issue

no-ad-hoc-jsonl-parser: isLineSource doesn't traverse ConditionalExpression, missing live ad-hoc parse in conclusion_admission.c

未关闭 适合新手
#71,028 0 条评论 0 个 reaction 已指派 0 人 在 GitHub 查看

维护者通常 1 天内回复

还没有人认领这个 Issue。

评估

难度
2/5
预计耗时
1-3 小时
新手友好度
75/100
Issue 类型
缺陷
描述清晰度
描述清楚
活跃度
活跃
技术栈
eslint, github-actions, typescript
领域
tooling

调研方向

从 eslint-factory/src/rules/no-ad-hoc-jsonl-parser.ts 及其在 no-ad-hoc-jsonl-parser.test.ts 中的测试开始;追踪 isLineSource() 和 fromLine() 如何解析条件表达式。添加 issue 中描述的合成有效和无效用例,然后运行规则测试,并用该规则检查 actions/setup/js/conclusion_admission.cjs。目标是:三元表达式拆分的情况会被报告,而无关的文档数组不会被标记。

由索引模型根据 Issue 内容生成。

描述

cookie eslint
Summary

no-ad-hoc-jsonl-parser's isLineSource() helper (eslint-factory/src/rules/no-ad-hoc-jsonl-parser.ts:76-98) only resolves a variable's "line-ness" through one hop of identifier-to-initializer resolution (Identifier → initializer()) and through a small whitelist of chained CallExpression methods (split, filter, slice, reverse, toReversed). It never unwraps a ConditionalExpression (ternary) to check whether either branch is itself a line source. Any line array built behind a ternary — a very ordinary "empty vs. split" guard — escapes detection entirely, including when it is subsequently JSON.parse'd per-element, which is exactly the ad-hoc-parsing idiom this rule exists to catch.

Live, grounded false negative

actions/setup/js/conclusion_admission.cjs:50-54:

const lines = compact.session === "" ? [] : compact.session.split("\n");
if (lines.at(-1) === "") lines.pop();
if ((!compact.session.endsWith("\n") && compact.session !== "") || lines.length !== compact.included_events) throw new AdmissionError();
try {
  const projected = compactUnifiedSession(lines.map(line => JSON.parse(line)));

This is a manual split-by-newline followed by .map(line => JSON.parse(line)) — the canonical pattern the rule is designed to flag (compare to the rule's own invalid test case const lines = text.split((r/redacted)?\n/); ... JSON.parse(line)). It is not wrapped by iterateJsonl/iterateJsonlEvents/JsonlParser from jsonl_helpers.cjs, yet the rule produces zero diagnostic here.

Root cause

Tracing lines in isLineSource():

  1. lines is an Identifier → initializer(node) returns its VariableDeclarator init, which is the ConditionalExpression compact.session === "" ? [] : compact.session.split("\n").
  2. isLineSource(conditionalExpr) hits if (node.type !== "CallExpression") return false; (line 83) immediately, since ConditionalExpression is neither Identifier nor CallExpression.
  3. Because isLineSource(lines) is false, the CallExpression visitor's lineArray check for lines.map(...) (arrayCallbacks.has("map") && isLineSource(node.callee.object)) never marks line as a line binding, so the later JSON.parse(line) inside the map callback is never reported.

The same gap applies to fromLine() (used for the Program:exit cross-call propagation pass), which also only descends through Identifier/ArrayExpression/MemberExpression(computed)/a small CallExpression method whitelist — no ConditionalExpression handling there either.

Proposed fix

In isLineSource() (and ideally the equivalent place in fromLine()), add a branch: if (node.type === "ConditionalExpression") return isLineSource(node.consequent, seen) || isLineSource(node.alternate, seen);. This directly fixes the cond ? [] : x.split("\n") idiom; an empty-array consequent is harmless since an empty array can't ever actually be the source of a flagged JSON.parse call.

Acceptance criteria
  • isLineSource() recognizes a ConditionalExpression as a line source when at least one branch resolves to a line source (via recursive isLineSource on consequent/alternate).
  • New invalid test case reproducing the live shape: const lines = cond ? [] : text.split("\n"); lines.map(line => JSON.parse(line)); must report adHoc.
  • A valid-case test confirms a ConditionalExpression where neither branch is a line source (e.g. cond ? documents : otherDocuments) is still not flagged.
  • conclusion_admission.cjs:54 is verified to now be caught after the fix (run against the real file, not just the synthetic test).
  • No existing passing test in no-ad-hoc-jsonl-parser.test.ts regresses.
Scope note

Out of scope for this issue: fixing conclusion_admission.cjs itself (app code, not rule code) — this is purely about closing the detection gap in the ESLint rule so a future regression or similar idiom elsewhere is caught.

Generated by 🤖 ESLint Refiner · claude · agent · 99.9 AIC · ⌖ 0.868 AIC · ⊞ 6K · ◷
Work 6b99120dce1d760d9b16b2c32e2b3939143961ca50ff5820849e9da583d8e97f · Claim c_2d1370e23519794ff88ba3c5ce7e17ee202e9a6904e679f8ad827e073d503dae_3

  • expires on Oct 28, 2026, 8:03 PM UTC-08:00
主要语言
Go
星标
5.4k
派生
596
平均合并
3 小时 40 分钟
30 天内合并 PR
830

环境准备

在 Codespaces 中打开

在浏览器里用你自己的 GitHub 账号启动这个项目的开发容器。

  • 提供 Dockerfile 或 Docker Compose 文件
  • 没有 Pull Request 模板
  • 阅读贡献指南

从这里开始

  1. 先读完整个 Issue,再读项目的贡献指南。
  2. 在 Issue 下留言说明你要接手 —— 这能避免两个人做同样的事。
  3. Fork 仓库,在一个分支上完成修改。
  4. 提交 Pull Request,并在描述里引用这个 Issue 编号。

github/gh-aw 的其他 Issue

查看 github/gh-aw 的全部 Issue

相似的 Issue

更多 Go Issue

把新 issue 发到你的邮箱

精选适合新手参与的 GitHub issue 摘要。