Uh oh!
There was an error while loading. Please reload this page.
ADFA-5231: Gate the resolution-side KtFile door and record ADR 0015 - #1747
Open
itsaky-adfa wants to merge 6 commits into
Open
ADFA-5231: Gate the resolution-side KtFile door and record ADR 0015#1747itsaky-adfa wants to merge 6 commits into
itsaky-adfa wants to merge 6 commits into
Conversation
There was a problem hiding this comment.
Claude Code Review
This repository is configured for manual code reviews. Comment @claude review for a one-time review, or @claude review always to subscribe this PR to a review on every future push.
Tip: disable this comment in your organization's Code Review settings.
jatezzz
reviewed
Aug 26, 2026
Uh oh!
There was an error while loading. Please reload this page.
jatezzz
reviewed
Aug 26, 2026
Uh oh!
There was an error while loading. Please reload this page.
itsaky-adfaforce-pushed
the
ADFA-5231-gate-resolution-door
branch
2 times, most recently
from
August 27, 2026 09:06
38d480c to
b74ec62Compare`internal` was not a gate: any file in this module, its test source set included, could take the live instance from `getKtFile` and analyse it unpinned, which is exactly the shape of the ADFA-3322 regression. The three Analysis API service providers that genuinely need to name the PSI for a path opt in per function, so each exemption stays visible in review. The three providers' whole-file reformat is the Spotless ratchet: touching one line in a file that predates the tab/ktlint convention pulls the file in entirely.
The escape hatch's justification covered analysis coherence only; its one caller does hand offsets from possibly-stale PSI into a buffer edit, which is the thing the isStale guards exist to prevent. And `LiveKtFile.analyzing` is not the only route to a live instance: the modified-file indexer is handed a raw one and analyses it unpinned. Both are pre-existing behaviour with follow-ups; the record should not assert otherwise.
The source-side markers cannot cover the whole door. The Analysis API interfaces the service providers implement re-export the live instances through their own public members, and those overrides may not carry an opt-in marker (OPT_IN_MARKER_ON_OVERRIDE is an error when the base declaration lacks it); marking the implementing class does not help either, since callers are typed as the platform interface. Requiring opt-in on analyzeMaybeDangling catches every such route at the one point they all arrive at.
itsaky-adfaforce-pushed
the
ADFA-5231-gate-resolution-door
branch
from
August 27, 2026 16:13
b74ec62 to
39b5a34Compare
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for freeto join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Stack 5 of 5 for ADFA-5231. Closes the last hole in the compile-time gate and records the decision.
Why this layer exists
The earlier PRs made the raw accessors private, but the gate did not actually hold inside the module.
KtSymbolIndex.getKtFilewas plaininternaland returns the live instance for an open path, andanalyzeMaybeDanglingis plaininternal inline. So anywhere inlsp/kotlin- including its test source set, and including wherever the next refactor lands - this compiled with no diagnostic:and reintroduced the bug. That is a literal description of how ADFA-3322 undid ADFA-4165's fix, so leaving it open would have meant shipping a fix whose headline claim was false.
Both
getKtFileoverloads now carry@RequiresOptIn(ERROR)ResolutionSideKtFileAccess, with@OptInat the three service providers that legitimately need the resolution-side door (DeclarationsProvider,AnnotationsResolver,DirectInheritorsProvider), one internal use, and five test sites.@OptInis on the narrowest scope that works, so every exemption stays visible in review.Verified rather than asserted: an un-opted-in version of the snippet above now fails compilation with the marker error at the
getKtFileacquisition. Checked twice, independently, with the probe file removed and the module recompiled clean each time.ADR 0015
Records the invariant, its history, and the consequences - the point being that ADFA-4165's fix was a property maintained by code, so a refactor undid it, whereas this one is carried by types. It also records honestly what the design costs: the cross-request staleness window, the three ways staleness is handled (edit sites refuse, diagnostics discards and reschedules, navigation tolerates), the partial escape guard, and the known follow-ups. Alternatives considered - a runtime check, one mutable
KtFileper path reparsed in place, a lint rule - each with why it was not taken.Two corrections to claims elsewhere in the codebase are included:
KtFileExts's "all Analysis API access must go through this helper" is now structural for an open file, and the "only route to a liveKtFile" claim is qualified, because the modified-file indexer does analyse one unpinned (a tracked follow-up).Testing
461 tests, 0 failures. Compile clean.