New J2K: separate logic in code builder to different classes

This commit is contained in:
Ilya Kirillov
2019-09-27 22:45:39 +03:00
parent 043a669812
commit 41935bdd34
7 changed files with 286 additions and 255 deletions
@@ -31,6 +31,7 @@ import kotlinx.coroutines.runBlocking
import kotlinx.coroutines.withContext
import org.jetbrains.kotlin.idea.core.util.EDT
import org.jetbrains.kotlin.j2k.*
import org.jetbrains.kotlin.nj2k.printing.JKCodeBuilder
import org.jetbrains.kotlin.nj2k.types.JKTypeFactory
import org.jetbrains.kotlin.psi.KtPsiFactory
@@ -135,7 +136,7 @@ class NewJavaToKotlinConverter(
processor.updateState(i, 1, phaseDescription)
val (element, ast) = elementWithAst
if (ast == null) return@mapIndexed null
val code = NewCodeBuilder(context).run { printCodeOut(ast) }
val code = JKCodeBuilder(context).run { printCodeOut(ast) }
val parseContext = when (element) {
is PsiStatement, is PsiExpression -> ParseContext.CODE_BLOCK
else -> ParseContext.TOP_LEVEL
@@ -3,76 +3,36 @@
* 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.nj2k
package org.jetbrains.kotlin.nj2k.printing
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.nj2k.symbols.JKSymbol
import org.jetbrains.kotlin.nj2k.*
import org.jetbrains.kotlin.nj2k.symbols.getDisplayFqName
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.tree.visitors.JKVisitorWithCommentsPrinting
import org.jetbrains.kotlin.nj2k.types.*
import org.jetbrains.kotlin.nj2k.types.JKContextType
import org.jetbrains.kotlin.nj2k.types.isInterface
import org.jetbrains.kotlin.nj2k.types.updateNullability
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class NewCodeBuilder(context: NewJ2kConverterContext) {
internal class JKCodeBuilder(context: NewJ2kConverterContext) {
private val elementInfoStorage = context.elementsInfoStorage
private val printer = JKPrinter(context.project, context.importStorage, elementInfoStorage)
private val commentPrinter = JKCommentPrinter(printer)
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"
fun printCodeOut(root: JKTreeElement): String {
Visitor().also { root.accept(it) }
return printer.toString().replace("\r\n", "\n")
}
inner class Visitor : JKVisitorWithCommentsPrinting() {
private val printedTokens = mutableSetOf<JKComment>()
//TODO move to ast transformation phase
private fun JKComment.shouldBeDropped(): Boolean =
text.startsWith("//noinspection")
private fun JKComment.createText() =
if (this !in printedTokens) {
printedTokens += this
text
} else null
private fun List<JKComment>.createText(): String = buildString {
var needNewLine = false
for (comment in this@createText) {
if (comment.shouldBeDropped()) continue
val text = comment.createText() ?: continue
if (needNewLine) appendln() else append(' ')
append(text)
needNewLine = text.startsWith("//") || '\n' in text
}
}
private fun String.hasNoLineBreakAfterSingleLineComment() = lastIndexOf('\n') < lastIndexOf("//")
private inner class Visitor : JKVisitorWithCommentsPrinting() {
override fun printLeftNonCodeElements(element: JKFormattingOwner) {
val text = element.trailingComments.createText()
printer.print(text)
val addNewLine = element.hasTrailingLineBreak
|| element is JKDeclaration && element.trailingComments.isNotEmpty() // add new line between comment & declaration
|| text.hasNoLineBreakAfterSingleLineComment()
if (addNewLine) printer.println()
commentPrinter.printTrailingComments(element)
}
override fun printRightNonCodeElements(element: JKFormattingOwner) {
val text = element.leadingComments.createText()
printer.print(text)
val addNewLine = element.hasLeadingLineBreak || text.hasNoLineBreakAfterSingleLineComment()
if (addNewLine) printer.println()
commentPrinter.printLeadingComments(element)
}
private fun renderTokenElement(tokenElement: JKTokenElement) {
@@ -81,24 +41,18 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
printRightNonCodeElements(tokenElement)
}
override fun visitModifierElementRaw(modifierElement: JKModifierElement) {
if (modifierElement.modifier != Modality.FINAL) {
printer.print(modifierElement.modifier.text)
}
}
private fun renderExtraTypeParametersUpperBounds(typeParameterList: JKTypeParameterList) {
val extraTypeBounds = typeParameterList.typeParameters
.filter { it.upperBounds.size > 1 }
if (extraTypeBounds.isNotEmpty()) {
printer.print(" where ")
val typeParametersWithBoudnds =
val typeParametersWithBounds =
extraTypeBounds.flatMap { typeParameter ->
typeParameter.upperBounds.map { bound ->
typeParameter.name to bound
}
}
printer.renderList(typeParametersWithBoudnds) { (name, bound) ->
printer.renderList(typeParametersWithBounds) { (name, bound) ->
name.accept(this)
printer.print(" : ")
bound.accept(this)
@@ -106,10 +60,35 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
}
}
private fun renderModifiersList(modifiersList: JKModifiersListOwner) {
val hasOverrideModifier = modifiersList
.safeAs<JKOtherModifiersOwner>()
?.hasOtherModifier(OtherModifier.OVERRIDE) == true
modifiersList.forEachModifier { modifierElement ->
if (modifierElement.modifier == Modality.FINAL || modifierElement.modifier == Visibility.PUBLIC) {
if (hasOverrideModifier) {
modifierElement.accept(this)
} else {
printLeftNonCodeElements(modifierElement)
printRightNonCodeElements(modifierElement)
}
} else {
modifierElement.accept(this)
}
printer.print(" ")
}
}
override fun visitTreeElementRaw(treeElement: JKTreeElement) {
printer.print("/* !!! Hit visitElement for element type: ${treeElement::class} !!! */")
}
override fun visitModifierElementRaw(modifierElement: JKModifierElement) {
if (modifierElement.modifier != Modality.FINAL) {
printer.print(modifierElement.modifier.text)
}
}
override fun visitTreeRootRaw(treeRoot: JKTreeRoot) {
treeRoot.element.accept(this)
}
@@ -195,26 +174,6 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
breakStatement.label.accept(this)
}
private fun renderModifiersList(modifiersList: JKModifiersListOwner) {
val hasOverrideModifier = modifiersList.safeAs<JKOtherModifiersOwner>()
?.otherModifierElements
?.any { it.otherModifier == OtherModifier.OVERRIDE } == true
modifiersList.forEachModifier { modifierElement ->
if (modifierElement.modifier == Modality.FINAL || modifierElement.modifier == Visibility.PUBLIC) {
if (hasOverrideModifier) {
modifierElement.accept(this)
} else {
printLeftNonCodeElements(modifierElement)
printRightNonCodeElements(modifierElement)
}
} else {
modifierElement.accept(this)
}
printer.print(" ")
}
}
override fun visitClassRaw(klass: JKClass) {
klass.annotationList.accept(this)
if (klass.annotationList.annotations.isNotEmpty()) {
@@ -222,7 +181,7 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
}
renderModifiersList(klass)
printer.print(" ")
printer.print(classKindString(klass.classKind))
printer.print(klass.classKind.text)
printer.print(" ")
klass.name.accept(this)
klass.typeParameterList.accept(this)
@@ -283,7 +242,6 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
}
}
override fun visitFieldRaw(field: JKField) {
field.annotationList.accept(this)
if (field.annotationList.annotations.isNotEmpty()) {
@@ -322,7 +280,6 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
}
}
override fun visitIsExpressionRaw(isExpression: JKIsExpression) {
isExpression.expression.accept(this)
printer.print(" is ")
@@ -353,7 +310,9 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
}
}
override fun visitKtAnnotationArrayInitializerExpressionRaw(ktAnnotationArrayInitializerExpression: JKKtAnnotationArrayInitializerExpression) {
override fun visitKtAnnotationArrayInitializerExpressionRaw(
ktAnnotationArrayInitializerExpression: JKKtAnnotationArrayInitializerExpression
) {
printer.print("[")
printer.renderList(ktAnnotationArrayInitializerExpression.initializers) {
it.accept(this)
@@ -431,7 +390,7 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
override fun visitTypeParameterListRaw(typeParameterList: JKTypeParameterList) {
if (typeParameterList.typeParameters.isNotEmpty()) {
printer.par(ParenthesisKind.ANGLE) {
printer.par(JKPrinterBase.ParenthesisKind.ANGLE) {
printer.renderList(typeParameterList.typeParameters) {
it.accept(this)
}
@@ -472,9 +431,7 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
printer.print(" ")
}
override fun visitLabelEmptyRaw(labelEmpty: JKLabelEmpty) {
}
override fun visitLabelEmptyRaw(labelEmpty: JKLabelEmpty) {}
override fun visitLabelTextRaw(labelText: JKLabelText) {
printer.print("@")
@@ -530,7 +487,7 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
override fun visitTypeArgumentListRaw(typeArgumentList: JKTypeArgumentList) {
if (typeArgumentList.typeArguments.isNotEmpty()) {
printer.par(ParenthesisKind.ANGLE) {
printer.par(JKPrinterBase.ParenthesisKind.ANGLE) {
printer.renderList(typeArgumentList.typeArguments) {
it.accept(this)
}
@@ -584,11 +541,9 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
}
}
override fun visitEmptyStatementRaw(emptyStatement: JKEmptyStatement) {
}
override fun visitEmptyStatementRaw(emptyStatement: JKEmptyStatement) {}
override fun visitStubExpressionRaw(stubExpression: JKStubExpression) {
}
override fun visitStubExpressionRaw(stubExpression: JKStubExpression) {}
override fun visitKtConvertedFromForLoopSyntheticWhileStatementRaw(
ktConvertedFromForLoopSyntheticWhileStatement: JKKtConvertedFromForLoopSyntheticWhileStatement
@@ -605,7 +560,7 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
printer.renderSymbol(newExpression.classSymbol, newExpression)
newExpression.typeArgumentList.accept(this)
if (!newExpression.classSymbol.isInterface() || newExpression.arguments.arguments.isNotEmpty()) {
printer.par(ParenthesisKind.ROUND) {
printer.par(JKPrinterBase.ParenthesisKind.ROUND) {
newExpression.arguments.accept(this)
}
}
@@ -706,7 +661,7 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
}
private fun renderParameterList(parameters: List<JKParameter>) {
printer.par(ParenthesisKind.ROUND) {
printer.par(JKPrinterBase.ParenthesisKind.ROUND) {
printer.renderList(parameters) {
it.accept(this)
}
@@ -740,14 +695,14 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
}
}
override fun visitLambdaExpressionRaw(lambdaExpression: JKLambdaExpression) {
val printLambda = {
printer.par(ParenthesisKind.CURVED) {
printer.par(JKPrinterBase.ParenthesisKind.CURVED) {
if (lambdaExpression.statement.statements.size > 1)
printer.println()
lambdaExpression.parameters.firstOrNull()?.accept(this)
lambdaExpression.parameters.asSequence().drop(1).forEach { printer.print(", "); it.accept(this) }
printer.renderList(lambdaExpression.parameters) {
it.accept(this)
}
if (lambdaExpression.parameters.isNotEmpty()) {
printer.print(" -> ")
}
@@ -758,14 +713,15 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
} else {
statement.accept(this)
}
if (lambdaExpression.statement.statements.size > 1)
if (lambdaExpression.statement.statements.size > 1) {
printer.println()
}
}
}
if (lambdaExpression.functionalType.present()) {
printer.renderType(lambdaExpression.functionalType.type, lambdaExpression)
printer.print(" ")
printer.par(ParenthesisKind.ROUND, printLambda)
printer.par(JKPrinterBase.ParenthesisKind.ROUND, printLambda)
} else {
printLambda()
}
@@ -846,14 +802,13 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
JKClassLiteralExpression.ClassLiteralType.KOTLIN_CLASS -> printer.print("class")
JKClassLiteralExpression.ClassLiteralType.JAVA_CLASS -> printer.print("class.java")
JKClassLiteralExpression.ClassLiteralType.JAVA_PRIMITIVE_CLASS -> printer.print("class.javaPrimitiveType")
JKClassLiteralExpression.ClassLiteralType.JAVA_VOID_TYPE -> {
}
JKClassLiteralExpression.ClassLiteralType.JAVA_VOID_TYPE -> Unit
}
}
}
override fun visitKtWhenCaseRaw(ktWhenCase: JKKtWhenCase) {
printer.renderList(ktWhenCase.labels, ", ") {
printer.renderList(ktWhenCase.labels) {
it.accept(this)
}
printer.print(" -> ")
@@ -868,148 +823,4 @@ class NewCodeBuilder(context: NewJ2kConverterContext) {
ktValueWhenLabel.expression.accept(this)
}
}
fun printCodeOut(root: JKTreeElement): String {
Visitor().also { root.accept(it) }
return printer.toString().replace("\r\n", "\n")
}
}
enum class ParenthesisKind(val open: String, val close: String) {
ROUND("(", ")"),
CURVED("{", "}"),
ANGLE("<", ">")
}
private class JKPrinter(
project: Project,
importStorage: JKImportStorage,
private val elementInfoStorage: JKElementInfoStorage
) {
val symbolRenderer = JKSymbolRenderer(importStorage, project)
private val stringBuilder: StringBuilder = StringBuilder()
private var currentIndent = 0;
private val indentSymbol = " ".repeat(4)
private var lastSymbolIsLineBreak = false
override fun toString(): String = stringBuilder.toString()
fun print(value: String) {
if (value.isNotEmpty()) {
lastSymbolIsLineBreak = false
}
stringBuilder.append(value)
}
fun println() {
if (lastSymbolIsLineBreak) return
stringBuilder.append('\n')
repeat(currentIndent) {
stringBuilder.append(indentSymbol)
}
lastSymbolIsLineBreak = true
}
inline fun indented(block: () -> Unit) {
currentIndent++
block()
currentIndent--
}
inline fun block(crossinline body: () -> Unit) {
par(ParenthesisKind.CURVED) {
indented(body)
}
}
inline fun par(kind: ParenthesisKind = ParenthesisKind.ROUND, body: () -> Unit) {
print(kind.open)
body()
print(kind.close)
}
private fun JKType.renderTypeInfo() {
this@JKPrinter.print(elementInfoStorage.getOrCreateInfoForElement(this).render())
}
fun renderType(type: JKType, owner: JKTreeElement?) {
if (type is JKNoType) return
if (type is JKCapturedType) {
when (val wildcard = type.wildcardType) {
is JKVarianceTypeParameterType -> {
renderType(wildcard.boundType, owner)
}
is JKStarProjectionType -> {
type.renderTypeInfo()
this.print("Any?")
}
}
return
}
type.renderTypeInfo()
when (type) {
is JKClassType -> {
renderSymbol(type.classReference, owner)
}
is JKContextType -> return
is JKStarProjectionType ->
this.print("*")
is JKTypeParameterType ->
this.print(type.identifier.name)
is JKVarianceTypeParameterType -> {
when (type.variance) {
JKVarianceTypeParameterType.Variance.IN -> this.print("in ")
JKVarianceTypeParameterType.Variance.OUT -> this.print("out ")
}
renderType(type.boundType, null)
}
else -> this.print("Unit /* TODO: ${type::class} */")
}
if (type is JKParametrizedType && type.parameters.isNotEmpty()) {
par(ParenthesisKind.ANGLE) {
renderList(type.parameters, renderElement = { renderType(it, null) })
}
}
// we print undefined types as nullable because we need smartcast to work in nullability inference in post-processing
if (type !is JKWildCardType
&& (type.nullability == Nullability.Default
&& owner?.safeAs<JKLambdaExpression>()?.functionalType?.type != type
|| type.nullability == Nullability.Nullable)
) {
this.print("?")
}
}
fun renderSymbol(symbol: JKSymbol, owner: JKTreeElement?) {
print(symbolRenderer.renderSymbol(symbol, owner))
}
inline fun <T> renderList(list: List<T>, separator: String = ", ", renderElement: (T) -> Unit) =
renderList(list, { this.print(separator) }, renderElement)
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)
}
}
}
fun String.escapedAsQualifiedName(): String =
split('.')
.map { it.escaped() }
.joinToString(".") { it }
private 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
}
@@ -0,0 +1,59 @@
/*
* Copyright 2010-2019 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.nj2k.printing
import org.jetbrains.kotlin.nj2k.tree.JKComment
import org.jetbrains.kotlin.nj2k.tree.JKDeclaration
import org.jetbrains.kotlin.nj2k.tree.JKFormattingOwner
internal class JKCommentPrinter(val printer: JKPrinter) {
private val printedTokens = mutableSetOf<JKComment>()
//TODO move to ast transformation phase
private fun JKComment.shouldBeDropped(): Boolean =
text.startsWith("//noinspection")
private fun JKComment.createText() =
if (this !in printedTokens) {
printedTokens += this
text
} else null
private fun List<JKComment>.createText(): String = buildString {
var needNewLine = false
for (comment in this@createText) {
if (comment.shouldBeDropped()) continue
val text = comment.createText() ?: continue
if (needNewLine) appendln() else append(' ')
append(text)
needNewLine = text.startsWith("//") || '\n' in text
}
}
private fun String.hasNoLineBreakAfterSingleLineComment() = lastIndexOf('\n') < lastIndexOf("//")
fun printLeadingComments(element: JKFormattingOwner) {
val text = element.leadingComments.createText()
printer.print(text)
val addNewLine = element.hasLeadingLineBreak || text.hasNoLineBreakAfterSingleLineComment()
if (addNewLine) printer.println()
}
fun printTrailingComments(element: JKFormattingOwner) {
val text = element.trailingComments.createText()
printer.print(text)
val addNewLine = element.hasTrailingLineBreak
|| element is JKDeclaration && element.trailingComments.isNotEmpty() // add new line between comment & declaration
|| text.hasNoLineBreakAfterSingleLineComment()
if (addNewLine) printer.println()
}
}
@@ -0,0 +1,141 @@
/*
* Copyright 2010-2019 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.nj2k.printing
import com.intellij.openapi.project.Project
import org.jetbrains.kotlin.j2k.ast.Nullability
import org.jetbrains.kotlin.nj2k.JKElementInfoStorage
import org.jetbrains.kotlin.nj2k.JKImportStorage
import org.jetbrains.kotlin.nj2k.symbols.JKSymbol
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.nj2k.types.*
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
internal open class JKPrinterBase {
private val stringBuilder: StringBuilder = StringBuilder()
var currentIndent = 0;
private val indentSymbol = " ".repeat(4)
private var lastSymbolIsLineBreak = false
override fun toString(): String = stringBuilder.toString()
fun print(value: String) {
if (value.isNotEmpty()) {
lastSymbolIsLineBreak = false
}
stringBuilder.append(value)
}
fun println() {
if (lastSymbolIsLineBreak) return
stringBuilder.append('\n')
repeat(currentIndent) {
stringBuilder.append(indentSymbol)
}
lastSymbolIsLineBreak = true
}
inline fun indented(block: () -> Unit) {
currentIndent++
block()
currentIndent--
}
inline fun block(body: () -> Unit) {
par(ParenthesisKind.CURVED) {
indented(body)
}
}
inline fun par(kind: ParenthesisKind = ParenthesisKind.ROUND, body: () -> Unit) {
print(kind.open)
body()
print(kind.close)
}
inline fun <T> renderList(list: List<T>, separator: String = ", ", renderElement: (T) -> Unit) =
renderList(list, { this.print(separator) }, renderElement)
inline fun <T> renderList(list: List<T>, separator: () -> Unit, renderElement: (T) -> Unit) {
if (list.isEmpty()) return
renderElement(list.first())
for (element in list.subList(1, list.size)) {
separator()
renderElement(element)
}
}
enum class ParenthesisKind(val open: String, val close: String) {
ROUND("(", ")"),
CURVED("{", "}"),
ANGLE("<", ">")
}
}
internal class JKPrinter(
project: Project,
importStorage: JKImportStorage,
private val elementInfoStorage: JKElementInfoStorage
) : JKPrinterBase() {
val symbolRenderer = JKSymbolRenderer(importStorage, project)
private fun JKType.renderTypeInfo() {
this@JKPrinter.print(elementInfoStorage.getOrCreateInfoForElement(this).render())
}
fun renderType(type: JKType, owner: JKTreeElement?) {
if (type is JKNoType) return
if (type is JKCapturedType) {
when (val wildcard = type.wildcardType) {
is JKVarianceTypeParameterType -> {
renderType(wildcard.boundType, owner)
}
is JKStarProjectionType -> {
type.renderTypeInfo()
this.print("Any?")
}
}
return
}
type.renderTypeInfo()
when (type) {
is JKClassType -> {
renderSymbol(type.classReference, owner)
}
is JKContextType -> return
is JKStarProjectionType ->
this.print("*")
is JKTypeParameterType ->
this.print(type.identifier.name)
is JKVarianceTypeParameterType -> {
when (type.variance) {
JKVarianceTypeParameterType.Variance.IN -> this.print("in ")
JKVarianceTypeParameterType.Variance.OUT -> this.print("out ")
}
renderType(type.boundType, null)
}
else -> this.print("Unit /* TODO: ${type::class} */")
}
if (type is JKParametrizedType && type.parameters.isNotEmpty()) {
par(ParenthesisKind.ANGLE) {
renderList(type.parameters, renderElement = { renderType(it, null) })
}
}
// we print undefined types as nullable because we need smartcast to work in nullability inference in post-processing
if (type !is JKWildCardType
&& (type.nullability == Nullability.Default
&& owner?.safeAs<JKLambdaExpression>()?.functionalType?.type != type
|| type.nullability == Nullability.Nullable)
) {
this.print("?")
}
}
fun renderSymbol(symbol: JKSymbol, owner: JKTreeElement?) {
print(symbolRenderer.renderSymbol(symbol, owner))
}
}
@@ -3,21 +3,22 @@
* 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.nj2k
package org.jetbrains.kotlin.nj2k.printing
import com.intellij.openapi.project.Project
import com.intellij.psi.search.GlobalSearchScope
import com.intellij.psi.search.PsiShortNamesCache
import com.intellij.util.Processor
import org.jetbrains.kotlin.builtins.KotlinBuiltIns
import org.jetbrains.kotlin.name.SpecialNames
import org.jetbrains.kotlin.nj2k.JKImportStorage
import org.jetbrains.kotlin.nj2k.escaped
import org.jetbrains.kotlin.nj2k.symbols.*
import org.jetbrains.kotlin.nj2k.tree.JKClassAccessExpression
import org.jetbrains.kotlin.nj2k.tree.JKQualifiedExpression
import org.jetbrains.kotlin.nj2k.tree.JKTreeElement
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
class JKSymbolRenderer(private val importStorage: JKImportStorage, project: Project) {
internal class JKSymbolRenderer(private val importStorage: JKImportStorage, project: Project) {
private val canBeShortenedClassNameCache = CanBeShortenedCache(project)
private fun JKSymbol.isFqNameExpected(owner: JKTreeElement?): Boolean {
@@ -0,0 +1,13 @@
/*
* Copyright 2010-2019 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.nj2k.printing
import org.jetbrains.kotlin.nj2k.escaped
internal fun String.escapedAsQualifiedName(): String =
split('.')
.map { it.escaped() }
.joinToString(".") { it }
@@ -35,8 +35,13 @@ class JKClass(
override var visibilityElement by child(visibilityElement)
override var modalityElement by child(modalityElement)
enum class ClassKind {
ANNOTATION, CLASS, ENUM, INTERFACE, OBJECT, COMPANION
enum class ClassKind(val text: String) {
ANNOTATION("annotation class"),
CLASS("class"),
ENUM("enum class"),
INTERFACE("interface"),
OBJECT("object"),
COMPANION("companion object")
}
}