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) { override fun visitClassAccessExpressionRaw(classAccessExpression: JKClassAccessExpression) {
printer.printWithNoIndent(classAccessExpression.identifier.displayName().escaped()) renderClassSymbol(classAccessExpression.identifier, classAccessExpression)
} }
override fun visitFileRaw(file: JKFile) { override fun visitFileRaw(file: JKFile) {
@@ -260,10 +260,10 @@ class NewCodeBuilder {
val extendTypes = inheritanceInfo.extends.map { it.type.updateNullability(Nullability.NotNull) } val extendTypes = inheritanceInfo.extends.map { it.type.updateNullability(Nullability.NotNull) }
val implementTypes = inheritanceInfo.implements.map { it.type.updateNullability(Nullability.NotNull) } val implementTypes = inheritanceInfo.implements.map { it.type.updateNullability(Nullability.NotNull) }
if (isInInterface) { if (isInInterface) {
renderList(extendTypes) { renderType(it) } renderList(extendTypes) { renderType(it, null) }
} else { } else {
extendTypes.singleOrNull()?.also { superType -> extendTypes.singleOrNull()?.also { superType ->
renderType(superType) renderType(superType, null)
val primaryConstructor = parentClass.primaryConstructor() val primaryConstructor = parentClass.primaryConstructor()
val delegationCall = val delegationCall =
primaryConstructor primaryConstructor
@@ -271,7 +271,7 @@ class NewCodeBuilder {
?.let { it as? JKDelegationConstructorCall } ?.let { it as? JKDelegationConstructorCall }
if (delegationCall != null) { if (delegationCall != null) {
printer.par { delegationCall.arguments.accept(this) } printer.par { delegationCall.arguments.accept(this) }
} else if (!superType.isInterface()) { } else if (!superType.isInterface() && primaryConstructor != null) {
printer.printWithNoIndent("()") printer.printWithNoIndent("()")
} }
} }
@@ -280,7 +280,7 @@ class NewCodeBuilder {
if (implementTypes.isNotEmpty() && extendTypes.size == 1) { if (implementTypes.isNotEmpty() && extendTypes.size == 1) {
printer.printWithNoIndent(", ") printer.printWithNoIndent(", ")
} }
renderList(implementTypes) { renderType(it) } renderList(implementTypes) { renderType(it, null) }
} }
@@ -647,13 +647,18 @@ class NewCodeBuilder {
ktConvertedFromForLoopSyntheticWhileStatement.whileStatement.accept(this) 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 is JKNoTypeImpl) return
if (type.nullability == Nullability.Default) { if (type.nullability == Nullability.Default) {
printer.print("/*UNDEFINED*/") printer.print("/*UNDEFINED*/")
} }
when (type) { when (type) {
is JKClassType -> printer.printWithNoIndent(type.classReference.displayName().escapedAsQualifiedName()) is JKClassType -> {
renderClassSymbol(type.classReference, owner)
}
is JKContextType -> return is JKContextType -> return
is JKStarProjectionType -> is JKStarProjectionType ->
printer.printWithNoIndent("*") printer.printWithNoIndent("*")
@@ -664,13 +669,13 @@ class NewCodeBuilder {
JKVarianceTypeParameterType.Variance.IN -> printer.printWithNoIndent("in ") JKVarianceTypeParameterType.Variance.IN -> printer.printWithNoIndent("in ")
JKVarianceTypeParameterType.Variance.OUT -> printer.printWithNoIndent("out ") JKVarianceTypeParameterType.Variance.OUT -> printer.printWithNoIndent("out ")
} }
renderType(type.boundType) renderType(type.boundType, null)
} }
else -> printer.printWithNoIndent("Unit /* TODO: ${type::class} */") else -> printer.printWithNoIndent("Unit /* TODO: ${type::class} */")
} }
if (type is JKParametrizedType && type.parameters.isNotEmpty()) { if (type is JKParametrizedType && type.parameters.isNotEmpty()) {
printer.par(ANGLE) { printer.par(ANGLE) {
renderList(type.parameters, renderElement = { renderType(it) }) renderList(type.parameters, renderElement = { renderType(it, null) })
} }
} }
if (type.nullability == Nullability.Nullable) { 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) { override fun visitJavaNewExpressionRaw(javaNewExpression: JKJavaNewExpression) {
if (javaNewExpression.isAnonymousClass()) { if (javaNewExpression.isAnonymousClass()) {
printer.printWithNoIndent("object : ") printer.printWithNoIndent("object : ")
} }
printer.printWithNoIndent(javaNewExpression.classSymbol.displayName().escapedAsQualifiedName()) renderClassSymbol(javaNewExpression.classSymbol, javaNewExpression)
javaNewExpression.typeArgumentList.accept(this) javaNewExpression.typeArgumentList.accept(this)
if (!javaNewExpression.classSymbol.isInterface()) { if (!javaNewExpression.classSymbol.isInterface()) {
printer.par(ROUND) { printer.par(ROUND) {
@@ -716,7 +730,7 @@ class NewCodeBuilder {
override fun visitEmptyClassBodyRaw(emptyClassBody: JKEmptyClassBody) {} override fun visitEmptyClassBodyRaw(emptyClassBody: JKEmptyClassBody) {}
override fun visitTypeElementRaw(typeElement: JKTypeElement) { override fun visitTypeElementRaw(typeElement: JKTypeElement) {
renderType(typeElement.type) renderType(typeElement.type, typeElement)
} }
override fun visitBlockRaw(block: JKBlock) { override fun visitBlockRaw(block: JKBlock) {
@@ -872,7 +886,7 @@ class NewCodeBuilder {
override fun visitAnnotationRaw(annotation: JKAnnotation) { override fun visitAnnotationRaw(annotation: JKAnnotation) {
printer.printWithNoIndent("@") printer.printWithNoIndent("@")
printer.printWithNoIndent(annotation.classSymbol.displayName().escapedAsQualifiedName()) printer.printWithNoIndent(annotation.classSymbol.fqName.escapedAsQualifiedName())
if (annotation.arguments.isNotEmpty()) { if (annotation.arguments.isNotEmpty()) {
printer.par { printer.par {
renderList(annotation.arguments) { it.accept(this) } renderList(annotation.arguments) { it.accept(this) }
@@ -894,7 +908,7 @@ class NewCodeBuilder {
if (classLiteralExpression.literalType == JKClassLiteralExpression.LiteralType.JAVA_VOID_TYPE) { if (classLiteralExpression.literalType == JKClassLiteralExpression.LiteralType.JAVA_VOID_TYPE) {
printer.printWithNoIndent("Void.TYPE") printer.printWithNoIndent("Void.TYPE")
} else { } else {
renderType(classLiteralExpression.classType.type) renderType(classLiteralExpression.classType.type, classLiteralExpression)
printer.printWithNoIndent("::") printer.printWithNoIndent("::")
when (classLiteralExpression.literalType) { when (classLiteralExpression.literalType) {
JKClassLiteralExpression.LiteralType.KOTLIN_CLASS -> printer.printWithNoIndent("class") 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() = private fun String.escaped() =
if (this in KEYWORDS || '$' in this) "`$this`" if (this in KEYWORDS || '$' in this) "`$this`"
else 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.nj2k.tree.*
import org.jetbrains.kotlin.psi.* import org.jetbrains.kotlin.psi.*
import org.jetbrains.kotlin.psi.psiUtil.containingClass import org.jetbrains.kotlin.psi.psiUtil.containingClass
import org.jetbrains.kotlin.utils.addToStdlib.safeAs
interface JKSymbol { interface JKSymbol {
val target: Any 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? = fun JKSymbol.fqNameToImport(): String? =
when { when {
@@ -114,23 +121,6 @@ class JKMultiverseKtClassSymbol(
get() = target.fqName?.asString() ?: name 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>() { class JKUniverseMethodSymbol(override val symbolProvider: JKSymbolProvider) : JKMethodSymbol, JKUniverseSymbol<JKMethod>() {
override val receiverType: JKType? override val receiverType: JKType?
get() = (target.parent as? JKClass)?.let { get() = (target.parent as? JKClass)?.let {