Support access to companion private members from nested classes

#KT-5363 Fixed
  #KT-6804 Fixed
This commit is contained in:
Michael Bogdanov
2015-10-19 13:15:48 +03:00
committed by Max Kammerer
parent 3d88df73e0
commit d977d29ec4
5 changed files with 59 additions and 2 deletions
@@ -206,7 +206,26 @@ public abstract class CodegenContext<T extends DeclarationDescriptor> {
@NotNull
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
@@ -43,7 +43,7 @@ public class NeedSyntheticChecker implements CallChecker {
//Necessary synthetic accessors in outer classes generated via old logic: CodegenContext.getAccessor
//Generation of accessors in nested classes (to invoke from outer,
// 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 &&
Visibilities.isPrivate(targetDescriptor.getVisibility()) &&
targetDescriptor.getContainingDeclaration() != invokationScope.getOwnerDescriptor().getContainingDeclaration();
+13
View File
@@ -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")
}
+13
View File
@@ -0,0 +1,13 @@
class Outer {
class Nested {
fun fn() = s
}
companion object {
private val s = "OK"
}
}
fun box(): String {
return Outer.Nested().fn()
}
@@ -4498,6 +4498,18 @@ public class BlackBoxCodegenTestGenerated extends AbstractBlackBoxCodegenTest {
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")
public void testNestedClassInObject() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/box/innerNested/nestedClassInObject.kt");