Commit Graph

9 Commits

Author SHA1 Message Date
overlookmotel d9a1b327d4 perf(linter/plugins): avoid array lookups where possible in CFG visitor (#21940)
Small optimization to CFG visitor. Skip array lookups unless the result is actually used.
2026-04-29 13:42:15 +00:00
overlookmotel fefefd8d72 perf(linter/plugins): replace addition with bitwise OR in CFG visitor (#21939)
Tiny optimization to CFG visitor. Bitwise OR is slightly cheaper than subtraction, and also gives V8 a guaranteed type (`i32` aka SMI) for the value being put into the array.
2026-04-29 13:42:15 +00:00
overlookmotel 92cfb14aa4 fix(linter/plugins): fix types for walkProgram and walkProgramWithCfg (#20081)
Fix a mistake in our (internal) types: `walkProgramWithCfg` was missing that elements can be `CfgVisitFn`.

Also refactor the types for `walkProgram`, importing the original `VisitFn` and `EnterExit` types from where they're defined.
2026-03-06 18:04:24 +00:00
sapphi-red e255fcd6b5 refactor(linter/plugins): enable TS strict option (#19675)
Enable TypeScript strict option in `apps/oxlint`.
2026-03-06 17:30:20 +00:00
overlookmotel fe6546f24e refactor(linter/plugins): replace typeAssertIs with debug assertions (#18606)
Pure refactor. Replace `typeAssertIs` with debug assertions. Both perform the same type assertion, but difference is that the debug assertion actually checks that the type is correct at runtime in debug build.
2026-01-26 23:31:24 +00:00
Rintaro Itokawa 3a6b41e8b2 perf(linter/plugins): replace ESLint Traverser with lightweight traverseNode (#18529)
Part 3 of #17232, continuing after #18527 and #18528 - CFG walker
optimization.

- Remove ESLint's `Traverser`
- Add lightweight `traverseNode` function that walks AST using visitor
keys
- Simplify traversal by only calling enter/leave callbacks without extra
overhead

Benefits:

- Eliminates ESLint Traverser overhead (ancestors tracking, etc.)
- Uses pre-generated visitor keys for child property lookup
- Reduces bundle size by removing unused ESLint internal module (~1.7KB
smaller)

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
2026-01-26 15:50:46 +00:00
Rintaro Itokawa 2b9d11542b perf(linter/plugins): use SoA pattern with 2 arrays for CFG steps (#18528)
Part 2 of #17232, continuing after #18527 - CFG walker optimization.

- Replace single `steps` array with 2 SoA (Struct of Arrays):
  - `stepTypeIds`: encoded type IDs
  - `stepData`: node or args array
- Encode step types using type ID offset:
  - Enter visits: typeId directly (0-164 for node types)
  - CFG events: typeId directly (165-171 for event types)
  - Exit visits: typeId + 256 (offset to distinguish from enter)
- Pre-compute type IDs during step preparation phase

Benefits:

- Reduces object creation overhead (no step objects needed).
- Halves the number of `NODE_TYPE_IDS_MAP` hash map lookups to convert
node types (strings) to type IDs.

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
2026-01-26 14:21:04 +00:00
Rintaro Itokawa 2ac7c96acf perf(linter/plugins): replace ESLint step classes with plain objects (#18527)
Part 1 of #17232 - CFG walker optimization.

- Remove `@eslint/plugin-kit` dependency (no longer needed)
- Replace `VisitNodeStep` and `CallMethodStep` classes with plain
objects
- Merge `kind` and `phase` into a single `type` property:
  - 0 = enter visit
  - 1 = exit visit
  - 2 = call method (CFG event)

This reduces object creation overhead and improves memory efficiency by
using simpler data structures.

---------

Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
Co-authored-by: overlookmotel <theoverlookmotel@gmail.com>
2026-01-26 13:00:08 +00:00
overlookmotel d913f8739e feat(linter/plugins): implement code path analysis (CFG) (#17229)
Implement CFG (or "code path analysis" as ESLint calls it).

This is the was the last remaining gap in our API.

The implementation is pretty slow, I imagine. I've pulled in ESLint's code for the actual control flow graph construction, and copied ESLint's code for the rest.

Fitting with how we combine enter and exit nodes for leaf nodes (`Identifier`s etc) required skipping creating "steps" for exiting leaf nodes, which should also be a perf gain, as they're so common. But that apart, I've made no effort to optimize it. There's plenty of scope for improving it. I've added comments with some starting points for doing that, and will open an issue in the hope someone would like to pick up on that.

I also cannot for the life of me figure out how to add the CFG event handlers (`onCodePathStart` etc) to `VisitorObject` type, without breaking everything. Me and Claude went at it for about an hour, and got nowhere. So I'm just leaving that for now.
2025-12-21 20:54:15 +00:00