Java to Kotlin converter: minor code refactorings after code review

This commit is contained in:
Valentin Kipyatkov
2014-06-23 14:20:54 +04:00
parent 6135ea5603
commit a28e7b0872
5 changed files with 43 additions and 41 deletions
@@ -80,8 +80,7 @@ fun PsiElement.getContainingConstructor(): PsiMethod? {
fun PsiMethodCallExpression.isSuperConstructorCall(): Boolean {
val ref = getMethodExpression()
if (ref.getCanonicalText() == "super") {
val target = ref.resolve()
return target is PsiMethod && target.isConstructor()
return ref.resolve()?.isConstructor() ?: false
}
return false
}
@@ -89,3 +88,4 @@ fun PsiMethodCallExpression.isSuperConstructorCall(): Boolean {
fun PsiReferenceExpression.isThisConstructorCall(): Boolean
= getReferences().filter { it.getCanonicalText() == "this" }.map { it.resolve() }.any { it is PsiMethod && it.isConstructor() }
fun PsiElement.isConstructor(): Boolean = this is PsiMethod && this.isConstructor()
+1 -1
View File
@@ -147,7 +147,7 @@ public class Converter private(val project: Project, val settings: ConverterSett
// do not convert private static methods into class object if possible
private fun shouldGenerateClassObject(psiClass: PsiClass, convertedMembers: Map<PsiMember, Member>): Boolean {
if (psiClass.isEnum()) return false
val members = convertedMembers.keySet().filter { it !is PsiMethod || !it.isConstructor() }
val members = convertedMembers.keySet().filter { !it.isConstructor() }
val classObjectMembers = members.filter { it !is PsiClass && it.hasModifierProperty(PsiModifier.STATIC) }
val nestedClasses = members.filterIsInstance(javaClass<PsiClass>()).filter { it.hasModifierProperty(PsiModifier.STATIC) }
if (classObjectMembers.all { it is PsiMethod && it.hasModifierProperty(PsiModifier.PRIVATE) }) {
@@ -37,8 +37,7 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver
importNames = importList?.imports?.mapTo(HashSet<String>()) { it.name } ?: setOf()
}
public var importNames: Set<String> = setOf()
private set
private var importNames: Set<String> = setOf()
public val importsToAdd: Collection<Import>
get() = classesToImport.map { Import(it) }
@@ -46,7 +45,7 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver
public fun convertType(`type`: PsiType?, nullability: Nullability = Nullability.Default): Type {
if (`type` == null) return Type.Empty
val result = `type`.accept<Type>(TypeVisitor(this, classesToImport))!!
val result = `type`.accept<Type>(TypeVisitor(this, importNames, classesToImport))!!
return when (nullability) {
Nullability.NotNull -> result.toNotNullType()
Nullability.Nullable -> result.toNullableType()
@@ -277,39 +277,7 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
if (resourceList != null) {
val variables = resourceList.getResourceVariables()
if (variables.isNotEmpty()) {
var wrapResultStatement: (Expression) -> Statement = { it }
var converterForBody = converter
val returns = collectReturns(tryBlock)
//TODO: support other returns when non-local returns supported by Kotlin
if (returns.size == 1 && returns.single() == tryBlock!!.getStatements().last()) {
wrapResultStatement = { ReturnStatement(it) }
converterForBody = converter.withStatementVisitor { object : StatementVisitor(it) {
override fun visitReturnStatement(statement: PsiReturnStatement) {
if (statement == returns.single()) {
result = converter.convertExpression(statement.getReturnValue(), tryStatement.getContainingMethod()?.getReturnType())
}
else {
super.visitReturnStatement(statement)
}
}
}}
}
var block = converterForBody.convertBlock(tryBlock)
var expression: Expression = Expression.Empty
for (variable in variables.reverse()) {
val lambda = LambdaExpression(Identifier.toKotlin(variable.getName()!!), block)
expression = MethodCallExpression.build(converter.convertExpression(variable.getInitializer()), "use", listOf(), listOf(), false, lambda)
block = Block(listOf(expression), LBrace(), RBrace())
}
if (catchesConverted.isEmpty() && finallyConverted.isEmpty) {
result = wrapResultStatement(expression)
return
}
result = TryStatement(Block(listOf(wrapResultStatement(expression)), LBrace(), RBrace(), true), catchesConverted, finallyConverted)
result = convertTryWithResources(tryBlock, variables, catchesConverted, finallyConverted)
return
}
}
@@ -317,6 +285,41 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
result = TryStatement(converter.convertBlock(tryBlock), catchesConverted, finallyConverted)
}
private fun convertTryWithResources(tryBlock: PsiCodeBlock?, resourceVariables: List<PsiResourceVariable>, catchesConverted: List<CatchStatement>, finallyConverted: Block): Statement {
var wrapResultStatement: (Expression) -> Statement = { it }
var converterForBody = converter
val returns = collectReturns(tryBlock)
//TODO: support other returns when non-local returns supported by Kotlin
if (returns.size == 1 && returns.single() == tryBlock!!.getStatements().last()) {
wrapResultStatement = { ReturnStatement(it) }
converterForBody = converter.withStatementVisitor { object : StatementVisitor(it) {
override fun visitReturnStatement(statement: PsiReturnStatement) {
if (statement == returns.single()) {
result = converter.convertExpression(statement.getReturnValue(), tryBlock!!.getContainingMethod()?.getReturnType())
}
else {
super.visitReturnStatement(statement)
}
}
}}
}
var block = converterForBody.convertBlock(tryBlock)
var expression: Expression = Expression.Empty
for (variable in resourceVariables.reverse()) {
val lambda = LambdaExpression(Identifier.toKotlin(variable.getName()!!), block)
expression = MethodCallExpression.build(converter.convertExpression(variable.getInitializer()), "use", listOf(), listOf(), false, lambda)
block = Block(listOf(expression), LBrace(), RBrace())
}
if (catchesConverted.isEmpty() && finallyConverted.isEmpty) {
return wrapResultStatement(expression)
}
return TryStatement(Block(listOf(wrapResultStatement(expression)), LBrace(), RBrace(), true), catchesConverted, finallyConverted)
}
private fun collectReturns(block: PsiCodeBlock?): Collection<PsiReturnStatement> {
val returns = ArrayList<PsiReturnStatement>()
block?.accept(object: JavaRecursiveElementVisitor() {
@@ -27,7 +27,7 @@ import org.jetbrains.jet.j2k.TypeConverter
private val PRIMITIVE_TYPES_NAMES = JvmPrimitiveType.values().map { it.getName() }
class TypeVisitor(private val converter: TypeConverter, private val classesToImport: MutableSet<String>) : PsiTypeVisitor<Type>() {
class TypeVisitor(private val converter: TypeConverter, private val importNames: Set<String>, private val classesToImport: MutableSet<String>) : PsiTypeVisitor<Type>() {
override fun visitPrimitiveType(primitiveType: PsiPrimitiveType): Type {
val name = primitiveType.getCanonicalText()
return if (name == "void") {
@@ -75,7 +75,7 @@ class TypeVisitor(private val converter: TypeConverter, private val classesToImp
val kotlinClassName = toKotlinTypesMap[javaClassName]
if (kotlinClassName != null) {
val kotlinShortName = getShortName(kotlinClassName)
if (kotlinShortName == getShortName(javaClassName!!) && converter.importNames.contains(getPackageName(javaClassName) + ".*")) {
if (kotlinShortName == getShortName(javaClassName!!) && importNames.contains(getPackageName(javaClassName) + ".*")) {
classesToImport.add(kotlinClassName)
}
return Identifier(kotlinShortName)