Skip to content

ADFA-3320: Avoid re-creating full K2 session by invalidating source files when needed#1142

Merged
itsaky-adfa merged 25 commits into
stagefrom
feat/ADFA-3320-session-source-files-invalidation
Apr 20, 2026
Merged

ADFA-3320: Avoid re-creating full K2 session by invalidating source files when needed#1142
itsaky-adfa merged 25 commits into
stagefrom
feat/ADFA-3320-session-source-files-invalidation

Conversation

@itsaky-adfa
Copy link
Copy Markdown
Contributor

@itsaky-adfa itsaky-adfa commented Apr 1, 2026

Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
fixes duplicate class errors for org.antrl.v4.* classes

Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
It is now included in the embeddable JAR (named UnsafeAndroid) with proper relocations.

Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
…ject re-sync

Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
@itsaky-adfa itsaky-adfa requested a review from a team April 1, 2026 10:20
@itsaky-adfa itsaky-adfa self-assigned this Apr 1, 2026
@itsaky-adfa itsaky-adfa changed the title ADFA-3220: Avoid re-creating full K2 session by invalidating source files when needed ADFA-3320: Avoid re-creating full K2 session by invalidating source files when needed Apr 1, 2026
@itsaky-adfa itsaky-adfa changed the base branch from stage to feat/ADFA-3319-basic-diagnostics-provider April 15, 2026 04:33
@itsaky-adfa itsaky-adfa marked this pull request as ready for review April 15, 2026 04:33
Comment thread eventbus-events/src/main/java/com/itsaky/androidide/eventbus/events/BuildEvent.kt Outdated
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Signed-off-by: Akash Yadav <akashyadav@appdevforall.org>
Base automatically changed from feat/ADFA-3319-basic-diagnostics-provider to stage April 18, 2026 07:18
@coderabbitai
Copy link
Copy Markdown
Contributor

coderabbitai Bot commented Apr 18, 2026

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: c1000ae2-77e7-4f20-8a7e-71910657911e

📥 Commits

Reviewing files that changed from the base of the PR and between 68e316a and 4988c26.

📒 Files selected for processing (1)
  • app/src/main/java/com/itsaky/androidide/services/builder/GradleBuildService.kt

📝 Walkthrough
  • Key improvements

    • Reuse K2 compiler sessions across project re-syncs; invalidate only affected source files to avoid full session recreation and reduce startup overhead.
    • Introduced KotlinProjectModel with listener-based change kinds (STRUCTURE, SOURCES) to drive incremental session updates.
    • KotlinLanguageServer now holds a long-lived project model and diagnostic provider; subsequent setup updates the model instead of recreating the session.
    • Compilation/diagnostics lifecycle: CompilationEnvironment now listens to project-model changes and rebuilds session/parser on STRUCTURE changes and refreshes sources on SOURCES changes. KotlinDiagnosticProvider now supports clearing cached analyze timestamps via clearTimestamps() and is closed explicitly on shutdown.
    • Build/run analytics: added BuildRunType (ProjectSync, TaskRun); BuildId now carries runType and BuildMetric.asBundle() includes run_type for analytics.
    • GradleBuildService.nextBuildId now accepts BuildRunType; executeTasks and task-related flows use TaskRun. Build completion/failure handling consolidated via dispatchBuildResult().
    • Desugaring support: new ReplaceClassRef data class for class-reference rewrite mappings; added desugar-plugin / class-name rewriting support in pipeline.
    • Tooling and test updates: eventbus-events module now depends on toolingApi; test launcher and other callers initialize BuildId with explicit runType.
    • Miscellaneous: relocated Unsafe implementation into embeddable UnsafeAndroid JAR; fixes for kotlin-android versions and JvmTarget resolution; logging and small cleanup changes.
  • Public/API surface changes (notable)

    • BuildId data class signature changed (added runType: BuildRunType) — affects serialization and callers constructing BuildId.
    • New BuildRunType enum introduced.
    • Compiler constructor now requires KotlinProjectModel; configureSession lambda removed.
    • CompilationEnvironment class signature changed (now implements KotlinProjectModel.ProjectModelListener and has altered constructor parameters).
    • New public class KotlinProjectModel and public ReplaceClassRef data class.
    • KotlinDiagnosticProvider: new internal clearTimestamps() method and changed close() behavior.
    • eventbus-events module dependency changed (implementation(projects.subprojects.toolingApi)).
  • Risks, regressions, and best-practice violations to watch

    • Binary/serialization compatibility risk: BuildId signature change (added runType) may break RPC/serialization compatibility, persisted states, or cross-module binaries that expect the old shape. Verify all producers/consumers and migration strategy.
    • API-breaking changes: Compiler and CompilationEnvironment constructor/signature changes and new KotlinProjectModel are breaking for any external consumers — update call-sites and document migration.
    • Reduced session customization: removal of configureSession lambda reduces post-construction customization points for session setup; may limit third-party extensions or tests that relied on that hook.
    • Lifecycle and listener safety: listener-based model requires correct registration/deregistration. Improper listener management can cause memory leaks, duplicate notifications, or missed updates. Ensure listeners are removed on close and no dangling references remain.
    • Incremental correctness assumptions: reusing sessions and relying on source invalidation assumes all necessary state gets updated for both source-only and structural changes. Edge cases could result in stale analysis state or missed diagnostics — add thorough integration tests covering structural changes, classpath/library updates, and mixed changes.
    • Ordering and race conditions: dispatchBuildResult() consolidation and explicit listener invocation ordering could change event timing; validate there are no race conditions between analytics dispatch and listeners.
    • Serialization stability for ReplaceClassRef: class is Serializable; ensure serialVersionUID choice and usage align with persistence/IPC expectations.
  • Testing & validation recommendations

    • Run full integration tests for LSP workflows: project sync (STRUCTURE), incremental edits (SOURCES), classpath/bootclasspath changes.
    • Validate analytics and tooling consumers for BuildId.runType presence and Bundle changes (BuildMetric.asBundle()).
    • Verify cross-module builds and any persisted or serialized BuildId objects for compatibility.
    • Smoke-test desugaring/class-ref rewrites and Android-specific changes (UnsafeAndroid relocation, JvmTarget fixes).

Walkthrough

This PR adds BuildRunType to build identifiers and analytics, propagates run-type usage across build services and test launcher, introduces a KotlinProjectModel-driven lifecycle for the Kotlin LSP compiler/compilation environment, adds ReplaceClassRef for desugaring, and updates related dependency and diagnostic cleanup code.

Changes

Cohort / File(s) Summary
Build ID core
subprojects/tooling-api/src/main/java/com/itsaky/androidide/tooling/api/messages/BuildId.kt
Added runType: BuildRunType to BuildId, introduced BuildRunType enum, and updated Unknown constant to include a run type.
Build ID usage & analytics
app/src/main/java/com/itsaky/androidide/services/builder/GradleBuildService.kt, app/src/main/java/com/itsaky/androidide/activities/editor/ProjectHandlerActivity.kt, app/src/main/java/com/itsaky/androidide/analytics/gradle/BuildMetric.kt, testing/tooling/src/main/java/com/itsaky/androidide/testing/tooling/ToolingApiTestLauncher.kt
Call sites updated to request/preserve BuildRunType (ProjectSync/TaskRun); BuildMetric.asBundle() now includes run_type; GradleBuildService uses explicit run types and refactored shared result dispatching.
Kotlin LSP: project model and compiler lifecycle
lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/KotlinProjectModel.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/Compiler.kt, lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/KotlinLanguageServer.kt
Added KotlinProjectModel with listener API; compilation environment and compiler refactored to use model-driven lifecycle (rebuild session/parser on STRUCTURE changes), updated constructor signatures and listener wiring; language server now retains/reuses project model and adjusts shutdown/diagnostic handling.
Diagnostics cleanup
lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/diagnostic/KotlinDiagnosticProvider.kt
Added clearTimestamps() and invoke it on close() to completely clear cached analyze timestamps during teardown.
Desugaring DSL
composite-builds/build-logic/desugaring/src/main/java/com/itsaky/androidide/desugaring/dsl/ReplaceClassRef.kt
New serializable ReplaceClassRef data class with fromClass/toClass and computed internal slash-notation accessors.
Build files
eventbus-events/build.gradle.kts
Added implementation(projects.subprojects.toolingApi) dependency.

Sequence Diagram(s)

sequenceDiagram
    participant PA as ProjectHandlerActivity
    participant GBS as GradleBuildService
    participant BI as BuildId
    participant BM as BuildMetric

    PA->>GBS: nextBuildId(BuildRunType.ProjectSync)
    activate GBS
    GBS->>BI: create BuildId(..., runType=ProjectSync)
    BI-->>GBS: BuildId
    GBS-->>PA: BuildId
    deactivate GBS

    PA->>BM: BuildMetric.asBundle(buildId)
    activate BM
    BM->>BI: read runType.typeName
    BM-->>PA: Bundle including run_type
    deactivate BM
Loading
sequenceDiagram
    participant KLS as KotlinLanguageServer
    participant KPM as KotlinProjectModel
    participant CE as CompilationEnvironment
    participant CMP as Compiler

    KLS->>KPM: instantiate KotlinProjectModel()
    KLS->>KPM: addListener(compilationEnv)
    KLS->>KPM: update(workspace, platform)
    activate KPM
    KPM->>KPM: configure modules
    KPM->>CE: notify onProjectModelChanged(STRUCTURE)
    activate CE
    CE->>CE: rebuild session & parser
    CE-->>KPM: done
    deactivate CE
    KPM-->>KLS: update complete
    KLS->>CMP: new Compiler(projectModel)
    CMP->>CE: create defaultCompilationEnv(projectModel)
    CMP-->>KLS: compiler ready
Loading

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~50 minutes

Possibly related PRs

Suggested reviewers

  • dara-abijo-adfa
  • jatezzz
  • Daniel-ADFA

Poem

🐰 I hopped through code where builds now know their name,
Syncs and tasks wear tags, no longer just the same.
Models listen, compilers wake and mend,
Rewrites hop in place — a bytecode friend.
Hooray for tidy trees at each build's end!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 7.69% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main objective of the changeset: avoiding K2 session recreation by implementing source file invalidation, which is reflected in the substantial refactoring of CompilationEnvironment and KotlinProjectModel.
Description check ✅ Passed The description references the associated JIRA issue (ADFA-3320) and lists merge dependencies, providing context about the PR's purpose and integration requirements.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ 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 feat/ADFA-3320-session-source-files-invalidation

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 and usage tips.

Copy link
Copy Markdown
Contributor

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

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

Actionable comments posted: 6

🧹 Nitpick comments (3)
composite-builds/build-logic/desugaring/src/main/java/com/itsaky/androidide/desugaring/dsl/ReplaceClassRef.kt (1)

21-24: Use private const val serialVersionUID: Long in the companion object.

For Serializable classes, the idiomatic Kotlin approach is:

Suggested change
 	companion object {
-		`@JvmField`
-		val serialVersionUID = 1L
+		private const val serialVersionUID: Long = 1L
 	}

const val produces a true compile-time constant that compiles directly to a private static final field with optimal bytecode. The current @JvmField val works at runtime but generates unnecessary getter methods and exposes the field publicly (missing private). Both are recognized by Java serialization, but const val is the preferred pattern in Kotlin.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@composite-builds/build-logic/desugaring/src/main/java/com/itsaky/androidide/desugaring/dsl/ReplaceClassRef.kt`
around lines 21 - 24, The companion object exposes serialVersionUID as a public
`@JvmField` val; change it to a true compile-time constant by replacing that
declaration inside the companion object with a private const val
serialVersionUID: Long = 1L so the compiler emits a private static final field
(update the declaration in ReplaceClassRef's companion object).
subprojects/tooling-api/src/main/java/com/itsaky/androidide/tooling/api/messages/BuildId.kt (1)

10-18: Consider declaring a serialVersionUID now that BuildId's shape is changing.

BuildId implements Serializable and this change adds a new non-optional field runType. Any previously serialized BuildId (e.g. persisted cache, cross-process state) will now fail to deserialize with InvalidClassException because the auto-generated serialVersionUID depends on the class shape. Even if today all transport is via JSON-RPC, pinning a serialVersionUID makes future additions safer and decouples binary serial compatibility from incidental field changes.

🛠️ Suggested addition
 data class BuildId(
 	val buildSessionId: String,
 	val buildId: Long,
 	val runType: BuildRunType,
 ) : Serializable {
 	companion object {
+		private const val serialVersionUID: Long = 1L
 		val Unknown = BuildId("unknown", -1, BuildRunType.TaskRun)
 	}
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@subprojects/tooling-api/src/main/java/com/itsaky/androidide/tooling/api/messages/BuildId.kt`
around lines 10 - 18, BuildId implements Serializable and now has a new
non-optional field, so add an explicit serialVersionUID to pin binary
compatibility: inside BuildId's companion object (the one that currently
contains Unknown) declare a private const val serialVersionUID: Long = 1L (or
another stable long) so deserialization does not break when the auto-generated
UID would change; bump this value only when making intentionally incompatible
binary changes to BuildId.
lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/KotlinProjectModel.kt (1)

62-66: update() unconditionally fires STRUCTURE.

Minor: each setupWithProject call — even when workspace/platform reference is effectively unchanged — will trigger a full session rebuild. Consider short-circuiting when workspace === this.workspace && platform == this.platform, or adding a separate hook to fire SOURCES from build-complete without a full structural rebuild (the enum anticipates this but no caller currently emits SOURCES). Not blocking for this PR.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In
`@lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/KotlinProjectModel.kt`
around lines 62 - 66, The update method in KotlinProjectModel unconditionally
calls notifyListeners(ChangeKind.STRUCTURE), causing full rebuilds even when
nothing changed; modify KotlinProjectModel.update(workspace: Workspace,
platform: TargetPlatform) to short-circuit early when the incoming workspace is
the same instance and platform equals the current ones (e.g., if (workspace ===
this.workspace && platform == this.platform) return), otherwise assign and
notify; alternatively consider emitting ChangeKind.SOURCES from the build
completion path instead of always STRUCTURE, but for this change implement the
identity/equality check in update to avoid unnecessary STRUCTURE notifications.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In
`@composite-builds/build-logic/desugaring/src/main/java/com/itsaky/androidide/desugaring/dsl/ReplaceClassRef.kt`:
- Around line 9-10: The KDoc is wrong because ReplaceClassRef's constructor
doesn't normalize class-name forms, causing ReplaceClassRef("a.b.C", ...) and
ReplaceClassRef("a/b/C", ...) to be unequal; fix by normalizing both fromClass
and toClass inside the ReplaceClassRef constructor (e.g., in an init block) to a
single canonical form (choose either dot-notation or internal slash-notation
consistent with fromInternal/toInternal), update the stored properties so
fromInternal/toInternal return the expected form, and ensure equals/hashCode
operate on the normalized values (use the same normalization routine used
elsewhere, or call the existing fromInternal/toInternal conversions to avoid
duplication).

In
`@lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/CompilationEnvironment.kt`:
- Around line 124-134: rebuildSession currently disposes the old disposable and
replaces it before calling buildSession(), which leaves session/parser pointing
at a disposed project if buildSession() throws; change to construct a new
Disposable first, pass it into a new helper (e.g. buildSessionWith(disposable))
that creates the Project/session without touching the fields, and only after
buildSessionWith succeeds atomically replace disposable, session, and parser
(create KtPsiFactory from the new session) so failures do not leave the
environment in a disposed state; also ensure access to
rebuildSession/onProjectModelChanged that mutate disposable/session/parser is
synchronized to prevent concurrent swaps and leaks.
- Around line 161-192: The nullable-safe casts use redundant trailing question
marks; change the casts from "as? KotlinStandaloneModificationTrackerFactory?"
to "as? KotlinStandaloneModificationTrackerFactory" and from "as?
SimpleModificationTracker?" to "as? SimpleModificationTracker" so the as?
operator alone provides the nullable type; update these casts in the block where
modificationTrackerFactory and sourceModificationTracker are initialized (look
for KotlinStandaloneModificationTrackerFactory and SimpleModificationTracker
symbols).

In
`@lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/KotlinProjectModel.kt`:
- Around line 33-56: The listeners collection in KotlinProjectModel is a plain
mutableListOf and is accessed by addListener, removeListener and notifyListeners
from multiple threads; replace it with a thread-safe structure (e.g.,
java.util.concurrent.CopyOnWriteArrayList) or protect all accesses with a single
lock so iteration during notifyListeners cannot throw
ConcurrentModificationException and adds/removes are not lost; update the
declaration of listeners and ensure addListener, removeListener and
notifyListeners use the new thread-safe approach.
- Around line 126-132: In KotlinProjectModel.kt update the logging in the block
that checks libDep (the if (libDep == null) branch) to fix the duplicated word
in the message and lower the severity: replace logger.error("Skipping
non-existent classpath classpath: {}", classpath) with a clearer message like
"Skipping non-existent classpath: {}" and use logger.warn(...) instead; keep
referencing the same variables (libDep, classpath) so behavior is unchanged.

In
`@lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/KotlinLanguageServer.kt`:
- Around line 137-162: The else branch that calls
projectModel?.update(workspace, jvmPlatform) can rebuild the compilation session
and invalidate diagnostics, but KotlinDiagnosticProvider.analyzeTimestamps is
keyed by file mtimes so stale timestamps suppress updated diagnostics; after
projectModel?.update(...) (i.e., in the update/STRUCTURE path) call
KotlinDiagnosticProvider.clearTimestamps()
(diagnosticProvider?.clearTimestamps()) to reset analyzeTimestamps so
diagnostics will be recomputed; alternatively register KotlinDiagnosticProvider
as a ProjectModel listener and clear timestamps on ChangeKind.STRUCTURE to cover
other callers.

---

Nitpick comments:
In
`@composite-builds/build-logic/desugaring/src/main/java/com/itsaky/androidide/desugaring/dsl/ReplaceClassRef.kt`:
- Around line 21-24: The companion object exposes serialVersionUID as a public
`@JvmField` val; change it to a true compile-time constant by replacing that
declaration inside the companion object with a private const val
serialVersionUID: Long = 1L so the compiler emits a private static final field
(update the declaration in ReplaceClassRef's companion object).

In
`@lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/KotlinProjectModel.kt`:
- Around line 62-66: The update method in KotlinProjectModel unconditionally
calls notifyListeners(ChangeKind.STRUCTURE), causing full rebuilds even when
nothing changed; modify KotlinProjectModel.update(workspace: Workspace,
platform: TargetPlatform) to short-circuit early when the incoming workspace is
the same instance and platform equals the current ones (e.g., if (workspace ===
this.workspace && platform == this.platform) return), otherwise assign and
notify; alternatively consider emitting ChangeKind.SOURCES from the build
completion path instead of always STRUCTURE, but for this change implement the
identity/equality check in update to avoid unnecessary STRUCTURE notifications.

In
`@subprojects/tooling-api/src/main/java/com/itsaky/androidide/tooling/api/messages/BuildId.kt`:
- Around line 10-18: BuildId implements Serializable and now has a new
non-optional field, so add an explicit serialVersionUID to pin binary
compatibility: inside BuildId's companion object (the one that currently
contains Unknown) declare a private const val serialVersionUID: Long = 1L (or
another stable long) so deserialization does not break when the auto-generated
UID would change; bump this value only when making intentionally incompatible
binary changes to BuildId.
🪄 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: f8253da0-2808-4011-aae1-7bb7646e19f0

📥 Commits

Reviewing files that changed from the base of the PR and between 43684b2 and 68e316a.

📒 Files selected for processing (12)
  • app/src/main/java/com/itsaky/androidide/activities/editor/ProjectHandlerActivity.kt
  • app/src/main/java/com/itsaky/androidide/analytics/gradle/BuildMetric.kt
  • app/src/main/java/com/itsaky/androidide/services/builder/GradleBuildService.kt
  • composite-builds/build-logic/desugaring/src/main/java/com/itsaky/androidide/desugaring/dsl/ReplaceClassRef.kt
  • eventbus-events/build.gradle.kts
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/KotlinLanguageServer.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/Compiler.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/compiler/KotlinProjectModel.kt
  • lsp/kotlin/src/main/java/com/itsaky/androidide/lsp/kotlin/diagnostic/KotlinDiagnosticProvider.kt
  • subprojects/tooling-api/src/main/java/com/itsaky/androidide/tooling/api/messages/BuildId.kt
  • testing/tooling/src/main/java/com/itsaky/androidide/testing/tooling/ToolingApiTestLauncher.kt

@itsaky-adfa itsaky-adfa merged commit 1c68ee1 into stage Apr 20, 2026
2 checks passed
@itsaky-adfa itsaky-adfa deleted the feat/ADFA-3320-session-source-files-invalidation branch April 20, 2026 17:13
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.

2 participants