Tests: fix handling of diag.txt files in diagnostic tests with backend

Also take into account diagnostics reported via
GenerationState.collectedExtraJvmDiagnostics, and render them in the
similar format to KtDiagnostic.

Don't make the test pass if the reported list of diagnostics is empty,
because that defeats the purpose of the test.
This commit is contained in:
Alexander Udalov
2023-06-24 01:05:24 +02:00
committed by Space Team
parent a17cdfe338
commit b03e50129e
4 changed files with 38 additions and 43 deletions
@@ -1,6 +1,3 @@
/indirectInlineCycle_ir.kt:8:24: error: the 'inlineFun2' invocation is a part of inline cycle /indirectInlineCycle_ir.kt:6:24: error: The 'inlineFun2' invocation is a part of inline cycle
fun method() { inlineFun2(p) }
^ /indirectInlineCycle_ir.kt:11:5: error: The 'inlineFun1' invocation is a part of inline cycle
/indirectInlineCycle_ir.kt:13:5: error: the 'inlineFun1' invocation is a part of inline cycle
inlineFun1(p)
^
@@ -1,6 +1,3 @@
/inlineCycle_ir.kt:8:5: error: the 'inlineFun2' invocation is a part of inline cycle /inlineCycle_ir.kt:6:5: error: The 'inlineFun2' invocation is a part of inline cycle
inlineFun2(p)
^ /inlineCycle_ir.kt:11:5: error: The 'inlineFun1' invocation is a part of inline cycle
/inlineCycle_ir.kt:13:5: error: the 'inlineFun1' invocation is a part of inline cycle
inlineFun1(p)
^
@@ -1,6 +1,3 @@
/suspendInlineCycle_ir.kt:8:5: error: the 'inlineFun2' invocation is a part of inline cycle /suspendInlineCycle_ir.kt:6:5: error: The 'inlineFun2' invocation is a part of inline cycle
inlineFun2(p)
^ /suspendInlineCycle_ir.kt:11:5: error: The 'inlineFun1' invocation is a part of inline cycle
/suspendInlineCycle_ir.kt:13:5: error: the 'inlineFun1' invocation is a part of inline cycle
inlineFun1(p)
^
@@ -5,18 +5,21 @@
package org.jetbrains.kotlin.test.backend.handlers package org.jetbrains.kotlin.test.backend.handlers
import com.intellij.openapi.util.TextRange
import com.intellij.openapi.util.io.FileUtil import com.intellij.openapi.util.io.FileUtil
import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport import org.jetbrains.kotlin.cli.common.messages.AnalyzerWithCompilerReport
import org.jetbrains.kotlin.codeMetaInfo.model.DiagnosticCodeMetaInfo
import org.jetbrains.kotlin.diagnostics.DiagnosticUtils import org.jetbrains.kotlin.diagnostics.DiagnosticUtils
import org.jetbrains.kotlin.diagnostics.KtDiagnostic import org.jetbrains.kotlin.diagnostics.Severity
import org.jetbrains.kotlin.diagnostics.PsiDiagnosticUtils
import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector import org.jetbrains.kotlin.diagnostics.impl.BaseDiagnosticsCollector
import org.jetbrains.kotlin.diagnostics.rendering.DefaultErrorMessages
import org.jetbrains.kotlin.fir.psi import org.jetbrains.kotlin.fir.psi
import org.jetbrains.kotlin.psi.KtFile import org.jetbrains.kotlin.psi.KtFile
import org.jetbrains.kotlin.resolve.jvm.diagnostics.KtDefaultJvmErrorMessages import org.jetbrains.kotlin.resolve.jvm.diagnostics.KtDefaultJvmErrorMessages
import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives import org.jetbrains.kotlin.test.directives.DiagnosticsDirectives
import org.jetbrains.kotlin.test.frontend.classic.handlers.ClassicDiagnosticReporter import org.jetbrains.kotlin.test.frontend.classic.handlers.ClassicDiagnosticReporter
import org.jetbrains.kotlin.test.frontend.classic.handlers.withNewInferenceModeEnabled import org.jetbrains.kotlin.test.frontend.classic.handlers.withNewInferenceModeEnabled
import org.jetbrains.kotlin.test.frontend.fir.handlers.FirDiagnosticCodeMetaInfo
import org.jetbrains.kotlin.test.frontend.fir.handlers.toMetaInfos import org.jetbrains.kotlin.test.frontend.fir.handlers.toMetaInfos
import org.jetbrains.kotlin.test.model.BinaryArtifacts import org.jetbrains.kotlin.test.model.BinaryArtifacts
import org.jetbrains.kotlin.test.model.FrontendKinds import org.jetbrains.kotlin.test.model.FrontendKinds
@@ -35,7 +38,7 @@ class JvmBackendDiagnosticsHandler(testServices: TestServices) : JvmBinaryArtifa
override fun processModule(module: TestModule, info: BinaryArtifacts.Jvm) { override fun processModule(module: TestModule, info: BinaryArtifacts.Jvm) {
reportDiagnostics(module, info) reportDiagnostics(module, info)
reportKtDiagnostics(module, info) reportKtDiagnostics(module, info)
checkFullDiagnosticRender(module, info) checkFullDiagnosticRender(module)
} }
private fun getKtFiles(module: TestModule): Map<TestFile, KtFile> { private fun getKtFiles(module: TestModule): Map<TestFile, KtFile> {
@@ -49,12 +52,6 @@ class JvmBackendDiagnosticsHandler(testServices: TestServices) : JvmBinaryArtifa
override fun processAfterAllModules(someAssertionWasFailed: Boolean) {} override fun processAfterAllModules(someAssertionWasFailed: Boolean) {}
private fun getLineAndColumnRange(diagnostic: KtDiagnostic): PsiDiagnosticUtils.LineAndColumnRange {
val file = diagnostic.psiElement.containingFile
val textRanges = diagnostic.textRanges
return DiagnosticUtils.getLineAndColumnRange(file, textRanges)
}
private fun reportDiagnostics(module: TestModule, info: BinaryArtifacts.Jvm) { private fun reportDiagnostics(module: TestModule, info: BinaryArtifacts.Jvm) {
val testFileToKtFileMap = getKtFiles(module) val testFileToKtFileMap = getKtFiles(module)
val ktFileToTestFileMap = testFileToKtFileMap.entries.associate { it.value to it.key } val ktFileToTestFileMap = testFileToKtFileMap.entries.associate { it.value to it.key }
@@ -86,29 +83,36 @@ class JvmBackendDiagnosticsHandler(testServices: TestServices) : JvmBinaryArtifa
} }
} }
private fun checkFullDiagnosticRender(module: TestModule, info: BinaryArtifacts.Jvm) { private fun checkFullDiagnosticRender(module: TestModule) {
if (DiagnosticsDirectives.RENDER_DIAGNOSTICS_FULL_TEXT !in module.directives) return if (DiagnosticsDirectives.RENDER_DIAGNOSTICS_FULL_TEXT !in module.directives) return
val testFileToKtFileMap = getKtFiles(module) val testFileToKtFileMap = getKtFiles(module)
val generationState = info.classFileFactory.generationState
val ktDiagnosticReporter = generationState.diagnosticReporter as BaseDiagnosticsCollector
val reportedDiagnostics = mutableListOf<String>() val reportedDiagnostics = mutableListOf<String>()
for (ktFile in testFileToKtFileMap.values) { for ((testFile, ktFile) in testFileToKtFileMap) {
val ktDiagnostics = ktDiagnosticReporter.diagnosticsByFilePath[ktFile.virtualFilePath] ?: continue for (metaInfo in testServices.globalMetadataInfoHandler.getReportedMetaInfosForFile(testFile).sortedBy { it.start }) {
ktDiagnostics.forEach { when (metaInfo) {
val severity = AnalyzerWithCompilerReport.convertSeverity(it.severity).toString().toLowerCaseAsciiOnly() is DiagnosticCodeMetaInfo -> metaInfo.diagnostic.let {
val message = KtDefaultJvmErrorMessages.MAP[it.factory]?.render(it) val message = DefaultErrorMessages.render(it)
val position = getLineAndColumnRange(it).start reportedDiagnostics += renderDiagnosticMessage(ktFile, it.severity, message, it.textRanges)
reportedDiagnostics += "/${ktFile.name}:${position.line}:${position.column}: $severity: $message" }
is FirDiagnosticCodeMetaInfo -> metaInfo.diagnostic.let {
val message = KtDefaultJvmErrorMessages.MAP[it.factory]?.render(it)
reportedDiagnostics += renderDiagnosticMessage(ktFile, it.severity, message, it.textRanges)
}
}
} }
} }
if (reportedDiagnostics.isNotEmpty()) { testServices.assertions.assertEqualsToFile(
testServices.assertions.assertEqualsToFile( File(FileUtil.getNameWithoutExtension(testFileToKtFileMap.keys.first().originalFile.absolutePath) + ".diag.txt"),
File(FileUtil.getNameWithoutExtension(testFileToKtFileMap.keys.first().originalFile.absolutePath) + ".diag.txt"), reportedDiagnostics.joinToString(separator = "\n\n", postfix = "\n")
reportedDiagnostics.joinToString(separator = "\n\n") )
) }
}
private fun renderDiagnosticMessage(file: KtFile, severity: Severity, message: String?, textRanges: List<TextRange>): String {
val severityString = AnalyzerWithCompilerReport.convertSeverity(severity).toString().toLowerCaseAsciiOnly()
val position = DiagnosticUtils.getLineAndColumnRange(file, textRanges).start
return "/${file.name}:${position.line}:${position.column}: $severityString: $message"
} }
} }