[K2, CLI] Support endOffset in Kotlin CLI

Duplicated messages in testdata appeared because default renderer
renders diagnostic spans ambiguously. It shows only start position.
In fact, there are 3 failures, 2 of them distinguish only by the
diagnostic end offset. See youtrack for more information.

The issue about inconvenient rendering is KT-64989.

#KT-64608
This commit is contained in:
Evgeniy.Zhelenskiy
2024-01-12 03:08:09 +01:00
committed by Space Team
parent 6404cede07
commit f05c972efb
12 changed files with 154 additions and 28 deletions
@@ -5,6 +5,9 @@
package org.jetbrains.kotlin.cli
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSeverity
import org.jetbrains.kotlin.cli.common.messages.CompilerMessageSourceLocation
import org.jetbrains.kotlin.cli.common.messages.MessageRenderer
import org.jetbrains.kotlin.cli.jvm.K2JVMCompiler
import org.jetbrains.kotlin.test.CompilerTestUtil
import org.jetbrains.kotlin.test.TestCaseWithTmpdir
@@ -104,15 +107,78 @@ class CustomCliTest : TestCaseWithTmpdir() {
compileAndCheckMainClass(listOf(mainKt), expectedMainClass = null)
}
private fun compileAndCheckMainClass(sourceFiles: List<File>, expectedMainClass: String?) {
private fun makeCompilerArgs(sourceFiles: List<File>, jarFile: File): List<String> {
// TODO: remove explicit version after implementing main fun detector (KT-44557)
return listOf("-language-version", "1.9", "-include-runtime", "-d", jarFile.absolutePath) + sourceFiles.map { it.absolutePath }
}
private fun compileAndCheckMainClass(sourceFiles: List<File>, expectedMainClass: String?, messageRenderer: MessageRenderer? = null) {
val jarFile = tmpdir.resolve("output.jar")
// TODO: remove explicit verion after implementing main fun detector (KT-44557)
val args = listOf("-language-version", "1.9", "-include-runtime", "-d", jarFile.absolutePath) + sourceFiles.map { it.absolutePath }
CompilerTestUtil.executeCompilerAssertSuccessful(K2JVMCompiler(), args)
val args = makeCompilerArgs(sourceFiles, jarFile)
CompilerTestUtil.executeCompilerAssertSuccessful(K2JVMCompiler(), args, messageRenderer)
JarFile(jarFile).use {
val mainClassAttr = it.manifest.mainAttributes.getValue("Main-Class")
Assert.assertEquals(expectedMainClass, mainClassAttr)
}
}
private fun compileAndGetDiagnostics(sourceFiles: List<File>): List<Diagnostic> {
val jarFile = tmpdir.resolve("output.jar")
val args = makeCompilerArgs(sourceFiles, jarFile)
val diagnostics = mutableListOf<Diagnostic>()
CompilerTestUtil.executeCompiler(K2JVMCompiler(), args, LoggingMessageRenderer(diagnostics))
return diagnostics
}
private data class Diagnostic(
val severity: CompilerMessageSeverity,
val message: String,
val location: CompilerMessageSourceLocation?
)
private class LoggingMessageRenderer(val diagnostics: MutableList<Diagnostic>) : MessageRenderer {
override fun renderPreamble(): String = ""
override fun render(
severity: CompilerMessageSeverity,
message: String,
location: CompilerMessageSourceLocation?
): String {
diagnostics.add(Diagnostic(severity, message, location))
return ""
}
override fun renderUsage(usage: String): String =
render(CompilerMessageSeverity.STRONG_WARNING, usage, null)
override fun renderConclusion(): String = ""
override fun getName(): String = "Redirector"
}
fun testDiagnosticRanges() {
val mainKt = tmpdir.resolve("main.kt").apply {
val quotes = "\"".repeat(3)
writeText(
"""
|fun main(args: Array<String>) {
| val x: Int = $quotes
| some
| multiline
| string
| $quotes
|}""".trimMargin()
)
}
val diagnostics = compileAndGetDiagnostics(listOf(mainKt))
require(diagnostics.size == 1) { "Expected 1 diagnostic, but found ${diagnostics.size}:\n${diagnostics.joinToString("\n")}" }
val diagnostic = diagnostics.single()
assertEquals(2, diagnostic.location?.line)
assertEquals(18, diagnostic.location?.column)
assertEquals(6, diagnostic.location?.lineEnd)
assertEquals(8, diagnostic.location?.columnEnd)
}
}