From 94bf38a7b554c8ea6c0c80995ad6418d40775a57 Mon Sep 17 00:00:00 2001 From: Alexander Dudinsky Date: Sat, 10 Oct 2020 10:05:03 +0300 Subject: [PATCH] Added support for various platforms for CodeMetaInfo tests. ^KT-41996 The tests need to be able to parse and render CodeMetaInfo for different platforms. For example, we must draw a run gutter a MAC application on OSX, but for a Win application, the gutter should not be drawn at the same time. This commit allows to do such checks. In order to indicate on which platform it should be rendered, it is necessary to specify the platform for a specific CodeMetaInfo in the test data in the format {OSX,Unix,Win}, if the block with platforms is missing, this means that it should be rendered on each platform. - should only be on OSX - should be on any platform --- .../kotlin/checkers/utils/CheckerTestUtil.kt | 2 +- .../codeMetaInfo/AbstractCodeMetaInfoTest.kt | 70 ++++++---- .../idea/codeMetaInfo/CodeMetaInfoParser.kt | 65 ++++++++++ .../idea/codeMetaInfo/CodeMetaInfoRenderer.kt | 53 +++----- .../idea/codeMetaInfo/models/CodeMetaInfo.kt | 122 ++++++++++-------- ...AbstractCodeMetaInfoRenderConfiguration.kt | 54 ++++---- 6 files changed, 226 insertions(+), 140 deletions(-) create mode 100644 idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoParser.kt diff --git a/compiler/frontend/src/org/jetbrains/kotlin/checkers/utils/CheckerTestUtil.kt b/compiler/frontend/src/org/jetbrains/kotlin/checkers/utils/CheckerTestUtil.kt index f26b939d807..8c50415868d 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/checkers/utils/CheckerTestUtil.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/checkers/utils/CheckerTestUtil.kt @@ -60,7 +60,7 @@ object CheckerTestUtil { const val OLD_INFERENCE_PREFIX = "OI" private const val IGNORE_DIAGNOSTIC_PARAMETER = "IGNORE" - private const val INDIVIDUAL_DIAGNOSTIC = """(\w+;)?(\w+:)?(\w+)(?:\(((?:".*?")(?:,\s*".*?")*)\))?""" + private const val INDIVIDUAL_DIAGNOSTIC = """(\w+;)?(\w+:)?(\w+)(\{[\w;]+})?(?:\(((?:".*?")(?:,\s*".*?")*)\))?""" val rangeStartOrEndPattern = Pattern.compile("()|()") val individualDiagnosticPattern: Pattern = Pattern.compile(INDIVIDUAL_DIAGNOSTIC) diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt index 4dd3922b15a..b82e39a2f52 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt @@ -32,13 +32,12 @@ import org.jetbrains.kotlin.checkers.BaseDiagnosticsTest import org.jetbrains.kotlin.checkers.diagnostics.SyntaxErrorDiagnostic import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil import org.jetbrains.kotlin.checkers.utils.DiagnosticsRenderingConfiguration +import org.jetbrains.kotlin.daemon.common.OSKind import org.jetbrains.kotlin.descriptors.impl.ModuleDescriptorImpl import org.jetbrains.kotlin.diagnostics.AbstractDiagnostic +import org.jetbrains.kotlin.diagnostics.Severity import org.jetbrains.kotlin.idea.caches.resolve.getResolutionFacade -import org.jetbrains.kotlin.idea.codeMetaInfo.models.CodeMetaInfoFactory -import org.jetbrains.kotlin.idea.codeMetaInfo.models.DiagnosticCodeMetaInfo -import org.jetbrains.kotlin.idea.codeMetaInfo.models.HighlightingCodeMetaInfo -import org.jetbrains.kotlin.idea.codeMetaInfo.models.ICodeMetaInfo +import org.jetbrains.kotlin.idea.codeMetaInfo.models.* import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.AbstractCodeMetaInfoRenderConfiguration import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.DiagnosticCodeMetaInfoRenderConfiguration import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.HighlightingRenderConfiguration @@ -53,12 +52,15 @@ import org.jetbrains.kotlin.test.KotlinTestUtils import java.io.File import java.nio.file.Paths -class CodeMetaInfoTestCase(val codeMetaInfoTypes: Collection) : DaemonAnalyzerTestCase() { +class CodeMetaInfoTestCase( + val codeMetaInfoTypes: Collection, + val checkNoDiagnosticError: Boolean = false +) : DaemonAnalyzerTestCase() { fun getDiagnosticCodeMetaInfos( - configuration: DiagnosticCodeMetaInfoRenderConfiguration?, + configuration: DiagnosticCodeMetaInfoRenderConfiguration = DiagnosticCodeMetaInfoRenderConfiguration(), parseDirective: Boolean = true - ): Collection { + ): List { val tempSourceKtFile = PsiManager.getInstance(project).findFile(file.virtualFile) as KtFile val resolutionFacade = tempSourceKtFile.getResolutionFacade() val (bindingContext, moduleDescriptor) = resolutionFacade.analyzeWithAllCompilerChecks(listOf(tempSourceKtFile)) @@ -77,23 +79,23 @@ class CodeMetaInfoTestCase(val codeMetaInfoTypes: Collection { + fun getLineMarkerCodeMetaInfos(configuration: LineMarkerRenderConfiguration): Collection { if ("!CHECK_HIGHLIGHTING" in file.text) return emptyList() CodeInsightTestFixtureImpl.instantiateAndRun(file, editor, TIntArrayList().toNativeArray(), false) val lineMarkers = DaemonCodeAnalyzerImpl.getLineMarkers(getDocument(file), project) - return CodeMetaInfoFactory.getCodeMetaInfo(lineMarkers, configuration) + return getCodeMetaInfo(lineMarkers, configuration) } - fun getHighlightingCodeMetaInfos(configuration: HighlightingRenderConfiguration?): Collection { + fun getHighlightingCodeMetaInfos(configuration: HighlightingRenderConfiguration): Collection { val infos = CodeInsightTestFixtureImpl.instantiateAndRun(file, editor, TIntArrayList().toNativeArray(), false) - return CodeMetaInfoFactory.getCodeMetaInfo(infos, configuration) + return getCodeMetaInfo(infos, configuration) } fun checkFile(expectedFile: File, project: Project, editor: Editor) { @@ -113,8 +115,7 @@ class CodeMetaInfoTestCase(val codeMetaInfoTypes: Collection() + val codeMetaInfoForCheck = mutableListOf() PsiDocumentManager.getInstance(myProject).commitAllDocuments() //to load text @@ -144,22 +145,46 @@ class CodeMetaInfoTestCase(val codeMetaInfoTypes: Collection() + getDiagnosticCodeMetaInfos(DiagnosticCodeMetaInfoRenderConfiguration(), false).filterIsInstance() ) } - + val parsedMetaInfo = CodeMetaInfoParser.getCodeMetaInfoFromText(expectedFile.readText()).toMutableList() + codeMetaInfoForCheck.forEach { codeMetaInfo -> + val correspondingParsed = parsedMetaInfo.firstOrNull { it == codeMetaInfo } + if (correspondingParsed != null) { + parsedMetaInfo.remove(correspondingParsed) + codeMetaInfo.platforms.addAll(correspondingParsed.platforms) + if (correspondingParsed.platforms.isNotEmpty() && OSKind.current.toString() !in correspondingParsed.platforms) + codeMetaInfo.platforms.add(OSKind.current.toString()) + } + } + if (parsedMetaInfo.isNotEmpty()) + parsedMetaInfo.forEach { + if (it.platforms.isNotEmpty() && OSKind.current.toString() !in it.platforms) codeMetaInfoForCheck.add( + it + ) + } val textWithCodeMetaInfo = CodeMetaInfoRenderer.renderTagsToText(codeMetaInfoForCheck, myEditor.document.text) KotlinTestUtils.assertEqualsToFile( expectedFile, textWithCodeMetaInfo.toString() ) + + if (checkNoDiagnosticError) { + val diagnosticsErrors = + getDiagnosticCodeMetaInfos().filter { (it as DiagnosticCodeMetaInfo).diagnostic.severity == Severity.ERROR } + assertTrue( + "Diagnostics with severity ERROR were found: ${diagnosticsErrors.joinToString { it.asString() }}", + diagnosticsErrors.isEmpty() + ) + } } private fun checkHighlightErrorItemsInDiagnostics( diagnostics: Collection ) { - val highlightItems: List = - getHighlightingCodeMetaInfos(null).filter { (it as HighlightingCodeMetaInfo).highlightingInfo.severity == HighlightSeverity.ERROR } + val highlightItems: List = + getHighlightingCodeMetaInfos(HighlightingRenderConfiguration()).filter { (it as HighlightingCodeMetaInfo).highlightingInfo.severity == HighlightSeverity.ERROR } highlightItems.forEach { highlightingCodeMetaInfo -> assert( @@ -201,7 +226,7 @@ abstract class AbstractHighlightingCodeMetaInfoTest : AbstractCodeMetaInfoTest() } abstract class AbstractCodeMetaInfoTest : AbstractMultiModuleTest() { - + open val checkNoDiagnosticError get() = false open fun getConfigurations() = listOf( DiagnosticCodeMetaInfoRenderConfiguration(), LineMarkerRenderConfiguration(), @@ -218,7 +243,7 @@ abstract class AbstractCodeMetaInfoTest : AbstractMultiModuleTest() { fun doTest(testDataPath: String) { val testRoot = File(testDataPath) - val checker = CodeMetaInfoTestCase(getConfigurations()) + val checker = CodeMetaInfoTestCase(getConfigurations(), checkNoDiagnosticError) setupProject(testDataPath) for (module in ModuleManager.getInstance(project).modules) { @@ -237,16 +262,13 @@ abstract class AbstractCodeMetaInfoTest : AbstractMultiModuleTest() { val tempRootPath = Paths.get(containingRoot.path) val tempProjectDirPath = tempRootPath.parent val tempSourcePath = Paths.get(path) - val relativeToProjectRootPath = tempProjectDirPath.relativize(tempSourcePath) - val testSourcesProjectDirPath = testDir.toPath() val testSourcePath = testSourcesProjectDirPath.resolve(relativeToProjectRootPath) require(testSourcePath.exists()) { "Can't find file in testdata for copied file $this: checked at path ${testSourcePath.toAbsolutePath()}" } - return testSourcePath.toFile() } } \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoParser.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoParser.kt new file mode 100644 index 00000000000..0888b5b084e --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoParser.kt @@ -0,0 +1,65 @@ +/* + * Copyright 2010-2020 JetBrains s.r.o. and Kotlin Programming Language contributors. + * Use of this source code is governed by the Apache 2.0 license that can be found in the license/LICENSE.txt file. + */ + +package org.jetbrains.kotlin.idea.codeMetaInfo + +import com.intellij.util.containers.Stack +import org.jetbrains.kotlin.idea.codeMetaInfo.models.ParsedCodeMetaInfo +import org.junit.Assert + +object CodeMetaInfoParser { + private val openingRegex = "(]+?)!>)".toRegex() + private val closingRegex = "()".toRegex() + + private val descriptionRegex = "\\(\".*?\"\\)".toRegex() + private val platformRegex = "\\{(.+)}".toRegex() + + fun getCodeMetaInfoFromText(renderedText: String): List { + var text = renderedText + val openingMatchResults = Stack() + val closingMatchResults = Stack() + val result = mutableListOf() + + while (true) { + var openingStartOffset = Int.MAX_VALUE + var closingStartOffset = Int.MAX_VALUE + val opening = openingRegex.find(text) + val closing = closingRegex.find(text) + if (opening == null && closing == null) break + + if (opening != null) + openingStartOffset = opening.range.first + if (closing != null) + closingStartOffset = closing.range.first + + text = if (openingStartOffset < closingStartOffset) { + openingMatchResults.push(opening) + text.removeRange(openingStartOffset, opening!!.range.last + 1) + } else { + closingMatchResults.push(closing) + text.removeRange(closingStartOffset, closing!!.range.last + 1) + } + } + if (openingMatchResults.size != closingMatchResults.size) { + Assert.fail("Opening and closing tags counts are not equals") + } + while (!openingMatchResults.isEmpty()) { + val openingMatchResult = openingMatchResults.pop() + val closingMatchResult = closingMatchResults.pop() + val metaInfoWithoutParams = openingMatchResult.groups[2]!!.value.replace(descriptionRegex, "") + metaInfoWithoutParams.split(",").forEach { + val tag = platformRegex.replace(it, "").trim() + val platforms = + if (platformRegex.containsMatchIn(it)) platformRegex.find(it)!!.destructured.component1().split(";") else listOf() + result.add( + ParsedCodeMetaInfo( + openingMatchResult.range.first, closingMatchResult.range.first, platforms.toMutableList(), tag, + ) + ) + } + } + return result + } +} \ No newline at end of file diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoRenderer.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoRenderer.kt index 326bfb18b04..a1f6da6e64f 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoRenderer.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoRenderer.kt @@ -7,13 +7,12 @@ package org.jetbrains.kotlin.idea.codeMetaInfo import com.intellij.util.containers.Stack import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil -import org.jetbrains.kotlin.idea.codeMetaInfo.models.ICodeMetaInfo +import org.jetbrains.kotlin.idea.codeMetaInfo.models.CodeMetaInfo import java.io.File object CodeMetaInfoRenderer { - fun renderTagsToText( - codeMetaInfos: List, + codeMetaInfos: List, originalText: String ): StringBuffer { val result = StringBuffer() @@ -22,25 +21,18 @@ object CodeMetaInfoRenderer { return result } val sortedMetaInfos = getSortedCodeMetaInfos(codeMetaInfos) - val opened = Stack() + val opened = Stack() - for (i in originalText.indices) { - val c = originalText[i] - var prev: ICodeMetaInfo? = null - - while (!opened.isEmpty() && i == opened.peek().end) { - if (prev == null || prev.start != opened.peek().start) - closeString(result) - prev = opened.pop() - } - if (sortedMetaInfos.any { it.start == i }) { + for ((i, c) in originalText.withIndex()) { + checkOpenedAndCloseStringIfNeeded(opened, i, result) + val matchedCodeMetaInfos = sortedMetaInfos.filter { it.start == i } + if (matchedCodeMetaInfos.isNotEmpty()) { openStartTag(result) - val matchedCodeMetaInfos = sortedMetaInfos.filter { it.start == i }.toMutableList() val iterator = matchedCodeMetaInfos.listIterator() - var current: ICodeMetaInfo? = iterator.next() + var current: CodeMetaInfo? = iterator.next() while (current != null) { - val next: ICodeMetaInfo? = if (iterator.hasNext()) iterator.next() else null + val next: CodeMetaInfo? = if (iterator.hasNext()) iterator.next() else null opened.push(current) result.append(current.asString()) when { @@ -56,30 +48,27 @@ object CodeMetaInfoRenderer { } result.append(c) } - var prev: ICodeMetaInfo? = null - - while (!opened.isEmpty() && originalText.length == opened.peek().end) { - if (prev == null || prev.start != opened.peek().start) - closeString(result) - prev = opened.pop() - } + checkOpenedAndCloseStringIfNeeded(opened, originalText.length, result) return result } - private fun getSortedCodeMetaInfos( - metaInfos: Collection, - ): MutableList { - val result = metaInfos.toMutableList() - result.sortWith(Comparator { d1: ICodeMetaInfo, d2: ICodeMetaInfo -> - if (d1.start != d2.start) d1.start - d2.start else d2.end - d1.end - }) - return result + private fun getSortedCodeMetaInfos(metaInfos: Collection): List { + return metaInfos.sortedWith(compareBy { it.start }.then(compareByDescending { it.end })) } private fun closeString(result: StringBuffer) = result.append("") private fun openStartTag(result: StringBuffer) = result.append("") private fun closeStartAndOpenNewTag(result: StringBuffer) = result.append("!>, end: Int, result: StringBuffer) { + var prev: CodeMetaInfo? = null + while (!opened.isEmpty() && end == opened.peek().end) { + if (prev == null || prev.start != opened.peek().start) + closeString(result) + prev = opened.pop() + } + } } fun clearFileFromDiagnosticMarkup(file: File) { diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/CodeMetaInfo.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/CodeMetaInfo.kt index 2e5fea44887..8e483721a5a 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/CodeMetaInfo.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/CodeMetaInfo.kt @@ -16,91 +16,103 @@ import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.LineMarkerRen import org.jetbrains.kotlin.idea.editor.fixers.end import org.jetbrains.kotlin.idea.editor.fixers.start -interface ICodeMetaInfo { - +interface CodeMetaInfo { val start: Int val end: Int - val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration? + val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration + val platforms: MutableList fun asString(): String + fun getTag(): String } class DiagnosticCodeMetaInfo( override val start: Int, override val end: Int, - override val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration?, + override val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration, val diagnostic: Diagnostic -) : - ICodeMetaInfo { +) : CodeMetaInfo { + override val platforms: MutableList = mutableListOf() - override fun asString(): String { - return renderConfiguration!!.asString(this) - } + override fun asString() = renderConfiguration.asString(this) + + override fun getTag() = (renderConfiguration as DiagnosticCodeMetaInfoRenderConfiguration).getTag(this) } class LineMarkerCodeMetaInfo( - override val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration?, + override val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration, val lineMarker: LineMarkerInfo<*> -) : ICodeMetaInfo { - +) : CodeMetaInfo { override val start: Int get() = lineMarker.startOffset override val end: Int get() = lineMarker.endOffset + override val platforms: MutableList = mutableListOf() - val withDescription = true + override fun asString() = renderConfiguration.asString(this) - override fun asString(): String { - return renderConfiguration!!.asString(this) - } + override fun getTag() = (renderConfiguration as LineMarkerRenderConfiguration).getTag() } class HighlightingCodeMetaInfo( - override val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration?, + override val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration, val highlightingInfo: HighlightInfo -) : ICodeMetaInfo { - +) : CodeMetaInfo { override val start: Int get() = highlightingInfo.startOffset override val end: Int get() = highlightingInfo.endOffset + override val platforms: MutableList = mutableListOf() - override fun asString(): String { - return renderConfiguration!!.asString(this) + override fun asString() = renderConfiguration.asString(this) + + override fun getTag() = (renderConfiguration as HighlightingRenderConfiguration).getTag() +} + +class ParsedCodeMetaInfo( + override val start: Int, + override val end: Int, + override val platforms: MutableList, + private val tag: String +) : CodeMetaInfo { + override val renderConfiguration = object : AbstractCodeMetaInfoRenderConfiguration(false) {} + + override fun asString() = renderConfiguration.asString(this) + + override fun equals(other: Any?): Boolean { + if (other == null || other !is CodeMetaInfo) return false + return this.tag == other.getTag() && this.start == other.start && this.end == other.end + } + + override fun getTag() = tag +} + +fun createCodeMetaInfo(obj: Any, renderConfiguration: AbstractCodeMetaInfoRenderConfiguration): List { + fun errorMessage() = "Unexpected render configuration for object $obj" + return when (obj) { + is Diagnostic -> { + require(renderConfiguration is DiagnosticCodeMetaInfoRenderConfiguration, ::errorMessage) + obj.textRanges.map { DiagnosticCodeMetaInfo(it.start, it.end, renderConfiguration, obj) } + } + is ActualDiagnostic -> { + require(renderConfiguration is DiagnosticCodeMetaInfoRenderConfiguration, ::errorMessage) + obj.diagnostic.textRanges.map { DiagnosticCodeMetaInfo(it.start, it.end, renderConfiguration, obj.diagnostic) } + } + is HighlightInfo -> { + require(renderConfiguration is HighlightingRenderConfiguration, ::errorMessage) + listOf(HighlightingCodeMetaInfo(renderConfiguration, obj)) + } + is LineMarkerInfo<*> -> { + require(renderConfiguration is LineMarkerRenderConfiguration, ::errorMessage) + listOf(LineMarkerCodeMetaInfo(renderConfiguration, obj)) + } + else -> throw IllegalArgumentException("Unknown type for creating CodeMetaInfo object $obj") } } -object CodeMetaInfoFactory { - private fun createCodeMetaInfo(obj: Any, renderConfiguration: AbstractCodeMetaInfoRenderConfiguration?): Collection { - return when (obj) { - is Diagnostic -> { - if (renderConfiguration != null && renderConfiguration !is DiagnosticCodeMetaInfoRenderConfiguration) - throw IllegalArgumentException("Unexpected render configuration for CodeMetaInfo object $obj") - obj.textRanges.map { DiagnosticCodeMetaInfo(it.start, it.end, renderConfiguration, obj) } - } - is ActualDiagnostic -> { - if (renderConfiguration != null && renderConfiguration !is DiagnosticCodeMetaInfoRenderConfiguration) - throw IllegalArgumentException("Unexpected render configuration for CodeMetaInfo object $obj") - obj.diagnostic.textRanges.map { DiagnosticCodeMetaInfo(it.start, it.end, renderConfiguration, obj.diagnostic) } - } - is HighlightInfo -> { - if (renderConfiguration != null && renderConfiguration !is HighlightingRenderConfiguration) - throw IllegalArgumentException("Unexpected render configuration for CodeMetaInfo object $obj") - listOf(HighlightingCodeMetaInfo(renderConfiguration, obj)) - } - is LineMarkerInfo<*> -> { - if (renderConfiguration != null && renderConfiguration !is LineMarkerRenderConfiguration) - throw IllegalArgumentException("Unexpected render configuration for CodeMetaInfo object $obj") - listOf(LineMarkerCodeMetaInfo(renderConfiguration, obj)) - } - else -> throw IllegalArgumentException("Unknown type for creating CodeMetaInfo object $obj") - } - } - - fun getCodeMetaInfo( - objects: Collection, - renderConfiguration: AbstractCodeMetaInfoRenderConfiguration? - ): Collection { - return objects.flatMap { createCodeMetaInfo(it, renderConfiguration) } - } -} \ No newline at end of file +fun getCodeMetaInfo( + objects: List, + renderConfiguration: AbstractCodeMetaInfoRenderConfiguration +): List { + return objects.flatMap { createCodeMetaInfo(it, renderConfiguration) } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt index f5a86b4caca..efb82bb2380 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt @@ -5,8 +5,6 @@ package org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations -import com.intellij.codeInsight.daemon.impl.HighlightInfo -import com.intellij.lang.annotation.HighlightSeverity import com.intellij.openapi.util.text.StringUtil import com.intellij.util.containers.ContainerUtil import org.jetbrains.kotlin.checkers.diagnostics.factories.DebugInfoDiagnosticFactory1 @@ -14,39 +12,48 @@ import org.jetbrains.kotlin.diagnostics.Diagnostic import org.jetbrains.kotlin.diagnostics.rendering.* import org.jetbrains.kotlin.idea.codeMetaInfo.models.DiagnosticCodeMetaInfo import org.jetbrains.kotlin.idea.codeMetaInfo.models.HighlightingCodeMetaInfo -import org.jetbrains.kotlin.idea.codeMetaInfo.models.ICodeMetaInfo +import org.jetbrains.kotlin.idea.codeMetaInfo.models.CodeMetaInfo import org.jetbrains.kotlin.idea.codeMetaInfo.models.LineMarkerCodeMetaInfo abstract class AbstractCodeMetaInfoRenderConfiguration(var renderParams: Boolean = true) { - abstract fun asString(codeMetaInfo: ICodeMetaInfo): String + open fun asString(codeMetaInfo: CodeMetaInfo) = codeMetaInfo.getTag() + getPlatformsString(codeMetaInfo) - open fun getAdditionalTags(codeMetaInfo: ICodeMetaInfo) = "" + open fun getAdditionalParams(codeMetaInfo: CodeMetaInfo) = "" protected fun sanitizeLineMarkerTooltip(originalText: String?): String { if (originalText == null) return "null" - val noHtmlTags = StringUtil.removeHtmlTags(originalText) + val noHtmlTags = StringUtil.removeHtmlTags(originalText).replace(" ", "") return sanitizeLineBreaks(noHtmlTags) } protected fun sanitizeLineBreaks(originalText: String): String { return StringUtil.replace(originalText, "\n", " ") } + + protected fun getPlatformsString(codeMetaInfo: CodeMetaInfo): String { + if (codeMetaInfo.platforms.isEmpty()) return "" + return "{${codeMetaInfo.platforms.joinToString(";")}}" + } } open class DiagnosticCodeMetaInfoRenderConfiguration( val withNewInference: Boolean = true, val renderSeverity: Boolean = false ) : AbstractCodeMetaInfoRenderConfiguration() { + private val crossPlatformLineBreak = """\r?\n""".toRegex() - override fun asString(codeMetaInfo: ICodeMetaInfo): String { + override fun asString(codeMetaInfo: CodeMetaInfo): String { if (codeMetaInfo !is DiagnosticCodeMetaInfo) return "" - return (getTag(codeMetaInfo) + if (renderParams) "(\"${getParamsString(codeMetaInfo)}\")" else "") - .replace(Regex("""\r?\n"""), "") + return (getTag(codeMetaInfo) + + getPlatformsString(codeMetaInfo) + + getParamsString(codeMetaInfo)) + .replace(crossPlatformLineBreak, "") } private fun getParamsString(codeMetaInfo: DiagnosticCodeMetaInfo): String { + if (!renderParams) return "" val params = mutableListOf() val renderer = when (codeMetaInfo.diagnostic.factory) { is DebugInfoDiagnosticFactory1 -> DiagnosticWithParameters1Renderer( @@ -62,25 +69,23 @@ open class DiagnosticCodeMetaInfoRenderConfiguration( if (renderSeverity) params.add("severity='${codeMetaInfo.diagnostic.severity}'") - params.add(getAdditionalTags(codeMetaInfo)) + params.add(getAdditionalParams(codeMetaInfo)) - return params.filter { it.isNotEmpty() }.joinToString("; ") + return "(\"${params.filter { it.isNotEmpty() }.joinToString("; ")}\")" } - private fun getTag(codeMetaInfo: DiagnosticCodeMetaInfo): String { + fun getTag(codeMetaInfo: DiagnosticCodeMetaInfo): String { return codeMetaInfo.diagnostic.factory.name } } open class LineMarkerRenderConfiguration(val renderDescription: Boolean = true) : AbstractCodeMetaInfoRenderConfiguration() { - override fun asString(codeMetaInfo: ICodeMetaInfo): String { + override fun asString(codeMetaInfo: CodeMetaInfo): String { if (codeMetaInfo !is LineMarkerCodeMetaInfo) return "" return getTag() + if (renderParams) "(\"${getParamsString(codeMetaInfo)}\")" else "" } - private fun getTag(): String { - return "LINE_MARKER" - } + fun getTag() = "LINE_MARKER" private fun getParamsString(lineMarkerCodeMetaInfo: LineMarkerCodeMetaInfo): String { val params = mutableListOf() @@ -88,7 +93,7 @@ open class LineMarkerRenderConfiguration(val renderDescription: Boolean = true) if (renderDescription) params.add("descr='${sanitizeLineMarkerTooltip(lineMarkerCodeMetaInfo.lineMarker.lineMarkerTooltip)}'") - params.add(getAdditionalTags(lineMarkerCodeMetaInfo)) + params.add(getAdditionalParams(lineMarkerCodeMetaInfo)) return params.filter { it.isNotEmpty() }.joinToString("; ") } @@ -100,32 +105,25 @@ open class HighlightingRenderConfiguration( val renderSeverity: Boolean = true ) : AbstractCodeMetaInfoRenderConfiguration() { - override fun asString(codeMetaInfo: ICodeMetaInfo): String { + override fun asString(codeMetaInfo: CodeMetaInfo): String { if (codeMetaInfo !is HighlightingCodeMetaInfo) return "" return getTag() + if (renderParams) "(${getParamsString(codeMetaInfo)})" else "" } - private fun getTag(): String { - return "HIGHLIGHTING" - } + fun getTag() = "HIGHLIGHTING" private fun getParamsString(highlightingCodeMetaInfo: HighlightingCodeMetaInfo): String { val params = mutableListOf() if (renderSeverity) - params.add("severity='${getSeverity(highlightingCodeMetaInfo.highlightingInfo)}'") + params.add("severity='${highlightingCodeMetaInfo.highlightingInfo.severity}'") if (renderDescription) params.add("descr='${sanitizeLineBreaks(highlightingCodeMetaInfo.highlightingInfo.description)}'") if (renderTextAttributesKey) params.add("textAttributesKey='${highlightingCodeMetaInfo.highlightingInfo.forcedTextAttributesKey}'") - params.add(getAdditionalTags(highlightingCodeMetaInfo)) + params.add(getAdditionalParams(highlightingCodeMetaInfo)) return params.filter { it.isNotEmpty() }.joinToString("; ") } - - private fun getSeverity(highlightingInfo: HighlightInfo): String { - return if (highlightingInfo.severity == HighlightSeverity.INFORMATION) "info" else highlightingInfo.severity.toString() - .toLowerCase() - } } \ No newline at end of file