J2K: do not generate super call to abstract property
This commit is contained in:
@@ -348,7 +348,7 @@ class Converter private constructor(
|
||||
getter = PropertyAccessor(AccessorKind.GETTER, method.annotations, Modifiers.Empty, method.parameterList, method.body)
|
||||
getter.assignPrototype(getMethod, CommentsAndSpacesInheritance.NO_SPACES)
|
||||
}
|
||||
else if (propertyInfo.modifiers.contains(Modifier.OVERRIDE)) {
|
||||
else if (propertyInfo.modifiers.contains(Modifier.OVERRIDE) && !(propertyInfo.superInfo?.isAbstract() ?: false)) {
|
||||
val superExpression = SuperExpression(Identifier.Empty).assignNoPrototype()
|
||||
val superAccess = QualifiedExpression(superExpression, propertyInfo.identifier).assignNoPrototype()
|
||||
val returnStatement = ReturnStatement(superAccess).assignNoPrototype()
|
||||
@@ -357,7 +357,10 @@ class Converter private constructor(
|
||||
getter = PropertyAccessor(AccessorKind.GETTER, Annotations.Empty, Modifiers.Empty, parameterList, deferredElement { body })
|
||||
getter.assignNoPrototype()
|
||||
}
|
||||
//TODO: what else?
|
||||
else {
|
||||
//TODO: what else?
|
||||
getter = PropertyAccessor(AccessorKind.GETTER, Annotations.Empty, Modifiers.Empty, null, null).assignNoPrototype()
|
||||
}
|
||||
}
|
||||
|
||||
var setter: PropertyAccessor? = null
|
||||
@@ -378,7 +381,7 @@ class Converter private constructor(
|
||||
setter = PropertyAccessor(AccessorKind.SETTER, method.annotations, accessorModifiers, parameterList, method.body)
|
||||
setter.assignPrototype(setMethod, CommentsAndSpacesInheritance.NO_SPACES)
|
||||
}
|
||||
else if (propertyInfo.modifiers.contains(Modifier.OVERRIDE)) {
|
||||
else if (propertyInfo.modifiers.contains(Modifier.OVERRIDE) && !(propertyInfo.superInfo?.isAbstract() ?: false)) {
|
||||
val superExpression = SuperExpression(Identifier.Empty).assignNoPrototype()
|
||||
val superAccess = QualifiedExpression(superExpression, propertyInfo.identifier).assignNoPrototype()
|
||||
val valueIdentifier = Identifier("value", false).assignNoPrototype()
|
||||
|
||||
@@ -20,6 +20,7 @@ import com.intellij.psi.*
|
||||
import com.intellij.psi.util.MethodSignatureUtil
|
||||
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
|
||||
@@ -38,7 +39,8 @@ class PropertyInfo(
|
||||
val isGetMethodBodyFieldAccess: Boolean,
|
||||
val isSetMethodBodyFieldAccess: Boolean,
|
||||
val modifiers: Modifiers,
|
||||
val specialSetterAccess: Modifier?
|
||||
val specialSetterAccess: Modifier?,
|
||||
val superInfo: SuperInfo?
|
||||
) {
|
||||
init {
|
||||
assert(field != null || getMethod != null || setMethod != null)
|
||||
@@ -73,7 +75,7 @@ class PropertyInfo(
|
||||
fun fromFieldWithNoAccessors(field: PsiField, converter: Converter): PropertyInfo {
|
||||
val isVar = field.isVar(converter.referenceSearcher)
|
||||
val modifiers = converter.convertModifiers(field, false)
|
||||
return PropertyInfo(field.declarationIdentifier(), isVar, field.type, field, null, null, false, false, modifiers, null)
|
||||
return PropertyInfo(field.declarationIdentifier(), isVar, field.type, field, null, null, false, false, modifiers, null, null)
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -92,6 +94,21 @@ class PropertyDetectionCache(private val converter: Converter) {
|
||||
}
|
||||
}
|
||||
|
||||
sealed class SuperInfo {
|
||||
class Property(
|
||||
val isVar: Boolean,
|
||||
val name: String,
|
||||
val hasAbstractModifier: Boolean
|
||||
//TODO: add visibility
|
||||
) : SuperInfo()
|
||||
|
||||
object Function : SuperInfo()
|
||||
|
||||
fun isAbstract(): Boolean {
|
||||
return if (this is Property) hasAbstractModifier else false
|
||||
}
|
||||
}
|
||||
|
||||
private class PropertyDetector(
|
||||
private val psiClass: PsiClass,
|
||||
private val converter: Converter
|
||||
@@ -151,7 +168,8 @@ private class PropertyDetector(
|
||||
|
||||
val type = getterInfo?.method?.returnType ?: setterInfo!!.method.parameterList.parameters.single()?.type!!
|
||||
|
||||
val isOverride = getterInfo?.superProperty != null || setterInfo?.superProperty != null
|
||||
val superProperty = getterInfo?.superProperty ?: setterInfo?.superProperty
|
||||
val isOverride = superProperty != null
|
||||
|
||||
val modifiers = convertModifiers(field, getterInfo?.method, setterInfo?.method, isOverride)
|
||||
|
||||
@@ -173,7 +191,8 @@ private class PropertyDetector(
|
||||
field != null && getterInfo?.field == field,
|
||||
field != null && setterInfo?.field == field,
|
||||
modifiers,
|
||||
specialSetterAccess)
|
||||
specialSetterAccess,
|
||||
superProperty)
|
||||
|
||||
if (field != null) {
|
||||
memberToPropertyInfo[field] = propertyInfo
|
||||
@@ -329,17 +348,6 @@ private class PropertyDetector(
|
||||
val superProperty: SuperInfo.Property?
|
||||
)
|
||||
|
||||
private sealed class SuperInfo {
|
||||
class Property(
|
||||
val isVar: Boolean,
|
||||
val name: String
|
||||
//TODO: add visibility
|
||||
) : SuperInfo()
|
||||
|
||||
object Function : SuperInfo()
|
||||
|
||||
}
|
||||
|
||||
private fun getGetterInfo(method: PsiMethod, superProperty: SuperInfo.Property?): AccessorInfo? {
|
||||
val propertyName = propertyNameByGetMethod(method) ?: return null
|
||||
val field = fieldFromGetterBody(method)
|
||||
@@ -364,11 +372,11 @@ private class PropertyDetector(
|
||||
val containingClass = superMethod.containingClass!!
|
||||
if (converter.inConversionScope(containingClass)) {
|
||||
val propertyInfo = converter.propertyDetectionCache[containingClass][superMethod]
|
||||
return if (propertyInfo != null) SuperInfo.Property(propertyInfo.isVar, propertyInfo.name) else SuperInfo.Function
|
||||
return if (propertyInfo != null) SuperInfo.Property(propertyInfo.isVar, propertyInfo.name, propertyInfo.modifiers.contains(Modifier.ABSTRACT)) else SuperInfo.Function
|
||||
}
|
||||
else if (superMethod is KtLightMethod) {
|
||||
val origin = superMethod.kotlinOrigin
|
||||
return if (origin is KtProperty) SuperInfo.Property(origin.isVar, origin.name ?: "") else SuperInfo.Function
|
||||
return if (origin is KtProperty) SuperInfo.Property(origin.isVar, origin.name ?: "", origin.hasModifier(KtTokens.ABSTRACT_KEYWORD)) else SuperInfo.Function
|
||||
}
|
||||
else {
|
||||
return SuperInfo.Function
|
||||
|
||||
Vendored
+4
@@ -70,3 +70,7 @@ public open class KotlinClassWithProperties {
|
||||
public open fun getSomething4() { return 1; }
|
||||
public open fun setSomething4(value: Int) { }
|
||||
}
|
||||
|
||||
public abstract class KotlinClassAbstractProperty {
|
||||
abstract val isVisible: Boolean
|
||||
}
|
||||
|
||||
+16
@@ -0,0 +1,16 @@
|
||||
package test;
|
||||
|
||||
import kotlinApi.*;
|
||||
|
||||
public class KotlinClassAbstractPropertyImpl extends KotlinClassAbstractProperty {
|
||||
private boolean myIsVisible;
|
||||
|
||||
@Override
|
||||
public boolean isVisible() {
|
||||
return myIsVisible;
|
||||
}
|
||||
|
||||
private void test() {
|
||||
myIsVisible = true;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
package test
|
||||
|
||||
import kotlinApi.*
|
||||
|
||||
class KotlinClassAbstractPropertyImpl : KotlinClassAbstractProperty() {
|
||||
override var isVisible: Boolean = false
|
||||
private set
|
||||
|
||||
private fun test() {
|
||||
isVisible = true
|
||||
}
|
||||
}
|
||||
+6
-8
@@ -1,6 +1,6 @@
|
||||
// ERROR: Abstract member cannot be accessed directly
|
||||
// ERROR: Abstract member cannot be accessed directly
|
||||
// ERROR: Abstract member cannot be accessed directly
|
||||
// ERROR: Property must be initialized
|
||||
// ERROR: Property must be initialized
|
||||
// ERROR: Property must be initialized
|
||||
internal interface I {
|
||||
val isSomething1: Boolean
|
||||
|
||||
@@ -23,17 +23,15 @@ internal abstract class C : I {
|
||||
|
||||
override var isSomething4: Boolean
|
||||
get() = false
|
||||
set(value: Boolean) {
|
||||
super.isSomething4 = value
|
||||
}
|
||||
set
|
||||
|
||||
override var isSomething5: Boolean
|
||||
get() = super.isSomething5
|
||||
get
|
||||
set(value) {
|
||||
}
|
||||
|
||||
override var something6: Boolean
|
||||
get() = super.something6
|
||||
get
|
||||
set(value) {
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
// ERROR: Abstract member cannot be accessed directly
|
||||
// ERROR: Abstract member cannot be accessed directly
|
||||
// ERROR: Property must be initialized
|
||||
// ERROR: Property must be initialized
|
||||
internal interface I {
|
||||
val something1: Int
|
||||
|
||||
@@ -56,12 +56,10 @@ internal abstract class C(override val something1: Int) : B(), I {
|
||||
|
||||
override var something4: Int
|
||||
get() = 0
|
||||
set(value: Int) {
|
||||
super.something4 = value
|
||||
}
|
||||
set
|
||||
|
||||
override var something5: Int
|
||||
get() = super.something5
|
||||
get
|
||||
set(value) {
|
||||
|
||||
}
|
||||
|
||||
@@ -1368,6 +1368,12 @@ public class JavaToKotlinConverterForWebDemoTestGenerated extends AbstractJavaTo
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class DetectProperties extends AbstractJavaToKotlinConverterForWebDemoTest {
|
||||
@TestMetadata("AbstractPropertyPrivateSetter.java")
|
||||
public void testAbstractPropertyPrivateSetter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/AbstractPropertyPrivateSetter.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("AccessInGetterWithThis.java")
|
||||
public void testAccessInGetterWithThis() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/AccessInGetterWithThis.java");
|
||||
|
||||
@@ -1368,6 +1368,12 @@ public class JavaToKotlinConverterSingleFileTestGenerated extends AbstractJavaTo
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class DetectProperties extends AbstractJavaToKotlinConverterSingleFileTest {
|
||||
@TestMetadata("AbstractPropertyPrivateSetter.java")
|
||||
public void testAbstractPropertyPrivateSetter() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/AbstractPropertyPrivateSetter.java");
|
||||
doTest(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("AccessInGetterWithThis.java")
|
||||
public void testAccessInGetterWithThis() throws Exception {
|
||||
String fileName = KotlinTestUtils.navigationMetadata("j2k/testData/fileOrElement/detectProperties/AccessInGetterWithThis.java");
|
||||
|
||||
Reference in New Issue
Block a user