## Summary: Fixing unicorn/expiring-todo-comments via jsPlugin
## Problem
The `unicorn/expiring-todo-comments` rule failed when run through
oxlint's jsPlugin system with error:
```TypeError: Either `node` or `loc` is required```
The rule spreads Comment instances (`{...comment}`) to process each line of multi-line comments, but lost the `loc` property because:
- Comment's `loc` was a prototype getter (not an own enumerable property)
- Spread only copies own enumerable properties
## Solution
Define `loc` as an own accessor property on every `Comment` instance using
`__defineGetter__`. Own properties are visible to spread, `JSON.stringify,` and
`for…in` iteration, so all three work without any extra workarounds.
The getter function is defined in the class static block and captured in a `const`
(`getCommentLoc`). Using a `const` rather than a `let` lets V8 skip reassignment checks
at the `defineGetter(this, "loc", getCommentLoc)` call site — a pattern already
established in the codebase for `resetCommentLoc`.
As a result:
- `toJSON()` is removed — `JSON.stringify` now works via the own property directly.
- `Object.defineProperty(Comment.prototype, "loc", { enumerable: true })` is removed —
no longer needed.
## Test Results
- ✅ unicorn/expiring-todo-comments rule works (detects expired TODOs)
- ✅ updated comments fixture pass
- ✅ All untouched existing tests pass
---------
Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
`loc` property of `Token`s and `Comment`s is a getter on these classes' prototypes. Add a `toJSON` method to both classes so `JSON.stringify` includes `loc` in the generated JSON.
Part of #18610.
Our intent is to move `definePlugin`, `defineRule`, and `eslintCompatPlugin` to a separate package `@oxlint/plugins` (plural to avoid confusion with naming convention for plugins `oxlint-plugin-xxx`).
So rename the current entry point which exports these functions from `oxlint/plugin` to `oxlint/plugins` (plural).
This is technically breaking (only for types), but custom plugins are experimental.
The ruletester/defineRule/definePlugin are re-exported but with a `@deprecated` tag which I think is a good enough trade off
I want to avoid users bringing in a ton of custom plugin code when doing `import { defineConfig } from 'oxlint'`
AST node, token, and comment objects have an object `NodeProto` / `TokenProto` as their prototype. Those objects provide a getter for `loc`.
Previously `NodeProto` and `TokenProto` had `null` as their prototype.
Turns out that was a problem as ESQuery (weirdly) compares nodes sometimes by converting them to strings with `${node}`. This relies on `Object.prototype.toString`, which wasn't present in the prototype chain.
Fix this by making `NodeProto` and `TokenProto` have `Object.prototype` as their prototype (like "normal" objects).
ESLint has undocumented `getRange` and `getLoc` methods on `SourceCode`. Add them.
These are the last 2 missing methods on `SourceCode` (according to Claude).
Also add more tests for correct functioning of `range` and `loc` properties.
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.
Format `oxlint` test fixtures. The directory `fixtures` contains not just the fixtures themselves, but also Oxlint plugins, which should be formatted.
Skip 2 specific test fixture files which must not be formatted to maintain correctness of the tests.
Part of #14564. Implement the remaining `SourceCode` APIs related to
comments (`getCommentsBefore`, `getCommentsAfter`, `getCommentsInside`,
`commentsExistBetween`).
---------
Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>