KE2: Put diagnostics from the analysis API into the database

This commit is contained in:
Ian Lynagh
2024-11-26 15:42:38 +00:00
parent 2c595417f1
commit cc0eb9ab36
4 changed files with 48 additions and 38 deletions

View File

@@ -1,7 +1,9 @@
package com.github.codeql
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import org.jetbrains.kotlin.analysis.api.components.KaDiagnosticCheckerFilter
import org.jetbrains.kotlin.analysis.api.diagnostics.KaSeverity
import org.jetbrains.kotlin.analysis.api.KaSession
import org.jetbrains.kotlin.analysis.api.types.KaType
import org.jetbrains.kotlin.KtNodeTypes
@@ -207,43 +209,38 @@ open class KotlinFileExtractor(
// TODO: Add comment
private fun extractDiagnostics(file: KtFile) {
// TODO: Put this in the database
println("=== Diagnostics")
val dcf = KaDiagnosticCheckerFilter.ONLY_COMMON_CHECKERS
for (d in file.collectDiagnostics(dcf)) {
println("--- Diagnostic:")
println(d.factoryName)
println(d.severity)
println(d.defaultMessage)
// TODO: We could try to link diagnostics to d.psi, but we
// don't have labels for lots of things. We'd either have
// to cache the labels, or extract diagnostics from all the
// element extractors.
for (tr in d.textRanges) {
val loc = getLocationInfo(file, tr)
println(loc)
val diagLabel = tw.getFreshIdLabel<DbDiagnostic>()
val severity = when (d.severity) {
KaSeverity.ERROR -> Severity.Error.sev
KaSeverity.WARNING -> Severity.Warn.sev
KaSeverity.INFO -> null
}
if (severity != null) {
val location = if (d.textRanges.isEmpty()) {
tw.getWholeFileLocation()
} else {
// We just use a random location from the set
tw.getLocation(file, d.textRanges.first())
}
tw.writeDiagnostics(
diagLabel,
"CodeQL Kotlin: Analysis API",
severity,
d.factoryName,
d.defaultMessage,
"",
location)
// TODO: We could try to link diagnostics to d.psi, but we
// don't have labels for lots of things. We'd either have
// to cache the labels, or extract diagnostics from all the
// element extractors.
}
}
println("--- End diagnostics")
}
// TODO: Common this up with TrapWriter's Location
private data class Location(val startLine: Int, val startColumn: Int, val endLine: Int, val endColumn: Int)
// TODO: Common this up with TrapWriter's getLocationInfo
private fun getLocationInfo(file: KtFile, range: TextRange): Location {
val document = file.getViewProvider().getDocument()
val start = range.getStartOffset()
val startLine0 = document.getLineNumber(start)
val startCol0 = start - document.getLineStartOffset(startLine0)
val end = range.getEndOffset()
val endLine0 = document.getLineNumber(end)
val endCol1 = end - document.getLineStartOffset(endLine0)
// TODO: unknown/synthetic locations?
return Location(startLine0 + 1, startCol0 + 1, endLine0 + 1, endCol1)
}
/*
OLD: KE1
private fun javaBinaryDeclaresMethod(c: IrClass, name: String) =

View File

@@ -4,7 +4,9 @@ package com.github.codeql
OLD: KE1
import com.github.codeql.KotlinUsesExtractor.LocallyVisibleFunctionLabels
*/
import com.intellij.openapi.util.TextRange
import com.intellij.psi.PsiElement
import com.intellij.psi.PsiFile
import com.semmle.extractor.java.PopulateFile
import com.semmle.util.unicode.UTF8Util
import org.jetbrains.kotlin.analysis.api.symbols.KaVariableSymbol
@@ -406,9 +408,8 @@ open class FileTrapWriter(
private data class Location(val startLine: Int, val startColumn: Int, val endLine: Int, val endColumn: Int)
private fun getLocationInfo(e: PsiElement): Location {
val range = e.getTextRange()
val document = e.getContainingFile().getViewProvider().getDocument()
private fun getLocationInfo(file: PsiFile, range: TextRange): Location {
val document = file.getViewProvider().getDocument()
val start = range.getStartOffset()
val startLine0 = document.getLineNumber(start)
val startCol0 = start - document.getLineStartOffset(startLine0)
@@ -420,11 +421,18 @@ open class FileTrapWriter(
}
/** Gets a label for the location of `e`. */
fun getLocation(e: PsiElement): Label<DbLocation> {
val loc = getLocationInfo(e)
fun getLocation(file: PsiFile, range: TextRange): Label<DbLocation> {
val loc = getLocationInfo(file, range)
return getLocation(fileId, loc.startLine, loc.startColumn, loc.endLine, loc.endColumn)
}
/** Gets a label for the location of `e`. */
fun getLocation(e: PsiElement): Label<DbLocation> {
val file = e.getContainingFile()
val range = e.getTextRange()
return getLocation(file, range)
}
/*
OLD: KE1
/** Gets a label for the location of `e`. */
@@ -447,7 +455,9 @@ open class FileTrapWriter(
* messages.
*/
/* TODO open */ fun getLocationString(e: PsiElement): String {
val loc = getLocationInfo(e)
val file = e.getContainingFile()
val range = e.getTextRange()
val loc = getLocationInfo(file, range)
return "file://$filePath:${loc.startLine}:${loc.startColumn}:${loc.endLine}:${loc.endColumn}"
/*

View File

@@ -226,7 +226,7 @@ class LoggerBase(val diagnosticCounter: DiagnosticCounter) : BasicLogger {
val diagLabel = dtw.getFreshIdLabel<DbDiagnostic>()
dtw.writeDiagnostics(
diagLabel,
"CodeQL Kotlin extractor",
"CodeQL Kotlin: PSI extractor",
severity.sev,
"",
msg,

View File

@@ -35,7 +35,10 @@ class Diagnostic extends @diagnostic {
*/
int getSeverity() { diagnostics(this, _, result, _, _, _, _) }
/** Gets the error code for this compiler message. */
/**
* Gets the error code for this compiler message.
* This is often the empty string.
*/
string getTag() { diagnostics(this, _, _, result, _, _, _) }
/** Holds if `s` is the error code for this compiler message. */