Merge PR #7752: fix(coding-agent): enabled multiline matching in ts-no-tiny-functions condition (@zhang17-24)

This commit is contained in:
can1357
2026-08-05 21:50:22 +02:00
3 changed files with 56 additions and 1 deletions
+4
View File
@@ -11,6 +11,10 @@
### Fixed
- Fixed `/usage`, `/advisor status`, and every other panel command looking dead mid-turn. `presentCommandOutput` defers panels while the agent streams so a growing turn cannot bury them, but said nothing, and on a long multi-subagent turn the panel is minutes away. The deferral is now acknowledged in the status line. A non-terminal settle also flushes the queue: `isStreaming` is already false by then, so a command issued after an async fan-out settles used to mount ahead of the panels queued before it.
### Fixed
- Fixed the bundled `ts-no-tiny-functions` TTSR rule never firing on one-line arrow functions in real files: the second alternative's `$` anchor only matched at the absolute end of input, so the trailing newline present in every real file suppressed the match. The condition now opens with the `(?m)` inline flag so the arrow body matches to the line end ([#6890](https://github.com/can1357/oh-my-pi/issues/6890)).
## [17.2.9] - 2026-08-05
### Breaking Changes
@@ -1,6 +1,6 @@
---
description: "Do not extract 1-2 line functions that only wrap an expression — inline them"
condition: "\\{\\s*return [^;{}\\n]+;?\\s*\\}|\\b(?:const|let|var)\\s+[\\w$]+\\s*=\\s*(\\([^)]*\\)|[a-zA-Z_$][\\w$]*)\\s*=>\\s*[^{\\n]+$"
condition: "(?m)\\{\\s*return [^;{}\\n]+;?\\s*\\}|\\b(?:const|let|var)\\s+[\\w$]+\\s*=\\s*(\\([^)]*\\)|[a-zA-Z_$][\\w$]*)\\s*=>\\s*[^{\\n]+$"
scope: "tool:edit(*.ts), tool:edit(*.tsx), tool:write(*.ts), tool:write(*.tsx)"
interruptMode: never
---
@@ -181,6 +181,57 @@ describe("builtin-defaults rule provider", () => {
}),
).toEqual([]);
});
it("opens every bundled regex condition that uses a bare line anchor with a translatable inline flag", async () => {
// Without the (?m)/(?s) inline flags a bare ^ or $ anchors to the
// absolute start/end of input, so a rule whose condition is anchored to
// a line silently stops matching in real files (see #6890). Enforce the
// pairing at load time so the failure class stays closed.
const rules = await loadBuiltinRules();
for (const rule of rules) {
for (const condition of rule.condition ?? []) {
const outsideCharClasses = condition.replace(/\[[^\]]*\]/g, "");
const hasBareAnchor = /(^|[^\\])[\^$]/.test(outsideCharClasses);
const opensWithTranslatableFlag = /^\(\?[ims]+\)/.test(condition);
expect(
hasBareAnchor ? opensWithTranslatableFlag : true,
`${rule.name}: a condition with a bare ^ or $ anchor must open with a translatable inline flag`,
).toBe(true);
}
}
});
it("fires ts-no-tiny-functions on one-line arrow functions even with a trailing newline", async () => {
const rules = await loadBuiltinRules();
const rule = rules.find(r => r.name === "ts-no-tiny-functions");
if (!rule) throw new Error("ts-no-tiny-functions rule missing");
const manager = new TtsrManager();
expect(manager.addRule(rule)).toBe(true);
const ctx: TtsrMatchContext = { source: "tool", toolName: "edit", filePaths: ["src/foo.ts"] };
// Real files end with a newline, so the arrow alternative must match
// before the line terminator, not only at the absolute end of input.
const hits = [
"const getName = (u) => u.profile.name;\n",
"const getName = (u) => u.profile.name;",
"const a = 1;\nconst getName = (u) => u.profile.name;\nconst b = 2;",
];
for (const snippet of hits) {
manager.resetBuffer();
expect(
manager.checkDelta(snippet, ctx).map(m => m.name),
snippet,
).toEqual(["ts-no-tiny-functions"]);
}
// Multi-statement functions (block bodies) are not tiny wrappers.
const misses = ["function f(v) { const x = v.a; return x; }", "const f = (v) => { const x = v.a; return x; };"];
for (const snippet of misses) {
manager.resetBuffer();
expect(manager.checkDelta(snippet, ctx), snippet).toEqual([]);
}
});
it("go-new-expr matches value→pointer helpers (named + generic) but not real functions, only on *.go", async () => {
const rules = await loadBuiltinRules();
const rule = rules.find(r => r.name === "go-new-expr");