Skip to content

fix(lint): inspect local GPUI handler paths - #62

Merged
1bye merged 3 commits into
mainfrom
codex/lint-deep-handlers-22
Nov 12, 2026
Merged

1bye merged 3 commits into
mainfrom
codex/lint-deep-handlers-22

Conversation

@1bye

@1bye 1bye commented Nov 12, 2026 •

Copy link
Copy Markdown
Owner

Refs #22

gpui-ui-blocking now checks local functions and methods passed directly by path to GPUI listener/action registration, including cx.listener(Self::save), on_action(cx.listener(Self::cancel)), .on_click(Self::handler) and .on_action(Self::handler).

A check_crate pre-pass visits every local HIR body, resolves registrations against the same GPUI method set as the inline-closure check, and collects callback FnDef IDs only when they are local. Blocking calls are checked when their exact enclosing body owner belongs to that set. This makes definition/registration order irrelevant and checks a registered function even when it is also called elsewhere. No call graph or parameter-name/type guesses are used.

Precision and render allocation:

  • Nested closures, nested functions and async blocks do not inherit a handler's UI context. Separately registered callbacks discovered inside nested bodies are still checked in their own right.
  • Unregistered methods, non-GPUI methods named listener, indirect function pointers, non-local definitions and transitive helper calls stay outside this new path.
  • gpui-render-new stays render-specific: creating an entity in an event handler is valid and has a negative regression case.
  • Iterator closures remain deferred. Iterator::map is lazy; identifying its closure does not prove consumption during render. A precise extension for .children(items.iter().map(...)) needs consumer-aware execution analysis. This PR deliberately does not infer a general render context through iterator adapters.

Regression evidence:

  • Before the implementation, the real pinned-GPUI UI suite missed all six new expected handler-path findings and had no unexpected findings.
  • After the implementation, 24 expected diagnostics, no extras (the existing 18 plus six new cases).
  • Positive cases cover methods before/after registration, direct click/action paths, a generic function path, a registration inside a closure, duplicate registration and a method also called elsewhere.
  • Negative cases cover the same sleeping method shape registered nowhere, cx.spawn work, nested closure/function/async bodies, a fake listener API and entity construction in a handler.

Corpus: python3 scripts/check-deep-lints.py passed: 728 root source files and 10 standalone inspector files, zero combined diagnostics, covering all workspace targets and examples. No real new findings, false positives, fixes or new suppressions were needed.

Verification on the Mac:

  • python3 scripts/test-deep-lints.py: passed, 24 expected diagnostics and no extras.
  • python3 scripts/update-deep-library.py: regenerated the committed source ZIP; archive drift test passed.
  • cargo test -p rake-app-cli --locked: passed serially at the fixed head, 361 passed, 2 existing ignored, across 17 suites, using the installed Homebrew Python. An initial overlapping-build run hit the scaffold revision-pin assertion because the test and binary embedded different commit revisions; the serial rerun passed without changing the assertion or test behavior.
  • cargo clippy --workspace --all-targets --locked -- -D warnings: passed.
  • cargo fmt --all --check and both standalone lint/UI manifest formatting checks: passed.
  • python3 scripts/check-spacing.py: passed without source fixes.
  • Updated docs/lint.md, the catalogue explanation and its generated skill. AGENTS generation is unchanged and its drift check passed.

No dependencies, toolchain pins, workflow files or default syntax-tier behavior changed. The PR remains draft. Remaining: final-head CI must pass, then temporary worktree/target/log cleanup.

🤖 Generated with Claude Code

1bye and others added 3 commits November 12, 2026 12:22
Add regressions for method, function and generic handlers, registration order, duplicate registrations, nested execution boundaries and unrelated listener APIs.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Collect registered local function definitions across HIR bodies before linting. Match exact enclosing body owners so nested closures, functions and async blocks do not inherit UI execution.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Regenerate the catalogue guide and document direct local handler paths, exact body ownership, opaque helpers and the deferred iterator-consumption analysis for render allocations.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
@1bye
1bye marked this pull request as ready for review November 12, 2026 13:03
@1bye
1bye merged commit 8ba48c2 into main Nov 12, 2026
8 checks passed
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant