Java to Kotlin converter: minor code refactorings after code review
This commit is contained in:
@@ -80,8 +80,7 @@ fun PsiElement.getContainingConstructor(): PsiMethod? {
|
|||||||
fun PsiMethodCallExpression.isSuperConstructorCall(): Boolean {
|
fun PsiMethodCallExpression.isSuperConstructorCall(): Boolean {
|
||||||
val ref = getMethodExpression()
|
val ref = getMethodExpression()
|
||||||
if (ref.getCanonicalText() == "super") {
|
if (ref.getCanonicalText() == "super") {
|
||||||
val target = ref.resolve()
|
return ref.resolve()?.isConstructor() ?: false
|
||||||
return target is PsiMethod && target.isConstructor()
|
|
||||||
}
|
}
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -89,3 +88,4 @@ fun PsiMethodCallExpression.isSuperConstructorCall(): Boolean {
|
|||||||
fun PsiReferenceExpression.isThisConstructorCall(): Boolean
|
fun PsiReferenceExpression.isThisConstructorCall(): Boolean
|
||||||
= getReferences().filter { it.getCanonicalText() == "this" }.map { it.resolve() }.any { it is PsiMethod && it.isConstructor() }
|
= getReferences().filter { it.getCanonicalText() == "this" }.map { it.resolve() }.any { it is PsiMethod && it.isConstructor() }
|
||||||
|
|
||||||
|
fun PsiElement.isConstructor(): Boolean = this is PsiMethod && this.isConstructor()
|
||||||
|
|||||||
@@ -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
|
// do not convert private static methods into class object if possible
|
||||||
private fun shouldGenerateClassObject(psiClass: PsiClass, convertedMembers: Map<PsiMember, Member>): Boolean {
|
private fun shouldGenerateClassObject(psiClass: PsiClass, convertedMembers: Map<PsiMember, Member>): Boolean {
|
||||||
if (psiClass.isEnum()) return false
|
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 classObjectMembers = members.filter { it !is PsiClass && it.hasModifierProperty(PsiModifier.STATIC) }
|
||||||
val nestedClasses = members.filterIsInstance(javaClass<PsiClass>()).filter { 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) }) {
|
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()
|
importNames = importList?.imports?.mapTo(HashSet<String>()) { it.name } ?: setOf()
|
||||||
|
|
||||||
}
|
}
|
||||||
public var importNames: Set<String> = setOf()
|
private var importNames: Set<String> = setOf()
|
||||||
private set
|
|
||||||
|
|
||||||
public val importsToAdd: Collection<Import>
|
public val importsToAdd: Collection<Import>
|
||||||
get() = classesToImport.map { Import(it) }
|
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 {
|
public fun convertType(`type`: PsiType?, nullability: Nullability = Nullability.Default): Type {
|
||||||
if (`type` == null) return Type.Empty
|
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) {
|
return when (nullability) {
|
||||||
Nullability.NotNull -> result.toNotNullType()
|
Nullability.NotNull -> result.toNotNullType()
|
||||||
Nullability.Nullable -> result.toNullableType()
|
Nullability.Nullable -> result.toNullableType()
|
||||||
|
|||||||
@@ -277,39 +277,7 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
|
|||||||
if (resourceList != null) {
|
if (resourceList != null) {
|
||||||
val variables = resourceList.getResourceVariables()
|
val variables = resourceList.getResourceVariables()
|
||||||
if (variables.isNotEmpty()) {
|
if (variables.isNotEmpty()) {
|
||||||
var wrapResultStatement: (Expression) -> Statement = { it }
|
result = convertTryWithResources(tryBlock, variables, catchesConverted, finallyConverted)
|
||||||
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)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -317,6 +285,41 @@ open class StatementVisitor(public val converter: Converter) : JavaElementVisito
|
|||||||
result = TryStatement(converter.convertBlock(tryBlock), catchesConverted, finallyConverted)
|
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> {
|
private fun collectReturns(block: PsiCodeBlock?): Collection<PsiReturnStatement> {
|
||||||
val returns = ArrayList<PsiReturnStatement>()
|
val returns = ArrayList<PsiReturnStatement>()
|
||||||
block?.accept(object: JavaRecursiveElementVisitor() {
|
block?.accept(object: JavaRecursiveElementVisitor() {
|
||||||
|
|||||||
@@ -27,7 +27,7 @@ import org.jetbrains.jet.j2k.TypeConverter
|
|||||||
|
|
||||||
private val PRIMITIVE_TYPES_NAMES = JvmPrimitiveType.values().map { it.getName() }
|
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 {
|
override fun visitPrimitiveType(primitiveType: PsiPrimitiveType): Type {
|
||||||
val name = primitiveType.getCanonicalText()
|
val name = primitiveType.getCanonicalText()
|
||||||
return if (name == "void") {
|
return if (name == "void") {
|
||||||
@@ -75,7 +75,7 @@ class TypeVisitor(private val converter: TypeConverter, private val classesToImp
|
|||||||
val kotlinClassName = toKotlinTypesMap[javaClassName]
|
val kotlinClassName = toKotlinTypesMap[javaClassName]
|
||||||
if (kotlinClassName != null) {
|
if (kotlinClassName != null) {
|
||||||
val kotlinShortName = getShortName(kotlinClassName)
|
val kotlinShortName = getShortName(kotlinClassName)
|
||||||
if (kotlinShortName == getShortName(javaClassName!!) && converter.importNames.contains(getPackageName(javaClassName) + ".*")) {
|
if (kotlinShortName == getShortName(javaClassName!!) && importNames.contains(getPackageName(javaClassName) + ".*")) {
|
||||||
classesToImport.add(kotlinClassName)
|
classesToImport.add(kotlinClassName)
|
||||||
}
|
}
|
||||||
return Identifier(kotlinShortName)
|
return Identifier(kotlinShortName)
|
||||||
|
|||||||
Reference in New Issue
Block a user