SIGN IN SIGN UP

fix(linter/eslint/no-unassigned-vars): skip Svelte and Vue files (#26042)

## Summary

Closes #26038.

`no-unassigned-vars` is a `correctness` rule, so this fires by default
with no config:

```svelte
<script lang="ts">
  let dialog: HTMLDialogElement;

  function openDialog() {
    dialog.showModal();
  }
</script>

<dialog bind:this={dialog}>Hello</dialog>
```

```text
repro.svelte:2:7: warning eslint(no-unassigned-vars): 'dialog' is always 'undefined' because it's never assigned.
```

## Why the rule cannot get this right today

The rule's decision is `has_read && no reference is_write()`, taken over
the symbol's references in the current script block. Oxlint reaches
`.svelte`/`.vue` through `PartialLoader`, which extracts the `<script>`
blocks and throws the markup away before parsing — so the template's
write is not in the AST the rule sees, and no reference on `dialog` is
ever a write. Every ingredient of the diagnostic is satisfied, and the
diagnostic is still wrong: Svelte assigns the element to `dialog` on
mount.

The same shape exists in Vue, where a `<script setup>` `let` is a
`setup-let` binding that `v-model="x"` and inline handlers such as
`@click="x = 1"` compile to direct assignments against.

This is not a matter of tightening the check — the write is in a part of
the file the linter never parses.

## The change

`prefer-const` hit exactly this and already skips both extensions
([#25148](https://github.com/oxc-project/oxc/pull/25148)):

```rust
fn should_run(&self, ctx: &crate::context::ContextHost) -> bool {
    // ignore svelte/vue: their templates can reassign a binding, which we can't see.
    !ctx.file_extension().is_some_and(|ext| ext == "svelte" || ext == "vue")
}
```

This applies the sibling rule's guard rather than inventing one, and
documents it in the rule docs under an `#### Ignored Files` heading,
matching `prefer-const`'s wording.

`.astro` is deliberately **not** included: an Astro template renders a
frontmatter binding but has no construct that writes back to it, so the
false positive does not arise there. `prefer-const` drew the same line.

## Scope, stated honestly

This trades a false positive for lost coverage: a genuinely unassigned
variable inside a `.svelte`/`.vue` `<script>` block is no longer
reported. That matches the precedent and the reporter's own request, and
a `correctness` false positive that fires on the documented Svelte idiom
costs more than the missed report. Restoring coverage needs
template-aware analysis, which is the language-support effort tracked
separately (#13017, #17991).

## Verification

- `cargo test -p oxc_linter --lib` — **1254 passed, 0 failed**.
- Two new tests, `test_svelte` and `test_vue`, cover the reported repro,
`bind:value`, a two-`<script>` Svelte component, `v-model`, and an
inline `@click` handler.
- **Revert-checked:** with `should_run` removed and the tests kept,
exactly those two tests fail and the rest pass. The failure output
reproduces the reported diagnostic verbatim, including the `let shared`
case from the two-script component — so the tests fail for the right
reason, not because the fixture path changed.
- `cargo clippy -p oxc_linter --lib --all-features` — no new findings
(the two `FromIterator::from_iter` warnings are pre-existing, in
`tsgolint.rs` and `lib.rs`).
- `cargo fmt --check` clean.
- The rule is not part of `docs_rule_pages.snap`, so the doc addition
needs no snapshot regeneration.

Built and tested on Windows with the `1.97.1-x86_64-pc-windows-gnu`
toolchain rather than the pinned `1.98.0`, and with `RUSTFLAGS`
overridden to drop the MSVC-only link args that `.cargo/config.toml`
applies to every `target_os = "windows"` target. Nothing in the
repository was changed for that.

---
Written with AI assistance (Claude Code), reviewed and tested by me
before submitting, per AGENTS.md.

---------

Signed-off-by: hamodywe <iosapk.org@gmail.com>
Co-authored-by: Claude Opus 5 (1M context) <noreply@anthropic.com>
H
Hamody We committed
3910e2b9b18dca0fa97c1dc912d9641200393db2
Parent: e4298fb
Committed by GitHub <noreply@github.com> on 8/26/2026, 7:32:41 AM