mirror of
https://github.com/github/codeql.git
synced 2026-07-27 05:51:56 +02:00
Kotlin: satisfy extractor lint in KDoc-section/owner code (no throw, no cast)
Once the extractor built again, the internal `possiblyThrowingExpressions`
query (a lint over the extractor's own Kotlin source that forbids constructs
which can abort extraction) flagged two spots in the KDoc code added earlier
this session:
* a `throw e` used to re-raise `ProcessCanceledException` from
`parseKDocSections`, and
* an unchecked `element as IrDeclaration` cast in the metadata-less
KDoc-owner pass.
Both were previously masked because the internal build did not compile (the
`com.intellij.psi` references failed first), so the query never ran.
Remove the re-raise and simply log and continue, matching how the rest of the
extractor handles parse failures (it never lets exceptions escape). This also
drops the last reference to `ProcessCanceledException`.
Replace the cast with a `when` over the concrete IR declaration types
(`IrEnumEntry`, `IrAnonymousInitializer`), which smart-casts each branch to the
common `IrDeclaration` supertype. A plain `&& element is IrDeclaration` guard
would instead trip the K2 compiler's "check for instance is always true"
warning, which `-Werror` turns into a build failure.
No expected-output changes: behaviour is unchanged; only the exception handling
and the type narrowing are rewritten. Verified all 12 extractor versions in
`versions.bzl` build warning-free.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
This commit is contained in:
@@ -69,14 +69,8 @@ class CommentExtractorLighterAST(
|
||||
val ktFile = factory.createFile("$commentText\nval __codeql_kdoc__ = 0")
|
||||
ktFile.declarations.firstOrNull()?.docComment?.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
|
||||
// name rather than by type because the class is not resolvable on every
|
||||
// supported compiler version (its embeddable classpath varies), and a
|
||||
// compile-time reference breaks the cross-version build.
|
||||
if (e.javaClass.name == "com.intellij.openapi.progress.ProcessCanceledException") {
|
||||
throw e
|
||||
}
|
||||
// Follow the extractor convention of never letting an exception escape:
|
||||
// log it and omit the sections rather than aborting extraction.
|
||||
logger.warn("Couldn't parse KDoc sections: ${e}")
|
||||
null
|
||||
}
|
||||
@@ -139,14 +133,22 @@ class CommentExtractorLighterAST(
|
||||
file.acceptVoid(
|
||||
object : IrVisitorVoid() {
|
||||
override fun visitElement(element: IrElement) {
|
||||
if (element is IrEnumEntry || element is IrAnonymousInitializer) {
|
||||
val decl = element as IrDeclaration
|
||||
if (
|
||||
decl.startOffset != UNDEFINED_OFFSET &&
|
||||
decl.startOffset != SYNTHETIC_OFFSET
|
||||
) {
|
||||
candidates.add(decl)
|
||||
// Enum entries and anonymous initializers are both `IrDeclaration`s.
|
||||
// A `when` over their concrete types smart-casts each branch to the
|
||||
// common `IrDeclaration` supertype, so `candidates` is populated
|
||||
// without an unchecked cast.
|
||||
val decl: IrDeclaration? =
|
||||
when (element) {
|
||||
is IrEnumEntry -> element
|
||||
is IrAnonymousInitializer -> element
|
||||
else -> null
|
||||
}
|
||||
if (
|
||||
decl != null &&
|
||||
decl.startOffset != UNDEFINED_OFFSET &&
|
||||
decl.startOffset != SYNTHETIC_OFFSET
|
||||
) {
|
||||
candidates.add(decl)
|
||||
}
|
||||
element.acceptChildrenVoid(this)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user