Files
kotlin-fork/j2k/newSrc/org/jetbrains/kotlin/j2k/NewCodeBuilder.kt
T

755 lines
30 KiB
Kotlin

/*
* Copyright 2010-2017 JetBrains s.r.o.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.jetbrains.kotlin.j2k
import org.jetbrains.kotlin.j2k.NewCodeBuilder.ParenthesisKind.*
import org.jetbrains.kotlin.j2k.ast.Mutability
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.j2k.tree.*
import org.jetbrains.kotlin.j2k.tree.impl.*
import org.jetbrains.kotlin.j2k.tree.visitors.JKVisitorVoid
import org.jetbrains.kotlin.name.FqName
import org.jetbrains.kotlin.utils.Printer
import org.jetbrains.kotlin.utils.addToStdlib.firstIsInstanceOrNull
class NewCodeBuilder {
val builder = StringBuilder()
val printer = Printer(builder)
private fun classKindString(kind: JKClass.ClassKind): String = when (kind) {
JKClass.ClassKind.ANNOTATION -> "annotation class"
JKClass.ClassKind.CLASS -> "class"
JKClass.ClassKind.ENUM -> "enum class"
JKClass.ClassKind.INTERFACE -> "interface"
JKClass.ClassKind.OBJECT -> "object"
JKClass.ClassKind.COMPANION -> "companion object"
}
inner class Visitor : JKVisitorVoid {
private fun renderExtraTypeParametersUpperBounds(typeParameterList: JKTypeParameterList) {
val extraTypeBounds = typeParameterList.typeParameters
.filter { it.upperBounds.size > 1 }
if (extraTypeBounds.isNotEmpty()) {
printer.printWithNoIndent(" where ")
val typeParametersWithBoudnds =
extraTypeBounds.flatMap { typeParameter ->
typeParameter.upperBounds.map { bound ->
typeParameter.name to bound
}
}
renderList(typeParametersWithBoudnds) { (name, bound) ->
name.accept(this)
printer.printWithNoIndent(" : ")
bound.accept(this)
}
}
}
override fun visitTreeElement(treeElement: JKTreeElement) {
printer.print("/* !!! Hit visitElement for element type: ${treeElement::class} !!! */")
}
override fun visitKtTryExpression(ktTryExpression: JKKtTryExpression) {
printer.printWithNoIndent("try ")
if (ktTryExpression.tryBlock != JKBodyStub) {
printer.block { ktTryExpression.tryBlock.accept(this) }
}
ktTryExpression.catchSections.forEach { it.accept(this) }
if (ktTryExpression.finallyBlock != JKBodyStub) {
printer.printWithNoIndent("finally ")
printer.block { ktTryExpression.finallyBlock.accept(this) }
}
}
override fun visitKtTryCatchSection(ktTryCatchSection: JKKtTryCatchSection) {
printer.printWithNoIndent("catch ")
printer.par {
ktTryCatchSection.parameter.accept(this)
}
if (ktTryCatchSection.block != JKBodyStub) {
printer.block { ktTryCatchSection.block.accept(this) }
}
}
override fun visitForInStatement(forInStatement: JKForInStatement) {
printer.printWithNoIndent("for (")
forInStatement.declaration.accept(this)
printer.printWithNoIndent(" in ")
forInStatement.iterationExpression.accept(this)
printer.printWithNoIndent(") ")
if (forInStatement.body.isEmpty()) {
printer.printWithNoIndent(";")
} else {
forInStatement.body.accept(this)
}
}
override fun visitKtThrowExpression(ktThrowExpression: JKKtThrowExpression) {
printer.printWithNoIndent("throw ")
ktThrowExpression.exception.accept(this)
}
override fun visitDoWhileStatement(doWhileStatement: JKDoWhileStatement) {
printer.printWithNoIndent("do")
doWhileStatement.body.accept(this)
printer.printWithNoIndent("while (")
doWhileStatement.condition.accept(this)
printer.printWithNoIndent(")")
}
override fun visitClassAccessExpression(classAccessExpression: JKClassAccessExpression) {
printer.printWithNoIndent(classAccessExpression.identifier.fqName)
}
override fun visitFile(file: JKFile) {
file.acceptChildren(this)
}
override fun visitBreakStatement(breakStatement: JKBreakStatement) {
printer.printWithNoIndent("break")
}
override fun visitBreakWithLabelStatement(breakWithLabelStatement: JKBreakWithLabelStatement) {
printer.printWithNoIndent("break@")
printer.printWithNoIndent(breakWithLabelStatement.label.value)
}
override fun visitModifierList(modifierList: JKModifierList) {
modifierList.modifiers.firstOrNull()?.accept(this)
for (i in 1..modifierList.modifiers.lastIndex) {
printer.printWithNoIndent(" ")
modifierList.modifiers[i].accept(this)
}
}
override fun visitAccessModifier(accessModifier: JKAccessModifier) {
printer.printWithNoIndent(
when (accessModifier.visibility) {
JKAccessModifier.Visibility.PUBLIC -> "public"
JKAccessModifier.Visibility.INTERNAL -> "internal"
JKAccessModifier.Visibility.PACKAGE_PRIVATE -> ""
// JKAccessModifier.Visibility.PACKAGE_PRIVATE -> "internal /* package_local! */"
JKAccessModifier.Visibility.PROTECTED -> "protected"
JKAccessModifier.Visibility.PRIVATE -> "private"
}
)
}
override fun visitModalityModifier(modalityModifier: JKModalityModifier) {
val containingDeclaration = modalityModifier.parent?.parent
//TODO: merge with bottom one
if (modalityModifier.modality == JKModalityModifier.Modality.ABSTRACT && containingDeclaration is JKClass) {
if (containingDeclaration.classKind != JKClass.ClassKind.CLASS) return
}
printer.printWithNoIndent(
when (modalityModifier.modality) {
JKModalityModifier.Modality.OPEN -> "open"
JKModalityModifier.Modality.FINAL -> "final"
JKModalityModifier.Modality.ABSTRACT -> "abstract"
JKModalityModifier.Modality.OVERRIDE -> "override"
}
)
}
override fun visitMutabilityModifier(mutabilityModifier: JKMutabilityModifier) {
if (mutabilityModifier.mutability == Mutability.NonMutable) printer.print("val")
else printer.print("var")
}
override fun visitKtModifier(ktModifier: JKKtModifier) {
printer.printWithNoIndent(
when (ktModifier.type) {
JKKtModifier.KtModifierType.ABSTRACT -> "abstract"
JKKtModifier.KtModifierType.INNER -> "inner"
JKKtModifier.KtModifierType.OPEN -> "open"
JKKtModifier.KtModifierType.PRIVATE -> "private"
JKKtModifier.KtModifierType.PROTECTED -> "protected"
else -> ktModifier.type.toString()
}
)
}
private inline fun <T> renderList(list: List<T>, separator: String = ", ", renderElement: (T) -> Unit) =
renderList(list, { printer.printWithNoIndent(separator) }, renderElement)
private inline fun <T> renderList(list: List<T>, separator: () -> Unit, renderElement: (T) -> Unit) {
val (head, tail) = list.headTail()
head?.let(renderElement) ?: return
tail?.forEach {
separator()
renderElement(it)
}
}
override fun visitClass(klass: JKClass) {
klass.modifierList.accept(this)
builder.append(" ")
printer.print(classKindString(klass.classKind))
builder.append(" ")
printer.printWithNoIndent(klass.name.value)
klass.typeParameterList.accept(this)
printer.printWithNoIndent(" ")
val primaryConstructor = klass.primaryConstructor()
primaryConstructor?.accept(this)
if (klass.inheritance.inherit.isNotEmpty()) {
printer.printWithNoIndent(" : ")
val delegationCall = primaryConstructor?.delegationCall as? JKDelegationConstructorCall
renderList(klass.inheritance.inherit) {
it.accept(this)
if (delegationCall != null && delegationCall.isCallOfConstructorOf(it.type)) {
printer.par {
delegationCall.arguments.accept(this)
}
}
}
}
//TODO should it be here?
renderExtraTypeParametersUpperBounds(klass.typeParameterList)
val declarationsToPrint = klass.declarationList.filterNot { it is JKKtPrimaryConstructor}
if (declarationsToPrint.isNotEmpty()) {
printer.block(multiline = true) {
renderEnumConstants(declarationsToPrint.filterIsInstance())
renderNonEnumClassDeclarations(declarationsToPrint.filterNot { it is JKEnumConstant })
}
} else {
printer.println()
}
}
private fun renderEnumConstants(enumConstants: List<JKEnumConstant>) {
renderList(enumConstants) {
it.accept(this)
}
}
private fun renderNonEnumClassDeclarations(declarations: List<JKDeclaration>) {
renderList(declarations, { printer.println() }) {
it.accept(this)
}
}
override fun visitKtProperty(ktProperty: JKKtProperty) {
ktProperty.modifierList.accept(this)
printer.printWithNoIndent(" ", ktProperty.name.value)
if (ktProperty.type.present()) {
printer.printWithNoIndent(":")
ktProperty.type.accept(this)
}
if (ktProperty.initializer !is JKStubExpression) {
printer.printWithNoIndent(" = ")
ktProperty.initializer.accept(this)
}
}
override fun visitEnumConstant(enumConstant: JKEnumConstant) {
enumConstant.name.accept(this)
if (enumConstant.arguments.expressions.isNotEmpty()) {
printer.par {
enumConstant.arguments.accept(this)
}
}
}
override fun visitKtInitDeclaration(ktInitDeclaration: JKKtInitDeclaration) {
if (ktInitDeclaration.block.statements.isNotEmpty()) {
printer.print("init ")
printer.block(multiline = true) {
ktInitDeclaration.block.accept(this)
}
}
}
override fun visitKtIsExpression(ktIsExpression: JKKtIsExpression) {
ktIsExpression.expression.accept(this)
printer.printWithNoIndent(" is ")
ktIsExpression.type.accept(this)
}
override fun visitParameter(parameter: JKParameter) {
parameter.modifierList.accept(this)
printer.printWithNoIndent(" ", parameter.name.value, ": ")
parameter.type.accept(this)
if (parameter.initializer !is JKStubExpression) {
printer.printWithNoIndent(" = ")
parameter.initializer.accept(this)
}
}
override fun visitKtFunction(ktFunction: JKKtFunction) {
printer.printIndent()
ktFunction.modifierList.accept(this)
printer.printWithNoIndent(" fun ")
ktFunction.typeParameterList.accept(this)
printer.printWithNoIndent(ktFunction.name.value, "(")
renderList(ktFunction.parameters) {
it.accept(this)
}
printer.printWithNoIndent(")", ": ")
ktFunction.returnType.accept(this)
renderExtraTypeParametersUpperBounds(ktFunction.typeParameterList)
if (ktFunction.block !== JKBodyStub) {
printer.block(multiline = ktFunction.block.statements.isNotEmpty()) {
ktFunction.block.accept(this)
}
}
}
override fun visitKtOperatorExpression(ktOperatorExpression: JKKtOperatorExpression) {
ktOperatorExpression.receiver.accept(this)
printer.printWithNoIndent(" ")
printer.printWithNoIndent(ktOperatorExpression.identifier.name)
printer.printWithNoIndent(" ")
ktOperatorExpression.argument.accept(this)
}
override fun visitIfElseExpression(ifElseExpression: JKIfElseExpression) {
printer.printWithNoIndent("if (")
ifElseExpression.condition.accept(this)
printer.printWithNoIndent(")")
ifElseExpression.thenBranch.accept(this)
printer.printWithNoIndent(" else ")
ifElseExpression.elseBranch.accept(this)
}
override fun visitIfStatement(ifStatement: JKIfStatement) {
printer.printWithNoIndent("if (")
ifStatement.condition.accept(this)
printer.printWithNoIndent(")")
renderStatementOrBlock(ifStatement.thenBranch)
}
override fun visitIfElseStatement(ifElseStatement: JKIfElseStatement) {
visitIfStatement(ifElseStatement)
printer.printWithNoIndent(" else ")
renderStatementOrBlock(ifElseStatement.elseBranch)
}
private fun renderStatementOrBlock(statement: JKStatement, multiline: Boolean = false) {
if (statement is JKBlockStatement) {
printer.block(multiline) {
statement.block.accept(this)
}
} else {
statement.accept(this)
}
}
override fun visitBinaryExpression(binaryExpression: JKBinaryExpression) {
binaryExpression.left.accept(this)
printer.printWithNoIndent(" ")
printer.printWithNoIndent(binaryExpression.operator.token.text)
printer.printWithNoIndent(" ")
binaryExpression.right.accept(this)
}
override fun visitTypeParameterList(typeParameterList: JKTypeParameterList) {
if (typeParameterList.typeParameters.isNotEmpty()) {
printer.par(ANGLE) {
renderList(typeParameterList.typeParameters) {
it.accept(this)
}
}
}
}
override fun visitTypeParameter(typeParameter: JKTypeParameter) {
typeParameter.name.accept(this)
if (typeParameter.upperBounds.size == 1) {
printer.printWithNoIndent(" : ")
typeParameter.upperBounds.single().accept(this)
}
}
override fun visitLiteralExpression(literalExpression: JKLiteralExpression) {
printer.printWithNoIndent(literalExpression.literal)
}
override fun visitPrefixExpression(prefixExpression: JKPrefixExpression) {
printer.printWithNoIndent(prefixExpression.operator.token.text)
prefixExpression.expression.accept(this)
}
override fun visitThisExpression(thisExpression: JKThisExpression) {
printer.printWithNoIndent("this")
}
override fun visitSuperExpression(superExpression: JKSuperExpression) {
printer.printWithNoIndent("super")
}
override fun visitContinueStatement(continueStatement: JKContinueStatement) {
printer.printWithNoIndent("continue ")
continueStatement.label.accept(this)
}
override fun visitLabelEmpty(labelEmpty: JKLabelEmpty) {
}
override fun visitLabelText(labelText: JKLabelText) {
printer.printWithNoIndent("@")
labelText.label.accept(this)
printer.printWithNoIndent(" ")
}
override fun visitLabeledStatement(labeledStatement: JKLabeledStatement) {
for (label in labeledStatement.labels) {
label.accept(this)
printer.printWithNoIndent("@")
}
labeledStatement.statement.accept(this)
}
override fun visitNameIdentifier(nameIdentifier: JKNameIdentifier) {
printer.printWithNoIndent(nameIdentifier.value)
}
override fun visitPostfixExpression(postfixExpression: JKPostfixExpression) {
postfixExpression.expression.accept(this)
printer.printWithNoIndent(postfixExpression.operator.token.text)
}
override fun visitQualifiedExpression(qualifiedExpression: JKQualifiedExpression) {
qualifiedExpression.receiver.accept(this)
printer.printWithNoIndent(
when (qualifiedExpression.operator) {
is JKJavaQualifierImpl.DOT /*<-remove this TODO!*/, is JKKtQualifierImpl.DOT -> "."
is JKKtQualifierImpl.SAFE -> "?."
else -> TODO()
}
)
qualifiedExpression.selector.accept(this)
}
override fun visitExpressionList(expressionList: JKExpressionList) {
renderList(expressionList.expressions) { it.accept(this) }
}
override fun visitMethodCallExpression(methodCallExpression: JKMethodCallExpression) {
printer.printWithNoIndent(FqName(methodCallExpression.identifier.fqName).shortName().asString())
if (methodCallExpression.typeArguments.isNotEmpty()) {
printer.par(ANGLE) {
renderList(methodCallExpression.typeArguments) { it.accept(this) }
}
}
printer.par {
methodCallExpression.arguments.accept(this)
}
}
override fun visitParenthesizedExpression(parenthesizedExpression: JKParenthesizedExpression) {
printer.par {
parenthesizedExpression.expression.accept(this)
}
}
override fun visitDeclarationStatement(declarationStatement: JKDeclarationStatement) {
declarationStatement.declaredStatements.forEach {
it.accept(this)
printer.printlnWithNoIndent()
}
}
override fun visitTypeCastExpression(typeCastExpression: JKTypeCastExpression) {
typeCastExpression.expression.accept(this)
printer.printWithNoIndent(" as ")
typeCastExpression.type.accept(this)
}
override fun visitWhileStatement(whileStatement: JKWhileStatement) {
printer.print("while(")
whileStatement.condition.accept(this)
printer.printWithNoIndent(")")
if (whileStatement.body.isEmpty()) {
printer.printWithNoIndent(";")
} else {
renderStatementOrBlock(whileStatement.body, multiline = true)
}
}
override fun visitLocalVariable(localVariable: JKLocalVariable) {
if (localVariable.parent !is JKForInStatement) {
if (localVariable.modifierList.modality == JKModalityModifier.Modality.FINAL) {
printer.print("val")
} else {
printer.print("var")
}
}
printer.printWithNoIndent(" ", localVariable.name.value)
if (localVariable.type.present() && localVariable.type.type != JKContextType) {
printer.printWithNoIndent(": ")
localVariable.type.accept(this)
}
if (localVariable.initializer !is JKStubExpression) {
printer.printWithNoIndent(" = ")
localVariable.initializer.accept(this)
}
}
override fun visitEmptyStatement(emptyStatement: JKEmptyStatement) {
}
override fun visitStubExpression(stubExpression: JKStubExpression) {
}
override fun visitKtConvertedFromForLoopSyntheticWhileStatement(
ktConvertedFromForLoopSyntheticWhileStatement: JKKtConvertedFromForLoopSyntheticWhileStatement
) {
ktConvertedFromForLoopSyntheticWhileStatement.variableDeclaration.accept(this)
printer.printlnWithNoIndent()
ktConvertedFromForLoopSyntheticWhileStatement.whileStatement.accept(this)
}
private fun renderType(type: JKType) {
if (type is JKNoTypeImpl) return
when (type) {
is JKClassType -> type.classReference.fqName?.let { printer.printWithNoIndent(FqName(it).shortName().asString()) }
is JKUnresolvedClassType -> printer.printWithNoIndent(type.name)
is JKContextType -> return
is JKStarProjectionType ->
printer.printWithNoIndent("*")
is JKTypeParameterType ->
printer.printWithNoIndent(type.name)
is JKVarianceTypeParameterType -> {
when (type.variance) {
JKVarianceTypeParameterType.Variance.IN -> printer.printWithNoIndent("in ")
JKVarianceTypeParameterType.Variance.OUT -> printer.printWithNoIndent("out ")
}
renderType(type.boundType)
}
else -> printer.printWithNoIndent("Unit /* TODO: ${type::class} */")
}
if (type is JKParametrizedType && type.parameters.isNotEmpty()) {
printer.par(ANGLE) {
renderList(type.parameters, renderElement = ::renderType)
}
}
when (type.nullability) {
Nullability.Nullable -> printer.printWithNoIndent("?")
Nullability.Default -> printer.printWithNoIndent("?")// /* TODO: Default */")
else -> {
}
}
}
override fun visitJavaNewExpression(javaNewExpression: JKJavaNewExpression) {
printer.printWithNoIndent(FqName(javaNewExpression.constructorSymbol.fqName).shortName())//TODO import name somehow?
printer.printWithNoIndent("(")
renderList(javaNewExpression.arguments.expressions, ", ") {
it.accept(this)
}
printer.printWithNoIndent(")")
}
override fun visitTypeElement(typeElement: JKTypeElement) {
renderType(typeElement.type)
}
override fun visitBlock(block: JKBlock) {
renderList(block.statements, { printer.println() }) {
it.accept(this)
}
}
override fun visitExpressionStatement(expressionStatement: JKExpressionStatement) {
printer.printIndent()
expressionStatement.expression.accept(this)
}
override fun visitReturnStatement(returnStatement: JKReturnStatement) {
printer.print("return ")
returnStatement.expression.accept(this)
}
override fun visitFieldAccessExpression(fieldAccessExpression: JKFieldAccessExpression) {
printer.printWithNoIndent(FqName(fieldAccessExpression.identifier.fqName).shortName().asString())
}
override fun visitArrayAccessExpression(arrayAccessExpression: JKArrayAccessExpression) {
arrayAccessExpression.expression.accept(this)
printer.par(SQUARE) { arrayAccessExpression.indexExpression.accept(this) }
}
override fun visitDelegationConstructorCall(delegationConstructorCall: JKDelegationConstructorCall) {
delegationConstructorCall.expression.accept(this)
printer.par {
delegationConstructorCall.arguments.accept(this)
}
}
private fun renderParameterList(parameters: List<JKParameter>) {
printer.par(ROUND) {
renderList(parameters) {
it.accept(this)
}
}
}
override fun visitKtConstructor(ktConstructor: JKKtConstructor) {
ktConstructor.modifierList.accept(this)
printer.print(" constructor")
renderParameterList(ktConstructor.parameters)
if (ktConstructor.delegationCall !is JKStubExpression) {
builder.append(" : ")
ktConstructor.delegationCall.accept(this)
}
if (ktConstructor.block !== JKBodyStub) {
printer.block(multiline = true) {
ktConstructor.block.accept(this)
}
}
}
override fun visitKtPrimaryConstructor(ktPrimaryConstructor: JKKtPrimaryConstructor) {
val hasInitDeclaration =
(ktPrimaryConstructor.parent as JKClass).declarationList.any { it is JKKtInitDeclaration }
val hasAccessModifier =
ktPrimaryConstructor.modifierList.modifiers.any { it is JKAccessModifier }
if (hasAccessModifier && hasInitDeclaration && ktPrimaryConstructor.parameters.isNotEmpty()) {
ktPrimaryConstructor.modifierList.accept(this)
printer.printWithNoIndent(" constructor ")
}
if (ktPrimaryConstructor.parameters.isNotEmpty()) {
renderParameterList(ktPrimaryConstructor.parameters)
}
}
private inline fun Printer.indented(block: () -> Unit) {
this.pushIndent()
block()
this.popIndent()
}
private inline fun Printer.block(multiline: Boolean = false, crossinline body: () -> Unit) {
par(if (multiline) CURVED_MULTILINE else CURVED) {
indented(body)
}
}
private inline fun Printer.par(kind: ParenthesisKind = ParenthesisKind.ROUND, body: () -> Unit) {
this.printWithNoIndent(kind.open)
body()
this.printWithNoIndent(kind.close)
}
override fun visitLambdaExpression(lambdaExpression: JKLambdaExpression) {
printer.par(CURVED_MULTILINE) {
lambdaExpression.parameters.firstOrNull()?.accept(this)
lambdaExpression.parameters.asSequence().drop(1).forEach { printer.printWithNoIndent(", "); it.accept(this) }
if (lambdaExpression.parameters.isNotEmpty()) {
printer.printWithNoIndent(" -> ")
}
val statement = lambdaExpression.statement
if (statement is JKBlockStatement) {
statement.block.statements.forEach { it.accept(this) }
} else {
statement.accept(this)
}
}
}
override fun visitBlockStatement(blockStatement: JKBlockStatement) {
printer.par(CURVED) {
blockStatement.block.accept(this)
}
}
/*override fun visitParameter(parameter: JKParameter) {
printer.printWithNoIndent(parameter.name.value)
}*/
override fun visitKtAssignmentStatement(ktAssignmentStatement: JKKtAssignmentStatement) {
ktAssignmentStatement.field.accept(this)
printer.printWithNoIndent(" ")
printer.printWithNoIndent(ktAssignmentStatement.operator.token.text)
printer.printWithNoIndent(" ")
ktAssignmentStatement.expression.accept(this)
}
override fun visitKtWhenStatement(ktWhenStatement: JKKtWhenStatement) {
printer.printWithNoIndent("when(")
ktWhenStatement.expression.accept(this)
printer.printWithNoIndent(")")
printer.block(multiline = true) {
ktWhenStatement.cases.forEach { it.accept(this) }
}
}
override fun visitKtWhenCase(ktWhenCase: JKKtWhenCase) {
renderList(ktWhenCase.labels, ", ") {
it.accept(this)
}
printer.printWithNoIndent(" -> ")
ktWhenCase.statement.accept(this)
}
override fun visitKtElseWhenLabel(ktElseWhenLabel: JKKtElseWhenLabel) {
printer.printWithNoIndent("else")
}
override fun visitKtValueWhenLabel(ktValueWhenLabel: JKKtValueWhenLabel) {
ktValueWhenLabel.expression.accept(this)
}
}
private enum class ParenthesisKind(val open: String, val close: String) {
ROUND("(", ")"), SQUARE("[", "]"), CURVED("{", "}"), CURVED_MULTILINE("{\n", "}\n"), INLINE_COMMENT("/*", "*/"), ANGLE("<", ">")
}
fun printCodeOut(root: JKTreeElement): String {
Visitor().also { root.accept(it) }
return builder.toString()
}
}
private inline fun <T> List<T>.headTail(): Pair<T?, List<T>?> {
val head = this.firstOrNull()
val tail = if (size <= 1) null else subList(1, size)
return head to tail
}
private inline fun JKClass.primaryConstructor(): JKKtPrimaryConstructor? {
return this.declarationList.firstIsInstanceOrNull()
}
private inline fun JKDelegationConstructorCall.isCallOfConstructorOf(type: JKType): Boolean {
return when (type) {
is JKClassType -> {
val symbol = type.classReference as? JKClassSymbol ?: return false
this.identifier.name == symbol.name && this.identifier.declaredIn == symbol
}
is JKUnresolvedClassType -> {
this.identifier.name == type.name
}
else -> false
}
}