From 846f2d99542055498581b6acfac4373949acfa83 Mon Sep 17 00:00:00 2001 From: Valentin Kipyatkov Date: Fri, 30 May 2014 20:34:16 +0400 Subject: [PATCH] Java to Kotlin convertor: more code improvements --- .../org/jetbrains/jet/j2k/ConstructorUtils.kt | 15 +- j2k/src/org/jetbrains/jet/j2k/Converter.kt | 140 +++++++++--------- j2k/src/org/jetbrains/jet/j2k/Utils.kt | 47 ++---- .../jet/j2k/visitors/ElementVisitor.kt | 6 +- .../jet/j2k/visitors/ExpressionVisitor.kt | 118 ++++----------- .../jet/j2k/visitors/StatementVisitor.kt | 20 +-- .../jet/j2k/visitors/SuperVisitor.kt | 4 +- 7 files changed, 134 insertions(+), 216 deletions(-) diff --git a/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt b/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt index cc7c5258caf..c5750a0c9b2 100644 --- a/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt +++ b/j2k/src/org/jetbrains/jet/j2k/ConstructorUtils.kt @@ -21,8 +21,8 @@ import com.intellij.psi.PsiClass import com.intellij.psi.PsiReferenceExpression import com.intellij.psi.JavaRecursiveElementVisitor import java.util.LinkedHashSet -import com.intellij.psi.PsiReference import com.intellij.psi.PsiElement +import com.intellij.psi.PsiMethodCallExpression fun PsiMethod.isPrimaryConstructor(): Boolean { if (!isConstructor()) return false @@ -64,12 +64,9 @@ fun PsiClass.getPrimaryConstructor(): PsiMethod? { } fun isInsidePrimaryConstructor(element: PsiElement): Boolean - = containingConstructor(element)?.isPrimaryConstructor() ?: false + = getContainingConstructor(element)?.isPrimaryConstructor() ?: false -fun isInsideSecondaryConstructor(element: PsiElement): Boolean - = !(containingConstructor(element)?.isPrimaryConstructor() ?: true) - -fun containingConstructor(element: PsiElement): PsiMethod? { +fun getContainingConstructor(element: PsiElement): PsiMethod? { var context = element.getContext() while (context != null) { val _context = context!! @@ -82,10 +79,14 @@ fun containingConstructor(element: PsiElement): PsiMethod? { return null } -fun isSuperConstructorRef(ref: PsiReference): Boolean { +fun PsiMethodCallExpression.isSuperConstructorCall(): Boolean { + val ref = getMethodExpression() if (ref.getCanonicalText().equals("super")) { val target = ref.resolve() return target is PsiMethod && target.isConstructor() } return false } + +fun PsiReferenceExpression.isThisConstructorCall(): Boolean + = getReferences().filter { it.getCanonicalText() == "this" }.map { it.resolve() }.any { it is PsiMethod && it.isConstructor() } diff --git a/j2k/src/org/jetbrains/jet/j2k/Converter.kt b/j2k/src/org/jetbrains/jet/j2k/Converter.kt index ccd79cf3430..3b677afbf05 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Converter.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Converter.kt @@ -55,7 +55,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) { is PsiJavaFile -> convertFile(element) is PsiClass -> convertClass(element) is PsiMethod -> convertMethod(element) - is PsiField -> convertField(element, element.getContainingClass()) + is PsiField -> convertField(element) is PsiStatement -> convertStatement(element) is PsiExpression -> convertExpression(element) is PsiComment -> Comment(element.getText()!!) @@ -78,7 +78,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) { private fun convertMembers(psiClass: PsiClass): List { val allChildren = psiClass.getChildren().toList() val lBraceIndex = allChildren.indexOf(psiClass.getLBrace()) - return allChildren.subList(lBraceIndex, allChildren.size).map { convertMember(it, psiClass) }.filterNotNull() + return allChildren.subList(lBraceIndex, allChildren.size).map { convertMember(it) }.filterNotNull() } private fun getComments(member: PsiMember): MemberComments { @@ -93,9 +93,9 @@ public class Converter(val project: Project, val settings: ConverterSettings) { return MemberComments(whiteSpacesAndComments) } - private fun convertMember(e: PsiElement?, containingClass: PsiClass): Element? = when(e) { + private fun convertMember(e: PsiElement?): Element? = when(e) { is PsiMethod -> convertMethod(e, true) - is PsiField -> convertField(e, containingClass) + is PsiField -> convertField(e) is PsiClass -> convertClass(e) is PsiClassInitializer -> convertInitializer(e) else -> convertElement(e) @@ -103,90 +103,86 @@ public class Converter(val project: Project, val settings: ConverterSettings) { private fun convertClass(psiClass: PsiClass): Class { val modifiers = convertModifierList(psiClass.getModifierList()) - val fields = convertFields(psiClass.getFields(), psiClass) val typeParameters = convertTypeParameterList(psiClass.getTypeParameterList()) val implementsTypes = convertToNotNullableTypes(psiClass.getImplementsListTypes()) val extendsTypes = convertToNotNullableTypes(psiClass.getExtendsListTypes()) val name = Identifier(psiClass.getName()!!) val members = ArrayList(convertMembers(psiClass)) - val baseClassParams: List = run { - val superVisitor = SuperVisitor() - psiClass.accept(superVisitor) - val resolvedSuperCallParameters = superVisitor.resolvedSuperCallParameters - if (resolvedSuperCallParameters.size() == 1) { - convertExpressions(resolvedSuperCallParameters.single().getExpressions()) - } - else { - listOf() - } - } + when { + psiClass.isInterface() -> return Trait(this, name, getComments(psiClass), modifiers, typeParameters, extendsTypes, listOf(), implementsTypes, members) - if (!psiClass.isEnum() && !psiClass.isInterface() && psiClass.getConstructors().size > 1 && psiClass.getPrimaryConstructor() == null) { - val finalOrWithEmptyInitializer = fields.filter { it.isVal() || it.initializer.toKotlin().isEmpty() } - val initializers = HashMap() - for (member in members) { - if (member is Constructor && !member.isPrimary) { - for (field in finalOrWithEmptyInitializer) { - initializers.put(field.identifier.toKotlin(), getDefaultInitializer(field)) - } + psiClass.isEnum() -> return Enum(this, name, getComments(psiClass), modifiers, typeParameters, listOf(), listOf(), implementsTypes, members) - val newStatements = ArrayList() - for (statement in member.block!!.statements) { - var isRemoved = false - if (statement is AssignmentExpression) { - val assignee = statement.left - if (assignee is CallChainExpression) { - for (field in finalOrWithEmptyInitializer) { - val id = field.identifier.toKotlin() - if (assignee.identifier.toKotlin().endsWith("." + id)) { - initializers.put(id, statement.right.toKotlin()) - isRemoved = true + else -> { + if (psiClass.getConstructors().size > 1 && psiClass.getPrimaryConstructor() == null) { + val finalOrWithEmptyInitializerFields = members.filterIsInstance(javaClass()).filter { it.isVal() || it.initializer.toKotlin().isEmpty() } + val initializers = HashMap() + for (member in members) { + if (member is Constructor && !member.isPrimary) { + for (field in finalOrWithEmptyInitializerFields) { + initializers.put(field.identifier.toKotlin(), getDefaultInitializer(field)) + } + + val newStatements = ArrayList() + for (statement in member.block!!.statements) { + var keepStatement = true + if (statement is AssignmentExpression) { + val assignee = statement.left + if (assignee is CallChainExpression) { + for (field in finalOrWithEmptyInitializerFields) { + val id = field.identifier.toKotlin() + if (assignee.identifier.toKotlin().endsWith("." + id)) { + initializers.put(id, statement.right.toKotlin()) + keepStatement = false + } + + } } } + + if (keepStatement) { + newStatements.add(statement) + } + } - + newStatements.add(0, DummyStringExpression("val __ = " + createPrimaryConstructorInvocation(name.toKotlin(), finalOrWithEmptyInitializerFields, initializers))) + member.block = Block(newStatements) } - - if (!isRemoved) { - newStatements.add(statement) - } - } - newStatements.add(0, DummyStringExpression("val __ = " + createPrimaryConstructorInvocation(name.toKotlin(), finalOrWithEmptyInitializer, initializers))) - member.block = Block(newStatements) + + //TODO: comments? + members.add(Constructor(this, Identifier.Empty, MemberComments.Empty, Collections.emptySet(), + ClassType(name, listOf(), false, this), + TypeParameterList.Empty, + ParameterList(createParametersFromFields(finalOrWithEmptyInitializerFields)), + Block(createInitStatementsFromFields(finalOrWithEmptyInitializerFields)), + true)) } + + val baseClassParams: List = run { + val superVisitor = SuperVisitor() + psiClass.accept(superVisitor) + val resolvedSuperCallParameters = superVisitor.resolvedSuperCallParameters + if (resolvedSuperCallParameters.size() == 1) { + convertExpressions(resolvedSuperCallParameters.single().getExpressions()) + } + else { + listOf() + } + } + + return Class(this, name, getComments(psiClass), modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, members) } - //TODO: comments? - members.add(Constructor(this, Identifier.Empty, MemberComments.Empty, Collections.emptySet(), - ClassType(name, listOf(), false, this), - TypeParameterList.Empty, - ParameterList(createParametersFromFields(finalOrWithEmptyInitializer)), - Block(createInitStatementsFromFields(finalOrWithEmptyInitializer)), - true)) } - - if (psiClass.isInterface()) { - return Trait(this, name, getComments(psiClass), modifiers, typeParameters, extendsTypes, listOf(), implementsTypes, members) - } - - if (psiClass.isEnum()) { - return Enum(this, name, getComments(psiClass), modifiers, typeParameters, listOf(), listOf(), implementsTypes, members) - } - - return Class(this, name, getComments(psiClass), modifiers, typeParameters, extendsTypes, baseClassParams, implementsTypes, members) } private fun convertInitializer(initializer: PsiClassInitializer): Initializer { return Initializer(convertBlock(initializer.getBody(), true), convertModifierList(initializer.getModifierList())) } - private fun convertFields(fields: Array, psiClass: PsiClass): List { - return fields.map { convertField(it, psiClass) } - } - - private fun convertField(field: PsiField, psiClass: PsiClass?): Field { + private fun convertField(field: PsiField): Field { val modifiers = convertModifierList(field.getModifierList()) if (field is PsiEnumConstant) { return EnumConstant(Identifier(field.getName()!!), @@ -196,8 +192,8 @@ public class Converter(val project: Project, val settings: ConverterSettings) { convertElement(field.getArgumentList())) } - var kType = convertType(field.getType(), isAnnotatedAsNotNull(field.getModifierList())) - if (field.hasModifierProperty(PsiModifier.FINAL) && isDefinitelyNotNull(field.getInitializer())) { + var kType = convertType(field.getType(), field.isAnnotatedAsNotNull()) + if (field.hasModifierProperty(PsiModifier.FINAL) && field.getInitializer().isDefinitelyNotNull()) { kType = kType.convertedToNotNull(); } @@ -206,7 +202,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) { modifiers, kType, convertExpression(field.getInitializer(), field.getType()), - countWriteAccesses(field, psiClass)) + field.countWriteAccesses(field.getContainingClass())) } private fun convertMethod(method: PsiMethod): Function { @@ -222,7 +218,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) { } methodReturnType = method.getReturnType() val identifier = Identifier(method.getName()) - val returnType = convertType(method.getReturnType(), isAnnotatedAsNotNull(method.getModifierList())) + val returnType = convertType(method.getReturnType(), method.isAnnotatedAsNotNull()) val body = convertBlock(method.getBody(), notEmpty) val params = createFunctionParameters(method) @@ -253,8 +249,8 @@ public class Converter(val project: Project, val settings: ConverterSettings) { val result = ArrayList() for (parameter in method.getParameterList().getParameters()) { result.add(Parameter(Identifier(parameter.getName()!!), - convertType(parameter.getType(), isAnnotatedAsNotNull(parameter.getModifierList())), - isReadOnly(parameter, method.getBody()))) + convertType(parameter.getType(), parameter.isAnnotatedAsNotNull()), + parameter.countWriteAccesses(method.getBody()) == 0)) } return ParameterList(result) } @@ -339,7 +335,7 @@ public class Converter(val project: Project, val settings: ConverterSettings) { public fun convertParameter(parameter: PsiParameter, forceNotNull: Boolean = false): Parameter { return Parameter(Identifier(parameter.getName()!!), convertType(parameter.getType(), - forceNotNull || isAnnotatedAsNotNull(parameter.getModifierList())), true) + forceNotNull || parameter.isAnnotatedAsNotNull()), true) } public fun convertArguments(expression: PsiCallExpression): List { diff --git a/j2k/src/org/jetbrains/jet/j2k/Utils.kt b/j2k/src/org/jetbrains/jet/j2k/Utils.kt index d514d63f632..9aeb34fe2b3 100644 --- a/j2k/src/org/jetbrains/jet/j2k/Utils.kt +++ b/j2k/src/org/jetbrains/jet/j2k/Utils.kt @@ -19,53 +19,36 @@ package org.jetbrains.jet.j2k import org.jetbrains.jet.j2k.ast.Identifier import com.intellij.psi.PsiElement import com.intellij.psi.JavaRecursiveElementVisitor -import java.util.ArrayList import com.intellij.psi.PsiReferenceExpression -import com.intellij.psi.util.PsiUtil -import com.intellij.psi.PsiModifierList -import com.intellij.psi.PsiAnnotation import com.intellij.psi.PsiLiteralExpression import com.intellij.psi.PsiNewExpression import org.jetbrains.jet.j2k.ast.Field import org.jetbrains.jet.lang.types.expressions.OperatorConventions +import com.intellij.psi.util.PsiUtil +import com.intellij.psi.PsiModifierListOwner fun quoteKeywords(packageName: String): String = packageName.split("\\.").map { Identifier(it).toKotlin() }.makeString(".") -fun countWriteAccesses(element: PsiElement?, container: PsiElement?): Int { - if (container == null) return 0 - - class ReferenceCollector() : JavaRecursiveElementVisitor() { - private val _collectedReferences = ArrayList() - - public val collectedReferences: List - get() = _collectedReferences +fun PsiElement.countWriteAccesses(scope: PsiElement?): Int { + if (scope == null) return 0 + var writes = 0 + scope.accept(object: JavaRecursiveElementVisitor() { override fun visitReferenceExpression(expression: PsiReferenceExpression) { super.visitReferenceExpression(expression) - _collectedReferences.add(expression) + if (PsiUtil.isAccessedForWriting(expression) && expression.isReferenceTo(this@countWriteAccesses)) { + writes++ + } } - } - - val collector = ReferenceCollector() - container.accept(collector) - return collector.collectedReferences.count { it.isReferenceTo(element) && PsiUtil.isAccessedForWriting(it) } + }) + return writes } -fun isReadOnly(element: PsiElement?, container: PsiElement?): Boolean - = countWriteAccesses(element, container) == 0 +fun PsiModifierListOwner.isAnnotatedAsNotNull(): Boolean + = getModifierList()?.getAnnotations()?.any { NOT_NULL_ANNOTATIONS.contains(it.getQualifiedName()) } ?: false -fun isAnnotatedAsNotNull(modifierList: PsiModifierList?): Boolean { - if (modifierList != null) { - for (annotation in modifierList.getAnnotations()) { - val qualifiedName = annotation.getQualifiedName() - return qualifiedName != null && NOT_NULL_ANNOTATIONS.contains(qualifiedName) - } - } - return false -} - -fun isDefinitelyNotNull(element: PsiElement?): Boolean = when(element) { - is PsiLiteralExpression -> element.getValue() != null +fun PsiElement?.isDefinitelyNotNull(): Boolean = when(this) { + is PsiLiteralExpression -> getValue() != null is PsiNewExpression -> true else -> false } diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt index 8ec1176e663..b0834e4581b 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/ElementVisitor.kt @@ -26,9 +26,9 @@ class ElementVisitor(public val converter: Converter) : JavaElementVisitor() { protected set override fun visitLocalVariable(variable: PsiLocalVariable) { - var kType = converter.convertType(variable.getType(), isAnnotatedAsNotNull(variable.getModifierList())) - if (variable.hasModifierProperty(PsiModifier.FINAL) && isDefinitelyNotNull(variable.getInitializer())) { - kType = kType.convertedToNotNull(); + var kType = converter.convertType(variable.getType(), variable.isAnnotatedAsNotNull()) + if (variable.hasModifierProperty(PsiModifier.FINAL) && variable.getInitializer().isDefinitelyNotNull()) { + kType = kType.convertedToNotNull() } result = LocalVariable(Identifier(variable.getName()!!), converter.convertModifierList(variable.getModifierList()), diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt index a73498caf61..ef4c34da369 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/ExpressionVisitor.kt @@ -141,7 +141,7 @@ open class ExpressionVisitor(public val converter: Converter) : JavaElementVisit } protected fun convertMethodCallExpression(expression: PsiMethodCallExpression) { - if (!isSuperConstructorRef(expression.getMethodExpression()) || !isInsidePrimaryConstructor(expression)) { + if (!expression.isSuperConstructorCall() || !isInsidePrimaryConstructor(expression)) { result = MethodCallExpression(converter.convertExpression(expression.getMethodExpression()), converter.convertArguments(expression), converter.convertTypes(expression.getTypeArguments()), @@ -212,21 +212,20 @@ open class ExpressionVisitor(public val converter: Converter) : JavaElementVisit } override fun visitReferenceExpression(expression: PsiReferenceExpression) { - val isFieldReference = isFieldReference(expression, getContainingClass(expression)) - val insideSecondaryConstructor = isInsideSecondaryConstructor(expression) - val hasReceiver = isFieldReference && insideSecondaryConstructor - val isThis = isThisExpression(expression) - val notNull = isResolvedToNotNull(expression) - val isNullable = converter.convertType(expression.getType(), notNull).isNullable - val className = getClassNameWithConstructor(expression) + val containingConstructor = getContainingConstructor(expression) + val insideSecondaryConstructor = containingConstructor != null && !containingConstructor.isPrimaryConstructor() + val addReceiver = insideSecondaryConstructor && (expression.getReference()?.resolve() as? PsiField)?.getContainingClass() == containingConstructor!!.getContainingClass() + + val isNullable = converter.convertType(expression.getType(), expression.isResolvedToNotNull()).isNullable val referencedName = expression.getReferenceName()!! var identifier: Expression = Identifier(referencedName, isNullable) val qualifier = expression.getQualifierExpression() - if (hasReceiver) { + + if (addReceiver) { identifier = CallChainExpression(Identifier("__", false), Identifier(referencedName, isNullable)) } - else if (insideSecondaryConstructor && isThis) { - identifier = Identifier("val __ = " + className) + else if (insideSecondaryConstructor && expression.isThisConstructorCall()) { + identifier = Identifier("val __ = " + (containingConstructor?.getContainingClass()?.getNameIdentifier()?.getText() ?: "")) } else if (qualifier != null && qualifier.getType() is PsiArrayType && referencedName == "length") { identifier = Identifier("size", isNullable) @@ -259,15 +258,13 @@ open class ExpressionVisitor(public val converter: Converter) : JavaElementVisit result = CallChainExpression(converter.convertExpression(qualifier), identifier) } - private fun isResolvedToNotNull(expression: PsiReference): Boolean { - val target = expression.resolve() - if (target is PsiEnumConstant) { - return true; + private fun PsiReference.isResolvedToNotNull(): Boolean { + val target = resolve() + return when(target) { + is PsiEnumConstant -> true + is PsiModifierListOwner -> target.isAnnotatedAsNotNull() + else -> false } - if (target is PsiModifierListOwner) { - return isAnnotatedAsNotNull(target.getModifierList()); - } - return false; } override fun visitSuperExpression(expression: PsiSuperExpression) { @@ -287,19 +284,17 @@ open class ExpressionVisitor(public val converter: Converter) : JavaElementVisit } override fun visitTypeCastExpression(expression: PsiTypeCastExpression) { - val castType: PsiTypeElement? = expression.getCastType() - if (castType != null) { - val operand = expression.getOperand() - val operandType = operand?.getType() - val typeText = castType.getType().getCanonicalText() - val typeConversion = PRIMITIVE_TYPE_CONVERSIONS[typeText] - if (operandType is PsiPrimitiveType && typeConversion != null) { - result = MethodCallExpression.build(converter.convertExpression(operand), typeConversion) - } - else { - result = TypeCastExpression(converter.convertType(castType.getType()), - converter.convertExpression(operand)) - } + val castType = expression.getCastType() ?: return + val operand = expression.getOperand() + val operandType = operand?.getType() + val typeText = castType.getType().getCanonicalText() + val typeConversion = PRIMITIVE_TYPE_CONVERSIONS[typeText] + if (operandType is PsiPrimitiveType && typeConversion != null) { + result = MethodCallExpression.build(converter.convertExpression(operand), typeConversion) + } + else { + result = TypeCastExpression(converter.convertType(castType.getType()), + converter.convertExpression(operand)) } } @@ -339,26 +334,6 @@ open class ExpressionVisitor(public val converter: Converter) : JavaElementVisit } } - private fun getClassNameWithConstructor(expression: PsiReferenceExpression): String { - var context = expression.getContext() - while (context != null) { - val _context = context!! - if (_context is PsiMethod && _context.isConstructor()) { - val containingClass = _context.getContainingClass() - if (containingClass != null) { - val identifier = containingClass.getNameIdentifier() - if (identifier != null) { - return identifier.getText()!! - } - } - - } - - context = _context.getContext() - } - return "" - } - protected fun getClassName(expression: PsiExpression): String { var context = expression.getContext() while (context != null) { @@ -376,45 +351,6 @@ open class ExpressionVisitor(public val converter: Converter) : JavaElementVisit return "" } - private fun isFieldReference(expression: PsiReferenceExpression, currentClass: PsiClass?): Boolean { - val reference = expression.getReference() - if (reference != null) { - val target = reference.resolve() - if (target is PsiField) { - return target.getContainingClass() == currentClass - } - } - - return false - } - - private fun getContainingClass(expression: PsiExpression): PsiClass? { - var context = expression.getContext() - while (context != null) { - val _context = context!! - if (_context is PsiMethod && _context.isConstructor()) { - return _context.getContainingClass() - } - - context = _context.getContext() - } - return null - } - - private fun isThisExpression(expression: PsiReferenceExpression): Boolean { - for (ref in expression.getReferences()) { - if (ref.getCanonicalText() == "this") { - val target = ref.resolve() - if (target is PsiMethod && target.isConstructor()) { - return true - } - - } - } - - return false - } - private fun isStaticallyImported(member: PsiMember, context: PsiElement): Boolean { val containingFile = context.getContainingFile() val targetContainingClass = member.getContainingClass() diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt index dfefbbb5063..0d44b928a52 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/StatementVisitor.kt @@ -79,11 +79,13 @@ class StatementVisitor(public val converter: Converter) : JavaElementVisitor() { val update = statement.getUpdate() val condition = statement.getCondition() val body = statement.getBody() - val firstChildLocalVar = initialization?.getFirstChild() as? PsiLocalVariable - var bodyWriteCount = countWriteAccesses(firstChildLocalVar, body) - var conditionWriteCount = countWriteAccesses(firstChildLocalVar, condition) - var updateWriteCount = countWriteAccesses(firstChildLocalVar, update) - val onceWritableIterator = updateWriteCount == 1 && bodyWriteCount + conditionWriteCount == 0 + + val initializationVar = initialization?.getFirstChild() as? PsiLocalVariable + val onceWritableIterator = initializationVar != null + && initializationVar.countWriteAccesses(body) == 0 + && initializationVar.countWriteAccesses(condition) == 0 + && initializationVar.countWriteAccesses(update) == 1 + val operationTokenType = (condition as? PsiBinaryExpression)?.getOperationTokenType() if (initialization is PsiDeclarationStatement && initialization.getFirstChild() == initialization.getLastChild() @@ -92,16 +94,16 @@ class StatementVisitor(public val converter: Converter) : JavaElementVisitor() { && update.getChildren().size == 1 && isPlusPlusExpression(update.getChildren().single()) && (operationTokenType == JavaTokenType.LT || operationTokenType == JavaTokenType.LE) - && firstChildLocalVar != null - && firstChildLocalVar.getNameIdentifier() != null + && initializationVar != null + && initializationVar.getNameIdentifier() != null && onceWritableIterator) { val end = converter.convertExpression((condition as PsiBinaryExpression).getROperand()) val endExpression = if (operationTokenType == JavaTokenType.LT) BinaryExpression(end, Identifier("1"), "-") else end - result = ForeachWithRangeStatement(Identifier(firstChildLocalVar.getName()!!), - converter.convertExpression(firstChildLocalVar.getInitializer()), + result = ForeachWithRangeStatement(Identifier(initializationVar.getName()!!), + converter.convertExpression(initializationVar.getInitializer()), endExpression, converter.convertStatement(body)) } diff --git a/j2k/src/org/jetbrains/jet/j2k/visitors/SuperVisitor.kt b/j2k/src/org/jetbrains/jet/j2k/visitors/SuperVisitor.kt index 1f1c9d24581..05e0bca5d67 100644 --- a/j2k/src/org/jetbrains/jet/j2k/visitors/SuperVisitor.kt +++ b/j2k/src/org/jetbrains/jet/j2k/visitors/SuperVisitor.kt @@ -18,7 +18,7 @@ package org.jetbrains.jet.j2k.visitors import com.intellij.psi.* import java.util.HashSet -import org.jetbrains.jet.j2k.isSuperConstructorRef +import org.jetbrains.jet.j2k.isSuperConstructorCall class SuperVisitor() : JavaRecursiveElementVisitor() { private val _resolvedSuperCallParameters = HashSet() @@ -27,7 +27,7 @@ class SuperVisitor() : JavaRecursiveElementVisitor() { get() = _resolvedSuperCallParameters override fun visitMethodCallExpression(expression: PsiMethodCallExpression) { - if (isSuperConstructorRef(expression.getMethodExpression())) { + if (expression.isSuperConstructorCall()) { _resolvedSuperCallParameters.add(expression.getArgumentList()) } }