diff --git a/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt b/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt index cc9330dfc5d..1a5608ce4e5 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt @@ -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() diff --git a/j2k/src/org/jetbrains/jet/j2k/Converter.kt b/j2k/src/org/jetbrains/jet/j2k/Converter.kt index 853877dea11..05375a6ddbf 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Converter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Converter.kt @@ -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): 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()).filter { it.hasModifierProperty(PsiModifier.STATIC) } if (classObjectMembers.all { it is PsiMethod && it.hasModifierProperty(PsiModifier.PRIVATE) }) { diff --git a/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt b/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt index c92d79ba8c3..0611a67d5bb 100644 --- a/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/TypeConverter.kt @@ -37,8 +37,7 @@ class TypeConverter(val settings: ConverterSettings, val conversionScope: Conver importNames = importList?.imports?.mapTo(HashSet()) { it.name } ?: setOf() } - public var importNames: Set = setOf() - private set + private var importNames: Set = setOf() public val importsToAdd: Collection 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(TypeVisitor(this, classesToImport))!! + val result = `type`.accept(TypeVisitor(this, importNames, classesToImport))!! return when (nullability) { Nullability.NotNull -> result.toNotNullType() Nullability.Nullable -> result.toNullableType() diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt index b71246f1c03..ab314010adf 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt @@ -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, catchesConverted: List, 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 { val returns = ArrayList() block?.accept(object: JavaRecursiveElementVisitor() { diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/TypeVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/TypeVisitor.kt index 39f6ef5a425..5d9ceb111d9 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/TypeVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/TypeVisitor.kt @@ -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) : PsiTypeVisitor() { +class TypeVisitor(private val converter: TypeConverter, private val importNames: Set, private val classesToImport: MutableSet) : PsiTypeVisitor() { 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)