Support for synthetic extensions in codegen
This commit is contained in:
@@ -76,6 +76,7 @@ import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterKind;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodParameterSignature;
|
||||
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature;
|
||||
import org.jetbrains.kotlin.resolve.scopes.receivers.*;
|
||||
import org.jetbrains.kotlin.synthetic.SyntheticExtensionPropertyDescriptor;
|
||||
import org.jetbrains.kotlin.types.JetType;
|
||||
import org.jetbrains.kotlin.types.TypeProjection;
|
||||
import org.jetbrains.kotlin.types.TypeUtils;
|
||||
@@ -2144,6 +2145,10 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
@NotNull MethodKind methodKind,
|
||||
StackValue receiver
|
||||
) {
|
||||
if (propertyDescriptor instanceof SyntheticExtensionPropertyDescriptor) {
|
||||
return intermediateValueForSyntheticExtensionProperty((SyntheticExtensionPropertyDescriptor) propertyDescriptor, receiver);
|
||||
}
|
||||
|
||||
DeclarationDescriptor containingDeclaration = propertyDescriptor.getContainingDeclaration();
|
||||
|
||||
boolean isBackingFieldInAnotherClass = AsmUtil.isPropertyWithBackingFieldInOuterClass(propertyDescriptor);
|
||||
@@ -2166,10 +2171,12 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
if (isBackingFieldInAnotherClass && forceField) {
|
||||
backingFieldContext = context.findParentContextWithDescriptor(containingDeclaration.getContainingDeclaration());
|
||||
int flags = AsmUtil.getVisibilityForSpecialPropertyBackingField(propertyDescriptor, isDelegatedProperty);
|
||||
skipPropertyAccessors = (flags & ACC_PRIVATE) == 0 || methodKind == MethodKind.SYNTHETIC_ACCESSOR || methodKind == MethodKind.INITIALIZER;
|
||||
skipPropertyAccessors =
|
||||
(flags & ACC_PRIVATE) == 0 || methodKind == MethodKind.SYNTHETIC_ACCESSOR || methodKind == MethodKind.INITIALIZER;
|
||||
if (!skipPropertyAccessors) {
|
||||
propertyDescriptor = (PropertyDescriptor) backingFieldContext.getAccessor(propertyDescriptor, true, delegateType);
|
||||
changeOwnerOnTypeMapping = changeOwnerOnTypeMapping && !(propertyDescriptor instanceof AccessorForPropertyBackingFieldInOuterClass);
|
||||
changeOwnerOnTypeMapping =
|
||||
changeOwnerOnTypeMapping && !(propertyDescriptor instanceof AccessorForPropertyBackingFieldInOuterClass);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2191,7 +2198,8 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
|
||||
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
|
||||
if (getter != null) {
|
||||
callableGetter = typeMapper.mapToCallableMethod(getter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, context);
|
||||
callableGetter =
|
||||
typeMapper.mapToCallableMethod(getter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, context);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2202,14 +2210,16 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
callableSetter = null;
|
||||
}
|
||||
else {
|
||||
callableSetter = typeMapper.mapToCallableMethod(setter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, context);
|
||||
callableSetter =
|
||||
typeMapper.mapToCallableMethod(setter, isSuper || MethodKind.SYNTHETIC_ACCESSOR == methodKind, context);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
propertyDescriptor = DescriptorUtils.unwrapFakeOverride(propertyDescriptor);
|
||||
Type backingFieldOwner = typeMapper.mapOwner(changeOwnerOnTypeMapping ? propertyDescriptor.getContainingDeclaration() : propertyDescriptor,
|
||||
Type backingFieldOwner =
|
||||
typeMapper.mapOwner(changeOwnerOnTypeMapping ? propertyDescriptor.getContainingDeclaration() : propertyDescriptor,
|
||||
isCallInsideSameModuleAsDeclared(propertyDescriptor, context, state.getOutDirectory()));
|
||||
|
||||
String fieldName;
|
||||
@@ -2226,9 +2236,18 @@ public class ExpressionCodegen extends JetVisitor<StackValue, StackValue> implem
|
||||
}
|
||||
|
||||
return StackValue.property(propertyDescriptor, backingFieldOwner,
|
||||
typeMapper.mapType(isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()),
|
||||
isStaticBackingField, fieldName, callableGetter, callableSetter, state, receiver);
|
||||
typeMapper.mapType(
|
||||
isDelegatedProperty && forceField ? delegateType : propertyDescriptor.getOriginal().getType()),
|
||||
isStaticBackingField, fieldName, callableGetter, callableSetter, state, receiver);
|
||||
}
|
||||
|
||||
@NotNull
|
||||
private StackValue.Property intermediateValueForSyntheticExtensionProperty(@NotNull SyntheticExtensionPropertyDescriptor propertyDescriptor, StackValue receiver) {
|
||||
Type type = typeMapper.mapType(propertyDescriptor.getOriginal().getType());
|
||||
CallableMethod callableGetter = typeMapper.mapToCallableMethod(propertyDescriptor.getGetMethod(), false, context);
|
||||
FunctionDescriptor setMethod = propertyDescriptor.getSetMethod();
|
||||
CallableMethod callableSetter = setMethod != null ? typeMapper.mapToCallableMethod(setMethod, false, context) : null;
|
||||
return StackValue.property(propertyDescriptor, null, type, false, null, callableGetter, callableSetter, state, receiver);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -248,7 +248,7 @@ public abstract class StackValue {
|
||||
@NotNull
|
||||
public static Property property(
|
||||
@NotNull PropertyDescriptor descriptor,
|
||||
@NotNull Type backingFieldOwner,
|
||||
@Nullable Type backingFieldOwner,
|
||||
@NotNull Type type,
|
||||
boolean isStaticBackingField,
|
||||
@Nullable String fieldName,
|
||||
@@ -989,7 +989,7 @@ public abstract class StackValue {
|
||||
private final String fieldName;
|
||||
|
||||
public Property(
|
||||
@NotNull PropertyDescriptor descriptor, @NotNull Type backingFieldOwner,
|
||||
@NotNull PropertyDescriptor descriptor, @Nullable Type backingFieldOwner,
|
||||
@Nullable CallableMethod getter, @Nullable CallableMethod setter, boolean isStaticBackingField,
|
||||
@Nullable String fieldName, @NotNull Type type, @NotNull GenerationState state,
|
||||
@NotNull StackValue receiver
|
||||
@@ -1007,6 +1007,7 @@ public abstract class StackValue {
|
||||
public void putSelector(@NotNull Type type, @NotNull InstructionAdapter v) {
|
||||
if (getter == null) {
|
||||
assert fieldName != null : "Property should have either a getter or a field name: " + descriptor;
|
||||
assert backingFieldOwner != null : "Property should have either a getter or a backingFieldOwner: " + descriptor;
|
||||
v.visitFieldInsn(isStaticPut ? GETSTATIC : GETFIELD, backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor());
|
||||
genNotNullAssertionForField(v, state, descriptor);
|
||||
coerceTo(type, v);
|
||||
@@ -1022,6 +1023,7 @@ public abstract class StackValue {
|
||||
coerceFrom(topOfStackType, v);
|
||||
if (setter == null) {
|
||||
assert fieldName != null : "Property should have either a setter or a field name: " + descriptor;
|
||||
assert backingFieldOwner != null : "Property should have either a setter or a backingFieldOwner: " + descriptor;
|
||||
v.visitFieldInsn(isStaticStore ? PUTSTATIC : PUTFIELD, backingFieldOwner.getInternalName(), fieldName, this.type.getDescriptor());
|
||||
}
|
||||
else {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
class JavaClass {
|
||||
public String getOk() { return "OK"; }
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
fun box(): String {
|
||||
return JavaClass().ok
|
||||
}
|
||||
+11
@@ -0,0 +1,11 @@
|
||||
class JavaClass {
|
||||
private String myX;
|
||||
|
||||
public String getX() {
|
||||
return myX;
|
||||
}
|
||||
|
||||
public void setX(String x) {
|
||||
myX = x;
|
||||
}
|
||||
}
|
||||
+8
@@ -0,0 +1,8 @@
|
||||
fun box(): String {
|
||||
return JavaClass().doIt()
|
||||
}
|
||||
|
||||
fun JavaClass.doIt(): String {
|
||||
x = "OK"
|
||||
return x
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class JavaClass {
|
||||
private int myX = 0;
|
||||
|
||||
public int getX() {
|
||||
return myX;
|
||||
}
|
||||
|
||||
public void setX(int x) {
|
||||
myX = x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
fun box(): String {
|
||||
val javaClass = JavaClass()
|
||||
javaClass.x++
|
||||
return if (javaClass.x == 1) "OK" else "ERROR"
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
class JavaClass {
|
||||
private String myX;
|
||||
|
||||
public String getX() {
|
||||
return myX;
|
||||
}
|
||||
|
||||
public void setX(String x) {
|
||||
myX = x;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
fun box(): String {
|
||||
val javaClass = JavaClass()
|
||||
javaClass.x = "OK"
|
||||
return javaClass.x
|
||||
}
|
||||
+33
@@ -827,6 +827,39 @@ public class BlackBoxAgainstJavaCodegenTestGenerated extends AbstractBlackBoxCod
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxAgainstJava/syntheticExtensions")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
public static class SyntheticExtensions extends AbstractBlackBoxCodegenTest {
|
||||
public void testAllFilesPresentInSyntheticExtensions() throws Exception {
|
||||
JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxAgainstJava/syntheticExtensions"), Pattern.compile("^(.+)\\.kt$"), true);
|
||||
}
|
||||
|
||||
@TestMetadata("getter.kt")
|
||||
public void testGetter() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/syntheticExtensions/getter.kt");
|
||||
doTestAgainstJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("implicitReceiver.kt")
|
||||
public void testImplicitReceiver() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/syntheticExtensions/implicitReceiver.kt");
|
||||
doTestAgainstJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("plusPlus.kt")
|
||||
public void testPlusPlus() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/syntheticExtensions/plusPlus.kt");
|
||||
doTestAgainstJava(fileName);
|
||||
}
|
||||
|
||||
@TestMetadata("setter.kt")
|
||||
public void testSetter() throws Exception {
|
||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxAgainstJava/syntheticExtensions/setter.kt");
|
||||
doTestAgainstJava(fileName);
|
||||
}
|
||||
}
|
||||
|
||||
@TestMetadata("compiler/testData/codegen/boxAgainstJava/visibility")
|
||||
@TestDataPath("$PROJECT_ROOT")
|
||||
@RunWith(JUnit3RunnerWithInners.class)
|
||||
|
||||
Reference in New Issue
Block a user