Skip to content

Commit fe88f1b

Browse files
ZviBaratzclaude
andauthored
fix(ego-lint): tighten R-SLOP-38 to reduce over-long identifier false positives (#82)
## Summary - Tightened R-SLOP-38 main pattern to exclude underscore-containing identifiers (`[a-zA-Z0-9]` instead of `\w`), since snake_case names follow GLib/C convention and are never AI-generated in JavaScript - Expanded guard-pattern to suppress domain-specific suffixes: `Function`, `Callback`, `Handler`, `Listener` (15+ chars), and `Id` (20+ chars) — common in GNOME/GLib naming conventions - Eliminates FPs on: blur-my-shell (`dash_not_already_destroyed`), dash-to-panel (`sortWindowsCompareFunction`, `taskbarBoxAllocationChangedId`), and similar descriptive identifiers in v-shell (8 hits) ## Test plan - [x] New fixture `slop-long-id-guard@test` verifies guarded cases (Function suffix, Id suffix, Handler suffix) are suppressed while AI-style verbose names still fire - [x] Existing `slop-long-params@test` still fires (camelCase TP preserved) - [x] Existing `long-param-default@test` still suppressed (default param guard still works) - [x] Existing `compiled-ts-extension@test` still SKIPped - [x] Full test suite: 538 passed, 0 failed Closes #71 🤖 Generated with [Claude Code](https://claude.com/claude-code) Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 4d00563 commit fe88f1b

File tree

6 files changed

+55
-6
lines changed

6 files changed

+55
-6
lines changed

rules/patterns.yaml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -601,13 +601,13 @@
601601
guard-pattern: "\\b(const|export\\s+const)\\s+\\w+\\s*=\\s*Object\\.freeze"
602602

603603
- id: R-SLOP-38
604-
pattern: "\\(\\s*[a-z]\\w{25,}\\s*[,)]"
604+
pattern: "\\(\\s*[a-z][a-zA-Z0-9]{25,}\\s*[,)]"
605605
scope: ["*.js"]
606606
severity: advisory
607607
message: "Over-long identifier (>25 chars) is an AI verbosity indicator"
608608
category: ai-slop
609609
fix: "Shorten parameter names to be concise but clear (e.g., currentBatteryThresholdValue → threshold)"
610-
guard-pattern: "\\w{25,}\\s*="
610+
guard-pattern: "[a-zA-Z0-9]{26,}\\s*=|\\w{15,}(?:Function|Callback|Handler|Listener)\\b|\\w{20,}Id\\b"
611611
skip-if-compiled: true
612612

613613
- id: R-SLOP-40

skills/ego-lint/references/rules-reference.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -2470,11 +2470,11 @@ Rules for APIs removed or changed in specific GNOME Shell versions. These rules
24702470
### R-SLOP-38: Over-long identifier in function call
24712471
- **Severity**: advisory
24722472
- **Checked by**: apply-patterns.py
2473-
- **Rule**: Identifiers 26+ characters (starting with lowercase) inside function call parentheses.
2474-
- **Rationale**: AI-generated code tends to use excessively descriptive camelCase names like `currentBatteryThresholdValue` or `updatedNotificationMessage`. Human-written GNOME code favors concise names (`threshold`, `message`). The lowercase-start filter avoids false positives on PascalCase class names and UPPER_SNAKE constants. Threshold raised from 20 to 25 to avoid FPs on standard Clutter API names (e.g., `brightnessContrastEffect` at 24 chars).
2473+
- **Rule**: Alphanumeric identifiers 26+ characters (starting with lowercase, no underscores) inside function call parentheses.
2474+
- **Rationale**: AI-generated code tends to use excessively descriptive camelCase names like `currentBatteryThresholdValue` or `updatedNotificationMessage`. Human-written GNOME code favors concise names (`threshold`, `message`). The lowercase-start filter avoids false positives on PascalCase class names and UPPER_SNAKE constants. Threshold raised from 20 to 25 to avoid FPs on standard Clutter API names (e.g., `brightnessContrastEffect` at 24 chars). Snake_case identifiers (GLib/C naming convention) are excluded from the pattern since AI never generates underscore-separated names in JavaScript.
24752475
- **Fix**: Shorten parameter/argument names to be concise but clear.
2476-
- **Tested by**: `tests/fixtures/slop-long-params@test/`
2477-
- **Note**: Suppressed (`skip-if-compiled`) for extensions compiled from TypeScript via esbuild, where verbose parameter names from TypeScript signatures survive compilation.
2476+
- **Tested by**: `tests/fixtures/slop-long-params@test/`, `tests/fixtures/slop-long-id-guard@test/`
2477+
- **Note**: Suppressed (`skip-if-compiled`) for extensions compiled from TypeScript via esbuild, where verbose parameter names from TypeScript signatures survive compilation. Also suppressed for identifiers ending in domain-specific suffixes (`Function`, `Callback`, `Handler`, `Listener`, long `Id`) which are common in GNOME/GLib naming conventions.
24782478

24792479
### R-SLOP-40: Manual Promise wrapper
24802480
- **Severity**: advisory
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
# R-SLOP-38 guard for domain-specific identifier suffixes
2+
# Sourced by run-tests.sh — uses run_lint, assert_output_contains, assert_exit_code, etc.
3+
4+
# --- slop-long-id-guard (R-SLOP-38 suffix guards) ---
5+
echo "=== slop-long-id-guard ==="
6+
run_lint "slop-long-id-guard@test"
7+
assert_exit_code "exits with 0 (advisory only)" 0
8+
assert_output_contains "warns on AI-style verbose name" "\[WARN\].*R-SLOP-38"
9+
assert_output_count "only 1 R-SLOP-38 warning (guarded cases suppressed)" "\[WARN\].*R-SLOP-38" 1
10+
echo ""
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
SPDX-License-Identifier: GPL-2.0-or-later
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
import {Extension} from 'resource:///org/gnome/shell/extensions/extension.js';
2+
3+
// Guarded: callback/function-ref suffix — should NOT trigger R-SLOP-38
4+
function sortWindowsCompareFunction(a, b) {
5+
return a.x - b.x;
6+
}
7+
8+
export default class TestExtension extends Extension {
9+
enable() {
10+
// Guarded: long identifier ending in Id — should NOT trigger
11+
const taskbarBoxAllocationChangedId = this._box.connect('allocation-changed', () => {});
12+
this._box.disconnect(taskbarBoxAllocationChangedId);
13+
14+
// Guarded: callback suffix — should NOT trigger
15+
this._windows.sort(sortWindowsCompareFunction);
16+
17+
// Guarded: handler suffix — should NOT trigger
18+
this._runPanelAnimationHandler(data);
19+
20+
// NOT guarded: AI-style verbose name — SHOULD trigger R-SLOP-38
21+
this._process(currentBatteryThresholdValue);
22+
}
23+
24+
_runPanelAnimationHandler(data) {
25+
return data;
26+
}
27+
28+
disable() {
29+
this._box = null;
30+
}
31+
}
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
{
2+
"uuid": "slop-long-id-guard@test",
3+
"name": "Slop Long ID Guard Test",
4+
"description": "Test R-SLOP-38 guard for domain-specific identifier suffixes",
5+
"shell-version": ["45", "46"],
6+
"url": ""
7+
}

0 commit comments

Comments
 (0)