Commit Graph

34 Commits

Author SHA1 Message Date
overlookmotel c95951f563 feat(linter/plugins): implement sourceCode.markVariableAsUsed (#20357)
Fixes #19971.

Implement `sourceCode.markVariableAsUsed`.

It has some shortcomings at present - it does mark vars as used, so any other JS plugins can see that, but it doesn't communicate this info back to Rust side, so `no-unused-vars` doesn't act on it. But at least it doesn't cause a crash with "unimplemented" error.

The remaining issue is tracked in #20350.
2026-03-14 01:01:25 +00:00
overlookmotel de7c0e2b97 fix(linter/plugins): correct error message for markVariableAsUsed (#20152)
Related to #19971. The error message for `sourceCode.markVariableAsUsed` was misleading. Correct it.
2026-03-09 11:39:22 +00:00
overlookmotel b069269c4d docs(linter/plugins): add comment about deprecated ScopeManager methods (#19363)
Document which `ScopeManager` APIs are implemented, and the reason why we omit deprecated methods/properties.
2026-02-13 10:41:31 +00:00
overlookmotel 3d349ca4d3 refactor(linter/plugins): bump @typescript-eslint/scope-manager dependency (#18632)
Closes #18398.

Bump `@typescript-eslint/scope-manager` to latest. That release contains 2 bug fixes:

* https://github.com/typescript-eslint/typescript-eslint/pull/11982
* https://github.com/typescript-eslint/typescript-eslint/pull/11995

We had workarounds for both bugs, added in:

* #18312
* #18402

This PR bumps dependency to the new version which included the big fixes, and removes both workarounds, as they're no longer required.

Also bumped all other usages of `@typescript-eslint/*` packages, so we use the same versions for everything.
2026-01-27 17:33:44 +00:00
overlookmotel 31bbe3986e refactor(linter/plugins): reduce repeat code from createGlobalVariable (#18318)
Pure refactor. Clean up the code to reduce repetition.
2026-01-21 01:31:02 +00:00
overlookmotel 9e359d40eb fix(linter/plugins): set all properties on global vars objects (#18317)
Set additional properties on scope variable objects:

* `eslintImplicitGlobalSetting`
* `eslintExplicitGlobal`
* `eslintExplicitGlobalComments`
2026-01-21 01:31:01 +00:00
overlookmotel 39c7f32b67 fix(linter/plugins): set writeable flag on variables where defined as globals (#18316)
Set `writeable` flag on scope variables which exist in the file and are also defined as globals in config.
2026-01-21 01:31:01 +00:00
overlookmotel 2cc6ad25db feat(linter/plugins): add ecmaFeatures to parserOptions (#18313)
Add `ecmaFeatures` property to `context.languageOptions.parserOptions`, with `globalReturn` and `impliedStrict` properties.

In normal operation, these are set according to the source type. In conformance build, they can be overridden by config.
2026-01-21 00:14:27 +00:00
overlookmotel a570693ea3 fix(linter/plugins): fix CatchClause scopes (#18312)
TS-ESLint's scope manager has a bug with `CatchClause`s: https://github.com/typescript-eslint/typescript-eslint/issues/11981

```js
try {
  throw new Error("Oops");
} catch ({ message }) {}
```

ESLint has the `name` property of the `def` for the `message` binding as the `message` `Identifier` node, but TS-ESLint has it as the `ObjectPattern` `{ message }`.

Work around this bug by fixing any `CatchClause` scopes after TS-ESLint has produced the scope tree.
2026-01-20 21:26:39 +00:00
overlookmotel 4e246926d1 test(linter/plugins): handle globalReturn and impliedStrict options in conformance tests (#18307)
Closes #16862.

In conformance tests, support `globalReturn` and `impliedStrict` options. This fixes ~40 failing tests.

This PR does not add these options to actually linter, because Oxlint doesn't provide a way to set these options through config.

Ideally, we *would* support these options in `RuleTester` in `eslintCompat` mode, but that would add extra code to the main linter implementation. We can do that when we move `RuleTester` into its own package.
2026-01-20 18:25:34 +00:00
overlookmotel 44be0ebef4 fix(linter/plugins): set scope analyse settings based on source type (#18306)
Set `globalReturn` and `impliedStrict` options passed to TS-ESLint scope manager, dependent on source type. In particular, set `globalReturn: true` for CommonJS files. This adds an extra function scope above the global scope.
2026-01-20 18:25:33 +00:00
overlookmotel 16918919d9 refactor(linter/plugins): simplify scope analyse options (#18305)
Pure refactor. Simplify initialization of `analyzeOptions` passed to TS-ESLint scope analyzer. Also fill in all the options, and order properties in same order as the `AnalyzeOptions` type.
2026-01-20 18:25:33 +00:00
overlookmotel 7eaa660af6 fix(linter/plugins): set up global scope correctly (#17293)
Overhaul how variables in the global scope are set up.

* Create globals according to `env` and `globals` from config - previously we always used a standard "esnext" set.
* Remove the patch to `@typescript-eslint/scope-manager`. Instead do what ESLint does and patch up the global scope programmatically after TS-ESLint has produced the scope tree.
* Set `writable` property for global variables according to config.

This still isn't quite correct. There are many subtleties to this and I haven't got to the bottom of it all. But this PR fixes 500 conformance tests, so it's a large step in the right direction.

I haven't added more tests in this PR, because I'm not actually sure what behavior is correct, and what still needs to be fixed. Once all the conformance tests related to globals (which is most of the remaining failing ones) are fixed, we'll have the full picture and can add more tests.
2025-12-23 11:05:24 +00:00
overlookmotel fabe6f7509 refactor(linter/plugins): add TODO comments for @ts-expect-errors which need fixing (#16796)
Only alters comments.

* Make sure all `// @ts-expect-error` comments include "TODO" where it's an issue we need to fix.
* Format all the "TODO" comments consistently.
2025-12-13 14:33:39 +00:00
overlookmotel 3f3d646280 refactor(linter/plugins): imports use .ts extension (#16390)
Pure refactor. Use `.ts` extension when importing `.ts` files.
2025-12-02 14:08:49 +00:00
Boshen 523a30a016 style(all): apply oxfmt default options (#16091)
Embrace the defaults!

---------

Co-authored-by: Yuji Sugiura <y.sugiura.0316@gmail.com>
2025-11-25 15:56:24 +09:00
overlookmotel ae137042f5 refactor(linter/plugins): rename assertion functions (#15968)
Rename assertion functions to clarify that they're not "real" assertions which we can rely on for validating input, and are only for compile-time testing or debug assertions.

`typeAssertIs` is not a great name, but I couldn't come up with anything better. `debugAssertIs` would be not be accurate, as it'd imply that in debug builds in performs an actual assertion, which it doesn't.

In any case, we should replace `typeAssertIs` with specialized assertion functions which do actually perform runtime assertions in debug builds (e.g. `typeAssertIs<Fix>()` -> `debugAssertIsFix()`).
2025-11-22 15:54:17 +00:00
overlookmotel 512e43a204 refactor(linter/plugins): move assertions into own file (#15945)
Pure refactor. Split up `plugins/utils.ts` into 3 files in `utils` directory.

Most importantly, assertion functions are by themselves in an `asserts.ts` file. This paves the way for the next PR (#15946).
2025-11-21 14:42:25 +00:00
overlookmotel a72b093b05 refactor(linter/plugins): enable TS strictNullChecks (#15886)
Adapted from #15868. Enable `strictNullChecks` in TSConfig for `apps/oxlint`.

Rather than using `!` all over the place, I've added a function `assertIsNonNull`, which performs the same function. Idea is that we can later on produce a debug build where `assertIsNonNull` does an actual runtime assertion (rather than just a TS `asserts`) that the value is not `null` or `undefined`. We can use the debug build in tests, and catch any logic errors.

Unfortunately, TypeScript doesn't seem able to track side effects, so there seems to be no way to tell it "after calling `initAst()`, `ast` is always non-null". Don't want to switch to a having a `getAst` function which returns a non-null value, as that'd introduce unnecessary temp vars, and function calls, on hot paths. So this seems to be the best we can do without incurring runtime cost.
2025-11-20 15:52:49 +00:00
overlookmotel a8e505b241 refactor(linter/plugins): remove unnecessary code (#15817)
Remove an unnecessary check. `name` property of `Identifier` is always a string, so no need to check it. If user cooks up a fake AST node to pass to the message, they may get a weird error, but they deserve it!
2025-11-17 21:46:19 +00:00
overlookmotel 14f61b3a10 refactor(linter/plugins): improve error message (#15816)
Improve error message in `isGlobalReference`, to match our standard style.
2025-11-17 21:46:19 +00:00
overlookmotel 9f5ad7eea8 refactor(linter/plugins): move type defs to top of file in scope.ts (#15640)
Pure refactor. Just move type defs to top of the file.
2025-11-12 17:57:34 +00:00
overlookmotel 104a092ef5 refactor(linter/plugins): add unimplemented Context#markVariableAsUsed method (#15637)
Add `Context#markVariableAsUsed` method. It's unimplemented at present, so just throws an error saying "unimplemented". But that's better for user than "TypeError: context.markVariableAsUsed is not a function", and having the stub in codebase reminds us we need to implement it.
2025-11-12 16:50:03 +00:00
overlookmotel 1a4a7d8025 refactor(linter/plugins): simplify type for analyzeOptions (#15639)
Simplify the type of `analyseOptions` object, by introducing a `SetNullable` utility type (oooh fancy!).

`SetNullable` is adapted from `SetNonNullable` [from `type-fest` package](https://github.com/sindresorhus/type-fest/blob/2300245cb6f0b28ee36c2bb852ade872254073b8/source/set-non-nullable.d.ts).
2025-11-12 16:42:43 +00:00
overlookmotel 40231a616a fix(linter/plugins, napi/parser): add parent field to FormalParameterRest and TSParameterProperty in TS type defs (#15337)
Fix TS type defs. Add `parent` property to `FormalParameterRest` and `TSParameterProperty`, which both have their type definitions defined manually.
2025-11-05 16:23:53 +00:00
overlookmotel 861508afd7 fix(linter/plugins): make parent fields in TS type defs non-optional (#15336)
Fix TS type defs for AST types in linter. Make `parent` property non-optional on all node types.
2025-11-05 16:23:53 +00:00
overlookmotel 636e7edd23 refactor(linter/plugins): shorten ScopeManager code (#15335)
Follow on after #14890. Pure refactor. Just shorten code but compacting `if` statements to a single line. Also move type import to after "real" imports.
2025-11-05 16:23:53 +00:00
overlookmotel 8b31daad57 perf(linter/plugins): small optimizations to ScopeManager (#15334)
Follow-on after #14890. Small optimizations to `ScopeManager`.

* Remove temp vars.
* Test vars with `=== null` or `=== undefined` instead of `!`.
* Avoid reading out of bounds of arrays.
* Get length of array once before loop, rather than on each turn of loop.

Also add comments about potential future optimizations.
2025-11-05 16:23:53 +00:00
overlookmotel a7d9f1d63d docs(linter/plugins): reformat and clarify ScopeManager JSDoc comments (#15333)
Pure refactor. Reformat and reword comments on `ScopeManager` methods.
2025-11-05 16:23:52 +00:00
overlookmotel 4c0ba92e77 perf(linter/plugins): use singleton object for ScopeManager (#15332)
Follow-on after #14890.

That PR implemented `ScopeManager` class. Instead of a class, which an instance of is created for each file, use a singleton object, with the underlying TS-ESLint scope manager stored in a top-level var. Methods/getters of `SCOPE_MANAGER` lazily initialize the TS-ESLint scope manager as required, and cache it.

This pattern is the same as we use for `SourceCode`, enabled by the fact that only 1 file is linted at a time. This has several advantages:

1. Reduce object creation - less GC pressure.
2. Property accesses don't need to go up prototype chain, as they would for instances of a class.
3. No need for private properties, which are somewhat expensive to access.
2025-11-05 16:23:52 +00:00
Arsh f7bef7325f feat(linter/plugins): scope manager API (#14890)
- "For now" implementation of #14827
- Uses `@typescript-eslint/scope-manager` which works thanks to recent
efforts to align JS side AST with ESTree.
- `@typescript-eslint/scope-manager` is well-built: It is factored out
from `ts-eslint` neatly, and is pure scope analysis with minimal
dependencies. Tsconfig resolution and syntax parsing is done by its
dependents.
### Tasks
- [x] `ScopeManager` class instance at `sourceCode.scopeManager`
- [x] Direct usage APIs: `sourceCode.isGlobalReference`,
`sourceCode.getDeclaredVariables`, `sourceCode.getScope`,
~~`sourceCode.markVariableAsUsed`~~
  - [x] Tests
- [x] Limit API surface. We want maneuverability for our eventual
implementation, so we should limit the exposed methods to the only two
methods documented as non-deprecated: [ScopeManager |
ESLint](https://eslint.org/docs/latest/extend/scope-manager-interface#acquirenode-inner--false:~:text=ScopeManager%20interface-,Fields,getDeclaredVariables(node),-Deprecated%20members).
- Limiting other interfaces will probably need monkey patching; only
public types are limited instead.
### ScopeManager API real world use examples
-
[`eslint-plugin-import`](https://github.com/import-js/eslint-plugin-import/blob/01c9eb04331d2efa8d63f2d7f4bfec3bc44c94f3/src/rules/no-import-module-exports.js#L20)
-
[`eslint-plugin-react`](https://github.com/facebook/react/blob/71b3a03cc936c8eb30a6e6108abf5550f5037f71/packages/eslint-plugin-react-hooks/src/rules/ExhaustiveDeps.ts#L149)
-
[`eslint-plugin-vue`](https://github.com/vuejs/eslint-plugin-vue/blob/917787c46a268b1910b9c77e091656a428d70a89/lib/utils/scope.js#L14)
-
[`eslint-plugin-svelte`](https://github.com/search?q=repo%3Asveltejs%2Feslint-plugin-svelte%20scopeManager&type=code)

---------

Signed-off-by: Arsh <emmagoldmanvevo+github@pm.me>
Co-authored-by: autofix-ci[bot] <114827586+autofix-ci[bot]@users.noreply.github.com>
Co-authored-by: Cameron <cameron.clark@hey.com>
2025-10-29 10:53:35 +00:00
overlookmotel b9a3f46b4d refactor(linter/plugins): move scope-related SourceCode methods into separate file (#14771)
Pure refactor. Move methods of `SourceCode` related to scopes into a separate file, to make main `source_code.js` file less crowded.
2025-10-19 12:16:19 +00:00
overlookmotel 93d81641b2 refactor(linter/plugins): export AST types direct from oxlint package (#14353)
Export AST types directly from `oxlint` package, instead of depending on `@oxc-project/types`. This enables altering the types to reflect that `range` field is always present on AST node in Oxlint's AST (#14354).
2025-10-05 13:47:32 +00:00
overlookmotel 65873ba277 refactor(linter/plugins): add stubs for all SourceCode methods (#14285)
Add stub implementations for all methods and properties of `SourceCode`. All unimplemented methods/getters just throw an error.
2025-10-02 08:32:03 +00:00