[util] Introduce IndentingPrinter interface

This interface is more convenient to pass around so that it's easier
to replace different printer implementations.
This commit is contained in:
Sergej Jaskiewicz
2023-10-24 13:28:47 +02:00
committed by Space Team
parent 895d107ac5
commit aaf7ccbebd
5 changed files with 93 additions and 29 deletions
@@ -78,7 +78,7 @@ object ArgumentsConverterGenerator {
private fun SmartPrinter.generateSingleConverter(type: KClass<*>, converter: HLParameterConversion) {
println("private fun $CONVERT_ARGUMENT(argument: ${type.typeWithStars}, firSymbolBuilder: KtSymbolByFirBuilder): Any? {")
withIndent {
println("return ${converter.convertExpression("argument", ConversionContext(getCurrentIndentInUnits(), getIndentUnit()))}")
println("return ${converter.convertExpression("argument", ConversionContext(currentIndentLengthInUnits, indentUnitLength))}")
}
println("}")
println()
@@ -59,7 +59,7 @@ object FirDiagnosticToKtDiagnosticConverterRenderer : AbstractDiagnosticsDataCla
private fun SmartPrinter.printParameter(parameter: HLDiagnosticParameter) {
val expression = parameter.conversion.convertExpression(
"firDiagnostic.${parameter.originalParameterName}",
ConversionContext(getCurrentIndentInUnits(), getIndentUnit())
ConversionContext(currentIndentLengthInUnits, indentUnitLength)
)
println("$expression,")
}
@@ -0,0 +1,64 @@
/*
* Copyright 2010-2023 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.utils
/**
* A printer that is suitable for printing text with indentation.
*/
interface IndentingPrinter {
/**
* The current indentation level. Basically, this is the number of [pushIndent] calls that don't yet have a matching [popIndent] call.
*/
val currentIndentLengthInUnits: Int
/**
* The number of characters in a single indent unit.
*/
val indentUnitLength: Int
/**
* Prints [objects] by concatenating the results of their [Any.toString] calls, also appending a line break at the end.
*
* @return `this`
*/
fun println(vararg objects: Any?): IndentingPrinter
/**
* Prints [objects] by concatenating the results of their [Any.toString] calls.
*
* @return `this`
*/
fun print(vararg objects: Any?): IndentingPrinter
/**
* Increases the indentation level by one.
*
* @return `this`
*/
fun pushIndent(): IndentingPrinter
/**
* Decreases the indentation level by one.
*
* @return `this`
*/
fun popIndent(): IndentingPrinter
/**
* Returns the printed text.
*/
override fun toString(): String
}
/**
* The text printed within [block] will be indented.
*/
inline fun IndentingPrinter.withIndent(block: () -> Unit) {
pushIndent()
block()
popIndent()
}
@@ -25,7 +25,7 @@ open class Printer private constructor(
private val maxBlankLines: Int,
private val indentUnit: String,
private var indent: String
) {
) : IndentingPrinter {
private var blankLineCountIncludingCurrent = 0
private var withholdIndentOnce = false
private var length = 0
@@ -52,7 +52,7 @@ open class Printer private constructor(
}
}
fun println(vararg objects: Any?): Printer {
override fun println(vararg objects: Any?): Printer {
print(*objects)
printLineSeparator()
return this
@@ -65,7 +65,7 @@ open class Printer private constructor(
}
}
fun print(vararg objects: Any?): Printer {
override fun print(vararg objects: Any?): Printer {
if (withholdIndentOnce) {
withholdIndentOnce = false
} else if (objects.isNotEmpty()) {
@@ -98,12 +98,12 @@ open class Printer private constructor(
return this
}
fun pushIndent(): Printer {
override fun pushIndent(): Printer {
indent += indentUnit
return this
}
fun popIndent(): Printer {
override fun popIndent(): Printer {
check(indent.length >= indentUnit.length) { "No indentation to pop" }
indent = indent.substring(indentUnit.length)
return this
@@ -137,10 +137,10 @@ open class Printer private constructor(
return out.toString()
}
val currentIndentLengthInUnits: Int
override val currentIndentLengthInUnits: Int
get() = indent.length / indentUnit.length
val indentUnitLength: Int
override val indentUnitLength: Int
get() = indentUnit.length
companion object {
@@ -5,49 +5,49 @@
package org.jetbrains.kotlin.utils
class SmartPrinter(appendable: Appendable, indent: String = DEFAULT_INDENT) {
/**
* A wrapper around [Printer] that manages indentation in a smarter way.
*
* Unlike [Printer], which always prints the indentation unit whenever you call [print] or [println],
* [SmartPrinter] only prints the indentation unit at the start of the line.
*/
class SmartPrinter private constructor(private val printer: Printer) : IndentingPrinter by printer {
constructor(appendable: Appendable, indent: String = DEFAULT_INDENT) : this(Printer(appendable, indent))
companion object {
private const val DEFAULT_INDENT = " "
}
private val printer = Printer(appendable, indent)
private var notFirstPrint: Boolean = false
fun print(vararg objects: Any) {
override fun print(vararg objects: Any?): SmartPrinter {
if (notFirstPrint) {
printer.printWithNoIndent(*objects)
} else {
printer.print(*objects)
}
notFirstPrint = true
return this
}
fun println(vararg objects: Any) {
override fun println(vararg objects: Any?): SmartPrinter {
if (notFirstPrint) {
printer.printlnWithNoIndent(*objects)
} else {
printer.println(*objects)
}
notFirstPrint = false
return this
}
fun pushIndent() {
printer.pushIndent()
@Deprecated("Unit-returning method is removed", level = DeprecationLevel.HIDDEN)
fun print(objects: Array<Any?>) {
print(*objects)
}
fun popIndent() {
printer.popIndent()
@Deprecated("Unit-returning method is removed", level = DeprecationLevel.HIDDEN)
fun println(objects: Array<Any?>) {
println(*objects)
}
fun getCurrentIndentInUnits() = printer.currentIndentLengthInUnits
fun getIndentUnit() = printer.indentUnitLength
override fun toString(): String = printer.toString()
}
inline fun SmartPrinter.withIndent(block: () -> Unit) {
pushIndent()
block()
popIndent()
}