Skip to content

Commit 5459304

Browse files
committed
Re-introduce support for annotation declarations with self references
Closes gh-31400
1 parent 00d4830 commit 5459304

File tree

4 files changed

+152
-3
lines changed

4 files changed

+152
-3
lines changed

spring-core/src/main/java/org/springframework/core/annotation/AnnotationTypeMapping.java

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -45,6 +45,7 @@
4545
*
4646
* @author Phillip Webb
4747
* @author Sam Brannen
48+
* @author Juergen Hoeller
4849
* @since 5.2
4950
* @see AnnotationTypeMappings
5051
*/
@@ -402,9 +403,11 @@ private boolean computeSynthesizableFlag() {
402403
if (type.isAnnotation() || (type.isArray() && type.getComponentType().isAnnotation())) {
403404
Class<? extends Annotation> annotationType =
404405
(Class<? extends Annotation>) (type.isAnnotation() ? type : type.getComponentType());
405-
AnnotationTypeMapping mapping = AnnotationTypeMappings.forAnnotationType(annotationType).get(0);
406-
if (mapping.isSynthesizable()) {
407-
return true;
406+
if (annotationType != this.annotationType) {
407+
AnnotationTypeMapping mapping = AnnotationTypeMappings.forAnnotationType(annotationType).get(0);
408+
if (mapping.isSynthesizable()) {
409+
return true;
410+
}
408411
}
409412
}
410413
}
Lines changed: 86 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,86 @@
1+
/*
2+
* Copyright 2002-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.core.annotation
18+
19+
import org.assertj.core.api.Assertions.assertThat
20+
import org.junit.jupiter.api.Test
21+
22+
/**
23+
* Tests for {@link MergedAnnotations} and {@link MergedAnnotation} in Kotlin.
24+
*
25+
* @author Sam Brannen
26+
* @author Juergen Hoeller
27+
* @since 5.3.16
28+
*/
29+
class KotlinMergedAnnotationsTests {
30+
31+
@Test // gh-28012
32+
fun recursiveAnnotationWithAlias() {
33+
val method = javaClass.getMethod("personWithAliasMethod")
34+
35+
// MergedAnnotations
36+
val mergedAnnotations = MergedAnnotations.from(method)
37+
assertThat(mergedAnnotations.isPresent(PersonWithAlias::class.java)).isTrue();
38+
39+
// MergedAnnotation
40+
val mergedAnnotation = MergedAnnotation.from(method.getAnnotation(PersonWithAlias::class.java))
41+
assertThat(mergedAnnotation).isNotNull();
42+
43+
// Synthesized Annotations
44+
val jane = mergedAnnotation.synthesize()
45+
assertThat(jane.value).isEqualTo("jane")
46+
assertThat(jane.name).isEqualTo("jane")
47+
val synthesizedFriends = jane.friends
48+
assertThat(synthesizedFriends).hasSize(2)
49+
50+
val john = synthesizedFriends[0]
51+
assertThat(john.value).isEqualTo("john")
52+
assertThat(john.name).isEqualTo("john")
53+
54+
val sally = synthesizedFriends[1]
55+
assertThat(sally.value).isEqualTo("sally")
56+
assertThat(sally.name).isEqualTo("sally")
57+
}
58+
59+
@Test // gh-31400
60+
fun recursiveAnnotationWithoutAlias() {
61+
val method = javaClass.getMethod("personWithoutAliasMethod")
62+
63+
// MergedAnnotations
64+
val mergedAnnotations = MergedAnnotations.from(method)
65+
assertThat(mergedAnnotations.isPresent(PersonWithoutAlias::class.java)).isTrue();
66+
67+
// MergedAnnotation
68+
val mergedAnnotation = MergedAnnotation.from(method.getAnnotation(PersonWithoutAlias::class.java))
69+
assertThat(mergedAnnotation).isNotNull();
70+
71+
// Synthesized Annotations
72+
val jane = mergedAnnotation.synthesize()
73+
val synthesizedFriends = jane.friends
74+
assertThat(synthesizedFriends).hasSize(2)
75+
}
76+
77+
78+
@PersonWithAlias("jane", friends = [PersonWithAlias("john"), PersonWithAlias("sally")])
79+
fun personWithAliasMethod() {
80+
}
81+
82+
@PersonWithoutAlias("jane", friends = [PersonWithoutAlias("john"), PersonWithoutAlias("sally")])
83+
fun personWithoutAliasMethod() {
84+
}
85+
86+
}
Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,31 @@
1+
/*
2+
* Copyright 2002-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.core.annotation
18+
19+
@Target(AnnotationTarget.FUNCTION)
20+
@Retention(AnnotationRetention.RUNTIME)
21+
annotation class PersonWithAlias(
22+
23+
@get:AliasFor("name")
24+
val value: String = "",
25+
26+
@get:AliasFor("value")
27+
val name: String = "",
28+
29+
vararg val friends: PersonWithAlias = []
30+
31+
)
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
/*
2+
* Copyright 2002-2023 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.core.annotation
18+
19+
@Target(AnnotationTarget.FUNCTION)
20+
@Retention(AnnotationRetention.RUNTIME)
21+
annotation class PersonWithoutAlias(
22+
23+
val value: String = "",
24+
25+
val name: String = "",
26+
27+
vararg val friends: PersonWithoutAlias = []
28+
29+
)

0 commit comments

Comments
 (0)