Java to Kotlin convertor: more code improvements

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