Support access to companion private members from nested classes
#KT-5363 Fixed #KT-6804 Fixed
This commit is contained in:
committed by
Max Kammerer
parent
3d88df73e0
commit
d977d29ec4
@@ -206,7 +206,26 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
|
|||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind, GenerationState state) {
|
public ClassContext intoClass(ClassDescriptor descriptor, OwnerKind kind, GenerationState state) {
|
||||||
return new ClassContext(state.getTypeMapper(), descriptor, kind, this, null);
|
if (descriptor.isCompanionObject()) {
|
||||||
|
CodegenContext companionContext = this.findChildContext(descriptor);
|
||||||
|
if (companionContext != null) {
|
||||||
|
assert companionContext.getContextKind() == kind : "Kinds should be same, but: " +
|
||||||
|
companionContext.getContextKind() + "!= " + kind;
|
||||||
|
return (ClassContext) companionContext;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ClassContext classContext = new ClassContext(state.getTypeMapper(), descriptor, kind, this, null);
|
||||||
|
|
||||||
|
//We can't call descriptor.getCompanionObjectDescriptor() on light class generation
|
||||||
|
// because it triggers companion light class generation via putting it to BindingContext.CLASS
|
||||||
|
// (so MemberCodegen doesn't skip it in genClassOrObject).
|
||||||
|
if (state.getTypeMapper().getClassBuilderMode() != ClassBuilderMode.LIGHT_CLASSES &&
|
||||||
|
descriptor.getCompanionObjectDescriptor() != null) {
|
||||||
|
//We need to create companion object context ahead of time
|
||||||
|
// because otherwise we can't generate synthetic accessor for private members in companion object
|
||||||
|
classContext.intoClass(descriptor.getCompanionObjectDescriptor(), OwnerKind.IMPLEMENTATION, state);
|
||||||
|
}
|
||||||
|
return classContext;
|
||||||
}
|
}
|
||||||
|
|
||||||
@NotNull
|
@NotNull
|
||||||
|
|||||||
+1
-1
@@ -43,7 +43,7 @@ public class NeedSyntheticChecker implements CallChecker {
|
|||||||
//Necessary synthetic accessors in outer classes generated via old logic: CodegenContext.getAccessor
|
//Necessary synthetic accessors in outer classes generated via old logic: CodegenContext.getAccessor
|
||||||
//Generation of accessors in nested classes (to invoke from outer,
|
//Generation of accessors in nested classes (to invoke from outer,
|
||||||
// e.g.: from class to companion object) controlled via NEED_SYNTHETIC_ACCESSOR slice
|
// e.g.: from class to companion object) controlled via NEED_SYNTHETIC_ACCESSOR slice
|
||||||
private boolean needSyntheticAccessor(LexicalScope invokationScope, CallableDescriptor targetDescriptor) {
|
private static boolean needSyntheticAccessor(LexicalScope invokationScope, CallableDescriptor targetDescriptor) {
|
||||||
return targetDescriptor instanceof CallableMemberDescriptor &&
|
return targetDescriptor instanceof CallableMemberDescriptor &&
|
||||||
Visibilities.isPrivate(targetDescriptor.getVisibility()) &&
|
Visibilities.isPrivate(targetDescriptor.getVisibility()) &&
|
||||||
targetDescriptor.getContainingDeclaration() != invokationScope.getOwnerDescriptor().getContainingDeclaration();
|
targetDescriptor.getContainingDeclaration() != invokationScope.getOwnerDescriptor().getContainingDeclaration();
|
||||||
|
|||||||
@@ -0,0 +1,13 @@
|
|||||||
|
class Outer {
|
||||||
|
class Nested{
|
||||||
|
fun foo(s: String) = s.extension()
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private fun String.extension(): String = this
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return Outer.Nested().foo("OK")
|
||||||
|
}
|
||||||
@@ -0,0 +1,13 @@
|
|||||||
|
class Outer {
|
||||||
|
class Nested {
|
||||||
|
fun fn() = s
|
||||||
|
}
|
||||||
|
|
||||||
|
companion object {
|
||||||
|
private val s = "OK"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
fun box(): String {
|
||||||
|
return Outer.Nested().fn()
|
||||||
|
}
|
||||||
+12
@@ -4498,6 +4498,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
|
|||||||
doTest(fileName);
|
doTest(fileName);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt5363.kt")
|
||||||
|
public void testKt5363() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/innerNested/kt5363.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
|
@TestMetadata("kt6804.kt")
|
||||||
|
public void testKt6804() throws Exception {
|
||||||
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/innerNested/kt6804.kt");
|
||||||
|
doTest(fileName);
|
||||||
|
}
|
||||||
|
|
||||||
@TestMetadata("nestedClassInObject.kt")
|
@TestMetadata("nestedClassInObject.kt")
|
||||||
public void testNestedClassInObject() throws Exception {
|
public void testNestedClassInObject() throws Exception {
|
||||||
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/innerNested/nestedClassInObject.kt");
|
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/innerNested/nestedClassInObject.kt");
|
||||||
|
|||||||
Reference in New Issue
Block a user