Kotlin: Give context to diagnostics

We now get e.g.

[2022-03-09 13:59:04 K] [ERROR] Diagnostic(com.github.codeql.KotlinUsesExtractor.useSimpleType(KotlinUsesExtractor.kt:505)): Type alias ignored for <root>.Test<kotlin.String>{ <root>.Alias1<kotlin.String> }
  ...while extracting a function at file:///home/ian/code/dev/ql/java/ql/test/kotlin/library-tests/type_aliases/aliases_with_type_parameters.kt:7:1:7:41
  ...while extracting a function if real at file:///home/ian/code/dev/ql/java/ql/test/kotlin/library-tests/type_aliases/aliases_with_type_parameters.kt:7:1:7:41
  ...while extracting a declaration at file:///home/ian/code/dev/ql/java/ql/test/kotlin/library-tests/type_aliases/aliases_with_type_parameters.kt:7:1:7:41
  ...while extracting a file at file:///home/ian/code/dev/ql/java/ql/test/kotlin/library-tests/type_aliases/aliases_with_type_parameters.kt:1:1:8:0
This commit is contained in:
Ian Lynagh
2022-03-09 14:00:32 +00:00
parent a7e6ec9d02
commit 43a92f60b2
3 changed files with 22 additions and 9 deletions

View File

@@ -9,7 +9,6 @@ import java.io.File
import java.io.FileOutputStream
import java.nio.file.Files
import java.nio.file.Paths
import java.util.Stack
import com.semmle.util.files.FileUtil
import kotlin.system.exitProcess
@@ -121,8 +120,6 @@ class KotlinExtractorExtension(
}
}
data class ExtractorContext(val kind: String, val element: IrElement)
class KotlinExtractorGlobalState {
val genericSpecialisationsExtracted = HashSet<String>()
// These three record mappings of classes, functions and fields that should be replaced wherever they are found.
@@ -132,8 +129,6 @@ class KotlinExtractorGlobalState {
val syntheticToRealClassMap = HashMap<IrClass, IrClass?>()
val syntheticToRealFunctionMap = HashMap<IrSimpleFunction, IrSimpleFunction?>()
val syntheticToRealFieldMap = HashMap<IrField, IrField?>()
// TODO: This could be less global; it's really per-file
val context = Stack<ExtractorContext>()
}
/*

View File

@@ -40,9 +40,10 @@ open class KotlinFileExtractor(
inline fun <T> with(kind: String, element: IrElement, f: () -> T): T {
val loc = tw.getLocationString(element)
globalExtensionState.context.push(ExtractorContext(kind, element))
val context = logger.loggerBase.extractorContextStack
context.push(ExtractorContext(kind, element, loc))
try {
val depth = globalExtensionState.context.size
val depth = context.size
val depthDescription = "${"-".repeat(depth)} (${depth.toString()})"
val name = (element as? IrDeclarationWithName)?.name?.asString() ?: "<no name>"
logger.trace("$depthDescription: Starting a $kind ($name) at $loc")
@@ -52,7 +53,7 @@ open class KotlinFileExtractor(
} catch(exception: Exception) {
throw Exception("While extracting a $kind at $loc", exception)
} finally {
globalExtensionState.context.pop()
context.pop()
}
}

View File

@@ -6,6 +6,7 @@ import java.io.OutputStreamWriter
import java.io.Writer
import java.text.SimpleDateFormat
import java.util.Date
import java.util.Stack
import org.jetbrains.kotlin.ir.IrElement
class LogCounter() {
@@ -32,7 +33,11 @@ enum class Severity(val sev: Int) {
ErrorGlobal(8)
}
data class ExtractorContext(val kind: String, val element: IrElement, val loc: String)
open class LoggerBase(val logCounter: LogCounter) {
val extractorContextStack = Stack<ExtractorContext>()
private val verbosity: Int
init {
verbosity = System.getenv("CODEQL_EXTRACTOR_KOTLIN_VERBOSITY")?.toIntOrNull() ?: 3
@@ -85,7 +90,19 @@ open class LoggerBase(val logCounter: LogCounter) {
else -> ""
}
}
val fullMsg = "$msg\n$extraInfoStr$suffix"
val fullMsgBuilder = StringBuilder()
fullMsgBuilder.append(msg)
fullMsgBuilder.append('\n')
fullMsgBuilder.append(extraInfoStr)
val iter = extractorContextStack.listIterator(extractorContextStack.size)
while (iter.hasPrevious()) {
val x = iter.previous()
fullMsgBuilder.append(" ...while extracting a ${x.kind} at ${x.loc}\n")
}
fullMsgBuilder.append(suffix)
val fullMsg = fullMsgBuilder.toString()
val ts = timestamp()
// We don't actually make the location until after the `return` above
val locationId = mkLocationId()