Fix synthetic accessor generation for properties

Generate synthetic accessors for property accessors only if the
corresponding methods are accessible in the current context.

 #KT-19306 Fixed Target versions 1.1.5
This commit is contained in:
Dmitry Petrov
2017-08-01 09:02:33 +03:00
parent dde0efd8ab
commit 2427b2cc6c
3 changed files with 55 additions and 6 deletions
@@ -580,7 +580,8 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
superCallTarget = (ClassDescriptor) enclosed;
}
if (descriptorContext == null && withinInliningContext && superCallTarget != null) {
boolean isSuperCallTarget = superCallTarget != null;
if (descriptorContext == null && withinInliningContext && isSuperCallTarget) {
//generate super calls within inline function through synthetic accessors
descriptorContext = ExpressionCodegen.getParentContextSubclassOf((ClassDescriptor) enclosed, this);
}
@@ -606,8 +607,9 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
PropertyGetterDescriptor getter = propertyDescriptor.getGetter();
int getterAccessFlag = getter == null ? propertyAccessFlag
: propertyAccessFlag | getVisibilityAccessFlag(getter);
boolean getterAccessorRequired = isAccessorRequired(getterAccessFlag, unwrappedDescriptor, descriptorContext,
withinInliningContext, superCallTarget != null);
boolean getterAccessorRequired =
canGenerateAccessorInContext(getter == null ? propertyDescriptor : getter, descriptorContext) &&
isAccessorRequired(getterAccessFlag, unwrappedDescriptor, descriptorContext, withinInliningContext, isSuperCallTarget);
PropertySetterDescriptor setter = propertyDescriptor.getSetter();
@@ -615,8 +617,9 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
if (setter != null && setter.getVisibility().normalize() != Visibilities.INVISIBLE_FAKE) {
setterAccessFlag = propertyAccessFlag | getVisibilityAccessFlag(setter);
}
boolean setterAccessorRequired = isAccessorRequired(setterAccessFlag, unwrappedDescriptor, descriptorContext,
withinInliningContext, superCallTarget != null);
boolean setterAccessorRequired =
canGenerateAccessorInContext(setter == null ? propertyDescriptor : setter, descriptorContext) &&
isAccessorRequired(setterAccessFlag, unwrappedDescriptor, descriptorContext, withinInliningContext, isSuperCallTarget);
if (!getterAccessorRequired && !setterAccessorRequired) {
return descriptor;
@@ -625,13 +628,20 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
}
else {
int flag = getVisibilityAccessFlag(unwrappedDescriptor);
if (!isAccessorRequired(flag, unwrappedDescriptor, descriptorContext, withinInliningContext, superCallTarget != null)) {
if (!isAccessorRequired(flag, unwrappedDescriptor, descriptorContext, withinInliningContext, isSuperCallTarget)) {
return descriptor;
}
return (D) descriptorContext.getAccessor(descriptor, superCallTarget);
}
}
private static boolean canGenerateAccessorInContext(
@NotNull CallableMemberDescriptor callableDescriptor,
@NotNull CodegenContext hostContext
) {
return Visibilities.isVisibleWithAnyReceiver(callableDescriptor, hostContext.contextDescriptor);
}
private static boolean isAccessorRequired(
int accessFlag,
@NotNull CallableMemberDescriptor unwrappedDescriptor,
@@ -0,0 +1,24 @@
// FILE: A.kt
package a
abstract class A {
protected var property: String = ""
private set
}
// FILE: B.kt
package b
import a.A
class B : A() {
init {
invoke { property }
}
fun invoke(func: () -> String): String = func()
}
// TESTED_OBJECT_KIND: function
// TESTED_OBJECTS: b/B, access$setProperty$p
// ABSENT: true
@@ -746,6 +746,21 @@ public class WriteFlagsTestGenerated extends AbstractWriteFlagsTest {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/writeFlags/property"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
@TestMetadata("compiler/testData/writeFlags/property/accessors")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)
public static class Accessors extends AbstractWriteFlagsTest {
@TestMetadata("accessorForProtectedPropertyWithPrivateSetter.kt")
public void testAccessorForProtectedPropertyWithPrivateSetter() throws Exception {
String fileName = KotlinTestUtils.navigationMetadata("compiler/testData/writeFlags/property/accessors/accessorForProtectedPropertyWithPrivateSetter.kt");
doTest(fileName);
}
public void testAllFilesPresentInAccessors() throws Exception {
KotlinTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/writeFlags/property/accessors"), Pattern.compile("^(.+)\\.kt$"), TargetBackend.ANY, true);
}
}
@TestMetadata("compiler/testData/writeFlags/property/classObject")
@TestDataPath("$PROJECT_ROOT")
@RunWith(JUnit3RunnerWithInners.class)