Analysis API: extract PrettyPrinter from DebugSymbolRenderer to utils
This commit is contained in:
@@ -15,6 +15,7 @@ dependencies {
|
|||||||
compileOnly(project(":core:compiler.common"))
|
compileOnly(project(":core:compiler.common"))
|
||||||
compileOnly(project(":core:compiler.common.jvm"))
|
compileOnly(project(":core:compiler.common.jvm"))
|
||||||
compileOnly(project(":analysis:low-level-api-fir"))
|
compileOnly(project(":analysis:low-level-api-fir"))
|
||||||
|
implementation(project(":analysis:analysis-internal-utils"))
|
||||||
implementation(project(":analysis:analysis-api-providers"))
|
implementation(project(":analysis:analysis-api-providers"))
|
||||||
|
|
||||||
api(intellijCoreDep()) { includeJars("intellij-core", "guava", rootProject = rootProject) }
|
api(intellijCoreDep()) { includeJars("intellij-core", "guava", rootProject = rootProject) }
|
||||||
|
|||||||
+24
-68
@@ -16,9 +16,10 @@ import org.jetbrains.kotlin.analysis.api.components.KtSymbolInfoProviderMixIn
|
|||||||
import org.jetbrains.kotlin.analysis.api.symbols.markers.*
|
import org.jetbrains.kotlin.analysis.api.symbols.markers.*
|
||||||
import org.jetbrains.kotlin.analysis.api.types.KtClassErrorType
|
import org.jetbrains.kotlin.analysis.api.types.KtClassErrorType
|
||||||
import org.jetbrains.kotlin.analysis.api.types.KtType
|
import org.jetbrains.kotlin.analysis.api.types.KtType
|
||||||
|
import org.jetbrains.kotlin.analysis.utils.printer.PrettyPrinter
|
||||||
|
import org.jetbrains.kotlin.analysis.utils.printer.prettyPrint
|
||||||
import org.jetbrains.kotlin.descriptors.Visibility
|
import org.jetbrains.kotlin.descriptors.Visibility
|
||||||
import org.jetbrains.kotlin.name.*
|
import org.jetbrains.kotlin.name.*
|
||||||
import java.lang.Appendable
|
|
||||||
import java.lang.reflect.InvocationTargetException
|
import java.lang.reflect.InvocationTargetException
|
||||||
import kotlin.reflect.KClass
|
import kotlin.reflect.KClass
|
||||||
import kotlin.reflect.KProperty
|
import kotlin.reflect.KProperty
|
||||||
@@ -26,14 +27,14 @@ import kotlin.reflect.full.declaredMemberExtensionProperties
|
|||||||
import kotlin.reflect.full.extensionReceiverParameter
|
import kotlin.reflect.full.extensionReceiverParameter
|
||||||
|
|
||||||
public object DebugSymbolRenderer {
|
public object DebugSymbolRenderer {
|
||||||
public fun render(symbol: KtSymbol): String = Block().apply { renderSymbol(symbol) }.toString()
|
public fun render(symbol: KtSymbol): String = prettyPrint { renderSymbol(symbol) }
|
||||||
|
|
||||||
public fun renderAnnotationApplication(application: KtAnnotationApplication): String =
|
public fun renderAnnotationApplication(application: KtAnnotationApplication): String =
|
||||||
Block().apply { renderAnnotationApplication(application) }.toString()
|
prettyPrint { renderAnnotationApplication(application) }
|
||||||
|
|
||||||
public fun renderType(type: KtType): String = Block().apply { renderType(type) }.toString()
|
public fun renderType(type: KtType): String = prettyPrint { renderType(type) }
|
||||||
|
|
||||||
public fun KtAnalysisSession.renderExtra(symbol: KtSymbol): String = Block().apply {
|
public fun KtAnalysisSession.renderExtra(symbol: KtSymbol): String = prettyPrint {
|
||||||
renderSymbol(symbol)
|
renderSymbol(symbol)
|
||||||
|
|
||||||
withIndent {
|
withIndent {
|
||||||
@@ -48,10 +49,10 @@ public object DebugSymbolRenderer {
|
|||||||
.filter { (it.extensionReceiverParameter?.type?.classifier as? KClass<*>)?.isInstance(symbol) == true }
|
.filter { (it.extensionReceiverParameter?.type?.classifier as? KClass<*>)?.isInstance(symbol) == true }
|
||||||
.forEach { renderProperty(it, this@renderExtra, symbol) }
|
.forEach { renderProperty(it, this@renderExtra, symbol) }
|
||||||
}
|
}
|
||||||
}.toString()
|
}
|
||||||
|
|
||||||
public fun KtAnalysisSession.renderForSubstitutionOverrideUnwrappingTest(symbol: KtSymbol): String = Block().apply {
|
public fun KtAnalysisSession.renderForSubstitutionOverrideUnwrappingTest(symbol: KtSymbol): String = prettyPrint {
|
||||||
if (symbol !is KtCallableSymbol) return@apply
|
if (symbol !is KtCallableSymbol) return@prettyPrint
|
||||||
|
|
||||||
renderSymbolHeader(symbol)
|
renderSymbolHeader(symbol)
|
||||||
|
|
||||||
@@ -63,14 +64,14 @@ public object DebugSymbolRenderer {
|
|||||||
renderProperty(KtCallableSymbol::origin, symbol)
|
renderProperty(KtCallableSymbol::origin, symbol)
|
||||||
|
|
||||||
@Suppress("DEPRECATION")
|
@Suppress("DEPRECATION")
|
||||||
(symbol as? KtPossibleMemberSymbol)?.getDispatchReceiverType()?.let { dispatchType ->
|
(symbol as? KtCallableSymbol)?.getDispatchReceiverType()?.let { dispatchType ->
|
||||||
appendLine().append("getDispatchReceiver()").append(": ")
|
appendLine().append("getDispatchReceiver()").append(": ")
|
||||||
renderType(dispatchType)
|
renderType(dispatchType)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}.toString()
|
}.toString()
|
||||||
|
|
||||||
private fun Block.renderProperty(property: KProperty<*>, vararg args: Any) {
|
private fun PrettyPrinter.renderProperty(property: KProperty<*>, vararg args: Any) {
|
||||||
try {
|
try {
|
||||||
appendLine().append(property.name).append(": ")
|
appendLine().append(property.name).append(": ")
|
||||||
renderValue(property.getter.call(*args))
|
renderValue(property.getter.call(*args))
|
||||||
@@ -79,9 +80,8 @@ public object DebugSymbolRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Block.renderSymbol(symbol: KtSymbol) {
|
private fun PrettyPrinter.renderSymbol(symbol: KtSymbol) {
|
||||||
renderSymbolHeader(symbol)
|
renderSymbolHeader(symbol)
|
||||||
|
|
||||||
val apiClass = getSymbolApiClass(symbol)
|
val apiClass = getSymbolApiClass(symbol)
|
||||||
withIndent {
|
withIndent {
|
||||||
apiClass.members
|
apiClass.members
|
||||||
@@ -93,28 +93,26 @@ public object DebugSymbolRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Block.renderSymbolHeader(symbol: KtSymbol) {
|
private fun PrettyPrinter.renderSymbolHeader(symbol: KtSymbol) {
|
||||||
val apiClass = getSymbolApiClass(symbol)
|
val apiClass = getSymbolApiClass(symbol)
|
||||||
append(apiClass.simpleName).append(':')
|
append(apiClass.simpleName).append(':')
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Block.renderList(values: List<*>) {
|
private fun PrettyPrinter.renderList(values: List<*>) {
|
||||||
if (values.isEmpty()) {
|
if (values.isEmpty()) {
|
||||||
append("[]")
|
append("[]")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
append('[')
|
withIndentInSquareBrackets {
|
||||||
withIndent {
|
|
||||||
for (value in values) {
|
for (value in values) {
|
||||||
appendLine()
|
appendLine()
|
||||||
renderValue(value)
|
renderValue(value)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
appendLine().append(']')
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Block.renderSymbolTag(symbol: KtSymbol) {
|
private fun PrettyPrinter.renderSymbolTag(symbol: KtSymbol) {
|
||||||
fun renderId(id: Any?, symbol: KtSymbol) {
|
fun renderId(id: Any?, symbol: KtSymbol) {
|
||||||
if (id != null) {
|
if (id != null) {
|
||||||
renderValue(id)
|
renderValue(id)
|
||||||
@@ -138,16 +136,16 @@ public object DebugSymbolRenderer {
|
|||||||
append(")")
|
append(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Block.renderAnnotationValue(value: KtAnnotationValue) {
|
private fun PrettyPrinter.renderAnnotationValue(value: KtAnnotationValue) {
|
||||||
append(KtAnnotationValueRenderer.render(value))
|
append(KtAnnotationValueRenderer.render(value))
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Block.renderNamedConstantValue(value: KtNamedAnnotationValue) {
|
private fun PrettyPrinter.renderNamedConstantValue(value: KtNamedAnnotationValue) {
|
||||||
append(value.name).append(" = ")
|
append(value.name).append(" = ")
|
||||||
renderValue(value.expression)
|
renderValue(value.expression)
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Block.renderType(type: KtType) {
|
private fun PrettyPrinter.renderType(type: KtType) {
|
||||||
if (type.annotations.isNotEmpty()) {
|
if (type.annotations.isNotEmpty()) {
|
||||||
renderList(type.annotations)
|
renderList(type.annotations)
|
||||||
append(' ')
|
append(' ')
|
||||||
@@ -158,7 +156,7 @@ public object DebugSymbolRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Block.renderAnnotationApplication(call: KtAnnotationApplication) {
|
private fun PrettyPrinter.renderAnnotationApplication(call: KtAnnotationApplication) {
|
||||||
renderValue(call.classId)
|
renderValue(call.classId)
|
||||||
append('(')
|
append('(')
|
||||||
call.arguments.sortedBy { it.name }.forEachIndexed { index, value ->
|
call.arguments.sortedBy { it.name }.forEachIndexed { index, value ->
|
||||||
@@ -175,7 +173,7 @@ public object DebugSymbolRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Block.renderDeprecationInfo(info: DeprecationInfo) {
|
private fun PrettyPrinter.renderDeprecationInfo(info: DeprecationInfo) {
|
||||||
append("DeprecationInfo(")
|
append("DeprecationInfo(")
|
||||||
append("deprecationLevel=${info.deprecationLevel}, ")
|
append("deprecationLevel=${info.deprecationLevel}, ")
|
||||||
append("propagatesToOverrides=${info.propagatesToOverrides}, ")
|
append("propagatesToOverrides=${info.propagatesToOverrides}, ")
|
||||||
@@ -183,7 +181,7 @@ public object DebugSymbolRenderer {
|
|||||||
append(")")
|
append(")")
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Block.renderValue(value: Any?) {
|
private fun PrettyPrinter.renderValue(value: Any?) {
|
||||||
when (value) {
|
when (value) {
|
||||||
// Symbol-related values
|
// Symbol-related values
|
||||||
is KtSymbol -> renderSymbolTag(value)
|
is KtSymbol -> renderSymbolTag(value)
|
||||||
@@ -211,7 +209,7 @@ public object DebugSymbolRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Block.renderKtInitializerValue(value: KtInitializerValue) {
|
private fun PrettyPrinter.renderKtInitializerValue(value: KtInitializerValue) {
|
||||||
when (value) {
|
when (value) {
|
||||||
is KtConstantInitializerValue -> {
|
is KtConstantInitializerValue -> {
|
||||||
append("KtConstantInitializerValue(")
|
append("KtConstantInitializerValue(")
|
||||||
@@ -226,7 +224,7 @@ public object DebugSymbolRenderer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private fun Block.renderAnnotationsList(value: KtAnnotationsList) {
|
private fun PrettyPrinter.renderAnnotationsList(value: KtAnnotationsList) {
|
||||||
renderList(value.annotations)
|
renderList(value.annotations)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -255,46 +253,4 @@ public object DebugSymbolRenderer {
|
|||||||
"org.jetbrains.kotlin.analysis.api.fir",
|
"org.jetbrains.kotlin.analysis.api.fir",
|
||||||
"org.jetbrains.kotlin.analysis.api.descriptors",
|
"org.jetbrains.kotlin.analysis.api.descriptors",
|
||||||
)
|
)
|
||||||
}
|
|
||||||
|
|
||||||
private class Block : Appendable {
|
|
||||||
private val builder = StringBuilder()
|
|
||||||
private var indent = 0
|
|
||||||
|
|
||||||
override fun append(seq: CharSequence): Appendable = apply {
|
|
||||||
seq.split('\n').forEachIndexed { index, line ->
|
|
||||||
if (index > 0) {
|
|
||||||
builder.append('\n')
|
|
||||||
}
|
|
||||||
appendIndentIfNeeded()
|
|
||||||
builder.append(line)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun append(seq: CharSequence, start: Int, end: Int): Appendable = apply {
|
|
||||||
append(seq.subSequence(start, end))
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun append(c: Char): Appendable = apply {
|
|
||||||
if (c != '\n') {
|
|
||||||
appendIndentIfNeeded()
|
|
||||||
}
|
|
||||||
builder.append(c)
|
|
||||||
}
|
|
||||||
|
|
||||||
private fun appendIndentIfNeeded() {
|
|
||||||
if (builder.isEmpty() || builder[builder.lastIndex] == '\n') {
|
|
||||||
builder.append(" ".repeat(2 * indent))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
fun withIndent(block: Block.() -> Unit) {
|
|
||||||
indent += 1
|
|
||||||
block(this)
|
|
||||||
indent -= 1
|
|
||||||
}
|
|
||||||
|
|
||||||
override fun toString(): String {
|
|
||||||
return builder.toString()
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
+105
@@ -0,0 +1,105 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2010-2021 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.analysis.utils.printer
|
||||||
|
|
||||||
|
import java.lang.Appendable
|
||||||
|
|
||||||
|
public class PrettyPrinter(private val indentSize: Int = 2) : Appendable {
|
||||||
|
private val builder = StringBuilder()
|
||||||
|
public var indent: Int = 0
|
||||||
|
|
||||||
|
override fun append(seq: CharSequence): Appendable = apply {
|
||||||
|
seq.split('\n').forEachIndexed { index, line ->
|
||||||
|
if (index > 0) {
|
||||||
|
builder.append('\n')
|
||||||
|
}
|
||||||
|
appendIndentIfNeeded()
|
||||||
|
builder.append(line)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun append(seq: CharSequence, start: Int, end: Int): Appendable = apply {
|
||||||
|
append(seq.subSequence(start, end))
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun append(c: Char): Appendable = apply {
|
||||||
|
if (c != '\n') {
|
||||||
|
appendIndentIfNeeded()
|
||||||
|
}
|
||||||
|
builder.append(c)
|
||||||
|
}
|
||||||
|
|
||||||
|
public inline fun withIndent(block: PrettyPrinter.() -> Unit) {
|
||||||
|
indent += 1
|
||||||
|
block(this)
|
||||||
|
indent -= 1
|
||||||
|
}
|
||||||
|
|
||||||
|
public inline fun withIndentInBraces(block: PrettyPrinter.() -> Unit) {
|
||||||
|
withIndentWrapped(before = "{", after = "}", block)
|
||||||
|
}
|
||||||
|
|
||||||
|
public inline fun withIndentInSquareBrackets(block: PrettyPrinter.() -> Unit) {
|
||||||
|
withIndentWrapped(before = "[", after = "]", block)
|
||||||
|
}
|
||||||
|
|
||||||
|
public inline fun withIndentWrapped(before: String, after: String, block: PrettyPrinter.() -> Unit) {
|
||||||
|
append(before)
|
||||||
|
appendLine()
|
||||||
|
withIndent(block)
|
||||||
|
appendLine()
|
||||||
|
append(after)
|
||||||
|
}
|
||||||
|
|
||||||
|
public inline fun <T> printCollection(
|
||||||
|
collection: Iterable<T>,
|
||||||
|
separator: String = ", ",
|
||||||
|
prefix: String = "",
|
||||||
|
postfix: String = "",
|
||||||
|
renderItem: PrettyPrinter.(T) -> Unit
|
||||||
|
) {
|
||||||
|
append(prefix)
|
||||||
|
val iterator = collection.iterator()
|
||||||
|
while (iterator.hasNext()) {
|
||||||
|
renderItem(iterator.next())
|
||||||
|
if (iterator.hasNext()) {
|
||||||
|
append(separator)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
append(postfix)
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
public inline fun <T> printCollectionIfNotEmpty(
|
||||||
|
collection: Iterable<T>,
|
||||||
|
separator: String = ", ",
|
||||||
|
prefix: String = "",
|
||||||
|
postfix: String = "",
|
||||||
|
renderItem: PrettyPrinter.(T) -> Unit
|
||||||
|
) {
|
||||||
|
if (!collection.iterator().hasNext()) return
|
||||||
|
printCollection(collection, separator, prefix, postfix, renderItem)
|
||||||
|
}
|
||||||
|
|
||||||
|
public fun printCharIfNotThere(char: Char) {
|
||||||
|
if (builder.lastOrNull() != char) {
|
||||||
|
append(char)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private fun appendIndentIfNeeded() {
|
||||||
|
if (builder.isEmpty() || builder[builder.lastIndex] == '\n') {
|
||||||
|
builder.append(" ".repeat(indentSize * indent))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
override fun toString(): String {
|
||||||
|
return builder.toString()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public inline fun prettyPrint(body: PrettyPrinter.() -> Unit): String =
|
||||||
|
PrettyPrinter().apply(body).toString()
|
||||||
Reference in New Issue
Block a user