fix(rules): make magic-number detection far less noisy
Real-world test on a 321-file TS/Svelte monorepo flagged 454 magic-number findings, ~82% of them noise: literals already assigned to a named const/field and numbers merely buried under a binary expression (e.g. a call arg inside a string concat). Tighten all 5 languages to: (1) require the literal be a DIRECT operand of a binary/comparison expression, and (2) exclude initializers of a named binding (const/var/let/field). Cuts magic-number ~67% with no loss on fixtures (each language still detects its genuine `x > 5000` case). Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
co-authored by
Claude Opus 4.8
parent
6fb2210bbe
commit
8324dde1a2
@@ -30,9 +30,10 @@ language: Go
|
||||
severity: info
|
||||
message: "Magic number in an expression — consider a named constant."
|
||||
rule:
|
||||
kind: int_literal
|
||||
not:
|
||||
regex: "^(0|1|2|10|100|1000)$"
|
||||
inside:
|
||||
kind: binary_expression
|
||||
stopBy: end
|
||||
all:
|
||||
- kind: int_literal
|
||||
- not: { regex: "^(0|1|2|10|100|1000)$" }
|
||||
- inside: { kind: binary_expression }
|
||||
# Skip literals already named via const/var declaration.
|
||||
- not: { inside: { kind: const_spec, stopBy: end } }
|
||||
- not: { inside: { kind: var_spec, stopBy: end } }
|
||||
|
||||
@@ -30,9 +30,9 @@ language: Java
|
||||
severity: info
|
||||
message: "Magic number in an expression — consider a named constant."
|
||||
rule:
|
||||
kind: decimal_integer_literal
|
||||
not:
|
||||
regex: "^(0|1|2|10|100|1000)$"
|
||||
inside:
|
||||
kind: binary_expression
|
||||
stopBy: end
|
||||
all:
|
||||
- kind: decimal_integer_literal
|
||||
- not: { regex: "^(0|1|2|10|100|1000)$" }
|
||||
- inside: { kind: binary_expression }
|
||||
# Skip literals already named via field/variable declaration.
|
||||
- not: { inside: { kind: variable_declarator, stopBy: end } }
|
||||
|
||||
@@ -30,9 +30,9 @@ language: JavaScript
|
||||
severity: info
|
||||
message: "Magic number in an expression — consider a named constant."
|
||||
rule:
|
||||
kind: number
|
||||
not:
|
||||
regex: "^(0|1|2|-1|10|100|1000)$"
|
||||
inside:
|
||||
kind: binary_expression
|
||||
stopBy: end
|
||||
all:
|
||||
- kind: number
|
||||
- not: { regex: "^(0|1|2|-1|10|100|1000)$" }
|
||||
- inside: { kind: binary_expression }
|
||||
- not: { inside: { kind: variable_declarator, stopBy: end } }
|
||||
- not: { inside: { kind: field_definition, stopBy: end } }
|
||||
|
||||
@@ -33,11 +33,9 @@ language: Python
|
||||
severity: info
|
||||
message: "Magic number in an expression — consider a named constant."
|
||||
rule:
|
||||
kind: integer
|
||||
not:
|
||||
regex: "^(0|1|2|10|100|1000)$"
|
||||
inside:
|
||||
any:
|
||||
- kind: binary_operator
|
||||
- kind: comparison_operator
|
||||
stopBy: end
|
||||
all:
|
||||
- kind: integer
|
||||
- not: { regex: "^(0|1|2|10|100|1000)$" }
|
||||
- inside: { any: [{ kind: binary_operator }, { kind: comparison_operator }] }
|
||||
# Skip literals already named via assignment (e.g. `RETRIES = 5`).
|
||||
- not: { inside: { kind: assignment, stopBy: end } }
|
||||
|
||||
@@ -31,9 +31,10 @@ language: Rust
|
||||
severity: info
|
||||
message: "Magic number in an expression — consider a named constant."
|
||||
rule:
|
||||
kind: integer_literal
|
||||
not:
|
||||
regex: "^(0|1|2|10|100|1000)$"
|
||||
inside:
|
||||
kind: binary_expression
|
||||
stopBy: end
|
||||
all:
|
||||
- kind: integer_literal
|
||||
- not: { regex: "^(0|1|2|10|100|1000)$" }
|
||||
- inside: { kind: binary_expression }
|
||||
# Skip literals already named via `let`/`const`/`static` declaration.
|
||||
- not: { inside: { kind: let_declaration, stopBy: end } }
|
||||
- not: { inside: { kind: const_item, stopBy: end } }
|
||||
|
||||
@@ -38,9 +38,12 @@ severity: info
|
||||
message: "Magic number in an expression — consider a named constant."
|
||||
metadata: { pattern: magic-number, apply_track: llm, difficulty: semantic }
|
||||
rule:
|
||||
kind: number
|
||||
not:
|
||||
regex: "^(0|1|2|-1|10|100|1000)$"
|
||||
inside:
|
||||
kind: binary_expression
|
||||
stopBy: end
|
||||
all:
|
||||
- kind: number
|
||||
- not: { regex: "^(0|1|2|-1|10|100|1000)$" }
|
||||
# Must be a DIRECT operand of a comparison/arithmetic expression (e.g. `x > 5000`),
|
||||
# not just buried under one (avoids flagging call args inside a concat, etc.).
|
||||
- inside: { kind: binary_expression }
|
||||
# Skip literals that already have a name: the value of `const X = ...` or a class field.
|
||||
- not: { inside: { kind: variable_declarator, stopBy: end } }
|
||||
- not: { inside: { kind: public_field_definition, stopBy: end } }
|
||||
|
||||
Reference in New Issue
Block a user