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:
@@ -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,
|
||||
|
||||
Vendored
+24
@@ -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)
|
||||
|
||||
Reference in New Issue
Block a user