diff --git a/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt b/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt index 99f07fd3302..b29bd9b7235 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/Converter.kt @@ -336,7 +336,9 @@ class Converter private constructor( //TODO: usage processings for converting method's to property if (field != null) { - addUsageProcessing(FieldToPropertyProcessing(field, propertyInfo.name, propertyType.isNullable)) + addUsageProcessing(FieldToPropertyProcessing(field, propertyInfo.name, propertyType.isNullable, + replaceReadWithFieldReference = propertyInfo.getMethod != null && !propertyInfo.isGetMethodBodyFieldAccess, + replaceWriteWithFieldReference = propertyInfo.setMethod != null && !propertyInfo.isSetMethodBodyFieldAccess)) } //TODO: doc-comments @@ -366,7 +368,7 @@ class Converter private constructor( var setter: PropertyAccessor? = null if (propertyInfo.needExplicitSetter) { val accessorModifiers = Modifiers(propertyInfo.specialSetterAccess.singletonOrEmptyList()).assignNoPrototype() - if (setMethod != null) { + if (setMethod != null && !propertyInfo.isSetMethodBodyFieldAccess) { val method = setMethod.let { convertMethod(it, null, null, null, classKind)!! } val convertedParameter = method.parameterList!!.parameters.single() as FunctionParameter val parameterAnnotations = convertedParameter.annotations diff --git a/j2k/src/org/jetbrains/kotlin/j2k/propertyDetection.kt b/j2k/src/org/jetbrains/kotlin/j2k/propertyDetection.kt index bebecab3079..e7a2c1c02f0 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/propertyDetection.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/propertyDetection.kt @@ -18,12 +18,14 @@ package org.jetbrains.kotlin.j2k import com.intellij.psi.* import com.intellij.psi.util.MethodSignatureUtil +import com.intellij.psi.util.PsiUtil import org.jetbrains.kotlin.asJava.KtLightMethod import org.jetbrains.kotlin.j2k.ast.* import org.jetbrains.kotlin.lexer.KtTokens import org.jetbrains.kotlin.load.java.JvmAbi import org.jetbrains.kotlin.name.Name import org.jetbrains.kotlin.psi.KtProperty +import org.jetbrains.kotlin.psi.psiUtil.isAncestor import org.jetbrains.kotlin.synthetic.SyntheticJavaPropertyDescriptor import org.jetbrains.kotlin.utils.addIfNotNull import org.jetbrains.kotlin.utils.addToStdlib.check @@ -127,20 +129,16 @@ private class PropertyDetector( } val propertyNamesWithConflict = HashSet() - val prohibitedPropertyNames = psiClass.fields.mapNotNull { it.name }.toMutableSet() //TODO: fields from base - val propertyNameToGetterInfo = detectGetters(methodsToCheck, prohibitedPropertyNames, propertyNamesWithConflict) + val propertyNameToGetterInfo = detectGetters(methodsToCheck, propertyNamesWithConflict) - val propertyNameToSetterInfo = detectSetters(methodsToCheck, prohibitedPropertyNames, propertyNameToGetterInfo.keys, propertyNamesWithConflict) + val propertyNameToSetterInfo = detectSetters(methodsToCheck, propertyNameToGetterInfo.keys, propertyNamesWithConflict) val propertyNames = propertyNameToGetterInfo.keys + propertyNameToSetterInfo.keys - val memberToPropertyInfo = HashMap() - for (propertyName in propertyNames) { - // TODO: use "field" expression if the conflicting field is used only inside get/set-methods - if (propertyName in prohibitedPropertyNames) continue // cannot create such property - will conflict with existing field - //TODO: what about overrides in this case? + val propertyInfos = ArrayList() + for (propertyName in propertyNames) { val getterInfo = propertyNameToGetterInfo[propertyName] var setterInfo = propertyNameToSetterInfo[propertyName] @@ -153,8 +151,24 @@ private class PropertyDetector( var field = getterInfo?.field ?: setterInfo?.field - if (field != null && memberToPropertyInfo.containsKey(field)) { // already used in another property - field = null + if (field != null) { + fun PsiReferenceExpression.canBeReplacedWithFieldAccess(): Boolean { + if (getterInfo?.method?.isAncestor(this) != true && setterInfo?.method?.isAncestor(this) != true) return false // not inside property + return qualifier == null || qualifier is PsiThisExpression //TODO: check it's correct this + } + + if (getterInfo != null && getterInfo.field == null) { + if (!field.hasModifierProperty(PsiModifier.PRIVATE) + || converter.referenceSearcher.findVariableUsages(field, psiClass).any { PsiUtil.isAccessedForReading(it) && !it.canBeReplacedWithFieldAccess() }) { + field = null + } + } + else if (setterInfo != null && setterInfo.field == null) { + if (!field.hasModifierProperty(PsiModifier.PRIVATE) + || converter.referenceSearcher.findVariableUsages(field, psiClass).any { PsiUtil.isAccessedForWriting(it) && !it.canBeReplacedWithFieldAccess() }) { + field = null + } + } } //TODO: no body for getter OR setter @@ -193,20 +207,29 @@ private class PropertyDetector( modifiers, specialSetterAccess, superProperty) + propertyInfos.add(propertyInfo) + } + val memberToPropertyInfo = HashMap() + for (propertyInfo in propertyInfos) { + val field = propertyInfo.field if (field != null) { - memberToPropertyInfo[field] = propertyInfo - } - if (getterInfo != null) { - memberToPropertyInfo[getterInfo.method] = propertyInfo - } - if (setterInfo != null) { - memberToPropertyInfo[setterInfo.method] = propertyInfo + if (memberToPropertyInfo.containsKey(field)) { // field already in use by other property + continue + } + else { + memberToPropertyInfo[field] = propertyInfo + } } + + propertyInfo.getMethod?.let { memberToPropertyInfo[it] = propertyInfo } + propertyInfo.setMethod?.let { memberToPropertyInfo[it] = propertyInfo } } dropPropertiesWithConflictingAccessors(memberToPropertyInfo) + dropPropertiesConflictingWithFields(memberToPropertyInfo) + val mappedFields = memberToPropertyInfo.values .mapNotNull { it.field } .toSet() @@ -223,7 +246,6 @@ private class PropertyDetector( private fun detectGetters( methodsToCheck: List>, - prohibitedPropertyNames: MutableSet, propertyNamesWithConflict: MutableSet ): Map { val propertyNameToGetterInfo = LinkedHashMap() @@ -237,14 +259,12 @@ private class PropertyDetector( } propertyNameToGetterInfo[info.propertyName] = info - info.field?.let { prohibitedPropertyNames.remove(it.name) } } return propertyNameToGetterInfo } private fun detectSetters( methodsToCheck: List>, - prohibitedPropertyNames: MutableSet, propertyNamesFromGetters: Set, propertyNamesWithConflict: MutableSet ): Map { @@ -259,7 +279,6 @@ private class PropertyDetector( } propertyNameToSetterInfo[info.propertyName] = info - info.field?.let { prohibitedPropertyNames.remove(it.name) } } return propertyNameToSetterInfo } @@ -275,12 +294,6 @@ private class PropertyDetector( .map { it.getSignature(PsiSubstitutor.EMPTY) } .toSet() - fun dropProperty(propertyInfo: PropertyInfo) { - propertyInfo.field?.let { memberToPropertyInfo.remove(it) } - propertyInfo.getMethod?.let { memberToPropertyInfo.remove(it) } - propertyInfo.setMethod?.let { memberToPropertyInfo.remove(it) } - } - for (propertyInfo in propertyInfos) { if (propertyInfo.modifiers.contains(Modifier.OVERRIDE)) continue // cannot drop override @@ -288,7 +301,7 @@ private class PropertyDetector( val getterName = JvmAbi.getterName(propertyInfo.name) val getterSignature = MethodSignatureUtil.createMethodSignature(getterName, emptyArray(), emptyArray(), PsiSubstitutor.EMPTY) if (getterSignature in prohibitedSignatures) { - dropProperty(propertyInfo) + memberToPropertyInfo.dropProperty(propertyInfo) continue } @@ -296,13 +309,43 @@ private class PropertyDetector( val setterName = JvmAbi.setterName(propertyInfo.name) val setterSignature = MethodSignatureUtil.createMethodSignature(setterName, arrayOf(propertyInfo.psiType), emptyArray(), PsiSubstitutor.EMPTY) if (setterSignature in prohibitedSignatures) { - dropProperty(propertyInfo) + memberToPropertyInfo.dropProperty(propertyInfo) continue } } } } + private fun dropPropertiesConflictingWithFields(memberToPropertyInfo: HashMap) { + val fieldsByName = psiClass.fields.associateBy { it.name } //TODO: fields from base + + fun isPropertyNameProhibited(name: String): Boolean { + val field = fieldsByName[name] ?: return false + return !memberToPropertyInfo.containsKey(field) + } + + var repeatLoop: Boolean + do { + repeatLoop = false + for (propertyInfo in memberToPropertyInfo.values.distinct()) { + if (isPropertyNameProhibited(propertyInfo.name)) { + //TODO: what about overrides in this case? + memberToPropertyInfo.dropProperty(propertyInfo) + + if (propertyInfo.field != null) { + repeatLoop = true // need to repeat loop because a new field appeared + } + } + } + } while (repeatLoop) + } + + private fun MutableMap.dropProperty(propertyInfo: PropertyInfo) { + propertyInfo.field?.let { remove(it) } + propertyInfo.getMethod?.let { remove(it) } + propertyInfo.setMethod?.let { remove(it) } + } + private fun convertModifiers(field: PsiField?, getMethod: PsiMethod?, setMethod: PsiMethod?, isOverride: Boolean): Modifiers { val fieldModifiers = field?.let { converter.convertModifiers(it, false) } ?: Modifiers.Empty val getterModifiers = getMethod?.let { converter.convertModifiers(it, isOpenClass) } ?: Modifiers.Empty diff --git a/j2k/src/org/jetbrains/kotlin/j2k/usageProcessing/FieldToPropertyProcessing.kt b/j2k/src/org/jetbrains/kotlin/j2k/usageProcessing/FieldToPropertyProcessing.kt index c7f3fde3a15..449252d9d12 100644 --- a/j2k/src/org/jetbrains/kotlin/j2k/usageProcessing/FieldToPropertyProcessing.kt +++ b/j2k/src/org/jetbrains/kotlin/j2k/usageProcessing/FieldToPropertyProcessing.kt @@ -17,17 +17,24 @@ package org.jetbrains.kotlin.j2k.usageProcessing import com.intellij.psi.* +import com.intellij.psi.util.PsiUtil import com.intellij.util.IncorrectOperationException import org.jetbrains.kotlin.j2k.AccessorKind import org.jetbrains.kotlin.j2k.CodeConverter import org.jetbrains.kotlin.j2k.ast.* import org.jetbrains.kotlin.utils.addToStdlib.singletonList -class FieldToPropertyProcessing(val field: PsiField, val propertyName: String, val isNullable: Boolean) : UsageProcessing { +class FieldToPropertyProcessing( + private val field: PsiField, + private val propertyName: String, + private val isNullable: Boolean, + private val replaceReadWithFieldReference: Boolean, + private val replaceWriteWithFieldReference: Boolean +) : UsageProcessing { override val targetElement: PsiElement get() = this.field override val convertedCodeProcessor: ConvertedCodeProcessor? = - if (field.name != propertyName) MyConvertedCodeProcessor() else null + if (field.name != propertyName || replaceReadWithFieldReference || replaceWriteWithFieldReference) MyConvertedCodeProcessor() else null override var javaCodeProcessors = if (field.hasModifierProperty(PsiModifier.PRIVATE)) @@ -45,17 +52,21 @@ class FieldToPropertyProcessing(val field: PsiField, val propertyName: String, v private inner class MyConvertedCodeProcessor : ConvertedCodeProcessor { override fun convertVariableUsage(expression: PsiReferenceExpression, codeConverter: CodeConverter): Expression? { - val identifier = Identifier(propertyName, isNullable).assignNoPrototype() + val useFieldReference = replaceReadWithFieldReference && PsiUtil.isAccessedForReading(expression) + || replaceWriteWithFieldReference && PsiUtil.isAccessedForWriting(expression) + + //TODO: what if local "field" is declared? Should be rare case though + val identifier = Identifier(if (useFieldReference) "field" else propertyName, isNullable).assignNoPrototype() val qualifier = expression.qualifierExpression - if (qualifier != null) { + if (qualifier != null && !useFieldReference) { return QualifiedExpression(codeConverter.convertExpression(qualifier), identifier) } else { // check if field name is shadowed val elementFactory = PsiElementFactory.SERVICE.getInstance(expression.project) val refExpr = try { - elementFactory.createExpressionFromText(propertyName, expression) as? PsiReferenceExpression ?: return identifier + elementFactory.createExpressionFromText(identifier.name, expression) as? PsiReferenceExpression ?: return identifier } catch(e: IncorrectOperationException) { return identifier diff --git a/j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter.java b/j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter.java new file mode 100644 index 00000000000..04e6a9939b3 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter.java @@ -0,0 +1,11 @@ +public class C { + private String x = null; + + public String getX() { + return x; + } + + void setX(String x) { + this.x = x; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter.kt b/j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter.kt new file mode 100644 index 00000000000..8c136abc90c --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter.kt @@ -0,0 +1,4 @@ +class C { + var x: String? = null + internal set +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter2.java b/j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter2.java new file mode 100644 index 00000000000..b1b58d8ca41 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter2.java @@ -0,0 +1,16 @@ +public class C { + private String x = ""; + C other = null; + + public String getX() { + return x; + } + + void setX(String x) { + System.out.println("setter invoked"); + if (other != null) { + this.other.x = x; + } + this.x = x; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter2.kt b/j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter2.kt new file mode 100644 index 00000000000..5004dcb9b44 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter2.kt @@ -0,0 +1,16 @@ +class C { + private var x = "" + internal var other: C? = null + + fun getX(): String { + return x + } + + internal fun setX(x: String) { + println("setter invoked") + if (other != null) { + this.other!!.x = x + } + this.x = x + } +} diff --git a/j2k/testData/fileOrElement/detectProperties/FalseSetter.kt b/j2k/testData/fileOrElement/detectProperties/FalseSetter.kt index 30460dd5d83..c5d9872ce25 100644 --- a/j2k/testData/fileOrElement/detectProperties/FalseSetter.kt +++ b/j2k/testData/fileOrElement/detectProperties/FalseSetter.kt @@ -1,6 +1,6 @@ class AAA { var x = 42 set(x) { - this.x += x + field += x } } diff --git a/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect1.java b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect1.java new file mode 100644 index 00000000000..44d87cde67d --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect1.java @@ -0,0 +1,16 @@ +public class C { + private String myX = ""; + + public String getX() { + System.out.println("getter invoked"); + return myX; + } + + public void setX(String x) { + this.myX = x; + } + + void foo() { + System.out.println("myX = " + myX); + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect1.kt b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect1.kt new file mode 100644 index 00000000000..454171a08ca --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect1.kt @@ -0,0 +1,16 @@ +class C { + private var myX = "" + + var x: String + get() { + println("getter invoked") + return myX + } + set(x) { + this.myX = x + } + + internal fun foo() { + println("myX = " + myX) + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect2.java b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect2.java new file mode 100644 index 00000000000..56e66cd38fd --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect2.java @@ -0,0 +1,16 @@ +public class C { + private String x = ""; + + public String getX() { + System.out.println("getter invoked"); + return x; + } + + public void setX(String x) { + this.x = x; + } + + void foo() { + System.out.println("x = " + x); + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect2.kt b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect2.kt new file mode 100644 index 00000000000..0326d4a8579 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect2.kt @@ -0,0 +1,16 @@ +class C { + private var x = "" + + fun getX(): String { + println("getter invoked") + return x + } + + fun setX(x: String) { + this.x = x + } + + internal fun foo() { + println("x = " + x) + } +} diff --git a/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect3.java b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect3.java new file mode 100644 index 00000000000..b5715b357a1 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect3.java @@ -0,0 +1,12 @@ +public class C { + public String x = ""; + + public String getX() { + System.out.println("getter invoked"); + return x; + } + + public void setX(String x) { + this.x = x; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect3.kt b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect3.kt new file mode 100644 index 00000000000..433b9281cc1 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect3.kt @@ -0,0 +1,12 @@ +class C { + var x = "" + + fun getX(): String { + println("getter invoked") + return x + } + + fun setX(x: String) { + this.x = x + } +} diff --git a/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect4.java b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect4.java new file mode 100644 index 00000000000..5a994e0594c --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect4.java @@ -0,0 +1,12 @@ +public class C { + private String x = ""; + + public String getX() { + System.out.println("getter invoked"); + return x; + } + + public void setX(String x) { + this.x = x; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect4.kt b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect4.kt new file mode 100644 index 00000000000..de42ff80f32 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect4.kt @@ -0,0 +1,7 @@ +class C { + var x = "" + get() { + println("getter invoked") + return field + } +} diff --git a/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect5.java b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect5.java new file mode 100644 index 00000000000..b035e125e45 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect5.java @@ -0,0 +1,12 @@ +public class C { + private String x = ""; + + public String getX() { + System.out.println("getter invoked"); + return this.x; + } + + public void setX(String x) { + this.x = x; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect5.kt b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect5.kt new file mode 100644 index 00000000000..de42ff80f32 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect5.kt @@ -0,0 +1,7 @@ +class C { + var x = "" + get() { + println("getter invoked") + return field + } +} diff --git a/j2k/testData/fileOrElement/detectProperties/PropertyAndFieldConflicts.java b/j2k/testData/fileOrElement/detectProperties/PropertyAndFieldConflicts.java new file mode 100644 index 00000000000..aa5b860dc48 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/PropertyAndFieldConflicts.java @@ -0,0 +1,22 @@ +class C { + private int aaa = 0; + private int bbb = 0; + private int ccc = 0; + private int ddd = 0; + + public int getAaa() { + return bbb; + } + + public int getBbb() { + return ccc; + } + + public int getCcc() { + return ddd; + } + + public int getDdd() { + return 0; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/PropertyAndFieldConflicts.kt b/j2k/testData/fileOrElement/detectProperties/PropertyAndFieldConflicts.kt new file mode 100644 index 00000000000..76182ba63ee --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/PropertyAndFieldConflicts.kt @@ -0,0 +1,22 @@ +internal class C { + private val aaa = 0 + private val bbb = 0 + private val ccc = 0 + private val ddd = 0 + + fun getAaa(): Int { + return bbb + } + + fun getBbb(): Int { + return ccc + } + + fun getCcc(): Int { + return ddd + } + + fun getDdd(): Int { + return 0 + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect1.java b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect1.java new file mode 100644 index 00000000000..49f8d993021 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect1.java @@ -0,0 +1,16 @@ +public class C { + private String myX = ""; + + public String getX() { + return myX; + } + + public void setX(String x) { + System.out.println("setter invoked"); + this.myX = x; + } + + void foo() { + myX = "a"; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect1.kt b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect1.kt new file mode 100644 index 00000000000..9656e36bfef --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect1.kt @@ -0,0 +1,14 @@ +class C { + private var myX = "" + + var x: String + get() = myX + set(x) { + println("setter invoked") + this.myX = x + } + + internal fun foo() { + myX = "a" + } +} diff --git a/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect2.java b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect2.java new file mode 100644 index 00000000000..7805aac1acc --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect2.java @@ -0,0 +1,16 @@ +public class C { + private String x = ""; + + public String getX() { + return x; + } + + public void setX(String x) { + System.out.println("setter invoked"); + this.x = x; + } + + void foo() { + x = "a"; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect2.kt b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect2.kt new file mode 100644 index 00000000000..cb356a939bc --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect2.kt @@ -0,0 +1,16 @@ +class C { + private var x = "" + + fun getX(): String { + return x + } + + fun setX(x: String) { + println("setter invoked") + this.x = x + } + + internal fun foo() { + x = "a" + } +} diff --git a/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect3.java b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect3.java new file mode 100644 index 00000000000..4d1f7a87ef5 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect3.java @@ -0,0 +1,12 @@ +public class C { + protected String x = ""; + + public String getX() { + return x; + } + + public void setX(String x) { + System.out.println("setter invoked"); + this.x = x; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect3.kt b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect3.kt new file mode 100644 index 00000000000..3f0265232b3 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect3.kt @@ -0,0 +1,12 @@ +class C { + protected var x = "" + + fun getX(): String { + return x + } + + fun setX(x: String) { + println("setter invoked") + this.x = x + } +} diff --git a/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect4.java b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect4.java new file mode 100644 index 00000000000..0cd44495788 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect4.java @@ -0,0 +1,12 @@ +public class C { + private String x = ""; + + public String getX() { + return x; + } + + public void setX(String value) { + System.out.println("setter invoked"); + x = value; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect4.kt b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect4.kt new file mode 100644 index 00000000000..4ced9917081 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect4.kt @@ -0,0 +1,7 @@ +class C { + var x = "" + set(value) { + println("setter invoked") + field = value + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect5.java b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect5.java new file mode 100644 index 00000000000..ebbfadf625a --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect5.java @@ -0,0 +1,12 @@ +public class C { + private String x = ""; + + public String getX() { + return x; + } + + public void setX(String x) { + System.out.println("setter invoked"); + this.x = x; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect5.kt b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect5.kt new file mode 100644 index 00000000000..a2adae89393 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect5.kt @@ -0,0 +1,7 @@ +class C { + var x = "" + set(x) { + println("setter invoked") + field = x + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect6.java b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect6.java new file mode 100644 index 00000000000..2a1025d432c --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect6.java @@ -0,0 +1,12 @@ +public class C { + private String x = ""; + + public String getX() { + return x; + } + + public void setX(String x) { + System.out.println("old value: " + this.x); + this.x = x; + } +} \ No newline at end of file diff --git a/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect6.kt b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect6.kt new file mode 100644 index 00000000000..531904f9405 --- /dev/null +++ b/j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect6.kt @@ -0,0 +1,7 @@ +class C { + var x = "" + set(x) { + println("old value: " + this.x) + field = x + } +} diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java index a544efd0f2c..afe4acc6ff8 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterForWebDemoTestGenerated.java @@ -1396,6 +1396,18 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("AssignFieldInsideSetter.java") + public void testAssignFieldInsideSetter() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter.java"); + doTest(fileName); + } + + @TestMetadata("AssignFieldInsideSetter2.java") + public void testAssignFieldInsideSetter2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter2.java"); + doTest(fileName); + } + @TestMetadata("CannotDropOnlySetter.java") public void testCannotDropOnlySetter() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/CannotDropOnlySetter.java"); @@ -1498,6 +1510,36 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("GetterWithSideEffect1.java") + public void testGetterWithSideEffect1() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect1.java"); + doTest(fileName); + } + + @TestMetadata("GetterWithSideEffect2.java") + public void testGetterWithSideEffect2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect2.java"); + doTest(fileName); + } + + @TestMetadata("GetterWithSideEffect3.java") + public void testGetterWithSideEffect3() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect3.java"); + doTest(fileName); + } + + @TestMetadata("GetterWithSideEffect4.java") + public void testGetterWithSideEffect4() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect4.java"); + doTest(fileName); + } + + @TestMetadata("GetterWithSideEffect5.java") + public void testGetterWithSideEffect5() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect5.java"); + doTest(fileName); + } + @TestMetadata("InCompanionObject.java") public void testInCompanionObject() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/InCompanionObject.java"); @@ -1546,6 +1588,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("PropertyAndFieldConflicts.java") + public void testPropertyAndFieldConflicts() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/PropertyAndFieldConflicts.java"); + doTest(fileName); + } + @TestMetadata("PropertyType.java") public void testPropertyType() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/PropertyType.java"); @@ -1557,6 +1605,42 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/SetterTypeNotMatch.java"); doTest(fileName); } + + @TestMetadata("SetterWithSideEffect1.java") + public void testSetterWithSideEffect1() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect1.java"); + doTest(fileName); + } + + @TestMetadata("SetterWithSideEffect2.java") + public void testSetterWithSideEffect2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect2.java"); + doTest(fileName); + } + + @TestMetadata("SetterWithSideEffect3.java") + public void testSetterWithSideEffect3() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect3.java"); + doTest(fileName); + } + + @TestMetadata("SetterWithSideEffect4.java") + public void testSetterWithSideEffect4() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect4.java"); + doTest(fileName); + } + + @TestMetadata("SetterWithSideEffect5.java") + public void testSetterWithSideEffect5() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect5.java"); + doTest(fileName); + } + + @TestMetadata("SetterWithSideEffect6.java") + public void testSetterWithSideEffect6() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect6.java"); + doTest(fileName); + } } @TestMetadata("j2k/testData/fileOrElement/doWhileStatement") diff --git a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java index eac4836952d..7cf0d6da45d 100644 --- a/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java +++ b/j2k/tests/org/jetbrains/kotlin/j2k/JavaToKotlinConverterSingleFileTestGenerated.java @@ -1396,6 +1396,18 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("AssignFieldInsideSetter.java") + public void testAssignFieldInsideSetter() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter.java"); + doTest(fileName); + } + + @TestMetadata("AssignFieldInsideSetter2.java") + public void testAssignFieldInsideSetter2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/AssignFieldInsideSetter2.java"); + doTest(fileName); + } + @TestMetadata("CannotDropOnlySetter.java") public void testCannotDropOnlySetter() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/CannotDropOnlySetter.java"); @@ -1498,6 +1510,36 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("GetterWithSideEffect1.java") + public void testGetterWithSideEffect1() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect1.java"); + doTest(fileName); + } + + @TestMetadata("GetterWithSideEffect2.java") + public void testGetterWithSideEffect2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect2.java"); + doTest(fileName); + } + + @TestMetadata("GetterWithSideEffect3.java") + public void testGetterWithSideEffect3() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect3.java"); + doTest(fileName); + } + + @TestMetadata("GetterWithSideEffect4.java") + public void testGetterWithSideEffect4() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect4.java"); + doTest(fileName); + } + + @TestMetadata("GetterWithSideEffect5.java") + public void testGetterWithSideEffect5() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/GetterWithSideEffect5.java"); + doTest(fileName); + } + @TestMetadata("InCompanionObject.java") public void testInCompanionObject() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/InCompanionObject.java"); @@ -1546,6 +1588,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo doTest(fileName); } + @TestMetadata("PropertyAndFieldConflicts.java") + public void testPropertyAndFieldConflicts() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/PropertyAndFieldConflicts.java"); + doTest(fileName); + } + @TestMetadata("PropertyType.java") public void testPropertyType() throws Exception { String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/PropertyType.java"); @@ -1557,6 +1605,42 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/SetterTypeNotMatch.java"); doTest(fileName); } + + @TestMetadata("SetterWithSideEffect1.java") + public void testSetterWithSideEffect1() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect1.java"); + doTest(fileName); + } + + @TestMetadata("SetterWithSideEffect2.java") + public void testSetterWithSideEffect2() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect2.java"); + doTest(fileName); + } + + @TestMetadata("SetterWithSideEffect3.java") + public void testSetterWithSideEffect3() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect3.java"); + doTest(fileName); + } + + @TestMetadata("SetterWithSideEffect4.java") + public void testSetterWithSideEffect4() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect4.java"); + doTest(fileName); + } + + @TestMetadata("SetterWithSideEffect5.java") + public void testSetterWithSideEffect5() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect5.java"); + doTest(fileName); + } + + @TestMetadata("SetterWithSideEffect6.java") + public void testSetterWithSideEffect6() throws Exception { + String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/SetterWithSideEffect6.java"); + doTest(fileName); + } } @TestMetadata("j2k/testData/fileOrElement/doWhileStatement")