Record inner class info for interface and DefaultImpls
This commit is contained in:
@@ -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 {
|
||||
}
|
||||
}
|
||||
+5
-1
@@ -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 {
|
||||
}
|
||||
}
|
||||
+11
-1
@@ -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 {
|
||||
}
|
||||
}
|
||||
+4
@@ -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) {
|
||||
|
||||
+6
@@ -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/");
|
||||
|
||||
Reference in New Issue
Block a user