Adopt Biome lint rules#2926
Merged
Merged
Conversation
Turn on Biome's linter using the recommended rule preset. Of the 218 recommended rules, 30 currently report diagnostics on this codebase; those 30 are explicitly set to "off" for now so that lint passes with no code changes, leaving 188 recommended rules active. The disabled rules will be re-evaluated and either adopted (with violations fixed) or rejected with rationale in follow-up commits. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One violation: an unused lodash import in the PHP language utils. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Five violations, all unused catch-clause bindings; converted to optional catch binding (catch without a parameter). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three violations, all parsing a single character with Number.parseInt; added an explicit radix of 10, which preserves behavior. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Wrapped switch cases that declare variables in blocks so the declarations are properly scoped to their case. Safe fixes only. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Six violations, all "return panic(...)" statements in the GQLSchemaFromJSON constructor. Since panic() returns never, dropping the "return" keyword preserves behavior, and TypeScript's control-flow analysis now sees the definite assignment of queryType, making the existing @ts-expect-error directive obsolete. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Thirteen violations, all "return panic(...)", "return messageError(...)" or "return assertNever(...)" inside void-returning functions. All three helpers return never, so dropping the "return" keyword preserves behavior. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One violation: a redundant trailing continue in breakCycles. Safe fix. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One violation: a "java8" case clause that fell through to an adjacent default clause with the same body. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One violation: "propCount ? false : true" simplified to "!propCount". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two violations: redundant double-negations in boolean conditions in the test helpers. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two violations: "+new Date()" timing code in the test harness replaced with Date.now(). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One violation: an undefined-check-plus-method-call collapsed into an optional chain. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Seven violations: constructors that only forwarded their arguments to super with no other work. Removed them along with the type imports that only they used. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
24 violations: "let x: T | undefined = undefined" initializers where the explicit "= undefined" is redundant. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Thirteen violations of the banned "{}" type: eight "properties: {}"
members in the ErrorProperties union and five "getOptions(): {}"
signatures in option-less target languages. All replaced with the
precise Record<string, never> empty-object type.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One violation: a never-reassigned "let" arrow function changed to "const". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Six violations: Math.pow calls replaced with the ** operator. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Six violations: bare Node.js builtin imports now use the node:
protocol in the VS Code extension and the test harness. quicktype-core
is exempted via a config override because its "browser" package.json
field only remaps bare builtin specifiers ("fs"), not "node:fs" --
an invariant already enforced by test/unit/core-package.test.ts.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two violations in the System.Text.Json C# renderer: the transformers were already guarded against undefined, but the narrowing was lost inside emitBlock closures. Destructuring them into consts before the guard preserves the narrowing without assertions, matching the existing nullTransformer pattern in the same function. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Forty violations: string concatenations converted to template
literals. All conversions are straight stringifications; escapes for
literal ${, backticks, and backslash sequences were verified by hand.
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One violation: "sl instanceof Array" replaced with Array.isArray(sl), which is also correct across realms. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One violation: a @ts-ignore on a type-only import of a build artifact in test/languages.ts, replaced with @ts-expect-error and an explanation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three violations: added explicit type annotations to "let" bindings in the vendored get-stream helper and the Chance Mersenne Twister port. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two violations, both already using the safe Object.prototype.hasOwnProperty.call pattern. The suggested Object.hasOwn is not available under quicktype-core's es6 lib (and would raise the package's runtime floor), so both sites carry a targeted suppression instead. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two violations: a constructor parameter named toString in the C++ utils (renamed to toStringCode), and a hasOwnProperty import from collection-utils in TransformedStringType.ts, which now carries the same biome-ignore suppression used at the other import sites of that name (replacing a stale eslint-disable). Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Six violations converted to Number.isNaN. Every call site passes a value that is already a number (parseInt/parseFloat results, or values behind a typeof === "number" guard), so dropping the global isNaN coercion does not change behavior. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Seven violations in test/languages.ts: escaped double quotes inside template literals, where the backslash is a no-op. The resulting strings are byte-for-byte identical. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Nineteen violations: forEach callbacks written as expression-bodied arrows that implicitly returned a value. Converted each to a statement body; no return values were ever consumed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
25 violations. The six "any" members of the ErrorProperties union in Messages.ts became "unknown" (the values are only formatted into messages). The rest are deliberate anys -- heterogeneous attribute maps, arbitrary JSON containers, vendored get-stream code, untyped web-tree-sitter modules -- and now carry biome-ignore suppressions with reasons, replacing the stale eslint-disable comments where those existed. This also puts the two pre-existing noExplicitAny suppressions back into effect. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two violations: template literals without interpolation converted to plain string literals. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One violation: "p = p * cp" changed to "p *= cp". Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One violation: a redundant ": boolean" annotation on an initialized variable removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two violations in the Dart renderer: a leading "isNullable = false" default parameter followed by required parameters. A leading default can never be omitted, and every call site passes the argument explicitly, so it is now a required boolean parameter. Also drops the eslint-disable comments that waived the equivalent ESLint rule. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two violations in the multicore test helper: method-style interface signatures converted to property-style arrow signatures, which also get strict (non-bivariant) parameter checking. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One violation: the compose() overload pair in the Python renderer (previously waived with an eslint-disable) collapsed into the single union-typed signature the implementation already had. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One violation: an ambient "declare namespace Math" in the deepEquals test helper that added Math.fround for an ancient TypeScript lib. Math.fround has been in the standard lib since ES2015, so the declaration is simply removed. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One violation: "strict as assert" from node:assert now imports from node:assert/strict, which is the identical strict assert object. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Thirteen violations: private class properties that are never reassigned marked readonly. Type-level only; verified by tsc. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One violation: "nullableFromUnion(...) != null" changed to "!== null". The function returns Type | null (never undefined), so the loose comparison was equivalent. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two violations, both deliberate compile-time "satisfies" type checks; suppressed with explanations so the rule can guard against genuinely dead expressions. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Three violations, all default-sorts of string arrays (JSON Schema required lists and Java imports) where UTF-16 code unit order is the intended, deterministic order for generated code. Suppressed with explanations; the rule now guards against comparator-less sorts of non-string arrays. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Ten violations: nine in test/release-version.ts, a script-style test that runs its node:assert checks at module top level by design (now exempted via a config override), and one expect() in a test helper function, suppressed with an explanation. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
29 violations: one genuine shadow in JSONSchemaInput (a lambda parameter named "name" shadowing a function-scoped variable, renamed to "key"), and 28 in CJSONRenderer.ts, whose deeply nested emit closures reuse the same parameter names by design; that file is exempted via a config override because bulk-renaming those parameters would be high-risk churn. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Two violations. A genuine catch: the quicktype CLI imports wordwrap but only had @types/wordwrap declared, relying on hoisting from quicktype-core; wordwrap is now a declared dependency (lockfile updated, no version changes to existing entries). The vscode import in the extension is provided by the VS Code host at runtime and carries a suppression. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
One violation: __dirname in the CommonJS test harness, suppressed with an explanation. The rule now protects quicktype-core's dual CJS/ESM build from accidental __dirname/__filename usage, which would break the ES module leg. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Enables noUnusedInstantiation and useSingleJsDocAsterisk, which are already clean on the codebase, to guard against future violations. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Enables noDivRegex, noUselessCatchBinding, noUselessStringConcat, useArrayFind, useWhile, noRedundantDefaultExport and noExcessiveNestedTestSuites, all already clean on the codebase. noUselessCatchBinding also locks in the optional-catch-binding cleanup done for noUnusedVariables. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Enables noConstantBinaryExpressions, noVar, noFocusedTests, noSkippedTests, noReturnAssign, noDuplicateTestHooks, noDeprecatedImports, noDuplicateDependencies, useErrorMessage and noEmptySource, all already clean on the codebase. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Enables useThrowOnlyError, useTrimStartEnd, useSymbolDescription, useSpreadOverApply, useNumberNamespace, useGlobalThis and useErrorCause, all already clean on the codebase. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The delete operator is not used anywhere in the codebase; enabling the rule keeps it that way. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
schani
commented
Jul 13, 2026
The owner prefers explicit else blocks after returning branches; the flattened straight-line form loses the visual symmetry of the two arms. Rule set explicitly to "off" to document the deliberate rejection. Reverts commit e4df2f0. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
The owner prefers "return panic(...)" over a bare "panic(...)" statement in void-returning functions: the return makes the control-flow termination explicit at the call site. Rule set explicitly to "off" to document the deliberate rejection. Reverts commit 4509283. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
schani
commented
Jul 13, 2026
schani
left a comment
Member
Author
There was a problem hiding this comment.
One API-compatibility issue found.
Same idiom objection as noVoidTypeReturn: the owner prefers "return panic(...)" over a bare "panic(...)" statement. Restores the @ts-expect-error on queryType that the definite-assignment analysis had made obsolete. Rule set explicitly to "off" to document the deliberate rejection. Reverts commit 279491f. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
DartRenderer is exported from quicktype-core, so fromDynamicExpression and toDynamicExpression are downstream-subclass API; dropping their "isNullable = false" defaults was a breaking signature change. Restore the defaults and suppress useDefaultParameterLast at the two parameters instead. These were the rule's only two violations, so no other API surface was affected. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Adopt Biome lint rules
This PR turns Biome's linter on for real, on top of the formatter-only setup from #2923, and adopts rules deliberately:
recommendedpreset. Of the 218 recommended rules, 30 reported diagnostics on the codebase; those were temporarily set to"off"so the commit lands with lint green and zero code changes.nurserygroup was skipped as unstable, anda11yplus the framework-specific rules (React/Vue/Qwik/Solid/Next/DOM/CSS/GraphQL) don't apply to this library/CLI.Every commit keeps
npm run lint,npm run build, and the Vitest unit suite green. Lint fixes are behavior-preserving; where a fix would have been risky or wrong, a targetedbiome-ignoresuppression with a real explanation (or a scoped config override) is used instead. Notably,noUndeclaredDependenciescaught a genuine issue: the CLI importedwordwrapwithout declaring it, relying on hoisting from quicktype-core — it is now a declared dependency.Result: 270 rules active (215 recommended + 55 opted-in), 3 recommended rules off, 3 scoped overrides.
Adopted rules (with violations fixed)
Recommended preset (re-enabled one by one)
{}→Record<string, never>!!x ? false : true→!x= undefinedinitializers+new Date()→Date.now()!with narrowing via destructured constsMath.pow→**node:prefix; quicktype-core exempted via override (itsbrowserfield only remaps bare specifiers — enforced bycore-package.test.ts)unknown; deliberate anys (heterogeneous maps, vendored get-stream, untyped tree-sitter) suppressed with reasons.callsites suppressed;Object.hasOwnunavailable under core's es6 libtoStringparam renamed; collection-utilshasOwnPropertyimport suppressed@ts-expect-errorwith explanation\"in template literalsinstanceof Array→Array.isArrayNon-recommended rules (opted in, violations fixed)
wordwrapnow declared for the CLI;vscodehost module suppressedreturn;throw Error(...)→throw new Error(...)Object.assign({}, ...)→ spread; 3 sites needed type annotationssubstring→slice; one site got an explicit guard to preserve edge-case behaviorDartRenderer's protected dynamic-expression methods), so per review the defaults are kept with targeted suppressions — the rule now only guards new codedeclare namespace Math(fround is in ES2015 lib)Type | null, never undefinedsatisfieschecks suppressedtest/release-version.tsexempted via override; one test helper suppressedAlready-clean guard rules enabled (no violations)
correctness:
noUnusedInstantiation,useSingleJsDocAsterisk· complexity:noDivRegex,noUselessCatchBinding,noUselessStringConcat,useArrayFind,useWhile,noRedundantDefaultExport,noExcessiveNestedTestSuites· performance:noDelete· style:useThrowOnlyError,useTrimStartEnd,useSymbolDescription,useSpreadOverApply,useNumberNamespace,useGlobalThis,useErrorCause· suspicious:noConstantBinaryExpressions,noVar,noFocusedTests,noSkippedTests,noReturnAssign,noDuplicateTestHooks,noDeprecatedImports,noDuplicateDependencies,useErrorMessage,noEmptySourceRejected / skipped rules
Recommended rules kept off
${placeholder}templates in plain strings by design (Messages.ts, substituted at runtime bymessageError), and the Kotlin renderers emit Kotlin's own${}interpolation syntax. The rule flags the codebase's intended core patterns wholesale.return panic(...)in void functions — thereturnmakes the control-flow termination explicit at the call site. Initially adopted, then reverted.return panic(...)in a constructor. Reverting restored the@ts-expect-erroronqueryTypethat the fix had made obsolete.Non-recommended rules not adopted (off by default; rationale)
"off".Input.addSourceetc.) with sync bodiesvoid promisedeliberately marks fire-and-forget calls+str/!!xare deliberate idiomsimport *and barrel index files are the package structurelastIndexstate and hurts localitypublic; the rule's default demands the opposite.at()is not in quicktype-core's es6 libundefinedreturns/arguments are used deliberately with strict optional typingVerification
npm run lintexits 0 with zero diagnosticsnpm run build(all workspaces + CLI) succeedsnpm run test:unit— 70/70 Vitest tests pass🤖 Generated with Claude Code