Skip to content

ADFA-5231: Gate the resolution-side KtFile door and record ADR 0015 - #1747

Open
itsaky-adfa wants to merge 6 commits into
ADFA-5231-stale-pin-refusalsfrom
ADFA-5231-gate-resolution-door
Open

ADFA-5231: Gate the resolution-side KtFile door and record ADR 0015#1747
itsaky-adfa wants to merge 6 commits into
ADFA-5231-stale-pin-refusalsfrom
ADFA-5231-gate-resolution-door

Conversation

@itsaky-adfa

@itsaky-adfaitsaky-adfa commented Aug 25, 2026

Copy link
Copy Markdown
Contributor

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.getKtFile was plain internal and returns the live instance for an open path, and analyzeMaybeDangling is plain internal inline. So anywhere in lsp/kotlin - including its test source set, and including wherever the next refactor lands - this compiled with no diagnostic:

val f = env.ktSymbolIndex.getKtFile(path)!!
analyzeMaybeDangling(f, AnalysisPriority.COMMAND, checker) { /* ... */ }

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 getKtFile overloads now carry @RequiresOptIn(ERROR)ResolutionSideKtFileAccess, with @OptIn at the three service providers that legitimately need the resolution-side door (DeclarationsProvider, AnnotationsResolver, DirectInheritorsProvider), one internal use, and five test sites. @OptIn is 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 getKtFile acquisition. Checked twice, independently, with the probe file removed and the module recompiled clean each time.

Note: most of the line count in the three provider files is Spotless reformatting. Each gained one annotation, which pulled the whole file under the file-level ratchet. git diff -w on those files is ~20 lines of real change. They are isolated in this PR precisely so that noise stays out of the substantive layers.

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 KtFile per 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 live KtFile" claim is qualified, because the modified-file indexer does analyse one unpinned (a tracked follow-up).

Testing

461 tests, 0 failures. Compile clean.

@claudeclaudeBot 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 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.

@github-actionsgithub-actionsBot deleted a comment from atlassianBotAug 25, 2026
@itsaky-adfaitsaky-adfa self-assigned this Aug 25, 2026
@itsaky-adfa
itsaky-adfa requested a review from a teamAugust 25, 2026 16:54
@itsaky-adfaitsaky-adfa changed the title ADFA 5231 gate resolution doorADFA-5231: Gate the resolution-side KtFile door and record ADR 0015Aug 25, 2026
Comment threaddocs/adr/0015-one-pinned-ktfile-per-analysis.md Outdated
@itsaky-adfa
itsaky-adfaforce-pushed the ADFA-5231-gate-resolution-door branch 2 times, most recently from 38d480c to b74ec62CompareAugust 27, 2026 09:06

@jatezzzjatezzz left a comment

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

LGTM

`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-adfa
itsaky-adfaforce-pushed the ADFA-5231-gate-resolution-door branch from b74ec62 to 39b5a34CompareAugust 27, 2026 16:13
Sign up for freeto 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

@itsaky-adfa@jatezzz