mirror of
https://github.com/github/codeql.git
synced 2026-07-26 21:44:02 +02:00
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>