diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoParser.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/CodeMetaInfoParser.kt similarity index 72% rename from idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoParser.kt rename to compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/CodeMetaInfoParser.kt index 0888b5b084e..45d44a5d788 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoParser.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/CodeMetaInfoParser.kt @@ -3,11 +3,9 @@ * 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 +package org.jetbrains.kotlin.codeMetaInfo -import com.intellij.util.containers.Stack -import org.jetbrains.kotlin.idea.codeMetaInfo.models.ParsedCodeMetaInfo -import org.junit.Assert +import org.jetbrains.kotlin.codeMetaInfo.model.ParsedCodeMetaInfo object CodeMetaInfoParser { private val openingRegex = "(]+?)!>)".toRegex() @@ -18,8 +16,8 @@ object CodeMetaInfoParser { fun getCodeMetaInfoFromText(renderedText: String): List { var text = renderedText - val openingMatchResults = Stack() - val closingMatchResults = Stack() + val openingMatchResults = ArrayDeque() + val closingMatchResults = ArrayDeque() val result = mutableListOf() while (true) { @@ -35,19 +33,21 @@ object CodeMetaInfoParser { closingStartOffset = closing.range.first text = if (openingStartOffset < closingStartOffset) { - openingMatchResults.push(opening) - text.removeRange(openingStartOffset, opening!!.range.last + 1) + requireNotNull(opening) + openingMatchResults.addLast(opening) + text.removeRange(openingStartOffset, opening.range.last + 1) } else { - closingMatchResults.push(closing) - text.removeRange(closingStartOffset, closing!!.range.last + 1) + requireNotNull(closing) + closingMatchResults.addLast(closing) + text.removeRange(closingStartOffset, closing.range.last + 1) } } if (openingMatchResults.size != closingMatchResults.size) { - Assert.fail("Opening and closing tags counts are not equals") + error("Opening and closing tags counts are not equals") } while (!openingMatchResults.isEmpty()) { - val openingMatchResult = openingMatchResults.pop() - val closingMatchResult = closingMatchResults.pop() + val openingMatchResult = openingMatchResults.removeLast() + val closingMatchResult = closingMatchResults.removeLast() val metaInfoWithoutParams = openingMatchResult.groups[2]!!.value.replace(descriptionRegex, "") metaInfoWithoutParams.split(",").forEach { val tag = platformRegex.replace(it, "").trim() @@ -62,4 +62,4 @@ object CodeMetaInfoParser { } return result } -} \ No newline at end of file +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoRenderer.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/CodeMetaInfoRenderer.kt similarity index 94% rename from idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoRenderer.kt rename to compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/CodeMetaInfoRenderer.kt index a1f6da6e64f..20684f1b177 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/CodeMetaInfoRenderer.kt +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/CodeMetaInfoRenderer.kt @@ -3,11 +3,11 @@ * 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 +package org.jetbrains.kotlin.codeMetaInfo import com.intellij.util.containers.Stack import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil -import org.jetbrains.kotlin.idea.codeMetaInfo.models.CodeMetaInfo +import org.jetbrains.kotlin.codeMetaInfo.model.CodeMetaInfo import java.io.File object CodeMetaInfoRenderer { @@ -77,4 +77,4 @@ fun clearFileFromDiagnosticMarkup(file: File) { file.writeText(cleanText) } -fun clearTextFromDiagnosticMarkup(text: String): String = CheckerTestUtil.rangeStartOrEndPattern.matcher(text).replaceAll("") \ No newline at end of file +fun clearTextFromDiagnosticMarkup(text: String): String = CheckerTestUtil.rangeStartOrEndPattern.matcher(text).replaceAll("") diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/model/CodeMetaInfo.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/model/CodeMetaInfo.kt new file mode 100644 index 00000000000..a50d791152e --- /dev/null +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/model/CodeMetaInfo.kt @@ -0,0 +1,18 @@ +/* + * 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.codeMetaInfo.model + +import org.jetbrains.kotlin.codeMetaInfo.renderConfigurations.AbstractCodeMetaInfoRenderConfiguration + +interface CodeMetaInfo { + val start: Int + val end: Int + val renderConfiguration: AbstractCodeMetaInfoRenderConfiguration + val platforms: MutableList + + fun asString(): String + fun getTag(): String +} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/model/DiagnosticCodeMetaInfo.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/model/DiagnosticCodeMetaInfo.kt new file mode 100644 index 00000000000..2a262659015 --- /dev/null +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/model/DiagnosticCodeMetaInfo.kt @@ -0,0 +1,22 @@ +/* + * 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.codeMetaInfo.model + +import org.jetbrains.kotlin.codeMetaInfo.renderConfigurations.DiagnosticCodeMetaInfoRenderConfiguration +import org.jetbrains.kotlin.diagnostics.Diagnostic + +class DiagnosticCodeMetaInfo( + override val start: Int, + override val end: Int, + override val renderConfiguration: DiagnosticCodeMetaInfoRenderConfiguration, + val diagnostic: Diagnostic +) : CodeMetaInfo { + override val platforms: MutableList = mutableListOf() + + override fun asString(): String = renderConfiguration.asString(this) + + override fun getTag(): String = renderConfiguration.getTag(this) +} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/model/ParsedCodeMetaInfo.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/model/ParsedCodeMetaInfo.kt new file mode 100644 index 00000000000..d90342af2bd --- /dev/null +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/model/ParsedCodeMetaInfo.kt @@ -0,0 +1,33 @@ +/* + * 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.codeMetaInfo.model + +import org.jetbrains.kotlin.codeMetaInfo.renderConfigurations.AbstractCodeMetaInfoRenderConfiguration + +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(): String = renderConfiguration.asString(this) + + override fun getTag(): String = tag + + 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 hashCode(): Int { + var result = start + result = 31 * result + end + result = 31 * result + tag.hashCode() + return result + } +} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt new file mode 100644 index 00000000000..e76f705402f --- /dev/null +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt @@ -0,0 +1,38 @@ +/* + * 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.codeMetaInfo.renderConfigurations + +import com.intellij.openapi.util.text.StringUtil +import org.jetbrains.kotlin.codeMetaInfo.model.CodeMetaInfo + +abstract class AbstractCodeMetaInfoRenderConfiguration(var renderParams: Boolean = true) { + private val clickOrPressRegex = "Click or press (.*)to navigate".toRegex() // We have different hotkeys on different platforms + open fun asString(codeMetaInfo: CodeMetaInfo) = codeMetaInfo.getTag() + getPlatformsString(codeMetaInfo) + + open fun getAdditionalParams(codeMetaInfo: CodeMetaInfo) = "" + + protected fun sanitizeLineMarkerTooltip(originalText: String?): String { + if (originalText == null) return "null" + val noHtmlTags = StringUtil.removeHtmlTags(originalText) + .replace(" ", "") + .replace(clickOrPressRegex, "") + .trim() + return sanitizeLineBreaks(noHtmlTags) + } + + protected fun sanitizeLineBreaks(originalText: String): String { + var sanitizedText = originalText + sanitizedText = StringUtil.replace(sanitizedText, "\r\n", " ") + sanitizedText = StringUtil.replace(sanitizedText, "\n", " ") + sanitizedText = StringUtil.replace(sanitizedText, "\r", " ") + return sanitizedText + } + + protected fun getPlatformsString(codeMetaInfo: CodeMetaInfo): String { + if (codeMetaInfo.platforms.isEmpty()) return "" + return "{${codeMetaInfo.platforms.joinToString(";")}}" + } +} diff --git a/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/renderConfigurations/DiagnosticCodeMetaInfoRenderConfiguration.kt b/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/renderConfigurations/DiagnosticCodeMetaInfoRenderConfiguration.kt new file mode 100644 index 00000000000..6357a18f5cd --- /dev/null +++ b/compiler/tests-common/tests/org/jetbrains/kotlin/codeMetaInfo/renderConfigurations/DiagnosticCodeMetaInfoRenderConfiguration.kt @@ -0,0 +1,56 @@ +/* + * 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.codeMetaInfo.renderConfigurations + +import com.intellij.util.containers.ContainerUtil +import org.jetbrains.kotlin.checkers.diagnostics.factories.DebugInfoDiagnosticFactory1 +import org.jetbrains.kotlin.codeMetaInfo.model.CodeMetaInfo +import org.jetbrains.kotlin.codeMetaInfo.model.DiagnosticCodeMetaInfo +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.diagnostics.rendering.* + +open class DiagnosticCodeMetaInfoRenderConfiguration( + val withNewInference: Boolean = true, + val renderSeverity: Boolean = false +) : AbstractCodeMetaInfoRenderConfiguration() { + private val crossPlatformLineBreak = """\r?\n""".toRegex() + + override fun asString(codeMetaInfo: CodeMetaInfo): String { + if (codeMetaInfo !is DiagnosticCodeMetaInfo) return "" + return (getTag(codeMetaInfo) + + getPlatformsString(codeMetaInfo) + + getParamsString(codeMetaInfo)) + .replace(crossPlatformLineBreak, "") + } + + private fun getParamsString(codeMetaInfo: DiagnosticCodeMetaInfo): String { + if (!renderParams) return "" + val params = mutableListOf() + + @Suppress("UNCHECKED_CAST") + val renderer = when (codeMetaInfo.diagnostic.factory) { + is DebugInfoDiagnosticFactory1 -> DiagnosticWithParameters1Renderer( + "{0}", + Renderers.TO_STRING + ) as DiagnosticRenderer + else -> DefaultErrorMessages.getRendererForDiagnostic(codeMetaInfo.diagnostic) + } + if (renderer is AbstractDiagnosticWithParametersRenderer) { + val renderParameters = renderer.renderParameters(codeMetaInfo.diagnostic) + params.addAll(ContainerUtil.map(renderParameters) { it.toString() }) + } + if (renderSeverity) + params.add("severity='${codeMetaInfo.diagnostic.severity}'") + + params.add(getAdditionalParams(codeMetaInfo)) + + return "(\"${params.filter { it.isNotEmpty() }.joinToString("; ")}\")" + } + + fun getTag(codeMetaInfo: DiagnosticCodeMetaInfo): String { + return codeMetaInfo.diagnostic.factory.name + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt index 32de9fc1d22..17ce19618b9 100644 --- a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/AbstractCodeMetaInfoTest.kt @@ -34,14 +34,18 @@ import org.jetbrains.kotlin.checkers.diagnostics.SyntaxErrorDiagnostic import org.jetbrains.kotlin.checkers.diagnostics.factories.DebugInfoDiagnosticFactory0 import org.jetbrains.kotlin.checkers.utils.CheckerTestUtil import org.jetbrains.kotlin.checkers.utils.DiagnosticsRenderingConfiguration +import org.jetbrains.kotlin.codeMetaInfo.CodeMetaInfoParser +import org.jetbrains.kotlin.codeMetaInfo.CodeMetaInfoRenderer +import org.jetbrains.kotlin.codeMetaInfo.model.CodeMetaInfo +import org.jetbrains.kotlin.codeMetaInfo.model.DiagnosticCodeMetaInfo +import org.jetbrains.kotlin.codeMetaInfo.renderConfigurations.AbstractCodeMetaInfoRenderConfiguration +import org.jetbrains.kotlin.codeMetaInfo.renderConfigurations.DiagnosticCodeMetaInfoRenderConfiguration 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.* -import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.AbstractCodeMetaInfoRenderConfiguration -import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.DiagnosticCodeMetaInfoRenderConfiguration import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.HighlightingRenderConfiguration import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.LineMarkerRenderConfiguration import org.jetbrains.kotlin.idea.multiplatform.setupMppProjectFromTextFile @@ -193,17 +197,14 @@ class CodeMetaInfoTestCase( assert( diagnostics.any { diagnosticCodeMetaInfo -> diagnosticCodeMetaInfo.start == highlightingCodeMetaInfo.start && - when (diagnosticCodeMetaInfo.diagnostic) { + when (val diagnostic = diagnosticCodeMetaInfo.diagnostic) { is SyntaxErrorDiagnostic -> { - val diagnostic: SyntaxErrorDiagnostic = diagnosticCodeMetaInfo.diagnostic (highlightingCodeMetaInfo as HighlightingCodeMetaInfo).highlightingInfo.description in (diagnostic.psiElement as PsiErrorElementImpl).errorDescription } is AbstractDiagnostic<*> -> { - val diagnostic: AbstractDiagnostic<*> = diagnosticCodeMetaInfo.diagnostic diagnostic.factory.toString() in (highlightingCodeMetaInfo as HighlightingCodeMetaInfo).highlightingInfo.description } is DebugInfoDiagnostic -> { - val diagnostic: DebugInfoDiagnostic = diagnosticCodeMetaInfo.diagnostic diagnostic.factory == DebugInfoDiagnosticFactory0.MISSING_UNRESOLVED && "[DEBUG] Reference is not resolved to anything, but is not marked unresolved" in (highlightingCodeMetaInfo as HighlightingCodeMetaInfo).highlightingInfo.description } @@ -279,4 +280,4 @@ abstract class AbstractCodeMetaInfoTest : AbstractMultiModuleTest() { } return testSourcePath.toFile() } -} \ No newline at end of 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 deleted file mode 100644 index 81e670030e7..00000000000 --- a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/CodeMetaInfo.kt +++ /dev/null @@ -1,125 +0,0 @@ -/* - * 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.models - -import com.intellij.codeInsight.daemon.LineMarkerInfo -import com.intellij.codeInsight.daemon.impl.HighlightInfo -import org.jetbrains.kotlin.checkers.diagnostics.ActualDiagnostic -import org.jetbrains.kotlin.diagnostics.Diagnostic -import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.AbstractCodeMetaInfoRenderConfiguration -import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.DiagnosticCodeMetaInfoRenderConfiguration -import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.HighlightingRenderConfiguration -import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.LineMarkerRenderConfiguration -import org.jetbrains.kotlin.idea.editor.fixers.end -import org.jetbrains.kotlin.idea.editor.fixers.start - -interface CodeMetaInfo { - val start: Int - val end: Int - 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: DiagnosticCodeMetaInfoRenderConfiguration, - val diagnostic: Diagnostic -) : CodeMetaInfo { - override val platforms: MutableList = mutableListOf() - - override fun asString(): String = renderConfiguration.asString(this) - - override fun getTag(): String = renderConfiguration.getTag(this) -} - -class LineMarkerCodeMetaInfo( - override val renderConfiguration: LineMarkerRenderConfiguration, - val lineMarker: LineMarkerInfo<*> -) : CodeMetaInfo { - override val start: Int - get() = lineMarker.startOffset - override val end: Int - get() = lineMarker.endOffset - override val platforms: MutableList = mutableListOf() - - override fun asString(): String = renderConfiguration.asString(this) - - override fun getTag(): String = renderConfiguration.getTag() -} - -class HighlightingCodeMetaInfo( - override val renderConfiguration: HighlightingRenderConfiguration, - val highlightingInfo: HighlightInfo -) : CodeMetaInfo { - override val start: Int - get() = highlightingInfo.startOffset - override val end: Int - get() = highlightingInfo.endOffset - override val platforms: MutableList = mutableListOf() - - override fun asString(): String = renderConfiguration.asString(this) - - override fun getTag(): String = renderConfiguration.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(): String = renderConfiguration.asString(this) - - override fun getTag(): String = tag - - 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 hashCode(): Int { - var result = start - result = 31 * result + end - result = 31 * result + tag.hashCode() - return result - } -} - -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") - } -} - -fun getCodeMetaInfo( - objects: List, - renderConfiguration: AbstractCodeMetaInfoRenderConfiguration -): List { - return objects.flatMap { createCodeMetaInfo(it, renderConfiguration) } -} diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/CodeMetaInfoFactory.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/CodeMetaInfoFactory.kt new file mode 100644 index 00000000000..aabf7375acf --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/CodeMetaInfoFactory.kt @@ -0,0 +1,49 @@ +/* + * 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.models + +import com.intellij.codeInsight.daemon.LineMarkerInfo +import com.intellij.codeInsight.daemon.impl.HighlightInfo +import org.jetbrains.kotlin.checkers.diagnostics.ActualDiagnostic +import org.jetbrains.kotlin.codeMetaInfo.model.CodeMetaInfo +import org.jetbrains.kotlin.codeMetaInfo.model.DiagnosticCodeMetaInfo +import org.jetbrains.kotlin.codeMetaInfo.renderConfigurations.AbstractCodeMetaInfoRenderConfiguration +import org.jetbrains.kotlin.codeMetaInfo.renderConfigurations.DiagnosticCodeMetaInfoRenderConfiguration +import org.jetbrains.kotlin.diagnostics.Diagnostic +import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.HighlightingRenderConfiguration +import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.LineMarkerRenderConfiguration +import org.jetbrains.kotlin.idea.editor.fixers.end +import org.jetbrains.kotlin.idea.editor.fixers.start + +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") + } +} + +fun getCodeMetaInfo( + objects: List, + renderConfiguration: AbstractCodeMetaInfoRenderConfiguration +): List { + return objects.flatMap { createCodeMetaInfo(it, renderConfiguration) } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/HighlightingCodeMetaInfo.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/HighlightingCodeMetaInfo.kt new file mode 100644 index 00000000000..8c6b456b257 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/HighlightingCodeMetaInfo.kt @@ -0,0 +1,25 @@ +/* + * 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.models + +import com.intellij.codeInsight.daemon.impl.HighlightInfo +import org.jetbrains.kotlin.codeMetaInfo.model.CodeMetaInfo +import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.HighlightingRenderConfiguration + +class HighlightingCodeMetaInfo( + override val renderConfiguration: HighlightingRenderConfiguration, + val highlightingInfo: HighlightInfo +) : CodeMetaInfo { + override val start: Int + get() = highlightingInfo.startOffset + override val end: Int + get() = highlightingInfo.endOffset + override val platforms: MutableList = mutableListOf() + + override fun asString(): String = renderConfiguration.asString(this) + + override fun getTag(): String = renderConfiguration.getTag() +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/LineMarkerCodeMetaInfo.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/LineMarkerCodeMetaInfo.kt new file mode 100644 index 00000000000..4ae09ef6735 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/models/LineMarkerCodeMetaInfo.kt @@ -0,0 +1,25 @@ +/* + * 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.models + +import com.intellij.codeInsight.daemon.LineMarkerInfo +import org.jetbrains.kotlin.codeMetaInfo.model.CodeMetaInfo +import org.jetbrains.kotlin.idea.codeMetaInfo.renderConfigurations.LineMarkerRenderConfiguration + +class LineMarkerCodeMetaInfo( + override val renderConfiguration: LineMarkerRenderConfiguration, + val lineMarker: LineMarkerInfo<*> +) : CodeMetaInfo { + override val start: Int + get() = lineMarker.startOffset + override val end: Int + get() = lineMarker.endOffset + override val platforms: MutableList = mutableListOf() + + override fun asString(): String = renderConfiguration.asString(this) + + override fun getTag(): String = renderConfiguration.getTag() +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt deleted file mode 100644 index f0b135a2a1b..00000000000 --- a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/AbstractCodeMetaInfoRenderConfiguration.kt +++ /dev/null @@ -1,142 +0,0 @@ -/* - * 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.renderConfigurations - -import com.intellij.openapi.util.text.StringUtil -import com.intellij.util.containers.ContainerUtil -import org.jetbrains.kotlin.checkers.diagnostics.factories.DebugInfoDiagnosticFactory1 -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.CodeMetaInfo -import org.jetbrains.kotlin.idea.codeMetaInfo.models.LineMarkerCodeMetaInfo - - -abstract class AbstractCodeMetaInfoRenderConfiguration(var renderParams: Boolean = true) { - private val clickOrPressRegex = "Click or press (.*)to navigate".toRegex() // We have different hotkeys on different platforms - open fun asString(codeMetaInfo: CodeMetaInfo) = codeMetaInfo.getTag() + getPlatformsString(codeMetaInfo) - - open fun getAdditionalParams(codeMetaInfo: CodeMetaInfo) = "" - - protected fun sanitizeLineMarkerTooltip(originalText: String?): String { - if (originalText == null) return "null" - val noHtmlTags = StringUtil.removeHtmlTags(originalText) - .replace(" ", "") - .replace(clickOrPressRegex, "") - .trim() - return sanitizeLineBreaks(noHtmlTags) - } - - protected fun sanitizeLineBreaks(originalText: String): String { - var sanitizedText = originalText - sanitizedText = StringUtil.replace(sanitizedText, "\r\n", " ") - sanitizedText = StringUtil.replace(sanitizedText, "\n", " ") - sanitizedText = StringUtil.replace(sanitizedText, "\r", " ") - return sanitizedText - } - - 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: CodeMetaInfo): String { - if (codeMetaInfo !is DiagnosticCodeMetaInfo) return "" - return (getTag(codeMetaInfo) - + getPlatformsString(codeMetaInfo) - + getParamsString(codeMetaInfo)) - .replace(crossPlatformLineBreak, "") - } - - private fun getParamsString(codeMetaInfo: DiagnosticCodeMetaInfo): String { - if (!renderParams) return "" - val params = mutableListOf() - - @Suppress("UNCHECKED_CAST") - val renderer = when (codeMetaInfo.diagnostic.factory) { - is DebugInfoDiagnosticFactory1 -> DiagnosticWithParameters1Renderer( - "{0}", - Renderers.TO_STRING - ) as DiagnosticRenderer - else -> DefaultErrorMessages.getRendererForDiagnostic(codeMetaInfo.diagnostic) - } - if (renderer is AbstractDiagnosticWithParametersRenderer) { - val renderParameters = renderer.renderParameters(codeMetaInfo.diagnostic) - params.addAll(ContainerUtil.map(renderParameters) { it.toString() }) - } - if (renderSeverity) - params.add("severity='${codeMetaInfo.diagnostic.severity}'") - - params.add(getAdditionalParams(codeMetaInfo)) - - return "(\"${params.filter { it.isNotEmpty() }.joinToString("; ")}\")" - } - - fun getTag(codeMetaInfo: DiagnosticCodeMetaInfo): String { - return codeMetaInfo.diagnostic.factory.name!! - } -} - -open class LineMarkerRenderConfiguration(var renderDescription: Boolean = true) : AbstractCodeMetaInfoRenderConfiguration() { - override fun asString(codeMetaInfo: CodeMetaInfo): String { - if (codeMetaInfo !is LineMarkerCodeMetaInfo) return "" - return getTag() + getParamsString(codeMetaInfo) - } - - fun getTag() = "LINE_MARKER" - - private fun getParamsString(lineMarkerCodeMetaInfo: LineMarkerCodeMetaInfo): String { - if (!renderParams) return "" - val params = mutableListOf() - - if (renderDescription) - params.add("descr='${sanitizeLineMarkerTooltip(lineMarkerCodeMetaInfo.lineMarker.lineMarkerTooltip)}'") - - params.add(getAdditionalParams(lineMarkerCodeMetaInfo)) - - val paramsString = params.filter { it.isNotEmpty() }.joinToString("; ") - return if (paramsString.isEmpty()) "" else "(\"$paramsString\")" - } -} - -open class HighlightingRenderConfiguration( - val renderDescription: Boolean = true, - val renderTextAttributesKey: Boolean = true, - val renderSeverity: Boolean = true -) : AbstractCodeMetaInfoRenderConfiguration() { - - override fun asString(codeMetaInfo: CodeMetaInfo): String { - if (codeMetaInfo !is HighlightingCodeMetaInfo) return "" - return getTag() + getParamsString(codeMetaInfo) - } - - fun getTag() = "HIGHLIGHTING" - - private fun getParamsString(highlightingCodeMetaInfo: HighlightingCodeMetaInfo): String { - if (!renderParams) return "" - - val params = mutableListOf() - if (renderSeverity) - 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(getAdditionalParams(highlightingCodeMetaInfo)) - val paramsString = params.filter { it.isNotEmpty() }.joinToString("; ") - - return if (paramsString.isEmpty()) "" else "(\"$paramsString\")" - } -} diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/HighlightingRenderConfiguration.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/HighlightingRenderConfiguration.kt new file mode 100644 index 00000000000..f3f15bc0e0a --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/HighlightingRenderConfiguration.kt @@ -0,0 +1,41 @@ +/* + * 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.renderConfigurations + +import org.jetbrains.kotlin.codeMetaInfo.model.CodeMetaInfo +import org.jetbrains.kotlin.codeMetaInfo.renderConfigurations.AbstractCodeMetaInfoRenderConfiguration +import org.jetbrains.kotlin.idea.codeMetaInfo.models.HighlightingCodeMetaInfo + +open class HighlightingRenderConfiguration( + val renderDescription: Boolean = true, + val renderTextAttributesKey: Boolean = true, + val renderSeverity: Boolean = true +) : AbstractCodeMetaInfoRenderConfiguration() { + + override fun asString(codeMetaInfo: CodeMetaInfo): String { + if (codeMetaInfo !is HighlightingCodeMetaInfo) return "" + return getTag() + getParamsString(codeMetaInfo) + } + + fun getTag() = "HIGHLIGHTING" + + private fun getParamsString(highlightingCodeMetaInfo: HighlightingCodeMetaInfo): String { + if (!renderParams) return "" + + val params = mutableListOf() + if (renderSeverity) + 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(getAdditionalParams(highlightingCodeMetaInfo)) + val paramsString = params.filter { it.isNotEmpty() }.joinToString("; ") + + return if (paramsString.isEmpty()) "" else "(\"$paramsString\")" + } +} diff --git a/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/LineMarkerRenderConfiguration.kt b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/LineMarkerRenderConfiguration.kt new file mode 100644 index 00000000000..4c5d5fec618 --- /dev/null +++ b/idea/tests/org/jetbrains/kotlin/idea/codeMetaInfo/renderConfigurations/LineMarkerRenderConfiguration.kt @@ -0,0 +1,32 @@ +/* + * 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.renderConfigurations + +import org.jetbrains.kotlin.codeMetaInfo.model.CodeMetaInfo +import org.jetbrains.kotlin.codeMetaInfo.renderConfigurations.AbstractCodeMetaInfoRenderConfiguration +import org.jetbrains.kotlin.idea.codeMetaInfo.models.LineMarkerCodeMetaInfo + +open class LineMarkerRenderConfiguration(var renderDescription: Boolean = true) : AbstractCodeMetaInfoRenderConfiguration() { + override fun asString(codeMetaInfo: CodeMetaInfo): String { + if (codeMetaInfo !is LineMarkerCodeMetaInfo) return "" + return getTag() + getParamsString(codeMetaInfo) + } + + fun getTag() = "LINE_MARKER" + + private fun getParamsString(lineMarkerCodeMetaInfo: LineMarkerCodeMetaInfo): String { + if (!renderParams) return "" + val params = mutableListOf() + + if (renderDescription) + params.add("descr='${sanitizeLineMarkerTooltip(lineMarkerCodeMetaInfo.lineMarker.lineMarkerTooltip)}'") + + params.add(getAdditionalParams(lineMarkerCodeMetaInfo)) + + val paramsString = params.filter { it.isNotEmpty() }.joinToString("; ") + return if (paramsString.isEmpty()) "" else "(\"$paramsString\")" + } +}