Write KotlinSyntheticClass to anonymous and local classes
This commit is contained in:
@@ -35,7 +35,6 @@ import java.util.List;
|
||||
import static org.jetbrains.asm4.Opcodes.ACC_STATIC;
|
||||
import static org.jetbrains.asm4.Opcodes.RETURN;
|
||||
import static org.jetbrains.jet.codegen.binding.CodegenBinding.enumEntryNeedSubclass;
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.isTopLevelOrInnerClass;
|
||||
|
||||
public abstract class ClassBodyCodegen extends MemberCodegen {
|
||||
protected final JetClassOrObject myClass;
|
||||
@@ -70,9 +69,7 @@ public abstract class ClassBodyCodegen extends MemberCodegen {
|
||||
|
||||
generateStaticInitializer();
|
||||
|
||||
if (state.getClassBuilderMode() == ClassBuilderMode.FULL && isTopLevelOrInnerClass(descriptor)) {
|
||||
generateKotlinAnnotation();
|
||||
}
|
||||
generateKotlinAnnotation();
|
||||
}
|
||||
|
||||
protected abstract void generateDeclaration();
|
||||
|
||||
@@ -70,6 +70,7 @@ import static org.jetbrains.jet.lang.resolve.BindingContextUtils.descriptorToDec
|
||||
import static org.jetbrains.jet.lang.resolve.DescriptorUtils.*;
|
||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.JAVA_STRING_TYPE;
|
||||
import static org.jetbrains.jet.lang.resolve.java.AsmTypeConstants.OBJECT_TYPE;
|
||||
import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KotlinSyntheticClass;
|
||||
|
||||
public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
private static final String VALUES = "$VALUES";
|
||||
@@ -209,6 +210,19 @@ public class ImplementationBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
@Override
|
||||
protected void generateKotlinAnnotation() {
|
||||
if (isAnonymousObject(descriptor)) {
|
||||
writeKotlinSyntheticClassAnnotation(v, KotlinSyntheticClass.Kind.ANONYMOUS_OBJECT);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!isTopLevelOrInnerClass(descriptor)) {
|
||||
// LOCAL_CLASS is also written to inner classes of local classes
|
||||
writeKotlinSyntheticClassAnnotation(v, KotlinSyntheticClass.Kind.LOCAL_CLASS);
|
||||
return;
|
||||
}
|
||||
|
||||
if (state.getClassBuilderMode() != ClassBuilderMode.FULL) return;
|
||||
|
||||
DescriptorSerializer serializer = new DescriptorSerializer(new JavaSerializerExtension(v.getSerializationBindings()));
|
||||
|
||||
ProtoBuf.Class classProto = serializer.classProto(descriptor).build();
|
||||
|
||||
@@ -21,6 +21,7 @@ import org.jetbrains.annotations.Nullable;
|
||||
import org.jetbrains.jet.codegen.context.ClassContext;
|
||||
import org.jetbrains.jet.codegen.state.GenerationState;
|
||||
import org.jetbrains.jet.lang.psi.JetClassOrObject;
|
||||
import org.jetbrains.jet.lang.resolve.DescriptorUtils;
|
||||
|
||||
import static org.jetbrains.asm4.Opcodes.*;
|
||||
import static org.jetbrains.jet.codegen.AsmUtil.writeKotlinSyntheticClassAnnotation;
|
||||
@@ -52,6 +53,10 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen {
|
||||
|
||||
@Override
|
||||
protected void generateKotlinAnnotation() {
|
||||
writeKotlinSyntheticClassAnnotation(v, KotlinSyntheticClass.Kind.TRAIT_IMPL);
|
||||
// We write LOCAL_CLASS to local trait-impl, because we don't want PSI classes to be constructed for such files
|
||||
// (currently PSI for synthetic class is built only if this class is a trait-impl, see DecompiledUtils.kt)
|
||||
writeKotlinSyntheticClassAnnotation(v, DescriptorUtils.isTopLevelOrInnerClass(descriptor)
|
||||
? KotlinSyntheticClass.Kind.TRAIT_IMPL
|
||||
: KotlinSyntheticClass.Kind.LOCAL_CLASS);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -120,6 +120,10 @@ public class LambdaTransformer {
|
||||
superName,
|
||||
interfaces
|
||||
);
|
||||
|
||||
// TODO: load synthetic class kind from the transformed class and write the same kind to the copy of that class here
|
||||
// See AsmUtil.writeKotlinSyntheticClassAnnotation
|
||||
|
||||
ParametersBuilder builder = ParametersBuilder.newBuilder();
|
||||
Parameters parameters = getLambdaParameters(builder, invocation);
|
||||
|
||||
|
||||
@@ -84,6 +84,30 @@ public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase {
|
||||
ANONYMOUS_FUNCTION);
|
||||
}
|
||||
|
||||
public void testLocalClass() {
|
||||
doTest("fun foo() { class Local }",
|
||||
"Local",
|
||||
LOCAL_CLASS);
|
||||
}
|
||||
|
||||
public void testLocalTraitImpl() {
|
||||
doTest("fun foo() { trait Local { fun bar() = 42 } }",
|
||||
"Local",
|
||||
LOCAL_CLASS);
|
||||
}
|
||||
|
||||
public void testInnerClassOfLocalClass() {
|
||||
doTest("fun foo() { class Local { inner class Inner } }",
|
||||
"Inner",
|
||||
LOCAL_CLASS);
|
||||
}
|
||||
|
||||
public void testAnonymousObject() {
|
||||
doTest("val o = object {}",
|
||||
"$",
|
||||
ANONYMOUS_OBJECT);
|
||||
}
|
||||
|
||||
private void doTest(@NotNull String code, @NotNull final String classNamePart, @NotNull KotlinSyntheticClass.Kind expectedKind) {
|
||||
loadText("package " + PACKAGE_NAME + "\n\n" + code);
|
||||
List<OutputFile> output = generateClassesInFile().asList();
|
||||
|
||||
+2
@@ -55,6 +55,8 @@ public final class JvmAnnotationNames {
|
||||
CALLABLE_REFERENCE_WRAPPER,
|
||||
LOCAL_FUNCTION,
|
||||
ANONYMOUS_FUNCTION,
|
||||
LOCAL_CLASS,
|
||||
ANONYMOUS_OBJECT,
|
||||
;
|
||||
|
||||
@Nullable
|
||||
|
||||
@@ -25,6 +25,8 @@ public @interface KotlinSyntheticClass {
|
||||
|
||||
Kind kind();
|
||||
|
||||
// Inner classes of local classes have kind LOCAL_CLASS
|
||||
// Local trait-impl also has kind LOCAL_CLASS
|
||||
public static enum Kind {
|
||||
PACKAGE_PART,
|
||||
TRAIT_IMPL,
|
||||
@@ -33,5 +35,7 @@ public @interface KotlinSyntheticClass {
|
||||
CALLABLE_REFERENCE_WRAPPER,
|
||||
LOCAL_FUNCTION,
|
||||
ANONYMOUS_FUNCTION,
|
||||
LOCAL_CLASS,
|
||||
ANONYMOUS_OBJECT,
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user