diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java index fccd8638cab..50657defa9c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ClassBodyCodegen.java @@ -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(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java index f4144f6fce7..6e0fbd36740 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/ImplementationBodyCodegen.java @@ -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(); diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java index 899d730aecb..51569cb529c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java @@ -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); } } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/inline/LambdaTransformer.java b/compiler/backend/src/org/jetbrains/jet/codegen/inline/LambdaTransformer.java index 62aabbe90f8..4688daf398d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/inline/LambdaTransformer.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/inline/LambdaTransformer.java @@ -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); diff --git a/compiler/tests/org/jetbrains/jet/codegen/KotlinSyntheticClassAnnotationTest.java b/compiler/tests/org/jetbrains/jet/codegen/KotlinSyntheticClassAnnotationTest.java index 41b7f72256e..3072c488931 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/KotlinSyntheticClassAnnotationTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/KotlinSyntheticClassAnnotationTest.java @@ -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 output = generateClassesInFile().asList(); diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JvmAnnotationNames.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JvmAnnotationNames.java index d1cc7765484..5c056ed428a 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JvmAnnotationNames.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/JvmAnnotationNames.java @@ -55,6 +55,8 @@ public final class JvmAnnotationNames { CALLABLE_REFERENCE_WRAPPER, LOCAL_FUNCTION, ANONYMOUS_FUNCTION, + LOCAL_CLASS, + ANONYMOUS_OBJECT, ; @Nullable diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinSyntheticClass.java b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinSyntheticClass.java index 63fb158ed08..90baa81cb3c 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinSyntheticClass.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinSyntheticClass.java @@ -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, } }