Files
codeql/java
Anders Fugmann aeb5cab7d9 Kotlin: extract KDoc sections under the K2/FIR frontend
The comment extractor has two implementations selected at runtime: the
PSI-based `CommentExtractorPSI` (used when the IR is built from PSI, i.e.
the K1 frontend) and `CommentExtractorLighterAST` (used under the K2/FIR
frontend, where no PSI is available and comments are recovered from the
FIR lighter AST). The PSI extractor writes a row per KDoc section
(`comment.getAllSections()`: the default section plus `@property`,
`@constructor`, ... tag sections), but the lighter-AST extractor did not,
because the KDOC node in the FIR lighter AST is a leaf: its section/tag
structure is never expanded there. As a result, `ktCommentSections`,
`ktCommentSectionNames` and `ktCommentSectionSubjectNames` were entirely
absent under K2, producing a large divergence from the K1 output.

KDoc section structure can only be recovered by parsing the KDoc text
into real PSI, which needs a `Project`. The compiler passes one to the
component registrar's `registerProjectComponents`, so we capture it there
into `KDocProjectHolder` (a process-global; a weak reference guarded by
`isDisposed` avoids keeping a disposed project alive). The lighter-AST
extractor then re-parses each KDoc's text with `KtPsiFactory` and reads
`getAllSections()`, writing exactly the same rows as the PSI extractor.
Because both paths delegate to the same compiler KDoc parser, the section
content, names and subject names are reproduced identically.

Trade-offs:

- A process-global project holder is used rather than threading the
  project through the extension/extractor constructors, which would touch
  a lot of unrelated wiring. Each CodeQL extraction is a single compiler
  invocation, so one project per process is a safe assumption; the weak
  reference and `isDisposed` check bound the lifetime risk.

- The re-parse forces the KDoc text into a doc-comment position via a
  throwaway trailing declaration. A KDoc is only recognised as a doc
  comment when it precedes a declaration; the appended declaration is
  inert and does not affect section parsing.

- Section output is byte-identical between K1 (2.3.20) and K2 (2.4.0)
  today because both use the compiler's own KDoc parser. This is a
  version-coupled compatibility shim rather than a guaranteed invariant;
  the shared test suite will catch any future drift.

Only the K2 expectations gain rows; the K1 output is unchanged. The
`test-kotlin2` comment section relations now match `test-kotlin1`
byte-for-byte, except for the line-1 KDoc whose source text still differs
between the two suites (addressed separately).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-07-14 02:33:16 +02:00
..