Skip to content

Conversation

@connorshea
Copy link
Member

@connorshea connorshea commented Jan 26, 2026

This started as an exploration of adding an is_inside method using Claude Code to see how much simpler it makes some of the linter code.

is_inside takes an AST node ID and a closure and then returns true or false based on the closure. The goal is to simplify a common pattern across the linter codebase for checking the ancestors of a given AST node.

I think there are still more places where we could apply this pattern, but I had Claude go through a decent number of iterations already.

cc: @Boshen

AI Disclosure: Most of the exploration was done using Claude Code, obviously :) Then cleaned up by me afterward.

connorshea and others added 9 commits January 25, 2026 20:15
…ontext`

Add two convenience methods to `LintContext` for the common pattern of checking if a node is inside a particular kind of AST node:

- `is_inside(node_id, types)`: Check if any ancestor matches any of the provided `AstType`s
- `is_inside_where(node_id, predicate)`: Check if any ancestor satisfies a custom predicate

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Refactor `prefer_await_to_then` and `prefer_await_to_callbacks` rules to use the new `ctx.is_inside()` helper method, removing the local `is_inside_yield_or_await` helper functions.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Refactor rules to use the new `ctx.is_inside_where()` helper method for cleaner ancestor checking with custom predicates:

- `no_var`, `vars_on_top`, `no_namespace`: Check for TypeScript ambient declarations
- `state_in_constructor`: Check for ES6 components
- `no_unsafe`: Check for ES5 components
- `no_return_wrap`, `no_promise_in_callback`, `no_nesting`: Check for promise callbacks

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- `prefer_each`: Refactor `is_in_test` function
- `no_conditional_in_test`: Refactor inline ancestor check
- `require_local_test_context_for_concurrent_snapshots`: Refactor inline ancestor check

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
…patterns

- `no_unassigned_vars`: Use `is_inside` with parent_id instead of `.skip(1).any()`
- `jsx_key`: Use `is_inside_where` with parent_id instead of `.skip(1).filter_map().any()`

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- `no_explicit_any`: Simplify `is_in_rest` function
- `consistent_type_definitions`: Simplify `is_within_declare_global_block` function

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
@github-actions github-actions bot added A-linter Area - Linter C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior labels Jan 26, 2026
…re instead.

`is_inside` is the better name, and the list of types pattern wasn't really that useful in many places. So we can simplify it down to just the one method.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

A-linter Area - Linter C-cleanup Category - technical debt or refactoring. Solution not expected to change behavior

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants