[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) { private fun SmartPrinter.generateSingleConverter(type: KClass<*>, converter: HLParameterConversion) {
println("private fun $CONVERT_ARGUMENT(argument: ${type.typeWithStars}, firSymbolBuilder: KtSymbolByFirBuilder): Any? {") println("private fun $CONVERT_ARGUMENT(argument: ${type.typeWithStars}, firSymbolBuilder: KtSymbolByFirBuilder): Any? {")
withIndent { withIndent {
println("return ${converter.convertExpression("argument", ConversionContext(getCurrentIndentInUnits(), getIndentUnit()))}") println("return ${converter.convertExpression("argument", ConversionContext(currentIndentLengthInUnits, indentUnitLength))}")
} }
println("}") println("}")
println() println()
@@ -59,7 +59,7 @@ object FirDiagnosticToKtDiagnosticConverterRenderer : AbstractDiagnosticsDataCla
private fun SmartPrinter.printParameter(parameter: HLDiagnosticParameter) { private fun SmartPrinter.printParameter(parameter: HLDiagnosticParameter) {
val expression = parameter.conversion.convertExpression( val expression = parameter.conversion.convertExpression(
"firDiagnostic.${parameter.originalParameterName}", "firDiagnostic.${parameter.originalParameterName}",
ConversionContext(getCurrentIndentInUnits(), getIndentUnit()) ConversionContext(currentIndentLengthInUnits, indentUnitLength)
) )
println("$expression,") 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 maxBlankLines: Int,
private val indentUnit: String, private val indentUnit: String,
private var indent: String private var indent: String
) { ) : IndentingPrinter {
private var blankLineCountIncludingCurrent = 0 private var blankLineCountIncludingCurrent = 0
private var withholdIndentOnce = false private var withholdIndentOnce = false
private var length = 0 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) print(*objects)
printLineSeparator() printLineSeparator()
return this 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) { if (withholdIndentOnce) {
withholdIndentOnce = false withholdIndentOnce = false
} else if (objects.isNotEmpty()) { } else if (objects.isNotEmpty()) {
@@ -98,12 +98,12 @@ open class Printer private constructor(
return this return this
} }
fun pushIndent(): Printer { override fun pushIndent(): Printer {
indent += indentUnit indent += indentUnit
return this return this
} }
fun popIndent(): Printer { override fun popIndent(): Printer {
check(indent.length >= indentUnit.length) { "No indentation to pop" } check(indent.length >= indentUnit.length) { "No indentation to pop" }
indent = indent.substring(indentUnit.length) indent = indent.substring(indentUnit.length)
return this return this
@@ -137,10 +137,10 @@ open class Printer private constructor(
return out.toString() return out.toString()
} }
val currentIndentLengthInUnits: Int override val currentIndentLengthInUnits: Int
get() = indent.length / indentUnit.length get() = indent.length / indentUnit.length
val indentUnitLength: Int override val indentUnitLength: Int
get() = indentUnit.length get() = indentUnit.length
companion object { companion object {
@@ -5,49 +5,49 @@
package org.jetbrains.kotlin.utils 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 { companion object {
private const val DEFAULT_INDENT = " " private const val DEFAULT_INDENT = " "
} }
private val printer = Printer(appendable, indent)
private var notFirstPrint: Boolean = false private var notFirstPrint: Boolean = false
fun print(vararg objects: Any) { override fun print(vararg objects: Any?): SmartPrinter {
if (notFirstPrint) { if (notFirstPrint) {
printer.printWithNoIndent(*objects) printer.printWithNoIndent(*objects)
} else { } else {
printer.print(*objects) printer.print(*objects)
} }
notFirstPrint = true notFirstPrint = true
return this
} }
fun println(vararg objects: Any) { override fun println(vararg objects: Any?): SmartPrinter {
if (notFirstPrint) { if (notFirstPrint) {
printer.printlnWithNoIndent(*objects) printer.printlnWithNoIndent(*objects)
} else { } else {
printer.println(*objects) printer.println(*objects)
} }
notFirstPrint = false notFirstPrint = false
return this
} }
fun pushIndent() { @Deprecated("Unit-returning method is removed", level = DeprecationLevel.HIDDEN)
printer.pushIndent() fun print(objects: Array<Any?>) {
print(*objects)
} }
fun popIndent() { @Deprecated("Unit-returning method is removed", level = DeprecationLevel.HIDDEN)
printer.popIndent() 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()
} }