Commit Graph

251 Commits

Author SHA1 Message Date
camc314 beb724dce2 fix(linter/eslint/no-unused-vars): report bare underscore parameters (#25663)
## Summary

- report a bare underscore parameter when no args ignore pattern is configured
- preserve the optimized underscore-prefix behavior for explicit argsIgnorePattern configuration
- update focused rule coverage and generated documentation

Closes #25626
2026-08-14 13:16:16 +00:00
Faris Tristan Fabian 2b027111db fix(oxlint): correct --warn flag help text (#25059)
The `-W, --warn` help text says "Deny the rule or category (emit a
warning)", copied from the `-D, --deny` entry.

With that wording, `--warn` and `--deny` look like they do the same
thing in `--help`, but `-W` reports a warning and `-D` reports an error.

Evidence why I think this is not intentional, and instead a typo:

- The other two entries start with their own flag's verb ("Allow the
rule...", "Deny the rule..."). Only the `-W` entry starts with its
sibling's verb, in a sentence identical to the `-D` one except the
parenthetical.
- These flags mirror rustc and clippy's `-A`/`-W`/`-D`, where warn and
deny are two different levels and deny specifically means "make it an
error".
- In this same file, `-W` maps to `AllowWarnDeny::Warn` and `-D` maps to
`AllowWarnDeny::Deny` (`into_tuple`). The internal name for what `-W`
does is warn, not deny.

What changed:

- The `-W` help text is now "Warn on the rule or category (emit a
warning)"
- Updated the two website_linter snapshots, so the generated CLI docs
page picks up the fix

I used Claude Code to help find and fix this.

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-07-29 11:05:18 +01:00
Boshen 3ff2e0e6fa docs(linter): clarify config extends types (#24936)
The generated config reference only described the JSON schema's `string[]` form. Clarify that `oxlint.config.ts` accepts imported `OxlintConfig[]`, add an example and public JSDoc, and regenerate the derived artifacts.

Closes #20238.

Validated with the website generator suite, targeted TypeScript checks, and the relevant Oxlint tests. The full `just ready` run reached an unrelated parallel suppression-fixture cleanup race; the failing test passes in isolation.

AI-assisted.
2026-07-27 01:51:16 +00:00
Mikhail Baev 678bbb5f34 feat(linter/typescript-eslint): implement suggestion for class-literal-property-style rule (#24766)
this PR implements suggestion for
`typescript-eslint/class-literal-property-style` rule. Passes all (19)
[upstream test
cases](https://github.com/typescript-eslint/typescript-eslint/blob/main/packages/eslint-plugin/tests/rules/class-literal-property-style.test.ts)

issue #2180
2026-07-22 11:52:59 +01:00
Boshen baf022d74d refactor(ast)!: remove old AstBuilder methods (#24563)
Closes the migration tracked in #23043.

The new builder API (methods on the AST types themselves) has been in place for a while, all Oxc crates are migrated, and every crate which uses `AstBuilder` already enables `disable_old_builder` in its tests. The module docs said "after a few weeks, we will remove `AstBuilder`'s own methods entirely" — this does that.

## What's removed

- `crates/oxc_ast/src/generated/ast_builder.rs` and `builder/methods.rs` — `AstBuilder`'s own node and primitive constructors.
- `AstBuilderGenerator`, which produced the former.
- The `disable_old_builder` Cargo feature, plus the dev-dependency hacks it required across 33 manifests. Eight crates depended on `oxc_ast` *purely* to turn the feature on; those deps and their `cargo-shear` ignore entries are gone too.

## One thing worth reviewing

`AstBuilderGenerator` owned the `#[builder(default)]` / `#[builder(skip)]` attr registration that `BuilderMethodsGenerator` only *reads* — its doc comment said as much. Deleting it naively would have silently dropped `skip`/`default` handling for the 12 AST types using those attrs, so `attrs()` and `parse_attr()` move to `BuilderMethodsGenerator`.

The evidence this was faithful: after regenerating, `builder_methods.rs` and every other generated file are **byte-identical**. The only generated change in the diff is the deletion.

## Breaking changes

- `AstBuilder`'s own methods are gone. Use the AST type methods: `Statement::new_expression_statement(span, expr, &builder)` instead of `builder.statement_expression(span, expr)`.
- `AstBuilder` is no longer `Copy`/`Clone`, and its `allocator` field is private — use the `allocator` method from `GetAllocator`.
- `AstBuilder` and `NONE` are no longer re-exported from the crate root; import them from `oxc_ast::builder`. (The `disable_old_builder` feature already gated these off, so nothing in-tree used the root path.)
- The `disable_old_builder` feature no longer exists — remove it from any manifest that sets it.

A migration note covering all of the above is in `crates/oxc_ast/src/builder/mod.rs`.

---

Implemented with AI assistance (Claude Code); design, review, and verification driven by the author per the repo AI-usage policy.
2026-07-21 15:22:46 +00:00
camc314 92f154a07c feat(oxlint,oxfmt): auto-discover .mts config files (#24357)
## Summary

- auto-discover `oxfmt.config.mts` and `oxlint.config.mts`
- watch `.mts` configs in the language server and reject `.ts`/`.mts` conflicts
- add focused CLI and LSP coverage
2026-07-10 11:38:35 +00:00
leaysgur 83378351e4 fix(linter): error on ignorePatterns that cannot match files aoutside the config directory (#24341)
Follow up on #24339

- Added the same guard as Oxfmt
- Since they are identical, I moved them into `oxc_config` so they can be shared
2026-07-10 09:05:48 +00:00
leaysgur 2ce5a33ecc fix(linter): resolve ignorePatterns relative to the config dir (#24339)
Fixes #24310

Root config's `ignorePatterns` are now resolved relative to the directory containing the config file, instead of CWD.

Also fixes a latent issue: a `--config <path>` containing `..` silently disabled all `ignorePatterns` (the unnormalized parent dir never prefix-matches lint target paths). Explicit config paths are now lexically normalized, same as Oxfmt.

### Behavior change

The new anchoring applies in all cases, including `--config` / LSP `configPath`. This intentionally differs from ESLint, which resolves alternate-config ignore patterns relative to CWD:

- `extends`, `overrides[].files`, and JS plugin specifiers are already config-file-relative, including via `--config`
  - rooting only `ignorePatterns` at CWD would give one file two coordinate systems
- Wrappers like Vite+ pass `--config <workspace-root config>` as an implementation detail while CWD stays at the invocation directory, so "`--config` means CWD-relative" does not hold in practice
  - #24276

Impact should be small: bare names (`dist`, `*.min.js`) and `**/`-prefixed patterns are unaffected by the anchor.

The updated `config_ignore_patterns/with_oxlintrc` snapshot shows the `--config` case.
2026-07-10 08:39:56 +00:00
ColemanDunn 002ab355ec fix(linter/unicorn): avoid prefer-array-find rest destructuring false positive (#23654)
## Summary

This PR fixes two issues in `unicorn/prefer-array-find`:

- Oxlint reports a false positive for rest destructuring from
`filter()`, where `find()` is not an equivalent replacement.
- The rule docs are missing supported cases that the implementation
already detects, including array destructuring and `findLast()`-style
patterns. The upstream [eslint-plugin-unicorn
docs](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-find.md)
cover these cases, so this brings Oxlint's docs closer to the equivalent
rule.

## False positive

On this line, Oxlint currently reports a false positive diagnostic from
`unicorn/prefer-array-find`:

```js
const [element, ...restElements] = myArray.filter(isEven);
```

That diagnostic is incorrect because the code keeps both the first
matching element and the remaining matching elements. Replacing it with
`find()` would drop `restElements`, so it is not an equivalent
transformation.

The fix is to only report array destructuring when there is no rest
element. This still reports valid cases like:

```js
const [element] = myArray.filter(isEven);
```

## Docs mismatch

Oxlint already detects more than the docs describe. In addition to
`filter(...)[0]` and `.shift()`, the implementation handles simple array
destructuring and last-match cases using `.at(-1)` or `.pop()`.

This PR updates the docs to include those supported patterns and their
`find()` / `findLast()` replacements, matching the upstream
[eslint-plugin-unicorn
docs](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-find.md)
more closely for the cases Oxlint currently implements.

## Upstream parity mismatch still exists


[`eslint-plugin-unicorn`](https://github.com/sindresorhus/eslint-plugin-unicorn/blob/main/docs/rules/prefer-array-find.md)
also documents and detects `.filter(fn).slice(-1)[0]`-style last-element
patterns. Oxlint does not currently detect that pattern, so this PR does
not document it. That can be handled as a separate parity follow-up.

## Tests

- `cargo fmt -p oxc_linter`
- `cargo test -p oxc_linter prefer_array_find -- --nocapture`
- Manual local repro with `oxlint -D unicorn/prefer-array-find`

## AI assistance

AI assistance was used to prepare this change. I have reviewed the code
and remain responsible for the submission.

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-07-02 17:36:49 +01:00
Mikhail Baev 743e22293b feat(linter/react): add disallowedValues option for forbid-dom-props rule (#23970)
fixes #23049. Tests regenerated from upstream
2026-06-30 09:06:52 +01:00
overlookmotel 85a6853e0b fix(tasks): enable disable_old_builder Cargo feature for oxc_ast crate for all tasks (#23885)
Part of #23043.

We don't enable `oxc_ast`'s `disable_old_builder` Cargo feature in any of our published crates, or crates that are depended on by published crates.

Tasks are private to the repo, so enable this feature on them, to ensure no usage of legacy `AstBuilder` methods sneak in during the transition period before we delete these methods.
2026-06-28 12:13:17 +00:00
Connor Shea 9fff263920 docs(linter): Add short descriptions to more rules that lacked them (#23389)
This adds more short descriptions to rules that lacked them, completes
all the rules in the following plugins:

- Oxc
- JSDoc
- Vue
- Nextjs
- Promise
- jsx-a11y

About 200 rules still lack short descriptions, so I'll do those in
subsequent PRs to avoid needing review on any massive sets.

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-06-14 13:56:51 +01:00
Sysix b0d39d7942 test(website): fix tests for win32 (#23398)
fixes the tests on main:
https://github.com/oxc-project/oxc/actions/runs/27479376607/job/81224340552

introduced in https://github.com/oxc-project/oxc/pull/23387
2026-06-14 11:59:06 +00:00
Sysix 49e5649653 test(website): don't snapshot on schema validation (#23387)
It sounds stupid to create a snapshot from an already existing file.
Works on https://github.com/oxc-project/oxc/issues/22955 showed they will always match.

The PR changes the tests so it just checks if the existing file matches the output, without snapshots.
2026-06-13 21:14:05 +00:00
WaterWhisperer f4250d0d08 feat(linter): add schema for unicorn/import-style (#23386)
Adds verified config schema generation for `unicorn/import-style`.

Refs #22955.

Signed-off-by: Alexander S. <sysix@sysix-coding.de>
Co-authored-by: Alexander S. <sysix@sysix-coding.de>
2026-06-13 20:15:53 +02:00
Sysix 26ddac621e fix(linter): avoid config schema generation for jsx_a11y/no-noninteractive-element-interactions (#23385)
Fixes #23299 for now.
We can look later how and where we need to make changes.
2026-06-13 17:57:00 +00:00
Sysix 30c74ce6bf feat(linter): add schema for jsx_a11y/no-noninteractive-element-to-interactive-role (#23384)
+ little refactoring on the other rule, we want to know the defaults from the `Config` and not from the `Rule`.
2026-06-13 17:31:56 +00:00
WaterWhisperer cfbe8dc639 feat(linter): add schema for jsx_a11y/no-interactive-element-to-noninteractive-role (#23382)
Adds verified config schema generation for
`jsx_a11y/no-interactive-element-to-noninteractive-role`.

Refs #22955.
2026-06-13 19:21:13 +02:00
WaterWhisperer d15b7ff197 feat(linter): add schema for typescript/no-restricted-types (#23381)
Adds verified config schema generation for
`typescript/no-restricted-types`.

Refs #22955.

Signed-off-by: Alexander S. <sysix@sysix-coding.de>
Co-authored-by: Alexander S. <sysix@sysix-coding.de>
2026-06-13 18:59:08 +02:00
Sysix 028a8117d3 feat(linter): add schema for jsx-a11y/media-has-caption (#23377) 2026-06-13 16:22:32 +00:00
Sysix b3b1038f38 feat(linter): add schema for jsx-a11y/label-has-associated-control (#23376) 2026-06-13 16:22:32 +00:00
WaterWhisperer 7ada6b2446 feat(linter): add schema for jsx_a11y/no-distracting-elements (#23379)
Adds verified config schema generation for
`jsx_a11y/no-distracting-elements`.

Refs #22955.
2026-06-13 18:15:21 +02:00
Sysix ee3dd49e8b feat(linter): add schema for jsx-a11y/img-redundant-alt (#23374) 2026-06-13 15:54:30 +00:00
Connor Shea df5f8dd5f4 feat(linter): Add short descriptions to most lint rules. (#23365)
This adds short description fields using a codemod script and then
reviewing the result (by myself and with Claude to find any
possibly-weird ones and flag them for me) and then cleaning up some
overly-long or weirdly-formatted rule short descriptions (by myself).

This _does not_ cover all rules, as the codemod was not built to handle
the shared jest/vitest rules or "What it does" sections that were any
more complex than a single sentence. But it handles >75% of them. I'll
work on the remainder in the next few days after we get this part
merged.

I've also made modifications/edits to various rule descriptions and
short descriptions when I noticed as part of this work that they were
overly verbose, inconsistent with the description format of most other
rules, or grammatically incorrect.

<details>
<summary>Codemod script for reference</summary>

```js
#!/usr/bin/env node
// Insert a `short_description = "..."` argument into the
// `declare_oxc_lint!` macro for every rule whose inline-doc "What it does"
// section is a single sentence.
//
// Notes:
//   - Only handles rules with INLINE `///` doc comments. Shared-docs rules
//     (vitest/jest rules pulling from rules/shared) are intentionally skipped.
//   - Markdown links `[text](url)` are flattened to `text`.
//   - The insertion goes right after `version = "...",` so `short_description`
//     sits at the end of the macro arguments. Indentation mirrors `version`.
//   - `declare_oxc_lint!` must accept the `short_description = "..."` argument
//     (see crates/oxc_macros/src/declare_oxc_lint.rs); otherwise the generated
//     code will not compile.
//
// Usage: node insert_short_descriptions.mjs            # dry-run, prints stats + sample diffs
//        node insert_short_descriptions.mjs --write    # actually modify files
//        node insert_short_descriptions.mjs --show <substring>   # preview generated insertions

import { readFileSync, writeFileSync, readdirSync, statSync } from "node:fs";
import { join, relative } from "node:path";

const RULES_DIR = "~/code/oxc/crates/oxc_linter/src/rules";
const SHARED_DIR = join(RULES_DIR, "shared");

function walk(dir) {
  const out = [];
  for (const entry of readdirSync(dir)) {
    const p = join(dir, entry);
    const s = statSync(p);
    if (s.isDirectory()) out.push(...walk(p));
    else if (entry.endsWith(".rs")) out.push(p);
  }
  return out;
}

// --- extraction (inline-only) --------------------------------------------

function ruleDocLines(source) {
  const out = [];
  for (const line of source.split("\n")) {
    const m = line.match(/^\s*\/\/\/ ?(.*)$/);
    if (m) out.push(m[1]);
  }
  return out;
}

function extractWhatItDoesFromMarkdown(lines) {
  let start = -1;
  for (let i = 0; i < lines.length; i++) {
    if (/^\s*###\s+What it does\s*$/i.test(lines[i])) {
      start = i + 1;
      break;
    }
  }
  if (start === -1) return null;
  const body = [];
  for (let i = start; i < lines.length; i++) {
    if (/^\s*###\s+/.test(lines[i])) break;
    body.push(lines[i]);
  }
  while (body.length && body[0].trim() === "") body.shift();
  while (body.length && body[body.length - 1].trim() === "") body.pop();
  return body;
}

// A "What it does" body that contains a markdown list or a URL can't be
// faithfully reduced to a one-line sentence — flattening it produces a run-on
// string (the whole list inlined) or a description that leads with a raw URL.
// Skip these rather than emit garbage.
function hasListOrUrl(bodyLines) {
  let inFence = false;
  for (const line of bodyLines) {
    if (/^\s*```/.test(line)) { inFence = !inFence; continue; }
    if (inFence) continue;
    if (/^\s*([-*+]|\d+\.)\s+/.test(line)) return true; // markdown list item
    if (/https?:\/\//.test(line)) return true;          // bare/inline URL
  }
  return false;
}

function countSentences(bodyLines) {
  const kept = [];
  let inFence = false;
  for (const line of bodyLines) {
    if (/^\s*```/.test(line)) { inFence = !inFence; continue; }
    if (!inFence) kept.push(line);
  }
  let text = kept.join(" ").trim();
  if (!text) return 0;
  text = text.replace(/`[^`]*`/g, "X");
  text = text.replace(/\b(e\.g|i\.e|etc|vs|cf|approx|Mr|Mrs|Ms|Dr|Jr|Sr)\./gi, "$1");
  text = text.replace(/(\d)\.(\d)/g, "$1$2");
  const matches = text.match(/[.!?]+(?=\s|$)/g);
  return matches ? matches.length : 0;
}

// --- build short_description ---------------------------------------------

function bodyToShortDescription(bodyLines) {
  const kept = [];
  let inFence = false;
  for (const line of bodyLines) {
    if (/^\s*```/.test(line)) { inFence = !inFence; continue; }
    if (!inFence) kept.push(line);
  }
  let text = kept.join(" ").replace(/\s+/g, " ").trim();
  let prev;
  do {
    prev = text;
    text = text.replace(/\[([^\]]*)\]\(([^)]*)\)/g, "$1");
  } while (text !== prev);
  return text;
}

function escapeForRustString(s) {
  return s.replace(/\\/g, "\\\\").replace(/"/g, '\\"');
}

// --- macro surgery -------------------------------------------------------

function findMacroSpan(source) {
  const idx = source.indexOf("declare_oxc_lint!");
  if (idx === -1) return null;
  let i = idx + "declare_oxc_lint!".length;
  while (i < source.length && /\s/.test(source[i])) i++;
  if (source[i] !== "(") return null;
  const open = i;
  let depth = 1;
  i++;
  while (i < source.length && depth > 0) {
    const c = source[i];
    if (c === '"') {
      i++;
      while (i < source.length && source[i] !== '"') {
        if (source[i] === "\\") i++;
        i++;
      }
    } else if (c === "/" && source[i + 1] === "/") {
      while (i < source.length && source[i] !== "\n") i++;
    } else if (c === "(") {
      depth++;
    } else if (c === ")") {
      depth--;
      if (depth === 0) return { open, close: i };
    }
    i++;
  }
  return null;
}

function insertShortDescription(source, sentence) {
  const span = findMacroSpan(source);
  if (!span) return null;
  const inner = source.slice(span.open + 1, span.close);

  // Don't touch rules that already have the field.
  if (/\bshort_description\s*=/.test(inner)) return source;

  // Match the last `version = "..."` assignment. Last-match wins so we skip
  // any stray mentions in doc comments. The trailing comma (if any) is
  // detected separately below — folding `\s*,?` into this regex would let
  // `\s*` swallow the following newline when there is no comma, misplacing the
  // insertion point.
  const versionRe = /\bversion\s*=\s*"(?:[^"\\]|\\.)*"/g;
  let lastMatch = null;
  let vm;
  while ((vm = versionRe.exec(inner)) !== null) lastMatch = vm;
  if (!lastMatch) return null;

  const matchStartAbs = span.open + 1 + lastMatch.index;
  let matchEndAbs = matchStartAbs + lastMatch[0].length;

  // Consume an optional trailing comma that sits on the same line (after only
  // horizontal whitespace), leaving any newline untouched.
  let j = matchEndAbs;
  while (source[j] === " " || source[j] === "\t") j++;
  const hasTrailingComma = source[j] === ",";
  if (hasTrailingComma) matchEndAbs = j + 1;

  let lineStart = matchStartAbs;
  while (lineStart > 0 && source[lineStart - 1] !== "\n") lineStart--;
  const indent = source.slice(lineStart, matchStartAbs);
  const isOnOwnLine = /^\s*$/.test(indent);

  const escaped = escapeForRustString(sentence);

  let insertion;
  if (isOnOwnLine) {
    const prefix = hasTrailingComma ? "" : ",";
    insertion = `${prefix}\n${indent}short_description = "${escaped}",`;
  } else {
    const prefix = hasTrailingComma ? " " : ", ";
    insertion = `${prefix}short_description = "${escaped}",`;
  }

  return source.slice(0, matchEndAbs) + insertion + source.slice(matchEndAbs);
}

// --- main ----------------------------------------------------------------

const args = process.argv.slice(2);
const flag = (n) => args.includes(n);
const showIdx = args.indexOf("--show");
const showNeedle = showIdx >= 0 ? args[showIdx + 1] : null;
const writeMode = flag("--write");

const files = walk(RULES_DIR).sort();

let processed = 0;
let skippedShared = 0;
let skippedMulti = 0;
let skippedListOrUrl = 0;
let skippedMissing = 0;
let skippedAlreadyHas = 0;
let skippedNoVersion = 0;
let changed = 0;
const samples = [];

for (const file of files) {
  if (file.startsWith(SHARED_DIR + "/")) continue;
  const src = readFileSync(file, "utf8");
  if (!/declare_oxc_lint!/.test(src)) continue;
  processed++;

  const docLines = ruleDocLines(src);
  const body = extractWhatItDoesFromMarkdown(docLines);
  if (body === null) { skippedShared++; continue; }
  if (body.length === 0) { skippedMissing++; continue; }
  if (hasListOrUrl(body)) { skippedListOrUrl++; continue; }
  const n = countSentences(body);
  if (n !== 1) { skippedMulti++; continue; }

  const sentence = bodyToShortDescription(body);
  if (!sentence) { skippedMissing++; continue; }

  if (/\bshort_description\s*=/.test(src)) { skippedAlreadyHas++; continue; }

  const updated = insertShortDescription(src, sentence);
  if (updated === null) { skippedNoVersion++; continue; }
  if (updated === src) { skippedAlreadyHas++; continue; }

  if (showNeedle && file.includes(showNeedle)) {
    samples.push({ file, sentence, updated });
  } else if (samples.length < 3 && !showNeedle) {
    samples.push({ file, sentence, updated });
  }

  if (writeMode) writeFileSync(file, updated);
  changed++;
}

console.log(`Rule files scanned:                ${processed}`);
console.log(`Would insert short_description:    ${changed}`);
console.log(`Skipped (shared-docs / no inline): ${skippedShared}`);
console.log(`Skipped (multi-sentence / none):   ${skippedMulti}`);
console.log(`Skipped (list or URL body):        ${skippedListOrUrl}`);
console.log(`Skipped (empty/missing body):      ${skippedMissing}`);
console.log(`Skipped (already has field):       ${skippedAlreadyHas}`);
console.log(`Skipped (no version= found):       ${skippedNoVersion}`);
console.log(writeMode ? `\nWROTE ${changed} files.` : `\nDry run. Pass --write to apply.`);

if (samples.length) {
  console.log("\nSamples:\n");
  for (const s of samples) {
    console.log(`--- ${relative(RULES_DIR, s.file)} ---`);
    console.log(`  short_description = "${escapeForRustString(s.sentence)}"`);
    const span = findMacroSpan(s.updated);
    if (span) {
      const chunk = s.updated.slice(span.open - 20, span.close + 2);
      console.log("");
      for (const line of chunk.split("\n")) console.log("    " + line);
    }
    console.log("");
  }
}
```
</details>

---------

Co-authored-by: Cameron Clark <cameron.clark@hey.com>
2026-06-13 16:54:21 +01:00
Sysix 40556ad8b5 fix(linter): parse jsx-a11y/control-has-associated-label config with DefaultRuleConfig (#23373)
- Used `DefaultRuleConfig` to parse the `serde_json` value
- Moved the 25 cap, to the `Deserializer`
- added schema validation + deny unknown fields
- removed test cases where the upstream rule auto-generated options for every rule
2026-06-13 15:30:37 +00:00
Sysix e3fd735e59 feat(linter): add schema for jsx_a11y/alt-text (#23369)
upstream docs: https://github.com/jsx-eslint/eslint-plugin-jsx-a11y/blob/main/docs/rules/alt-text.md
2026-06-13 15:08:23 +00:00
Mikhail Baev 0f2fff48d2 feat(linter): add schema for react/exhaustive-deps (#23372)
part of #22955
2026-06-13 15:51:43 +01:00
Mikhail Baev e3e4e105bc feat(linter): add schema for react_perf/jsx-no-new-object-as-prop (#23368)
issue #22955

---------

Signed-off-by: Alexander S. <sysix@sysix-coding.de>
Co-authored-by: Alexander S. <sysix@sysix-coding.de>
2026-06-13 15:38:33 +02:00
WaterWhisperer 9366d44cc2 feat(linter): add schema for unicorn/prefer-at (#23366)
Adds verified config schema generation for `unicorn/prefer-at`.

Refs #22955.
2026-06-13 15:29:35 +02:00
Sysix f57b55db11 feat(linter): add schema for typescript/array-type (#23355) 2026-06-12 17:37:36 +00:00
Sysix 0dcf912b16 feat(linter): add schema for typescript/ban-ts-comment (#23354)
Requesting a little review, because the types are little bit complex.
Should be aligned with our tests and the upstream TS type:
https://typescript-eslint.io/rules/ban-ts-comment/#options
2026-06-12 17:26:26 +00:00
Mikhail Baev 51fa83ef5f feat(linter): add schema for react/no-did-update-set-state (#23357)
issue #22955

There are three rules that use the same config and default value:
- `react/no-did-mount-set-state`
- `react/no-did-update-set-state`
- `react/no-will-update-set-state`

this PR also moves that config into a shared `SetStateInFunctionConfig`
type to avoid duplication, similar to the `AlwaysNever` enum
2026-06-12 19:20:41 +02:00
Sysix 59db0bd215 feat(linter): add schema for consistent-generic-constructors (#23353) 2026-06-12 15:07:59 +00:00
Sysix c4775c01b5 feat(linter): add schema for typescript/consistent-type-assertions (#23349)
`assertionStyle` can only be `never` without any other options. This is currently not reflected within the schema.
Upstream docs:
https://typescript-eslint.io/rules/consistent-type-assertions/
2026-06-12 14:05:40 +00:00
Sysix 6e516f75b6 feat(linter): add schema for typescript/consistent-type-imports (#23348) 2026-06-12 14:05:40 +00:00
WaterWhisperer 012134d6cb feat(linter): add schema for react/jsx-no-target-blank (#23345)
Adds verified config schema generation for `react/jsx-no-target-blank`.

Refs #22955.

---------

Signed-off-by: Cameron <cameron.clark@hey.com>
Co-authored-by: Cameron <cameron.clark@hey.com>
2026-06-12 14:44:22 +01:00
Mikhail Baev 0806aae474 feat(linter): add schema for jsx_a11y/no-noninteractive-tabindex (#23337)
issue #22955

also replaced manual config parsing with `DefaultRuleConfig`
2026-06-12 13:39:39 +02:00
Mikhail Baev 0708b5a233 feat(linter): add schema for react/jsx-filename-extension (#23315)
issue #22955

---------

Co-authored-by: Cameron <cameron.clark@hey.com>
2026-06-12 10:05:03 +01:00
Sysix 150bce13e4 feat(linter): add schema for typescript/no-empty-object-type (#23309) 2026-06-12 00:45:31 +00:00
Sysix f9e36f1738 feat(linter): add schema for typescript/no-duplicate-type-constituents (#23308) 2026-06-12 00:45:30 +00:00
Sysix 937accf58f feat(linter): add schema for typescript/no-invalid-void-type (#23307) 2026-06-11 23:58:30 +00:00
Sysix 3e042b9dbd feat(linter): add schema for typescript/no-misused-promises (#23306) 2026-06-11 23:58:30 +00:00
Sysix da212d1d1d feat(linter): add schema for typescript/no-unnecessary-condition (#23305)
The upstream rule has an option we do not to support:
```
    /** Whether to not error when running with a tsconfig that has strictNullChecks turned. */
    allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing?: boolean;
```
https://typescript-eslint.io/rules/no-unnecessary-condition/
2026-06-11 23:45:58 +00:00
Sysix f8f0d38eb3 feat(linter): add schema for typescript/parameter-properties (#23304) 2026-06-11 22:41:24 +00:00
Sysix 2275fc7ec1 feat(linter): add schema for typescript/prefer-nullish-coalescing (#23302)
The upstream rules does support one more option, but I guess we do not want this:

```
    /** Unless this is set to `true`, the rule will error on every file whose `tsconfig.json` does _not_ have the `strictNullChecks` compiler option (or `strict`) set to `true`. */
    allowRuleToRunWithoutStrictNullChecksIKnowWhatIAmDoing?: boolean;
```

https://typescript-eslint.io/rules/prefer-nullish-coalescing

Another little difference: The upstream rule marks as `true | IgnorePrimitivesOptions`, we support the `false` value too.
2026-06-11 22:20:24 +00:00
Sysix d353858d1c feat(linter): add schema for typescript/prefer-string-starts-ends-with (#23301)
Should we deprecate/remove the unicorn version of it?
https://oxc.rs/docs/guide/usage/linter/rules/unicorn/prefer-string-starts-ends-with

We marked some rules as unsupported because they should use the type-aware version. 🤔
2026-06-11 21:47:41 +00:00
Sysix 03060f5f06 feat(linter): add schema for typescript/triple-slash-reference (#23300)
Little review please because of the enum removal  🙇
#23301 has a question too.
2026-06-11 21:29:40 +00:00
Sysix 6619ceeffa feat(linter): add schema for promise/param-names (#23298) 2026-06-11 20:54:38 +00:00
Sysix 8bf108e2a1 feat(linter): add schema for promise/catch-or-return (#23297) 2026-06-11 20:40:14 +00:00
Sysix 48158d00b7 feat(linter): add schema for vitest/consistent-each-for (#23294) 2026-06-11 20:27:30 +00:00