[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
@@ -16,6 +16,7 @@ import org.jetbrains.kotlin.fir.analysis.diagnostics.FirErrors
import java.io.Closeable
import java.io.File
import java.io.InputStreamReader
import java.util.TreeSet
object FirDiagnosticsCompilerResultsReporter {
fun reportToMessageCollector(
@@ -54,7 +55,23 @@ object FirDiagnosticsCompilerResultsReporter {
}
try {
for (diagnostic in diagnosticsCollector.diagnosticsByFilePath[filePath].orEmpty().sortedWith(InFileDiagnosticsComparator)) {
val diagnosticList = diagnosticsCollector.diagnosticsByFilePath[filePath].orEmpty()
// Precomputing positions of the offsets in the ascending order of the offsets
val offsetsToPositions = positionFinder.value?.let { finder ->
val sortedOffsets = TreeSet<Int>().apply {
for (diagnostic in diagnosticList) {
if (diagnostic !is KtPsiDiagnostic) {
val range = DiagnosticUtils.firstRange(diagnostic.textRanges)
add(range.startOffset)
add(range.endOffset)
}
}
}
sortedOffsets.associateWith { finder.findNextPosition(it) }
}
for (diagnostic in diagnosticList.sortedWith(InFileDiagnosticsComparator)) {
when (diagnostic) {
is KtPsiDiagnostic -> {
val file = diagnostic.element.psi.containingFile
@@ -68,11 +85,14 @@ object FirDiagnosticsCompilerResultsReporter {
// TODO: bring KtSourceFile and KtSourceFileLinesMapping here and rewrite reporting via it to avoid code duplication
// NOTE: SequentialPositionFinder relies on the ascending order of the input offsets, so the code relies
// on the the appropriate sorting above
// Also the end offset is ignored, as it is irrelevant for the CLI reporting
positionFinder.value?.findNextPosition(DiagnosticUtils.firstRange(diagnostic.textRanges).startOffset)
?.let { pos ->
MessageUtil.createMessageLocation(filePath, pos.lineContent, pos.line, pos.column, -1, -1)
}
offsetsToPositions?.let {
val range = DiagnosticUtils.firstRange(diagnostic.textRanges)
val start = offsetsToPositions[range.startOffset]!!
val end = offsetsToPositions[range.endOffset]!!
MessageUtil.createMessageLocation(
filePath, start.lineContent, start.line, start.column, end.line, end.column
)
}
}
}?.let { location ->
report(diagnostic, location)