diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/PackagePartCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/PackagePartCodegen.java index d29f827b4c6..ec1c316a75c 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/PackagePartCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/PackagePartCodegen.java @@ -37,7 +37,8 @@ import java.util.Collections; import java.util.List; import static org.jetbrains.asm4.Opcodes.*; -import static org.jetbrains.jet.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses; +import static org.jetbrains.jet.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses; +import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS; public class PackagePartCodegen extends MemberCodegen { @@ -77,7 +78,7 @@ public class PackagePartCodegen extends MemberCodegen { ); v.visitSource(jetFile.getName(), null); - writeKotlinPackagePartAnnotation(); + writeKotlinAnnotation(); for (JetDeclaration declaration : jetFile.getDeclarations()) { if (declaration instanceof JetNamedFunction || declaration instanceof JetProperty) { @@ -90,9 +91,11 @@ public class PackagePartCodegen extends MemberCodegen { v.done(); } - private void writeKotlinPackagePartAnnotation() { - AnnotationVisitor av = v.newAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_PACKAGE_PART), true); + private void writeKotlinAnnotation() { + Type type = asmTypeByFqNameWithoutInnerClasses(KOTLIN_SYNTHETIC_CLASS); + AnnotationVisitor av = v.newAnnotation(type.getDescriptor(), true); av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION); + av.visitEnum("kind", "L" + type.getInternalName() + "$Kind;", "PACKAGE_PART"); av.visitEnd(); } diff --git a/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java b/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java index 3537eca605b..2702c28428d 100644 --- a/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java +++ b/compiler/backend/src/org/jetbrains/jet/codegen/TraitImplBodyCodegen.java @@ -19,6 +19,7 @@ package org.jetbrains.jet.codegen; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import org.jetbrains.asm4.AnnotationVisitor; +import org.jetbrains.asm4.Type; import org.jetbrains.jet.codegen.context.ClassContext; import org.jetbrains.jet.codegen.state.GenerationState; import org.jetbrains.jet.lang.psi.JetClassOrObject; @@ -26,7 +27,8 @@ import org.jetbrains.jet.lang.resolve.java.JvmAbi; import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames; import static org.jetbrains.asm4.Opcodes.*; -import static org.jetbrains.jet.codegen.AsmUtil.asmDescByFqNameWithoutInnerClasses; +import static org.jetbrains.jet.codegen.AsmUtil.asmTypeByFqNameWithoutInnerClasses; +import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS; public class TraitImplBodyCodegen extends ClassBodyCodegen { @@ -54,9 +56,11 @@ public class TraitImplBodyCodegen extends ClassBodyCodegen { @Override protected void generateKotlinAnnotation() { - AnnotationVisitor av = - v.getVisitor().visitAnnotation(asmDescByFqNameWithoutInnerClasses(JvmAnnotationNames.KOTLIN_TRAIT_IMPL), true); + Type type = asmTypeByFqNameWithoutInnerClasses(KOTLIN_SYNTHETIC_CLASS); + AnnotationVisitor av = v.getVisitor().visitAnnotation(type.getDescriptor(), true); + if (av == null) return; av.visit(JvmAnnotationNames.ABI_VERSION_FIELD_NAME, JvmAbi.VERSION); + av.visitEnum("kind", "L" + type.getInternalName() + "$Kind;", "TRAIT_IMPL"); av.visitEnd(); } } diff --git a/compiler/tests/org/jetbrains/jet/codegen/KotlinPackagePartAnnotationTest.java b/compiler/tests/org/jetbrains/jet/codegen/KotlinSyntheticClassAnnotationTest.java similarity index 54% rename from compiler/tests/org/jetbrains/jet/codegen/KotlinPackagePartAnnotationTest.java rename to compiler/tests/org/jetbrains/jet/codegen/KotlinSyntheticClassAnnotationTest.java index 708d24540f7..8d3a4a1b755 100644 --- a/compiler/tests/org/jetbrains/jet/codegen/KotlinPackagePartAnnotationTest.java +++ b/compiler/tests/org/jetbrains/jet/codegen/KotlinSyntheticClassAnnotationTest.java @@ -20,14 +20,15 @@ import org.jetbrains.jet.ConfigurationKind; import org.jetbrains.jet.OutputFile; import org.jetbrains.jet.OutputFileCollection; import org.jetbrains.jet.lang.resolve.java.AbiVersionUtil; -import org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames; import org.jetbrains.jet.lang.resolve.java.JvmClassName; import org.jetbrains.jet.lang.resolve.java.PackageClassUtils; import org.jetbrains.jet.lang.resolve.name.FqName; import java.lang.annotation.Annotation; -public class KotlinPackagePartAnnotationTest extends CodegenTestCase { +import static org.jetbrains.jet.lang.resolve.java.JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS; + +public class KotlinSyntheticClassAnnotationTest extends CodegenTestCase { public static final FqName PACKAGE_NAME = new FqName("test"); @Override @@ -36,35 +37,38 @@ public class KotlinPackagePartAnnotationTest extends CodegenTestCase { createEnvironmentWithMockJdkAndIdeaAnnotations(ConfigurationKind.JDK_ONLY); } - public void testKotlinPackagePartAnnotationIsWritten() throws Exception { + public void testAnnotationIsWrittenOnPackagePart() throws Exception { loadText("package " + PACKAGE_NAME + "\n\nfun foo() = 42\n"); String facadeFileName = JvmClassName.byFqNameWithoutInnerClasses(PackageClassUtils.getPackageClassFqName(PACKAGE_NAME)).getInternalName() + ".class"; OutputFileCollection outputFiles = generateClassesInFile(); for (OutputFile outputFile : outputFiles.asList()) { + // The file which is not a facade is a package part String filePath = outputFile.getRelativePath(); + if (filePath.equals(facadeFileName)) continue; - if (!filePath.equals(facadeFileName)) { - // The file which is not a facade is a package part - String fqName = filePath.substring(0, filePath.length() - ".class".length()).replace('/', '.'); - Class aClass = generateClass(fqName); + String fqName = filePath.substring(0, filePath.length() - ".class".length()).replace('/', '.'); + Class aClass = generateClass(fqName); - Class annotationClass = loadAnnotationClassQuietly(JvmAnnotationNames.KOTLIN_PACKAGE_PART.asString()); + Class annotationClass = loadAnnotationClassQuietly(KOTLIN_SYNTHETIC_CLASS.asString()); + assertTrue("No KotlinSyntheticClass annotation found on a package part", aClass.isAnnotationPresent(annotationClass)); - assertTrue("No KotlinPackagePart annotation on a package part", - aClass.isAnnotationPresent(annotationClass)); + Annotation annotation = aClass.getAnnotation(annotationClass); - Annotation kotlinPackagePart = aClass.getAnnotation(annotationClass); + Integer version = (Integer) CodegenTestUtil.getAnnotationAttribute(annotation, "abiVersion"); + assertNotNull(version); + assertTrue("KotlinSyntheticClass annotation is written with an unsupported format", + AbiVersionUtil.isAbiVersionCompatible(version)); - Integer version = (Integer) CodegenTestUtil.getAnnotationAttribute(kotlinPackagePart, "abiVersion"); - assertNotNull(version); - assertTrue("KotlinPackagePart annotation is written with an unsupported format", - AbiVersionUtil.isAbiVersionCompatible(version)); + Object kind = CodegenTestUtil.getAnnotationAttribute(annotation, "kind"); + assertNotNull(kind); + assertEquals("KotlinSyntheticClass annotation has the wrong kind", "PACKAGE_PART", kind.toString()); - return; - } + return; } fail("No package part was found: " + outputFiles.asList()); } + + // TODO: test that annotation is written on TImpl } 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 4ce96156f54..6cbf06ba96a 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 @@ -23,8 +23,7 @@ import org.jetbrains.jet.lang.resolve.name.Name; public final class JvmAnnotationNames { public static final FqName KOTLIN_CLASS = new FqName("kotlin.jvm.internal.KotlinClass"); public static final FqName KOTLIN_PACKAGE = new FqName("kotlin.jvm.internal.KotlinPackage"); - public static final FqName KOTLIN_PACKAGE_PART = new FqName("kotlin.jvm.internal.KotlinPackagePart"); - public static final FqName KOTLIN_TRAIT_IMPL = new FqName("kotlin.jvm.internal.KotlinTraitImpl"); + public static final FqName KOTLIN_SYNTHETIC_CLASS = new FqName("kotlin.jvm.internal.KotlinSyntheticClass"); public static final FqName KOTLIN_SIGNATURE = new FqName("kotlin.jvm.KotlinSignature"); public static final FqName OLD_KOTLIN_SIGNATURE = new FqName("jet.runtime.typeinfo.KotlinSignature"); diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DescriptorResolverUtils.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DescriptorResolverUtils.java index eb578cb028a..42884d176a2 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DescriptorResolverUtils.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/java/resolver/DescriptorResolverUtils.java @@ -44,7 +44,7 @@ public final class DescriptorResolverUtils { public static boolean isCompiledKotlinPackageClass(@NotNull JavaClass javaClass) { if (javaClass.getOriginKind() == JavaClass.OriginKind.COMPILED) { return javaClass.findAnnotation(JvmAnnotationNames.KOTLIN_PACKAGE) != null - || javaClass.findAnnotation(JvmAnnotationNames.KOTLIN_PACKAGE_PART) != null; + || javaClass.findAnnotation(JvmAnnotationNames.KOTLIN_SYNTHETIC_CLASS) != null; } return false; } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/KotlinClassHeader.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/KotlinClassHeader.java index b40f49ea5ef..5d132ef8b59 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/KotlinClassHeader.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/KotlinClassHeader.java @@ -24,8 +24,7 @@ public class KotlinClassHeader { public enum Kind { CLASS, PACKAGE_FACADE, - PACKAGE_PART, - TRAIT_IMPL, + SYNTHETIC_CLASS, INCOMPATIBLE_ABI_VERSION } diff --git a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java index 63b72816cb9..3719511e429 100644 --- a/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java +++ b/core/descriptor.loader.java/src/org/jetbrains/jet/lang/resolve/kotlin/header/ReadKotlinClassHeaderAnnotationVisitor.java @@ -39,8 +39,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor static { HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_CLASS), CLASS); HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_PACKAGE), PACKAGE_FACADE); - HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_PACKAGE_PART), PACKAGE_PART); - HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_TRAIT_IMPL), TRAIT_IMPL); + HEADER_KINDS.put(JvmClassName.byFqNameWithoutInnerClasses(KOTLIN_SYNTHETIC_CLASS), SYNTHETIC_CLASS); @SuppressWarnings("deprecation") List incompatible = Arrays.asList(OLD_JET_CLASS_ANNOTATION, OLD_JET_PACKAGE_CLASS_ANNOTATION, OLD_KOTLIN_CLASS, @@ -100,8 +99,8 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor if (newKind == CLASS || newKind == PACKAGE_FACADE) { return kotlinClassOrPackageVisitor(annotationClassName); } - else if (newKind == PACKAGE_PART || newKind == TRAIT_IMPL) { - return annotationWithAbiVersionVisitor(annotationClassName); + else if (newKind == SYNTHETIC_CLASS) { + return syntheticClassAnnotationVisitor(annotationClassName); } return null; @@ -175,7 +174,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor } @NotNull - private AnnotationArgumentVisitor annotationWithAbiVersionVisitor(@NotNull final JvmClassName annotationClassName) { + private AnnotationArgumentVisitor syntheticClassAnnotationVisitor(@NotNull final JvmClassName annotationClassName) { return new AnnotationArgumentVisitor() { @Override public void visit(@Nullable Name name, @Nullable Object value) { @@ -184,7 +183,7 @@ public class ReadKotlinClassHeaderAnnotationVisitor implements AnnotationVisitor @Override public void visitEnum(@NotNull Name name, @NotNull JvmClassName enumClassName, @NotNull Name enumEntryName) { - unexpectedArgument(name, annotationClassName); + // TODO: save kind to somewhere } @Nullable diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinPackagePart.java b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinSyntheticClass.java similarity index 85% rename from core/runtime.jvm/src/kotlin/jvm/internal/KotlinPackagePart.java rename to core/runtime.jvm/src/kotlin/jvm/internal/KotlinSyntheticClass.java index ad32f39eeac..a04b90f60d1 100644 --- a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinPackagePart.java +++ b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinSyntheticClass.java @@ -20,6 +20,13 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; @Retention(RetentionPolicy.RUNTIME) -public @interface KotlinPackagePart { +public @interface KotlinSyntheticClass { int abiVersion(); + + Kind kind(); + + public static enum Kind { + PACKAGE_PART, + TRAIT_IMPL + } } diff --git a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinTraitImpl.java b/core/runtime.jvm/src/kotlin/jvm/internal/KotlinTraitImpl.java deleted file mode 100644 index 6675edde146..00000000000 --- a/core/runtime.jvm/src/kotlin/jvm/internal/KotlinTraitImpl.java +++ /dev/null @@ -1,25 +0,0 @@ -/* - * Copyright 2010-2014 JetBrains s.r.o. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package kotlin.jvm.internal; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -@Retention(RetentionPolicy.RUNTIME) -public @interface KotlinTraitImpl { - int abiVersion(); -} diff --git a/idea/src/org/jetbrains/jet/plugin/stubindex/builder/EmptyPackageFragmentClsStubBuilderFactory.java b/idea/src/org/jetbrains/jet/plugin/stubindex/builder/EmptyPackageFragmentClsStubBuilderFactory.java index 843e10d88ae..f532561f418 100644 --- a/idea/src/org/jetbrains/jet/plugin/stubindex/builder/EmptyPackageFragmentClsStubBuilderFactory.java +++ b/idea/src/org/jetbrains/jet/plugin/stubindex/builder/EmptyPackageFragmentClsStubBuilderFactory.java @@ -46,7 +46,7 @@ public class EmptyPackageFragmentClsStubBuilderFactory extends ClsStubBuilderFac if (file.getName().contains(PackageClassUtils.PACKAGE_CLASS_NAME_SUFFIX + "-") && StdFileTypes.CLASS.getDefaultExtension().equals(file.getExtension())) { KotlinClassHeader header = new VirtualFileKotlinClass(LockBasedStorageManager.NO_LOCKS, file).getClassHeader(); - return header != null && header.getKind() == KotlinClassHeader.Kind.PACKAGE_PART; + return header != null && header.getKind() == KotlinClassHeader.Kind.SYNTHETIC_CLASS; } return false; }