KT-12046 Java to Kotlin dangerous conversion (recursive property set)
#KT-12046 Fixed
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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<String>()
|
||||
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<PsiMember, PropertyInfo>()
|
||||
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<PropertyInfo>()
|
||||
|
||||
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<PsiMember, PropertyInfo>()
|
||||
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<Pair<PsiMethod, SuperInfo.Property?>>,
|
||||
prohibitedPropertyNames: MutableSet<String>,
|
||||
propertyNamesWithConflict: MutableSet<String>
|
||||
): Map<String, AccessorInfo> {
|
||||
val propertyNameToGetterInfo = LinkedHashMap<String, AccessorInfo>()
|
||||
@@ -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<Pair<PsiMethod, SuperInfo.Property?>>,
|
||||
prohibitedPropertyNames: MutableSet<String>,
|
||||
propertyNamesFromGetters: Set<String>,
|
||||
propertyNamesWithConflict: MutableSet<String>
|
||||
): Map<String, AccessorInfo> {
|
||||
@@ -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<PsiMember, PropertyInfo>) {
|
||||
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<PsiMember, PropertyInfo>.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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
public class C {
|
||||
private String x = null;
|
||||
|
||||
public String getX() {
|
||||
return x;
|
||||
}
|
||||
|
||||
void setX(String x) {
|
||||
this.x = x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,4 @@
|
||||
class C {
|
||||
var x: String? = null
|
||||
internal set
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
class AAA {
|
||||
var x = 42
|
||||
set(x) {
|
||||
this.x += x
|
||||
field += x
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
@@ -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)
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
class C {
|
||||
var x = ""
|
||||
|
||||
fun getX(): String {
|
||||
println("getter invoked")
|
||||
return x
|
||||
}
|
||||
|
||||
fun setX(x: String) {
|
||||
this.x = x
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class C {
|
||||
var x = ""
|
||||
get() {
|
||||
println("getter invoked")
|
||||
return field
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class C {
|
||||
var x = ""
|
||||
get() {
|
||||
println("getter invoked")
|
||||
return field
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -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
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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";
|
||||
}
|
||||
}
|
||||
@@ -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"
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
class C {
|
||||
protected var x = ""
|
||||
|
||||
fun getX(): String {
|
||||
return x
|
||||
}
|
||||
|
||||
fun setX(x: String) {
|
||||
println("setter invoked")
|
||||
this.x = x
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class C {
|
||||
var x = ""
|
||||
set(value) {
|
||||
println("setter invoked")
|
||||
field = value
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class C {
|
||||
var x = ""
|
||||
set(x) {
|
||||
println("setter invoked")
|
||||
field = x
|
||||
}
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
class C {
|
||||
var x = ""
|
||||
set(x) {
|
||||
println("old value: " + this.x)
|
||||
field = x
|
||||
}
|
||||
}
|
||||
@@ -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")
|
||||
|
||||
@@ -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")
|
||||
|
||||
Reference in New Issue
Block a user