Skip to content

Track queried error types and report unresolved references in final round - #3236

Draft
cushon wants to merge 2 commits into
google:mainfrom
cushon:query-time-diagnostics
Draft

cushon wants to merge 2 commits into
google:mainfrom
cushon:query-time-diagnostics

Conversation

@cushon

@cushon cushon commented Sep 30, 2026

Copy link
Copy Markdown

Summary

Replaces whole-file AST type checking from #3200 with query-time error tracking on KSTypeReference.resolve(). Unrecovered errors are reported via logger.error(...) in the final round to fail the build (matching javac failure semantics), and synthetic Java annotation error types (__KSP_unresolved_*) are unwrapped to their original reference names.

Motivation

PR #3200 introduced whole-file diagnostic checks (file.collectDiagnostics()) on every round, which caused regressions:

  • Unqueried code & method bodies: Reported errors on code that processors never inspected, including method bodies and lambdas where unresolved types frequently appear during intermediate rounds.
  • Cross-round generation: Failed prematurely before downstream processors could generate missing types in subsequent rounds.
  • Performance: Running full-file diagnostics every round added significant overhead.

Conversely, KSP's historical behavior of silently ignoring unresolved queried types and exiting 0 when processors did not explicitly log errors allowed broken builds to pass or fail downstream with obscure errors.

Implementation

  1. Query-time tracking: Hooked into KSTypeReference.resolve() (KSTypeReferenceImpl and KSTypeReferenceResolvedImpl) to record unresolved types only when actively queried by a processor.
  2. Cross-round recovery: At the end of the final round, recorded errors are re-verified (isStillError()) against the final Analysis API session. Types generated in later rounds resolve cleanly and are discarded.
  3. Final-round reporting: Remaining unresolved references are reported via logger.error(...) in the final round before onError()/finish(), failing the build if unresolvable references remain.
  4. Diagnostic unwrapping: Java annotation placeholders like __KSP_unresolved_Inject are resolved to the underlying PsiJavaCodeReferenceElement to report Unresolved reference 'Inject'.
  5. Test updates: Updated expected output in unit tests that deliberately construct unresolved types to expect KSP FAILED WITH EXIT CODE: PROCESSING_ERROR.

Testing

All 652 tests in :kotlin-analysis-api:test pass cleanly.

…final round

Replace the whole-file AST diagnostic checker from PR google#3200 with
query-time error tracking at the KSP model boundary.

1. Record unresolved type references during KSTypeReference.resolve()
   in both syntax-backed (KSTypeReferenceImpl) and Analysis API-backed
   (KSTypeReferenceResolvedImpl) type references.
2. In the final processing round, re-verify recorded errors against the
   final Analysis API session to allow cross-round resolution of types
   generated by processors.
3. Report remaining unresolved references via logger.error(...) in the
   final round and unwrap synthetic Java annotation placeholder types
   to their underlying reference names.
…iagnostics

Update expectations in unit tests that deliberately construct unresolved
types to expect 'KSP FAILED WITH EXIT CODE: PROCESSING_ERROR' now that
unresolved queried types fail the build in the final round. Also override
testLocalAnnotationClass in PsiConfiguredUnitTestSuite to reflect that
the legacy PSI engine does not perform final-round diagnostic verification.
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