diff --git a/compiler/frontend/src/org/jetbrains/kotlin/extensions/AnnotationBasedExtension.kt b/compiler/frontend/src/org/jetbrains/kotlin/extensions/AnnotationBasedExtension.kt index bdcf687ffcc..1236a8d9c61 100644 --- a/compiler/frontend/src/org/jetbrains/kotlin/extensions/AnnotationBasedExtension.kt +++ b/compiler/frontend/src/org/jetbrains/kotlin/extensions/AnnotationBasedExtension.kt @@ -41,19 +41,26 @@ interface AnnotationBasedExtension { private fun AnnotationDescriptor.isASpecialAnnotation( modifierListOwner: KtModifierListOwner?, + visitedAnnotations: MutableSet = hashSetOf(), allowMetaAnnotations: Boolean = true ): Boolean { val annotationType = type.constructor.declarationDescriptor ?: return false - if (annotationType.fqNameSafe.asString() in getAnnotationFqNames(modifierListOwner)) return true + val annotationFqName = annotationType.fqNameSafe.asString() + if (annotationFqName in visitedAnnotations) return false // Prevent infinite recursion + if (annotationFqName in getAnnotationFqNames(modifierListOwner)) return true + + visitedAnnotations.add(annotationFqName) if (allowMetaAnnotations) { for (metaAnnotation in annotationType.annotations) { - if (metaAnnotation.isASpecialAnnotation(modifierListOwner, allowMetaAnnotations = false)) { + if (metaAnnotation.isASpecialAnnotation(modifierListOwner, visitedAnnotations, allowMetaAnnotations = true)) { return true } } } + visitedAnnotations.remove(annotationFqName) + return false } } \ No newline at end of file diff --git a/plugins/allopen/allopen-cli/testData/bytecodeListing/metaAnnotation.kt b/plugins/allopen/allopen-cli/testData/bytecodeListing/metaAnnotation.kt index 078b1c26757..75b6a42e42b 100644 --- a/plugins/allopen/allopen-cli/testData/bytecodeListing/metaAnnotation.kt +++ b/plugins/allopen/allopen-cli/testData/bytecodeListing/metaAnnotation.kt @@ -3,11 +3,20 @@ annotation class AllOpen @AllOpen annotation class MyComponent -@MyComponent // Double-transitive annotations is not supported +@MyComponent // Double-transitive annotations is supported annotation class OtherComponent +@OtherComponent +annotation class AnotherComponent + +@java.lang.annotation.Documented +annotation class Documented + class TestWithoutAnnotations_ShouldBeFinal +@Documented +class ClassWithDocumented + @AllOpen class TestAllOpen_ShouldBeOpen @@ -15,7 +24,10 @@ class TestAllOpen_ShouldBeOpen class TestMyComponent_ShouldBeOpen @OtherComponent -class TestOtherComponent_ShouldBeFinal +class TestOtherComponent_ShouldBeOpen + +@AnotherComponent +class TestAnotherComponent_ShouldBeOpen @MyComponent abstract class MyComponentBase diff --git a/plugins/allopen/allopen-cli/testData/bytecodeListing/metaAnnotation.txt b/plugins/allopen/allopen-cli/testData/bytecodeListing/metaAnnotation.txt index 71d36becf07..49f6038b091 100644 --- a/plugins/allopen/allopen-cli/testData/bytecodeListing/metaAnnotation.txt +++ b/plugins/allopen/allopen-cli/testData/bytecodeListing/metaAnnotation.txt @@ -2,6 +2,22 @@ @kotlin.Metadata public annotation class AllOpen +@OtherComponent +@java.lang.annotation.Retention +@kotlin.Metadata +public annotation class AnotherComponent + +@Documented +@kotlin.Metadata +public final class ClassWithDocumented { + public method (): void +} + +@java.lang.annotation.Documented +@java.lang.annotation.Retention +@kotlin.Metadata +public annotation class Documented + @AllOpen @java.lang.annotation.Retention @kotlin.Metadata @@ -42,6 +58,12 @@ public class TestAllOpen_ShouldBeOpen { public method (): void } +@AnotherComponent +@kotlin.Metadata +public class TestAnotherComponent_ShouldBeOpen { + public method (): void +} + @MyComponent @kotlin.Metadata public class TestMyComponent_ShouldBeOpen { @@ -50,7 +72,7 @@ public class TestMyComponent_ShouldBeOpen { @OtherComponent @kotlin.Metadata -public final class TestOtherComponent_ShouldBeFinal { +public class TestOtherComponent_ShouldBeOpen { public method (): void }