New J2K: always print fully qualified names in printer to avoid name conflicts

This commit is contained in:
Ilya Kirillov
2019-04-08 18:42:24 +03:00
parent aa53489e0b
commit d20e4bac1d
2 changed files with 44 additions and 30 deletions
@@ -165,7 +165,7 @@ class NewCodeBuilder {
}
override fun visitClassAccessExpressionRaw(classAccessExpression: JKClassAccessExpression) {
printer.printWithNoIndent(classAccessExpression.identifier.displayName().escaped())
renderClassSymbol(classAccessExpression.identifier, classAccessExpression)
}
override fun visitFileRaw(file: JKFile) {
@@ -260,10 +260,10 @@ class NewCodeBuilder {
val extendTypes = inheritanceInfo.extends.map { it.type.updateNullability(Nullability.NotNull) }
val implementTypes = inheritanceInfo.implements.map { it.type.updateNullability(Nullability.NotNull) }
if (isInInterface) {
renderList(extendTypes) { renderType(it) }
renderList(extendTypes) { renderType(it, null) }
} else {
extendTypes.singleOrNull()?.also { superType ->
renderType(superType)
renderType(superType, null)
val primaryConstructor = parentClass.primaryConstructor()
val delegationCall =
primaryConstructor
@@ -271,7 +271,7 @@ class NewCodeBuilder {
?.let { it as? JKDelegationConstructorCall }
if (delegationCall != null) {
printer.par { delegationCall.arguments.accept(this) }
} else if (!superType.isInterface()) {
} else if (!superType.isInterface() && primaryConstructor != null) {
printer.printWithNoIndent("()")
}
}
@@ -280,7 +280,7 @@ class NewCodeBuilder {
if (implementTypes.isNotEmpty() && extendTypes.size == 1) {
printer.printWithNoIndent(", ")
}
renderList(implementTypes) { renderType(it) }
renderList(implementTypes) { renderType(it, null) }
}
@@ -647,13 +647,18 @@ class NewCodeBuilder {
ktConvertedFromForLoopSyntheticWhileStatement.whileStatement.accept(this)
}
private fun renderType(type: JKType) {
private fun JKClassSymbol.needFqName(): Boolean =
fqName !in mappedToKotlinFqNames
private fun renderType(type: JKType, owner: JKTreeElement?) {
if (type is JKNoTypeImpl) return
if (type.nullability == Nullability.Default) {
printer.print("/*UNDEFINED*/")
}
when (type) {
is JKClassType -> printer.printWithNoIndent(type.classReference.displayName().escapedAsQualifiedName())
is JKClassType -> {
renderClassSymbol(type.classReference, owner)
}
is JKContextType -> return
is JKStarProjectionType ->
printer.printWithNoIndent("*")
@@ -664,13 +669,13 @@ class NewCodeBuilder {
JKVarianceTypeParameterType.Variance.IN -> printer.printWithNoIndent("in ")
JKVarianceTypeParameterType.Variance.OUT -> printer.printWithNoIndent("out ")
}
renderType(type.boundType)
renderType(type.boundType, null)
}
else -> printer.printWithNoIndent("Unit /* TODO: ${type::class} */")
}
if (type is JKParametrizedType && type.parameters.isNotEmpty()) {
printer.par(ANGLE) {
renderList(type.parameters, renderElement = { renderType(it) })
renderList(type.parameters, renderElement = { renderType(it, null) })
}
}
if (type.nullability == Nullability.Nullable) {
@@ -678,11 +683,20 @@ class NewCodeBuilder {
}
}
private fun renderClassSymbol(classSymbol: JKClassSymbol, owner: JKTreeElement?) {
val needFqName = classSymbol.needFqName() && owner?.isSelectorOfQualifiedExpression() != true
val displayName = if (needFqName) classSymbol.getDisplayName() else classSymbol.name
printer.printWithNoIndent(displayName.escapedAsQualifiedName())
}
private fun JKTreeElement.isSelectorOfQualifiedExpression() =
parent?.safeAs<JKQualifiedExpression>()?.selector == this
override fun visitJavaNewExpressionRaw(javaNewExpression: JKJavaNewExpression) {
if (javaNewExpression.isAnonymousClass()) {
printer.printWithNoIndent("object : ")
}
printer.printWithNoIndent(javaNewExpression.classSymbol.displayName().escapedAsQualifiedName())
renderClassSymbol(javaNewExpression.classSymbol, javaNewExpression)
javaNewExpression.typeArgumentList.accept(this)
if (!javaNewExpression.classSymbol.isInterface()) {
printer.par(ROUND) {
@@ -716,7 +730,7 @@ class NewCodeBuilder {
override fun visitEmptyClassBodyRaw(emptyClassBody: JKEmptyClassBody) {}
override fun visitTypeElementRaw(typeElement: JKTypeElement) {
renderType(typeElement.type)
renderType(typeElement.type, typeElement)
}
override fun visitBlockRaw(block: JKBlock) {
@@ -872,7 +886,7 @@ class NewCodeBuilder {
override fun visitAnnotationRaw(annotation: JKAnnotation) {
printer.printWithNoIndent("@")
printer.printWithNoIndent(annotation.classSymbol.displayName().escapedAsQualifiedName())
printer.printWithNoIndent(annotation.classSymbol.fqName.escapedAsQualifiedName())
if (annotation.arguments.isNotEmpty()) {
printer.par {
renderList(annotation.arguments) { it.accept(this) }
@@ -894,7 +908,7 @@ class NewCodeBuilder {
if (classLiteralExpression.literalType == JKClassLiteralExpression.LiteralType.JAVA_VOID_TYPE) {
printer.printWithNoIndent("Void.TYPE")
} else {
renderType(classLiteralExpression.classType.type)
renderType(classLiteralExpression.classType.type, classLiteralExpression)
printer.printWithNoIndent("::")
when (classLiteralExpression.literalType) {
JKClassLiteralExpression.LiteralType.KOTLIN_CLASS -> printer.printWithNoIndent("class")
@@ -954,3 +968,13 @@ private val KEYWORDS = KtTokens.KEYWORDS.types.map { (it as KtKeywordToken).valu
private fun String.escaped() =
if (this in KEYWORDS || '$' in this) "`$this`"
else this
private val mappedToKotlinFqNames =
setOf(
"java.util.ArrayList",
"java.util.LinkedHashMap",
"java.util.HashMap",
"java.util.LinkedHashSet",
"java.util.HashSet"
)
@@ -17,6 +17,7 @@ import org.jetbrains.kotlin.nj2k.conversions.parentOfType
import org.jetbrains.kotlin.nj2k.tree.*
import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClass
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
interface JKSymbol {
val target: Any
@@ -52,6 +53,12 @@ abstract class JKUniverseSymbol<T : JKTreeElement> : JKNamedSymbol {
}
}
fun JKSymbol.getDisplayName(): String {
if (this !is JKUniverseSymbol<*>) return fqName
return generateSequence(declaredIn as? JKUniverseClassSymbol) { symbol ->
symbol.declaredIn.safeAs<JKUniverseClassSymbol>()?.takeIf { !it.target.hasExtraModifier(ExtraModifier.INNER) }
}.fold(name) { acc, symbol -> "${symbol.name}.$acc" }
}
fun JKSymbol.fqNameToImport(): String? =
when {
@@ -114,23 +121,6 @@ class JKMultiverseKtClassSymbol(
get() = target.fqName?.asString() ?: name
}
fun JKClassSymbol.displayName() =
when (this) {
is JKUniverseClassSymbol ->
target.psi<PsiClass>()
?.nameWithOuterClasses()
?: name
is JKMultiverseClassSymbol -> target.nameWithOuterClasses()
else -> name
}
fun PsiClass.nameWithOuterClasses() =
generateSequence(this) { it.containingClass }
.toList()
.reversed()
.joinToString(separator = ".") { it.name!! }
class JKUniverseMethodSymbol(override val symbolProvider: JKSymbolProvider) : JKMethodSymbol, JKUniverseSymbol<JKMethod>() {
override val receiverType: JKType?
get() = (target.parent as? JKClass)?.let {