diff --git a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java index ba9beac12c0..e9929f44ddf 100644 --- a/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java +++ b/compiler/backend/src/org/jetbrains/kotlin/codegen/PackagePartCodegen.java @@ -19,16 +19,17 @@ package org.jetbrains.kotlin.codegen; import com.intellij.util.ArrayUtil; import kotlin.jvm.functions.Function0; import org.jetbrains.annotations.NotNull; +import org.jetbrains.kotlin.codegen.annotation.AnnotatedSimple; import org.jetbrains.kotlin.codegen.context.FieldOwnerContext; import org.jetbrains.kotlin.codegen.state.GenerationState; import org.jetbrains.kotlin.descriptors.DeclarationDescriptor; import org.jetbrains.kotlin.descriptors.SimpleFunctionDescriptor; import org.jetbrains.kotlin.descriptors.VariableDescriptor; +import org.jetbrains.kotlin.descriptors.annotations.Annotated; +import org.jetbrains.kotlin.descriptors.annotations.AnnotationDescriptor; +import org.jetbrains.kotlin.descriptors.annotations.AnnotationsImpl; import org.jetbrains.kotlin.load.java.JvmAnnotationNames; -import org.jetbrains.kotlin.psi.JetDeclaration; -import org.jetbrains.kotlin.psi.JetFile; -import org.jetbrains.kotlin.psi.JetNamedFunction; -import org.jetbrains.kotlin.psi.JetProperty; +import org.jetbrains.kotlin.psi.*; import org.jetbrains.kotlin.resolve.BindingContext; import org.jetbrains.kotlin.serialization.*; import org.jetbrains.kotlin.serialization.deserialization.NameResolver; @@ -68,6 +69,20 @@ public class PackagePartCodegen extends MemberCodegen { v.visitSource(element.getName(), null); generatePropertyMetadataArrayFieldIfNeeded(packagePartType); + + generateAnnotationsForPartClass(); + } + + private void generateAnnotationsForPartClass() { + List fileAnnotationDescriptors = new ArrayList(); + for (JetAnnotationEntry annotationEntry : element.getAnnotationEntries()) { + AnnotationDescriptor annotationDescriptor = state.getBindingContext().get(BindingContext.ANNOTATION, annotationEntry); + if (annotationDescriptor != null) { + fileAnnotationDescriptors.add(annotationDescriptor); + } + } + Annotated annotatedFile = new AnnotatedSimple(new AnnotationsImpl(fileAnnotationDescriptors)); + AnnotationCodegen.forClass(v.getVisitor(), state.getTypeMapper()).genAnnotations(annotatedFile, null); } @Override diff --git a/compiler/testData/asJava/lightClasses/facades/SingleJvmClassName.java b/compiler/testData/asJava/lightClasses/facades/SingleJvmClassName.java index d18dedd19ce..9ea81709ad3 100644 --- a/compiler/testData/asJava/lightClasses/facades/SingleJvmClassName.java +++ b/compiler/testData/asJava/lightClasses/facades/SingleJvmClassName.java @@ -1,3 +1,4 @@ +@kotlin.jvm.JvmName(name = "NewName") public final class NewName { public static final void foo() { /* compiled code */ } -} +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/annotatedFileClasses/javaAnnotationOnFileFacade/StringHolder.java b/compiler/testData/codegen/boxWithJava/annotatedFileClasses/javaAnnotationOnFileFacade/StringHolder.java new file mode 100644 index 00000000000..9ad0c301567 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/annotatedFileClasses/javaAnnotationOnFileFacade/StringHolder.java @@ -0,0 +1,10 @@ +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +@Target(ElementType.TYPE) +@Retention(RetentionPolicy.RUNTIME) +public @interface StringHolder { + public String value(); +} \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithJava/annotatedFileClasses/javaAnnotationOnFileFacade/fileFacade.kt b/compiler/testData/codegen/boxWithJava/annotatedFileClasses/javaAnnotationOnFileFacade/fileFacade.kt new file mode 100644 index 00000000000..a7c0fe8c083 --- /dev/null +++ b/compiler/testData/codegen/boxWithJava/annotatedFileClasses/javaAnnotationOnFileFacade/fileFacade.kt @@ -0,0 +1,4 @@ +@file:StringHolder("OK") + +fun box(): String = + Class.forName("FileFacadeKt").getAnnotation(StringHolder::class.java)?.value() ?: "null" \ No newline at end of file diff --git a/compiler/testData/codegen/boxWithStdlib/annotations/fileClassWithFileAnnotation.kt b/compiler/testData/codegen/boxWithStdlib/annotations/fileClassWithFileAnnotation.kt new file mode 100644 index 00000000000..466e448f00b --- /dev/null +++ b/compiler/testData/codegen/boxWithStdlib/annotations/fileClassWithFileAnnotation.kt @@ -0,0 +1,9 @@ +@file:StringHolder("OK") +@file:JvmName("FileClass") + +@Target(AnnotationTarget.FILE) +@Retention(AnnotationRetention.RUNTIME) +public annotation class StringHolder(val value: String) + +fun box(): String = + Class.forName("FileClass").getAnnotation(StringHolder::class.java)?.value ?: "null" \ No newline at end of file diff --git a/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/FileAnnotations.txt b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/FileAnnotations.txt new file mode 100644 index 00000000000..b243db16bca --- /dev/null +++ b/compiler/testData/diagnostics/tests/annotations/withUseSiteTarget/FileAnnotations.txt @@ -0,0 +1,15 @@ +package + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS}) @kotlin.annotation.annotation() public final class ClassAnn : kotlin.Annotation { + public constructor ClassAnn() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FILE}) @kotlin.annotation.annotation() public final class FileAnn : kotlin.Annotation { + public constructor FileAnn() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/multifileClassPart.txt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/multifileClassPart.txt new file mode 100644 index 00000000000..d75e22b8133 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/multifileClassPart.txt @@ -0,0 +1,22 @@ +package + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FILE}) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) @kotlin.annotation.annotation() public final class FileAnn : kotlin.Annotation { + public constructor FileAnn() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FILE}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) @kotlin.annotation.annotation() public final class FileBinaryAnn : kotlin.Annotation { + public constructor FileBinaryAnn() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.FILE}) @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) @kotlin.annotation.annotation() public final class FileSourceAnn : kotlin.Annotation { + public constructor FileSourceAnn() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/multifileClassPartWithJavaAnnotation.txt b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/multifileClassPartWithJavaAnnotation.txt new file mode 100644 index 00000000000..1cf02d796f5 --- /dev/null +++ b/compiler/testData/diagnostics/testsWithStdLib/annotations/annotationApplicability/multifileClassPartWithJavaAnnotation.txt @@ -0,0 +1,22 @@ +package + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.FILE}) @kotlin.annotation.Retention(value = AnnotationRetention.RUNTIME) public final class JavaAnn : kotlin.Annotation { + public constructor JavaAnn() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.FILE}) @kotlin.annotation.Retention(value = AnnotationRetention.BINARY) public final class JavaClassAnn : kotlin.Annotation { + public constructor JavaClassAnn() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} + +@kotlin.annotation.Target(allowedTargets = {AnnotationTarget.CLASS, AnnotationTarget.FILE}) @kotlin.annotation.Retention(value = AnnotationRetention.SOURCE) public final class JavaSourceAnn : kotlin.Annotation { + public constructor JavaSourceAnn() + public open override /*1*/ /*fake_override*/ fun equals(/*0*/ other: kotlin.Any?): kotlin.Boolean + public open override /*1*/ /*fake_override*/ fun hashCode(): kotlin.Int + public open override /*1*/ /*fake_override*/ fun toString(): kotlin.String +} diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java index b36dc15c0f8..0807eb97f83 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithJavaCodegenTestGenerated.java @@ -65,6 +65,22 @@ public class BlackBoxWithJavaCodegenTestGenerated extends AbstractBlackBoxCodege doTestWithJava(fileName); } + @TestMetadata("compiler/testData/codegen/boxWithJava/annotatedFileClasses") + @TestDataPath("$PROJECT_ROOT") + @RunWith(JUnit3RunnerWithInners.class) + public static class AnnotatedFileClasses extends AbstractBlackBoxCodegenTest { + public void testAllFilesPresentInAnnotatedFileClasses() throws Exception { + JetTestUtils.assertAllTestsPresentByMetadata(this.getClass(), new File("compiler/testData/codegen/boxWithJava/annotatedFileClasses"), Pattern.compile("^([^\\.]+)$"), true); + } + + @TestMetadata("javaAnnotationOnFileFacade") + public void testJavaAnnotationOnFileFacade() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithJava/annotatedFileClasses/javaAnnotationOnFileFacade/"); + doTestWithJava(fileName); + } + + } + @TestMetadata("compiler/testData/codegen/boxWithJava/annotationsWithKClass") @TestDataPath("$PROJECT_ROOT") @RunWith(JUnit3RunnerWithInners.class) diff --git a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java index 8f25a002e64..e0fec534f9b 100644 --- a/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java +++ b/compiler/tests/org/jetbrains/kotlin/codegen/generated/BlackBoxWithStdlibCodegenTestGenerated.java @@ -82,6 +82,12 @@ public class BlackBoxWithStdlibCodegenTestGenerated extends AbstractBlackBoxCode doTestWithStdlib(fileName); } + @TestMetadata("fileClassWithFileAnnotation.kt") + public void testFileClassWithFileAnnotation() throws Exception { + String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/annotations/fileClassWithFileAnnotation.kt"); + doTestWithStdlib(fileName); + } + @TestMetadata("kotlinPropertyFromClassObjectAsParameter.kt") public void testKotlinPropertyFromClassObjectAsParameter() throws Exception { String fileName = JetTestUtils.navigationMetadata("compiler/testData/codegen/boxWithStdlib/annotations/kotlinPropertyFromClassObjectAsParameter.kt");