Skip to content

Commit 095703c

Browse files
committed
improvement(audits): fail on unparsable files, refuse suppressed updates, require balanced dynamic segments
1 parent 9fec91e commit 095703c

3 files changed

Lines changed: 24 additions & 13 deletions

File tree

‎knip.jsonc‎

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,10 @@
44
// Unused exports, types, and duplicates are ratcheted by check:unused-exports,
55
// which reuses this config in the same knip pass.
66
"include": ["files", "dependencies", "unlisted", "unresolved"],
7-
// Package `exports`/`main`/`bin` targets are entries; their exports are public
8-
// contracts (ts-sdk, emcn, cli, …), so knip must never report them as unused.
7+
// knip's default, stated so it is a decision: no entry file's exports are reported.
8+
// That keeps package `exports`/`main`/`bin` contracts (ts-sdk, emcn, cli, …) and framework
9+
// entries (Next routes, Trigger tasks) public, and also exempts the other configured entries
10+
// (scripts, `*.integration.ts`, `background/**`, desktop and SDK examples).
911
"includeEntryExports": false,
1012
"workspaces": {
1113
".": {

‎scripts/check-explicit-any.ts‎

Lines changed: 19 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,15 @@ function collect(): Baseline {
6868
const ruleToMetric = new Map<string, Metric>(
6969
Object.entries(METRICS).map(([metric, rule]) => [rule, metric as Metric])
7070
)
71-
for (const line of result.stdout.toString().split('\n')) {
71+
const lines = result.stdout.toString().split('\n')
72+
// A file Biome cannot parse yields an undercount, so a parse error fails the audit outright.
73+
const unparsable = lines.filter((line) => line.startsWith('::error title=parse,'))
74+
if (unparsable.length) {
75+
console.error(`✗ Biome could not parse ${unparsable.length} location(s); fix the syntax first:`)
76+
for (const line of unparsable) console.error(` ${line.replace(/^::error title=parse,/, '')}`)
77+
process.exit(1)
78+
}
79+
for (const line of lines) {
7280
const match = /^::\w+ title=([^,]+),file=([^,]+),/.exec(line)
7381
const metric = match && ruleToMetric.get(match[1])
7482
if (!match || !metric) continue
@@ -131,7 +139,17 @@ function shrunkTo(after: Counts, before: Counts): Counts {
131139
)
132140
}
133141

142+
const suppressed = suppressions()
143+
if (suppressed.length) {
144+
console.error(
145+
`✗ ${suppressed.length} biome-ignore comment(s) hide an \`any\` or \`!\` from this check:`
146+
)
147+
for (const line of suppressed) console.error(` ${line}`)
148+
console.error(' Delete the suppression and fix the type instead.\n')
149+
}
150+
134151
if (process.argv.includes('--update')) {
152+
if (suppressed.length) process.exit(1)
135153
const next: Baseline = {
136154
explicitAny: sorted(shrunkTo(current.explicitAny, baseline.explicitAny ?? {})),
137155
nonNullAssertion: sorted(shrunkTo(current.nonNullAssertion, baseline.nonNullAssertion ?? {})),
@@ -162,15 +180,6 @@ let stale = 0
162180
/** A vanished baselined file next to a new file with no more hits: likely a rename. */
163181
const renames = new Set<string>()
164182

165-
const suppressed = suppressions()
166-
if (suppressed.length) {
167-
console.error(
168-
`✗ ${suppressed.length} biome-ignore comment(s) hide an \`any\` or \`!\` from this check:`
169-
)
170-
for (const line of suppressed) console.error(` ${line}`)
171-
console.error(' Delete the suppression and fix the type instead.\n')
172-
}
173-
174183
for (const metric of Object.keys(METRICS) as Metric[]) {
175184
const before = baseline[metric] ?? {}
176185
const after = current[metric]

‎scripts/check-file-names.ts‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -45,7 +45,7 @@ const BASELINE = path.join(ROOT, 'scripts/check-file-names.baseline.json')
4545
const SOURCE_FILE = /\.(?:[cm]?[jt]sx?)$/
4646
const KEBAB = /^[a-z0-9]+(?:-[a-z0-9]+)*$/
4747
const KEBAB_OR_SNAKE = /^[a-z0-9]+(?:[-_][a-z0-9]+)*$/
48-
const NEXT_DYNAMIC = /^\[{1,2}(?:\.\.\.)?[A-Za-z][A-Za-z0-9]*\]{1,2}$/
48+
const NEXT_DYNAMIC = /^(?:\[(?:\.\.\.)?[A-Za-z][A-Za-z0-9]*\]|\[\[\.\.\.[A-Za-z][A-Za-z0-9]*\]\])$/
4949
const NEXT_GROUP = /^\([a-z0-9]+(?:-[a-z0-9]+)*\)$/
5050
const NEXT_INTERCEPT = /^(?:\(\.{1,3}\)|(?:\(\.\.\))+)[a-z0-9]+(?:-[a-z0-9]+)*$/
5151
const NEXT_SLOT = /^@[a-z0-9]+(?:-[a-z0-9]+)*$/

0 commit comments

Comments
 (0)