Skip to content

ADFA-4174: prioritize code completion requests over analyze requests#1439

Open
itsaky-adfa wants to merge 22 commits into
stagefrom
fix/ADFA-4174
Open

ADFA-4174: prioritize code completion requests over analyze requests#1439
itsaky-adfa wants to merge 22 commits into
stagefrom
fix/ADFA-4174

Conversation

@itsaky-adfa

@itsaky-adfa itsaky-adfa commented Jun 24, 2026

Copy link
Copy Markdown
Contributor

See ADFA-4174 for more details.

itsaky and others added 4 commits June 19, 2026 22:28
Signed-off-by: Akash Yadav <itsaky01@gmail.com>
Signed-off-by: Akash Yadav <itsaky01@gmail.com>
… completion cleanup)

Apply the actionable items from Hal's review on PR #1428:

- Diagnostics: extract the unresolved-reference name inside the analyze block
  instead of storing the live KaDiagnosticWithPsi (a KaLifetimeOwner) in
  DiagnosticItem.extra. AddImportAction now reads the pre-extracted string,
  preventing KaInaccessibleLifetimeOwnerAccessException from the quick-fix path.
- CompilationEnvironment.notifyElementModifiedForPath: run
  handleElementModification inside project.write so the session mutation can't
  race a concurrent analyze (mirrors onFileContentChanged).
- KotlinCompletions: collapse manual withAnalysisLock + analyzeCopy into
  analyzeMaybeDangling, removing the only in-prod direct analyzeCopy call.
- KtFileExts: document that code under withAnalysisLock must not call
  project.write (non-upgradeable RW lock footgun).
Replace the FIFO analysis lock with AnalysisScheduler, a process-global,
priority-aware, preemptive, reentrant lock that serializes all Kotlin Analysis
API access while letting interactive work win.

Priority order: Completion > Diagnostics > Indexing.
- A higher-priority request preempts a strictly lower-priority in-progress
  analysis. Preemption is cooperative (the Analysis API can't be interrupted
  mid-analyze): the holder's ScheduledCancelChecker is flagged and the running
  analysis bails at its next abortIfCancelled() checkpoint with
  AnalysisPreemptedException.
- A lower-priority request waits while a higher-priority one holds.
- Preempted diagnostics/indexing work is auto-rescheduled so it still completes:
  diagnostics re-schedules via the fileAnalyzer; indexing re-queues the command.
- Indexing is now actively preemptible (was ICancelChecker.NOOP).

Wiring:
- KotlinCompletions: COMPLETION priority, request-scoped checker from Lookup.
- KotlinDiagnosticProvider: DIAGNOSTICS priority; CompilationEnvironment's
  fileAnalyzer catches AnalysisPreemptedException to re-schedule.
- IndexWorker/SourceFileIndexer: INDEXING priority; re-queue on preemption.

Tests: extend AnalysisSerializationTest with reentrancy, higher-preempts-lower,
and lower-waits-for-higher cases (all 5 tests pass).
@itsaky-adfa
itsaky-adfa requested a review from a team June 24, 2026 15:06
@itsaky-adfa itsaky-adfa self-assigned this Jun 24, 2026
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
…checker

ICancelChecker.invokeOnCancel(listener) pushes on cancel (fire-once, immediate if already cancelled, no-op on NOOP). ProgressManager gains register/unregister so cancel(thread) flips the request's own checker. Adds ICancelCheckerTest and ProgressManagerTest.
withAnalysisLock installs a cancellable Job and registers an invokeOnCancel listener so both scheduler preemption and ordinary editor cancellation abort mid-analyze via a single push (no polling). AnalysisScheduler.acquire is cancellation-aware while waiting so superseded requests bail instead of parking. KotlinCompletions uses params.cancelChecker (race-free) and classifies all cancellation exception types uniformly. Adds AnalysisSerializationTest coverage.
EditorCompletionWindow debounces keystrokes so at most one completion analysis runs at a time for the latest cursor position, preventing the CompletionThread/allocation pile-up. IDELanguage registers the request's CompletionCancelChecker on its thread so the editor's cancel routes to it and pushes the mid-analyze abort.
@itsaky-adfa
itsaky-adfa marked this pull request as ready for review July 4, 2026 03:40

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Claude Code Review

This repository is configured for manual code reviews. Comment @claude review to trigger a review and subscribe this PR to future pushes, or @claude review once for a one-time review.

Tip: disable this comment in your organization's Code Review settings.

@itsaky-adfa

Copy link
Copy Markdown
Contributor Author

@claude review

@claude claude Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Code review skipped — your organization's overage spend limit has been reached.

Code review is billed via overage credits. To resume reviews, an organization admin can raise the monthly limit at claude.ai/admin-settings/claude-code.

Once credits are available, comment @claude review on this pull request to trigger a review.

@coderabbitai

coderabbitai Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

Review Change Stack

Note

Reviews paused

It looks like this branch is under active development. To avoid overwhelming you with review comments due to an influx of new commits, CodeRabbit has automatically paused this review. You can configure this behavior by changing the reviews.auto_review.auto_pause_after_reviewed_commits setting.

Use the following commands to manage reviews:

  • @coderabbitai resume to resume automatic reviews.
  • @coderabbitai review to trigger a single review.

Use the checkboxes below for quick actions:

  • ▶️ Resume reviews
  • 🔍 Trigger review

No actionable comments were generated in the recent review. 🎉

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: fbf08301-e6a2-4602-9ad3-cf2978716519

📥 Commits

Reviewing files that changed from the base of the PR and between 66da411 and c4e3b67.

📒 Files selected for processing (7)
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/index/IndexWorker.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AnalysisScheduler.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/KtFileExts.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/signaturehelp/KotlinSignatureHelp.kt
  • shared/src/main/java/com/itsaky/androidide/progress/ICancelChecker.kt
  • shared/src/main/java/com/itsaky/androidide/progress/ProgressManager.kt
  • shared/src/test/java/com/itsaky/androidide/progress/ICancelCheckerTest.kt
🚧 Files skipped from review as they are similar to previous changes (5)
  • shared/src/main/java/com/itsaky/androidide/progress/ProgressManager.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/index/IndexWorker.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/signaturehelp/KotlinSignatureHelp.kt
  • shared/src/main/java/com/itsaky/androidide/progress/ICancelChecker.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AnalysisScheduler.kt

📝 Walkthrough
  • Added priority-aware Kotlin analysis scheduling so interactive code completion can preempt diagnostics and indexing work.
  • Added cooperative cancellation propagation across completion, signature help, diagnostics, indexing, IntelliJ progress APIs, and ProgressManager.
  • Debounced completion requests by 80 ms to coalesce rapid keystrokes and avoid stale work.
  • Automatically reschedules diagnostics and indexing after analysis preemption.
  • Added cancellation listener APIs and comprehensive concurrency/cancellation regression tests.
  • Limited unimported-symbol completion searches to 100 results.
  • Added required test JVM module access and Claude Code local-artifact ignores.
  • Risks: The scheduler introduces complex reentrant locking and preemption behavior; cancellation races or incomplete rescheduling could affect completion, diagnostics, or indexing reliability. The new 100-item search limit may omit valid completion candidates.

Walkthrough

This PR adds priority-aware, preemptive Kotlin analysis scheduling, propagates cancellation through indexing, diagnostics, completion, and signature help, debounces editor completion requests, updates progress APIs, adds regression tests, and adjusts test and repository configuration.

Changes

Analysis scheduling and cancellation core

Layer / File(s) Summary
Cancellation listeners and thread registration
shared/src/main/java/com/itsaky/androidide/progress/*, shared/src/test/java/com/itsaky/androidide/progress/*
Adds cancellation listeners, synchronized thread-checker registration, cleanup, and regression tests.
Analysis scheduler and cancellation bridges
lsp/kotlin/.../compiler/modules/AnalysisScheduler.kt, AnalysisThreadContext.java, CancelCheckerProgressIndicator.kt
Adds priorities, cooperative preemption, scheduler-controlled cancellation, thread-context job installation, and progress cancellation bridging.
Scheduler-backed analysis entry points
lsp/kotlin/.../compiler/modules/KtFileExts.kt
Runs analysis through the priority-aware scheduler and forwards cancellation through analysis calls.
Indexing, diagnostics, and interactive requests
lsp/kotlin/..., editor/src/main/java/com/itsaky/androidide/editor/...
Requeues preempted work, propagates cancellation through completion and signature help, bounds symbol lookup, registers completion threads, and debounces completion requests.
Analysis scheduler regression tests
lsp/kotlin/src/test/java/.../AnalysisSerializationTest.kt, lsp/kotlin/src/test/java/.../KtLspTest.kt
Covers reentrancy, priority ordering, preemption, cancellation, waiting, and same-priority supersession.
Build and repository hygiene
build.gradle.kts, .claude/.gitignore
Adds the required JPMS opening and ignores Claude Code local artifacts.

Estimated code review effort: 5 (Critical) | ~120 minutes

Sequence Diagram(s)

sequenceDiagram
  participant EditorCompletionWindow
  participant IDELanguage
  participant ProgressManager
  participant KotlinCompletions
  participant AnalysisScheduler

  EditorCompletionWindow->>EditorCompletionWindow: debounce completion request
  IDELanguage->>ProgressManager: register completion checker
  IDELanguage->>KotlinCompletions: doComplete(params)
  KotlinCompletions->>AnalysisScheduler: acquire INTERACTIVE priority
  AnalysisScheduler-->>KotlinCompletions: complete or preempt prior analysis
  IDELanguage->>ProgressManager: unregister completion thread
Loading

Possibly related PRs

Suggested reviewers: dara-abijo-adfa, hal-eisen-adfa, jatezzz

Poem

A rabbit tuned the scheduler bright,
Cancellations hopped left and right.
Completion waits, then springs anew,
Diagnostics queue their work in queue,
While indexed paths regain their flight. 🐇

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 21.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Title check ✅ Passed The title clearly matches the main change: prioritizing code completion requests over analyze requests.
Description check ✅ Passed The description references the linked ADFA-4174 issue, which is related to the pull request changes.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch fix/ADFA-4174

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 2

🧹 Nitpick comments (1)
lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AnalysisSerializationTest.kt (1)

160-162: 📐 Maintainability & Code Quality | 🔵 Trivial | 💤 Low value

Optional: silence detekt SwallowedException on the intentional preemption catches.

Catching AnalysisPreemptedException only to flip a flag is intentional here, but detekt flags the swallowed exception at Lines 160, 205, and 384. If detekt runs as a build gate, either reference the exception (e.g. rename to _) or add a brief justifying comment to keep it quiet without behavior change.

♻️ Example
-			} catch (e: AnalysisPreemptedException) {
+			} catch (_: AnalysisPreemptedException) {
 				preempted.set(true)
 			}

Also applies to: 205-207, 384-386

🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In
`@lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AnalysisSerializationTest.kt`
around lines 160 - 162, The intentional AnalysisPreemptedException catches in
AnalysisSerializationTest are being flagged by detekt as swallowed exceptions;
update the affected catch blocks in the test methods to make the intent
explicit, either by referencing the exception variable (for example with an
underscore-style naming convention if supported) or by adding a brief
explanatory comment right where the catch occurs. Keep the behavior the same in
the relevant catch sites around the AnalysisPreemptedException handling in
AnalysisSerializationTest, especially the preemption flag logic.

Source: Linters/SAST tools

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/KtFileExts.kt`:
- Around line 76-107: The cancellation hook setup around
AnalysisScheduler.acquire and AnalysisScheduler.release is outside the
lock-guarded try/finally, so a failure in cancelChecker.invokeOnCancel can
bypass release and deadlock Kotlin analysis globally. Move the invokeOnCancel
registration into the same try block that already wraps
AnalysisThreadContext.installJob and
ProgressManager.executeProcessUnderProgress, keeping AnalysisScheduler.release
in the finally so the lock is always released. Use the existing symbols
AnalysisScheduler.acquire, cancelChecker.invokeOnCancel, and
AnalysisScheduler.release to place the fix correctly.

In `@shared/src/main/java/com/itsaky/androidide/progress/ProgressManager.kt`:
- Around line 73-81: The race in `ProgressManager.abortIfCancelled()` comes from
checking `threads[thisThread]` and removing it in separate synchronized
sections, which can delete a newer registration for the same thread. Update
`abortIfCancelled()` so the lookup, cancellation check, and conditional
`threads.remove(thisThread)` happen atomically within one
`synchronized(threads)` block, using the current `checker` only if it is still
the same entry you observed.

---

Nitpick comments:
In
`@lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AnalysisSerializationTest.kt`:
- Around line 160-162: The intentional AnalysisPreemptedException catches in
AnalysisSerializationTest are being flagged by detekt as swallowed exceptions;
update the affected catch blocks in the test methods to make the intent
explicit, either by referencing the exception variable (for example with an
underscore-style naming convention if supported) or by adding a brief
explanatory comment right where the catch occurs. Keep the behavior the same in
the relevant catch sites around the AnalysisPreemptedException handling in
AnalysisSerializationTest, especially the preemption flag logic.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 8af68e26-ff1a-4dd5-ae48-25d3b719ee53

📥 Commits

Reviewing files that changed from the base of the PR and between bf89f5b and e2f579b.

📒 Files selected for processing (18)
  • .claude/.gitignore
  • build.gradle.kts
  • editor/src/main/java/com/itsaky/androidide/editor/language/IDELanguage.kt
  • editor/src/main/java/com/itsaky/androidide/editor/ui/EditorCompletionWindow.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/CompilationEnvironment.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/index/IndexWorker.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/index/SourceFileIndexer.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AnalysisScheduler.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AnalysisThreadContext.java
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/CancelCheckerProgressIndicator.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/KtFileExts.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/completion/KotlinCompletions.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/diagnostic/KotlinDiagnosticProvider.kt
  • lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AnalysisSerializationTest.kt
  • shared/src/main/java/com/itsaky/androidide/progress/ICancelChecker.kt
  • shared/src/main/java/com/itsaky/androidide/progress/ProgressManager.kt
  • shared/src/test/java/com/itsaky/androidide/progress/ICancelCheckerTest.kt
  • shared/src/test/java/com/itsaky/androidide/progress/ProgressManagerTest.kt

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

Inline comments:
In
`@lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/signaturehelp/KotlinSignatureHelp.kt`:
- Around line 124-134: Change the catch clause surrounding the signature-help
computation in KotlinSignatureHelp to catch Exception instead of Throwable.
Preserve the existing isAnalysisCancellation handling, logging, and
SignatureHelp.empty() fallback for exceptions while allowing fatal Error
subtypes to propagate.
🪄 Autofix (Beta)

Fix all unresolved CodeRabbit comments on this PR:

  • Push a commit to this branch (recommended)
  • Create a new PR with the fixes

ℹ️ Review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: 509590d0-07d1-4591-89b9-46dcb53eaeb1

📥 Commits

Reviewing files that changed from the base of the PR and between a403efc and 66da411.

📒 Files selected for processing (6)
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AnalysisScheduler.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/KtFileExts.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/completion/KotlinCompletions.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/signaturehelp/KotlinSignatureHelp.kt
  • lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AnalysisSerializationTest.kt
  • lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/fixtures/KtLspTest.kt
🚧 Files skipped from review as they are similar to previous changes (4)
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AnalysisScheduler.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/KtFileExts.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/completion/KotlinCompletions.kt
  • lsp/kotlin/src/test/java/com/itsaky/androidide/lsp/kotlin/compiler/modules/AnalysisSerializationTest.kt

@Daniel-ADFA Daniel-ADFA left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@dara-abijo-adfa dara-abijo-adfa left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

There's a duplicate word in the PR title.
I also added two comments.

@itsaky-adfa itsaky-adfa changed the title ADFA-4174: prioritize code completion requests over over analyze requests ADFA-4174: prioritize code completion requests over analyze requests Jul 14, 2026
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.

4 participants