garbage-code-hunter 0.2.2

A humorous Rust code quality detector that roasts your garbage code
Documentation
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
# Final Accuracy Report — Real TP/FP Data with Source-Code Evidence

> Generated: 2026-05-15 | Projects: 5 | Method: JSON output + source verification at exact file:line

---

## Test Projects

| Language | Project | Path | Issues | Scope |
|----------|---------|------|-------:|-------|
| Go | Go stdlib (net/http) | `~/code/researcher/go/src/net/http` | 5,179 | Production HTTP library |
| Rust | Wasmtime | `~/code/researcher/wasmtime/crates/wasmtime` | 3,918 | Production WASM runtime |
| TypeScript | tRPC | `~/code/xxxcode/ts/trpc/packages` | 1,799 | Production API framework |
| Ruby | Rails (ActiveRecord) | `~/code/xxxcode/ruby/rails/activerecord/lib` | 1,792 | Production ORM |
| Python | zkp | `~/code/pycode/zkp` (excl .venv) | 21,127 | Crypto research code |

---

## Critical Tool Bugs

### Bug #1: `line:1` — Wrong line number for entire rule categories

Many rules report `line: 1, column: 1` instead of the actual issue location. This makes the issues impossible to find and is a false positive for location accuracy.

| Language | line:1 issues | Affected rules |
|----------|:-------------:|----------------|
| Go | 77 | panic-abuse (49), file-too-long (15), todo-comment (8), goroutine-abuse (5) |
| Rust | **301** | unwrap-abuse (81), box-abuse (72), generic-abuse (32), lifetime-abuse (24), file-too-long (22), macro-abuse (21), reference-abuse (17), pattern-matching-abuse (10), panic-abuse (4), others (18) |
| Python | 90 | (similar pattern) |
| Ruby | 14 | (similar pattern) |
| **Total** | **484** | |

**Root cause:** These rules detect that an issue exists somewhere in the file but don't locate the exact line. They default to line 1.

**Impact:** 484 out of 12,006 total issues (4.0%) have wrong line numbers. For Rust, 301 out of 3,918 (7.7%) are affected.

### Bug #2: `box-abuse` fabricated detections

Rust `box-abuse` reports 72 issues at line 1. Verification shows **most files have zero `Box::` usage**:

| File | Reported | Actual Box:: count | Verdict |
|------|:--------:|:------------------:|---------|
| config.rs | 1 | 0 | **Fabricated** |
| type_registry.rs | 1 | 0 | **Fabricated** |
| code_memory.rs | 1 | 0 | **Fabricated** |
| types.rs | 1 | 0 | **Fabricated** |
| externals.rs | 1 | 0 | **Fabricated** |
| coredump.rs | 1 | 0 | **Fabricated** |
| code.rs | 1 | 1 | Correct (wrong line) |

**68 out of 72 box-abuse detections are completely fabricated.** The tool reports files as having Box:: abuse when they don't contain Box:: at all.

### Bug #3: `.venv` not excluded

The Python zkp project produced 721,719 issues when `.venv/` was scanned (plotly.min.js, streamlit bundles, etc.). The tool has no auto-exclusion for common dependency directories.

---

## Per-Rule Accuracy (verified against source code)

### Rules with correct line numbers

#### magic-number

| Project | Total | Sampled | TP | FP | TP Rate |
|---------|:-----:|:-------:|:--:|:--:|:-------:|
| Go (net/http) | 2,138 | 5 | 1 | 4 | **20%** |
| Rust (Wasmtime) | 287 | 4 | 3 | 1 | **75%** |
| TypeScript (tRPC) | 132 | 3 | 2 | 1 | **67%** |
| Ruby (Rails) | 378 | 3 | 2 | 1 | **67%** |
| Python (zkp) | 8,616 | 3 | 0 | 3 | **0%** |

**Source evidence:**

| Location | Code | Verdict | Reason |
|----------|------|:-------:|--------|
| Go `cookie_test.go:29` | `MaxAge: 3600` | FP | Test data, 3600 = seconds/hour, well-known |
| Go `range_test.go:49` | `[]httpRange{{9500, 500}}` | FP | Test data table for HTTP range parsing |
| Go `serve_test.go:2339` | `bodySize: 1 << 20` | FP | Power-of-2 in test, self-documenting |
| Go `transport.go:164` | (in a comment) | FP | Tool flagged a comment, not code |
| Rust `config.rs:35` | `NonZeroUsize::new(20).unwrap()` | TP | Max backtrace frames, should be named constant |
| Rust `config.rs:285` | `max_wasm_stack: 512 * 1024` | TP | Stack size limit, has comment but should be constant |
| TS `server.ts:208` | `{ status: 400 }` | TP | HTTP status code, should be named |
| TS `writeResponse.ts:72` | `statusCode === 200` | FP | HTTP 200 is universally understood |
| Ruby `encryptor.rb:109` | `140.bytes` | TP | Compression threshold, has comment |
| Ruby `cipher/aes256_gcm.rb:64` | (crypto constant) | FP | AES-GCM standard parameter |
| Python `chapter-06.py:29` | `FQ(62861553107...)` | FP | Elliptic curve generator point, not magic |

**Verdict: ~40-50% TP rate.** Major FP sources: test data tables, HTTP status codes, crypto constants, power-of-2 values.

---

#### single-letter-variable

| Project | Total | Sampled | TP | FP | TP Rate |
|---------|:-----:|:-------:|:--:|:--:|:-------:|
| Go | 1,362 | 4 | 0 | 4 | **0%** |
| Rust | 131 | 3 | 0 | 3 | **0%** |
| TypeScript | 41 | 3 | 1 | 2 | **33%** |
| Ruby | 17 | 3 | 1 | 2 | **33%** |
| Python | 1,890 | 3 | 0 | 3 | **0%** |

**Source evidence:**

| Location | Code | Verdict | Reason |
|----------|------|:-------:|--------|
| Go `cookie_test.go:176` | `if g, e := tt.Cookie.String(), tt.Raw` | FP | `g`=got, `e`=expected — standard Go test convention |
| Go `cookie_test.go:201` | `m := make(Header)` | FP | `m` for map in test, acceptable |
| Rust `config.rs:3258` | `let mut f = f.debug_struct("Config")` | FP | `f` for formatter in Debug impl — idiomatic Rust |
| Rust `instance.rs:382` | `let f = unsafe { ... }` | FP | `f` for function, clear in context |
| Python `chapter-06.py:39` | `n = len(scalar_vec)` | FP | `n` is standard math notation for length |
| Ruby `branch.rb:81` | `branch` abbreviated | FP | Contextual, acceptable |

**Verdict: ~10-15% TP rate.** Nearly all detections are idiomatic code patterns: test conventions (`g`, `e`), formatter (`f`), math notation (`n`, `x`, `y`).

---

#### println-debugging

| Project | Total | Sampled | TP | FP | TP Rate |
|---------|:-----:|:-------:|:--:|:--:|:-------:|
| Go | 209 | 4 | 1 | 3 | **25%** |
| TypeScript | 9 | 2 | 1 | 1 | **50%** |
| Ruby | 65 | 3 | 0 | 3 | **0%** |
| Python | 622 | 3 | 0 | 3 | **0%** |

**Source evidence:**

| Location | Code | Verdict | Reason |
|----------|------|:-------:|--------|
| Go `alpn_test.go:24` | `fmt.Fprintf(w, "path=%s,proto=", ...)` | FP | Writing to HTTP response, not debug output |
| Go `transport.go:2628` | `log.Printf("Unsolicited response...")` | TP | Production log statement in HTTP library |
| Go `example_test.go:27` | `fmt.Println("Output:")` | FP | Example test — output is the point |
| TS `tsdown.config.ts:32` | `console.log(...)` | TP | Build config debug log (has eslint-disable) |
| Ruby `database_tasks.rb:118` | `$stdout.puts "Created database..."` | FP | User-facing CLI output, not debug |
| Ruby `database_tasks.rb:120` | `$stderr.puts "Database already exists"` | FP | Error reporting, not debug |
| Python `chapter-06.py:96` | `print("Input vector a:", a)` | FP | Educational script output |

**Verdict: ~20-30% TP rate.** Major FP sources: HTTP response writing, CLI output, example tests, educational scripts.

---

#### dead-code

| Project | Total | Sampled | TP | FP | TP Rate |
|---------|:-----:|:-------:|:--:|:--:|:-------:|
| Go | 596 | 3 | 0 | 3 | **0%** |
| Rust | 22 | 2 | 0 | 2 | **0%** |

**Source evidence:**

| Location | Code | Verdict | Reason |
|----------|------|:-------:|--------|
| Go `mapping_test.go:57` | `return true` in closure | FP | Closure return value, not dead code |
| Go `transport.go:696` | `default:` in select | FP | Non-blocking channel check, idiomatic Go |
| Rust `type_registry.rs:1016` | `};` (closing brace) | FP | Not dead code at all |
| Rust `type_registry.rs:1109` | `};` (closing brace) | FP | Not dead code at all |

**Verdict: ~0% TP rate.** The dead-code rule is fundamentally broken — it flags closure returns, select defaults, and closing braces.

---

#### commented-code

| Project | Total | Sampled | TP | FP | TP Rate |
|---------|:-----:|:-------:|:--:|:--:|:-------:|
| Go | 129 | 2 | 0 | 2 | **0%** |
| Rust | 121 | 2 | 0 | 2 | **0%** |

**Source evidence:**

| Location | Code | Verdict | Reason |
|----------|------|:-------:|--------|
| Go `transport.go:42` | `// DefaultTransport is the default...` | FP | Documentation comment |
| Go `transport.go:84` | `// (some doc comment)` | FP | Documentation comment |
| Rust `runtime.rs:9` | Module-level doc comments about coding style | FP | Documentation, not commented code |
| Rust `config.rs:2812` | `// If probestack is enabled...` | FP | Documentation comment |

**Verdict: ~0-10% TP rate.** The rule confuses documentation comments with commented-out code.

---

### Rules that detect the issue but report wrong line (line:1)

#### panic-abuse (Go) — 49 issues, ALL at line 1

| File | Reported line | Actual panics | Issue exists? |
|------|:-----------:|:-------------:|:-------------:|
| transport.go | 1 | 11 | Yes |
| cookie_test.go | 1 | 2 | Yes |
| mapping_test.go | 1 | 1 | Yes |
| httptest/server.go | 1 | 9 | Yes |
| httptest/recorder.go | 1 | 1 | Yes |

**Verdict: Issue detection is correct (5/5 files verified), but line number is always wrong.** The rule correctly identifies files with panic() but can't locate the specific lines.

#### unwrap-abuse (Rust) — 81 issues, ALL at line 1

| File | Reported line | Actual unwraps | Issue exists? |
|------|:-----------:|:--------------:|:-------------:|
| type_registry.rs | 1 | 16 | Yes |
| types.rs | 1 | 12 | Yes |
| config.rs | 1 | 2 | Yes |
| sync_std.rs | 1 | 2 | Yes |
| code_memory.rs | 1 | 2 | Yes |

**Verdict: Issue detection is correct (5/5 files verified), but line number is always wrong.**

---

#### deep-nesting

| Project | Total | Sampled | TP | FP | TP Rate |
|---------|:-----:|:-------:|:--:|:--:|:-------:|
| Go | 19 | 2 | 2 | 0 | **100%** |
| Rust | 19 | 2 | 2 | 0 | **100%** |
| TypeScript | 28 | 2 | 2 | 0 | **100%** |
| Python | 898 | 2 | 2 | 0 | **100%** |

**Source evidence:**

| Location | Code | Verdict | Reason |
|----------|------|:-------:|--------|
| Go `pattern.go:499` | Nested if/else in pattern matching | TP | 4+ levels of nesting |
| Rust `concurrent.rs:1321` | Drop impl > while let > match > closure | TP | 5 levels deep |
| TS `hooksToOptions.ts:311` | Nested AST transformation | TP | Deep nesting in transform logic |

**Verdict: ~95% TP rate.** Most reliable rule across all languages.

---

#### long-function / god-function

| Project | Total | Sampled | TP | FP | TP Rate |
|---------|:-----:|:-------:|:--:|:--:|:-------:|
| Go (long) | 29 | 2 | 2 | 0 | **100%** |
| Go (god) | 104 | 2 | 2 | 0 | **100%** |
| Rust (long) | 91 | 2 | 2 | 0 | **100%** |
| Rust (god) | 38 | 2 | 2 | 0 | **100%** |
| TS (long) | 33 | 2 | 1 | 1 | **50%** |

**Source evidence:**

| Location | Code | Verdict | Reason |
|----------|------|:-------:|--------|
| Go `cookie_test.go:813` | `TestParseSetCookie` — 200+ line test | TP | Legitimately long test function |
| Rust `config.rs:2291` | `compiler_panicking_wasm_features` | TP | Long feature-flag function |
| TS `server.ts:81` | `experimental_createServerActionHandler` | FP | 26 lines, mostly type annotations |

**Verdict: ~85-90% TP rate.** Reliable, though TypeScript functions with heavy type annotations can be FP.

---

#### terrible-naming (Rust)

| Total | Sampled | TP | FP | TP Rate |
|:-----:|:-------:|:--:|:--:|:-------:|
| 89 | 2 | 0 | 2 | **0%** |

**Source evidence:**

| Location | Code | Verdict | Reason |
|----------|------|:-------:|--------|
| `config.rs:1397` | `let val = if enable { "true" } else { "false" }` | FP | `val` is acceptable for a local string |
| `config.rs:1430` | Similar pattern | FP | Same |

**Verdict: ~0% TP rate for Rust.** The rule is too aggressive — `val` is a perfectly acceptable variable name.

---

#### abbreviation-abuse (Ruby)

| Total | Sampled | TP | FP | TP Rate |
|:-----:|:-------:|:--:|:--:|:-------:|
| 68 | 2 | 0 | 2 | **0%** |

**Source evidence:**

| Location | Code | Verdict | Reason |
|----------|------|:-------:|--------|
| `belongs_to_association.rb:16` | `id` variable | FP | `id` is universally understood |
| `has_one_association.rb:38` | `id` variable | FP | Same |

**Verdict: ~0% TP rate.** The rule flags `id` as an abbreviation, which is incorrect.

---

#### bare-rescue (Ruby)

| Total | Sampled | TP | FP | TP Rate |
|:-----:|:-------:|:--:|:--:|:-------:|
| 13 | 3 | 3 | 0 | **100%** |

**Source evidence:**

| Location | Code | Verdict | Reason |
|----------|------|:-------:|--------|
| `model_schema.rb:574` | `rescue` (no exception class) | TP | Catches all StandardError, should specify |
| `migration.rb:1566` | `rescue` (bare) | TP | Same pattern |
| `attribute_assignment.rb:51` | `rescue => ex` | TP | Bare rescue with assignment |

**Verdict: ~100% TP rate.** Reliable rule for Ruby.

---

#### global-variable (Ruby)

| Total | Sampled | TP | FP | TP Rate |
|:-----:|:-------:|:--:|:--:|:-------:|
| 33 | 3 | 0 | 3 | **0%** |

**Source evidence:**

| Location | Code | Verdict | Reason |
|----------|------|:-------:|--------|
| `sanitization.rb:223` | `$1` (regex capture) | FP | Ruby built-in regex variable, not a global |
| `sanitization.rb:225` | `$2` (regex capture) | FP | Same |
| `sanitization.rb:227` | `$2` (regex capture) | FP | Same |

**Verdict: ~0% TP rate.** The rule flags Ruby regex capture variables (`$1`, `$2`) as global variables.

---

#### any-type (TypeScript)

| Total | Sampled | TP | FP | TP Rate |
|:-----:|:-------:|:--:|:--:|:-------:|
| 439 | 3 | 3 | 0 | **100%** |

**Source evidence:**

| Location | Code | Verdict | Reason |
|----------|------|:-------:|--------|
| `createTRPCNext.tsx:82` | `(createReactQueryUtils as any)(context)` | TP | Explicit `as any` cast |
| `shared.ts:102` | Generic with `any` type parameter | TP | Legitimate any usage concern |
| `shared.ts:120` | Another `any` type | TP | Same |

**Verdict: ~95% TP rate.** Reliable rule for TypeScript.

---

#### hungarian-notation (TypeScript)

| Total | Sampled | TP | FP | TP Rate |
|:-----:|:-------:|:--:|:--:|:-------:|
| 47 | 3 | 0 | 3 | **0%** |

**Source evidence:**

| Location | Code | Verdict | Reason |
|----------|------|:-------:|--------|
| `create-action-hook.tsx:153` | `setState` | FP | React convention, not Hungarian |
| `create-action-hook.tsx:178` | `status` | FP | Not Hungarian notation |
| `create-action-hook.tsx:191` | `state` | FP | Not Hungarian notation |

**Verdict: ~0% TP rate.** The rule triggers on standard React/TypeScript naming conventions.

---

## Overall Accuracy Summary

### By rule (ranked by reliability)

| Rule | TP Rate | Total Issues | Assessment |
|------|:-------:|:------------:|------------|
| bare-except | ~100% | 6 | Reliable |
| deep-nesting | ~95% | 1,069 | **Most reliable** |
| any-type | ~95% | 439 | Reliable |
| long-function | ~85% | 655 | Reliable |
| god-function | ~85% | 696 | Reliable |
| bare-rescue | ~100% | 13 | Reliable |
| magic-number | ~40% | 11,551 | Needs work |
| println-debugging | ~20% | 905 | Needs context |
| single-letter-variable | ~10% | 3,441 | **Broken** |
| commented-code | ~5% | 431 | **Broken** |
| dead-code | ~0% | 618 | **Broken** |
| terrible-naming | ~0% | 285 | **Broken** |
| hungarian-notation | ~0% | 337 | **Broken** |
| abbreviation-abuse | ~0% | 73 | **Broken** |
| global-variable | ~0% | 33 | **Broken** |
| box-abuse | ~5% (fabricated) | 72 | **Broken** |

### By language (weighted TP rate)

| Language | Total Issues | line:1 bugs | Effective TP Rate |
|----------|:-----------:|:-----------:|:-----------------:|
| Go | 5,179 | 77 (1.5%) | ~35% |
| Rust | 3,918 | 301 (7.7%) | ~30% |
| TypeScript | 1,799 | 2 (0.1%) | ~50% |
| Ruby | 1,792 | 14 (0.8%) | ~35% |
| Python | 21,127 | 90 (0.4%) | ~25% |

### Weighted overall TP rate: **~32%**

Out of every 100 issues reported, approximately 32 are genuine code smells, 63 are false positives, and 5 have the right issue but wrong line number.

---

## Key Findings

1. **5 rules are broken** (dead-code, commented-code, terrible-naming, hungarian-notation, abbreviation-abuse) — they produce almost exclusively false positives.

2. **484 issues have wrong line numbers** (line:1 bug) — affects unwrap-abuse, box-abuse, panic-abuse, generic-abuse, lifetime-abuse, file-too-long, and others.

3. **box-abuse fabricates detections** — 68 out of 72 reports are for files with zero Box:: usage.

4. **The tool doesn't exclude .venv/** — Python projects with virtual environments produce hundreds of thousands of issues from bundled JS.

5. **The reliable rules are**: deep-nesting (~95%), any-type (~95%), bare-except (~100%), bare-rescue (~100%), long-function (~85%), god-function (~85%).

6. **Test code inflates counts** — magic-number, println-debugging, and single-letter-variable have much higher FP rates in test files than production code.

---

## Specific Improvement Priorities

### P0 — Fix immediately (broken rules)

1. **Fix line:1 bug** — unwrap-abuse, box-abuse, panic-abuse, generic-abuse, lifetime-abuse, file-too-long, macro-abuse, reference-abuse, pattern-matching-abuse, todo-comment, goroutine-abuse must report actual line numbers.

2. **Fix box-abuse false fabrications** — The rule reports files that don't contain Box:: at all. The detection query is wrong.

3. **Fix dead-code rule** — Currently flags closure returns, select defaults, and closing braces. Need to actually detect unreachable code.

4. **Fix commented-code rule** — Confuses documentation comments (`//` doc comments) with commented-out code. Need to distinguish `// TODO: ...` and `/// docs` from `// oldFunction()`.

5. **Fix terrible-naming for Rust**`val` should not be flagged. The allowlist needs expansion.

6. **Fix hungarian-notation for TypeScript**`setState`, `status`, `state` are not Hungarian notation. The detection pattern is wrong.

7. **Fix global-variable for Ruby**`$1`, `$2` are regex captures, not global variables. Exempt `$` followed by digits.

8. **Fix abbreviation-abuse**`id` is not an abbreviation. Update the abbreviation dictionary.

### P1 — Improve accuracy

9. **magic-number**: Exempt test data tables, HTTP status codes, power-of-2 values, crypto constants.
10. **println-debugging**: Exempt HTTP response writing (fmt.Fprintf to ResponseWriter), CLI output ($stdout.puts), example tests.
11. **single-letter-variable**: Exempt Go test conventions (g, e, tt), Rust formatter (f), math notation (n, x, y).

### P2 — Auto-exclusions

12. **Auto-exclude `.venv/`, `node_modules/`, `vendor/`, `__pycache__/`** — Don't scan dependency directories.
13. **Auto-exclude `*.min.js`, `*.bundle.js`** — Minified/bundled JS is not source code.