From aaf7ccbebdb1a1a780ff4df922d2c0b9da32bd9d Mon Sep 17 00:00:00 2001 From: Sergej Jaskiewicz Date: Tue, 24 Oct 2023 13:28:47 +0200 Subject: [PATCH] [util] Introduce `IndentingPrinter` interface This interface is more convenient to pass around so that it's easier to replace different printer implementations. --- .../generator/ArgumentsConverterGenerator.kt | 2 +- ...agnosticToKtDiagnosticConverterRenderer.kt | 2 +- .../kotlin/utils/IndentingPrinter.kt | 64 +++++++++++++++++++ .../src/org/jetbrains/kotlin/utils/Printer.kt | 14 ++-- .../jetbrains/kotlin/utils/SmartPrinter.kt | 40 ++++++------ 5 files changed, 93 insertions(+), 29 deletions(-) create mode 100644 core/util.runtime/src/org/jetbrains/kotlin/utils/IndentingPrinter.kt diff --git a/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/ArgumentsConverterGenerator.kt b/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/ArgumentsConverterGenerator.kt index 21dad2496c8..07e755147e4 100644 --- a/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/ArgumentsConverterGenerator.kt +++ b/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/ArgumentsConverterGenerator.kt @@ -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() diff --git a/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/rendererrs/FirDiagnosticToKtDiagnosticConverterRenderer.kt b/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/rendererrs/FirDiagnosticToKtDiagnosticConverterRenderer.kt index b6e969d7c71..766379bc66e 100644 --- a/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/rendererrs/FirDiagnosticToKtDiagnosticConverterRenderer.kt +++ b/analysis/analysis-api-fir/analysis-api-fir-generator/src/org/jetbrains/kotlin/analysis/api/fir/generator/rendererrs/FirDiagnosticToKtDiagnosticConverterRenderer.kt @@ -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,") } diff --git a/core/util.runtime/src/org/jetbrains/kotlin/utils/IndentingPrinter.kt b/core/util.runtime/src/org/jetbrains/kotlin/utils/IndentingPrinter.kt new file mode 100644 index 00000000000..cad5f27e6f7 --- /dev/null +++ b/core/util.runtime/src/org/jetbrains/kotlin/utils/IndentingPrinter.kt @@ -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() +} diff --git a/core/util.runtime/src/org/jetbrains/kotlin/utils/Printer.kt b/core/util.runtime/src/org/jetbrains/kotlin/utils/Printer.kt index 00bbbac1ca8..ab59831c349 100644 --- a/core/util.runtime/src/org/jetbrains/kotlin/utils/Printer.kt +++ b/core/util.runtime/src/org/jetbrains/kotlin/utils/Printer.kt @@ -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 { diff --git a/core/util.runtime/src/org/jetbrains/kotlin/utils/SmartPrinter.kt b/core/util.runtime/src/org/jetbrains/kotlin/utils/SmartPrinter.kt index c9203c8a57e..edf4b42262a 100644 --- a/core/util.runtime/src/org/jetbrains/kotlin/utils/SmartPrinter.kt +++ b/core/util.runtime/src/org/jetbrains/kotlin/utils/SmartPrinter.kt @@ -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) { + print(*objects) } - fun popIndent() { - printer.popIndent() + @Deprecated("Unit-returning method is removed", level = DeprecationLevel.HIDDEN) + fun println(objects: Array) { + 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() }