Kotlin: drop PsiTreeUtil from KDoc-section parsing for build portability

The KDoc-section parser located the parsed KDoc via
`com.intellij.psi.util.PsiTreeUtil.findChildOfType`. Like the
`ProcessCanceledException` reference fixed in the previous commit, this
`com.intellij` utility class is not present on every build's compiler
classpath: the reduced/relocated embeddable classpath used by the internal
extractor build strips it, so the build failed with
`unresolved reference 'PsiTreeUtil'`. The standalone language-test builds
(2.3.20, 2.4.0) bundle the full classpath and so did not catch it.

Replace the utility call with a small hand-written depth-first search over the
core `com.intellij.psi.PsiElement` navigation API (`firstChild`/`nextSibling`),
which is always available (it is already used by the PSI comment extractor).
The search has the same semantics as `findChildOfType`: it returns the first
KDoc descendant in pre-order, so the parsed sections are unchanged.

No expected-output changes: the KDoc lookup mechanism is behaviour-equivalent.
Verified the standalone extractor still builds for 1.8.0, 1.9.20-Beta and 2.4.0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
Anders Fugmann
2026-07-14 11:31:48 +02:00
parent 97199fdc39
commit 0abbd89479

View File

@@ -52,6 +52,27 @@ class CommentExtractorLighterAST(
}
}
// Depth-first search for the first KDoc descendant of `element`. We navigate
// the PSI tree by hand rather than using `com.intellij.psi.util.PsiTreeUtil`,
// because that utility class is not present on every supported compiler's
// embeddable classpath (the reduced classpath used by some builds strips it),
// whereas the core `PsiElement` navigation API is always available.
private fun findKDocDescendant(
element: com.intellij.psi.PsiElement
): org.jetbrains.kotlin.kdoc.psi.api.KDoc? {
if (element is org.jetbrains.kotlin.kdoc.psi.api.KDoc) {
return element
}
var child = element.firstChild
while (child != null) {
findKDocDescendant(child)?.let {
return it
}
child = child.nextSibling
}
return null
}
private fun parseKDocSections(
commentText: String
): List<org.jetbrains.kotlin.kdoc.psi.impl.KDocSection>? {
@@ -60,12 +81,7 @@ class CommentExtractorLighterAST(
// A KDoc is only recognised as a doc comment when it precedes a
// declaration, so we append a throwaway declaration before parsing.
val ktFile = factory.createFile("$commentText\nval __codeql_kdoc__ = 0")
val kdoc =
com.intellij.psi.util.PsiTreeUtil.findChildOfType(
ktFile,
org.jetbrains.kotlin.kdoc.psi.api.KDoc::class.java
)
kdoc?.getAllSections()
findKDocDescendant(ktFile)?.getAllSections()
} catch (e: Exception) {
// Never swallow IntelliJ's ProcessCanceledException: it is a control-flow
// exception that must propagate for cancellation to work. We match it by