J2K: do not generate super call to abstract property

This commit is contained in:
Natalia Ukhorskaya
2016-04-12 17:14:42 +03:00
parent 72019a1b4e
commit 495be06fc5
9 changed files with 85 additions and 34 deletions
@@ -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
+4
View File
@@ -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
}
@@ -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
View File
@@ -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) {
}
}
+4 -6
View File
@@ -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");