Record inner class info for interface and DefaultImpls

This commit is contained in:
Denis Zharkov
2015-09-25 13:59:51 +03:00
parent c1bed7efc7
commit fd0c92e307
13 changed files with 104 additions and 13 deletions
@@ -23,17 +23,21 @@ import org.jetbrains.kotlin.codegen.AsmUtil.writeKotlinSyntheticClassAnnotation
import org.jetbrains.kotlin.codegen.context.ClassContext
import org.jetbrains.kotlin.codegen.state.GenerationState
import org.jetbrains.kotlin.descriptors.*
import org.jetbrains.kotlin.descriptors.impl.ClassDescriptorImpl
import org.jetbrains.kotlin.load.java.JvmAbi
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass.Kind.LOCAL_TRAIT_IMPL
import org.jetbrains.kotlin.load.java.JvmAnnotationNames.KotlinSyntheticClass.Kind.TRAIT_IMPL
import org.jetbrains.kotlin.load.java.descriptors.JavaMethodDescriptor
import org.jetbrains.kotlin.name.Name
import org.jetbrains.kotlin.psi.JetClassOrObject
import org.jetbrains.kotlin.resolve.DescriptorToSourceUtils
import org.jetbrains.kotlin.resolve.DescriptorUtils
import org.jetbrains.kotlin.resolve.jvm.diagnostics.DelegationToTraitImpl
import org.jetbrains.kotlin.resolve.jvm.jvmSignature.JvmMethodSignature
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_FINAL
import org.jetbrains.org.objectweb.asm.Opcodes.ACC_PUBLIC
import org.jetbrains.kotlin.resolve.scopes.JetScope
import org.jetbrains.org.objectweb.asm.Opcodes.*
import org.jetbrains.org.objectweb.asm.Opcodes.V1_6
import java.util.*
public class InterfaceImplBodyCodegen(
aClass: JetClassOrObject,
@@ -45,13 +49,23 @@ public class InterfaceImplBodyCodegen(
override fun generateDeclaration() {
v.defineClass(
myClass, V1_6, ACC_PUBLIC or ACC_FINAL,
typeMapper.mapDefaultImpls(descriptor).getInternalName(),
myClass, V1_6, ACC_PUBLIC or ACC_FINAL or ACC_STATIC,
typeMapper.mapDefaultImpls(descriptor).internalName,
null, "java/lang/Object", ArrayUtil.EMPTY_STRING_ARRAY
)
v.visitSource(myClass.getContainingFile().getName(), null)
}
override fun classForInnerClassRecord(): ClassDescriptor? {
if (DescriptorUtils.isLocal(descriptor)) return null
val classDescriptorImpl = ClassDescriptorImpl(
descriptor, Name.identifier(JvmAbi.DEFAULT_IMPLS_CLASS_NAME),
Modality.FINAL, Collections.emptyList(), SourceElement.NO_SOURCE)
classDescriptorImpl.initialize(JetScope.Empty, emptySet(), null)
return classDescriptorImpl
}
override fun generateSyntheticParts() {
for (memberDescriptor in descriptor.getDefaultType().getMemberScope().getAllDescriptors()) {
if (memberDescriptor !is CallableMemberDescriptor) continue
@@ -9,4 +9,8 @@ public interface Generic <N, NN> {
@org.jetbrains.annotations.Nullable
NN b1(@org.jetbrains.annotations.Nullable NN nn);
}
@kotlin.jvm.internal.KotlinSyntheticClass(version = {0, 27, 0}, abiVersion = 27, kind = kotlin.jvm.internal.KotlinSyntheticClass.Kind.TRAIT_IMPL)
static final class DefaultImpls {
}
}
@@ -40,4 +40,8 @@ public interface Primitives {
float getFloat();
double getDouble();
}
@kotlin.jvm.internal.KotlinSyntheticClass(version = {0, 27, 0}, abiVersion = 27, kind = kotlin.jvm.internal.KotlinSyntheticClass.Kind.TRAIT_IMPL)
static final class DefaultImpls {
}
}
@@ -1,2 +1,12 @@
public interface PrivateInTrait {
}
@kotlin.jvm.internal.KotlinSyntheticClass(version = {0, 27, 0}, abiVersion = 27, kind = kotlin.jvm.internal.KotlinSyntheticClass.Kind.TRAIT_IMPL)
static final class DefaultImpls {
@org.jetbrains.annotations.NotNull
static java.lang.String getNn(PrivateInTrait $this) { /* compiled code */ }
static void setNn(@org.jetbrains.annotations.NotNull PrivateInTrait $this, java.lang.String value) { /* compiled code */ }
@org.jetbrains.annotations.Nullable
static java.lang.String getN(PrivateInTrait $this) { /* compiled code */ }
}
}
@@ -34,4 +34,8 @@ public interface Trait {
java.lang.String getNotNullVar();
void setNotNullVar(@org.jetbrains.annotations.NotNull java.lang.String p);
}
@kotlin.jvm.internal.KotlinSyntheticClass(version = {0, 27, 0}, abiVersion = 27, kind = kotlin.jvm.internal.KotlinSyntheticClass.Kind.TRAIT_IMPL)
static final class DefaultImpls {
}
}
@@ -15,4 +15,8 @@ public interface TraitClassObjectField {
private Companion() { /* compiled code */ }
}
@kotlin.jvm.internal.KotlinSyntheticClass(version = {0, 27, 0}, abiVersion = 27, kind = kotlin.jvm.internal.KotlinSyntheticClass.Kind.TRAIT_IMPL)
static final class DefaultImpls {
}
}
@@ -0,0 +1,5 @@
class B {
static String test(A x) {
return A.DefaultImpls.foo(x);
}
}
@@ -0,0 +1,10 @@
interface A {
fun foo() = "OK"
}
fun box(): String {
val result = B.test(object : A {})
if (result != "OK") return "fail: $result"
return "OK"
}
@@ -0,0 +1,11 @@
interface A {
fun foo() = 1
object C {
}
companion object {}
}
// 2 public final static INNERCLASS A\$DefaultImpls A DefaultImpls
@@ -4,8 +4,8 @@ import java.util.ArrayList;
abstract class TraitImpl implements Trait {
{
Trait$DefaultImpls.simple(this);
Trait.DefaultImpls.simple(this);
Trait$DefaultImpls.generic(this, new ArrayList<String>());
Trait.DefaultImpls.generic(this, new ArrayList<String>());
}
}
@@ -143,6 +143,12 @@ public class BytecodeTextTestGenerated extends AbstractBytecodeTextTest {
doTest(fileName);
}
@TestMetadata("interfaceDefaultImpl.kt")
public void testInterfaceDefaultImpl() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/interfaceDefaultImpl.kt");
doTest(fileName);
}
@TestMetadata("javaExtensionPropertyIntrinsic.kt")
public void testJavaExtensionPropertyIntrinsic() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/bytecodeText/javaExtensionPropertyIntrinsic.kt");
@@ -16,6 +16,8 @@
package org.jetbrains.kotlin.codegen;
import kotlin.CollectionsKt;
import kotlin.jvm.functions.Function1;
import org.jetbrains.annotations.NotNull;
import org.jetbrains.annotations.Nullable;
import org.jetbrains.kotlin.backend.common.output.OutputFile;
@@ -86,6 +88,7 @@ public class InnerClassInfoGenTest extends CodegenTestCase {
checkAccess("A", "Annotation", ACC_PUBLIC | ACC_STATIC | ACC_INTERFACE | ACC_ABSTRACT | ACC_ANNOTATION);
checkAccess("A", "Enum", ACC_PUBLIC | ACC_STATIC | ACC_FINAL | ACC_ENUM);
checkAccess("A", "Trait", ACC_PUBLIC | ACC_STATIC | ACC_INTERFACE | ACC_ABSTRACT);
checkAccess("A$Trait", "DefaultImpls", ACC_PUBLIC | ACC_STATIC | ACC_FINAL);
checkAccess("A", "OpenStaticClass", ACC_PUBLIC | ACC_STATIC);
checkAccess("A", "FinalStaticClass", ACC_PUBLIC | ACC_STATIC | ACC_FINAL);
@@ -102,10 +105,20 @@ public class InnerClassInfoGenTest extends CodegenTestCase {
private void checkAccess(@NotNull String outerName, @NotNull String innerName, int accessFlags) {
private void checkAccess(@NotNull String outerName, @NotNull final String innerName, int accessFlags) {
String name = outerName + "$" + innerName;
InnerClassAttribute attribute = new InnerClassAttribute(name, outerName, innerName, accessFlags);
extractAndCompareInnerClasses(name, attribute);
InnerClassAttribute attribute = CollectionsKt.single(extractInnerClasses(name),
new Function1<InnerClassAttribute, Boolean>() {
@Override
public Boolean invoke(InnerClassAttribute attribute) {
return innerName.equals(attribute.innerName);
}
}
);
InnerClassAttribute expectedAttribute = new InnerClassAttribute(name, outerName, innerName, accessFlags);
assertEquals(expectedAttribute, attribute);
}
private void extractAndCompareInnerClasses(@NotNull String className, @NotNull InnerClassAttribute... expectedInnerClasses) {
@@ -59,6 +59,12 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege
doTestWithJava(fileName);
}
@TestMetadata("interfaceDefaultImpls")
public void testInterfaceDefaultImpls() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/interfaceDefaultImpls/");
doTestWithJava(fileName);
}
@TestMetadata("platformName")
public void testPlatformName() throws Exception {
String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/platformName/");