Skip to content

Commit 51ed232

Browse files
committed
GROOVY-9541
1 parent f3616f0 commit 51ed232

3 files changed

Lines changed: 56 additions & 49 deletions

File tree

base/org.codehaus.groovy25/src/org/codehaus/groovy/classgen/ExtendedVerifier.java

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -196,7 +196,7 @@ private void checkForDuplicateAnnotations(AnnotatedNode node, Map<String, List<A
196196
}
197197
if (repeatable != null) {
198198
AnnotationNode collector = new AnnotationNode(repeatable);
199-
/* GRECLIPSE edit
199+
/* GRECLIPSE edit -- GROOVY-4156, GROOVY-9541, et al.
200200
if (repeatable.isResolved()) {
201201
Class repeatableType = repeatable.getTypeClass();
202202
Retention retAnn = (Retention) repeatableType.getAnnotation(Retention.class);
@@ -214,8 +214,7 @@ private void checkForDuplicateAnnotations(AnnotatedNode node, Map<String, List<A
214214
collector.setClassRetention(repeatee.hasClassRetention());
215215
collector.setRuntimeRetention(repeatee.hasRuntimeRetention());
216216
// GRECLIPSE end
217-
218-
List<Expression> annos = new ArrayList<Expression>();
217+
List<Expression> annos = new ArrayList<>();
219218
for (AnnotationNode an : next.getValue()) {
220219
annos.add(new AnnotationConstantExpression(an));
221220
}

base/org.codehaus.groovy30/src/org/codehaus/groovy/classgen/ExtendedVerifier.java

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
import org.codehaus.groovy.ast.expr.ClassExpression;
3333
import org.codehaus.groovy.ast.expr.DeclarationExpression;
3434
import org.codehaus.groovy.ast.expr.Expression;
35-
import org.codehaus.groovy.ast.expr.ListExpression;
35+
import org.codehaus.groovy.ast.expr.PropertyExpression;
3636
import org.codehaus.groovy.ast.stmt.ReturnStatement;
3737
import org.codehaus.groovy.ast.stmt.Statement;
3838
import org.codehaus.groovy.control.AnnotationConstantsVisitor;
@@ -42,14 +42,15 @@
4242
import groovyjarjarasm.asm.Opcodes;
4343

4444
import java.lang.annotation.Retention;
45-
import java.lang.annotation.RetentionPolicy;
4645
import java.util.ArrayList;
4746
import java.util.LinkedHashMap;
4847
import java.util.List;
4948
import java.util.Map;
50-
import java.util.stream.Collectors;
5149

50+
import static java.util.stream.Collectors.toList;
51+
import static org.codehaus.groovy.ast.ClassHelper.makeCached;
5252
import static org.codehaus.groovy.ast.tools.GeneralUtils.getInterfacesAndSuperInterfaces;
53+
import static org.codehaus.groovy.ast.tools.GeneralUtils.listX;
5354
import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpec;
5455
import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecRecurse;
5556
import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec;
@@ -191,10 +192,10 @@ protected void visitAnnotations(AnnotatedNode node, int target) {
191192
}
192193

193194
private void checkForDuplicateAnnotations(AnnotatedNode node, Map<String, List<AnnotationNode>> nonSourceAnnotations) {
194-
for (Map.Entry<String, List<AnnotationNode>> next : nonSourceAnnotations.entrySet()) {
195-
if (next.getValue().size() > 1) {
195+
for (Map.Entry<String, List<AnnotationNode>> entry : nonSourceAnnotations.entrySet()) {
196+
if (entry.getValue().size() > 1) {
196197
ClassNode repeatable = null;
197-
AnnotationNode repeatee = next.getValue().get(0);
198+
AnnotationNode repeatee = entry.getValue().get(0);
198199
for (AnnotationNode anno : repeatee.getClassNode().getAnnotations()) {
199200
if (anno.getClassNode().getName().equals("java.lang.annotation.Repeatable")) {
200201
Expression value = anno.getMember("value");
@@ -206,29 +207,32 @@ private void checkForDuplicateAnnotations(AnnotatedNode node, Map<String, List<A
206207
}
207208
if (repeatable != null) {
208209
if (nonSourceAnnotations.containsKey(repeatable.getName())) {
209-
addError("Cannot specify duplicate annotation on the same member. Explicit " + repeatable.getName()
210-
+ " found when creating implicit container for " + next.getKey(), node);
210+
addError("Cannot specify duplicate annotation on the same member. Explicit " + repeatable.getName() + " found when creating implicit container for " + entry.getKey(), node);
211211
}
212212
AnnotationNode collector = new AnnotationNode(repeatable);
213-
if (repeatee.hasRuntimeRetention()) {
213+
if (repeatee.hasClassRetention()) {
214+
collector.setClassRetention(true);
215+
} else if (repeatee.hasRuntimeRetention()) {
214216
collector.setRuntimeRetention(true);
215-
} else if (repeatable.hasClass()) { // GRECLIPSE edit
216-
Class<?> repeatableType = repeatable.getTypeClass();
217-
Retention retention = repeatableType.getAnnotation(Retention.class);
218-
collector.setRuntimeRetention(retention != null && retention.value().equals(RetentionPolicy.RUNTIME));
219-
} else {
220-
for (AnnotationNode annotation : repeatable.getAnnotations()) {
221-
if (annotation.getClassNode().getName().equals("java.lang.annotation.Retention")) {
222-
Expression value = annotation.getMember("value"); assert value != null;
223-
Object retention = evaluateExpression(value, source.getConfiguration());
224-
collector.setRuntimeRetention(retention != null && retention.toString().equals("RUNTIME"));
225-
break;
217+
} else { // load retention policy from annotation definition
218+
List<AnnotationNode> retention = repeatable.getAnnotations(makeCached(Retention.class));
219+
if (!retention.isEmpty()) {
220+
Object policy;
221+
Expression value = retention.get(0).getMember("value");
222+
if (value instanceof PropertyExpression) {
223+
policy = ((PropertyExpression) value).getPropertyAsString();
224+
} else { // NOTE: it is risky to evaluate the expression from repeatable's source this way:
225+
policy = evaluateExpression(value, source.getConfiguration(), source.getClassLoader());
226+
}
227+
if ("CLASS".equals(policy)) {
228+
collector.setClassRetention(true);
229+
} else if ("RUNTIME".equals(policy)) {
230+
collector.setRuntimeRetention(true);
226231
}
227232
}
228233
}
229-
collector.addMember("value", new ListExpression(next.getValue().stream()
230-
.map(AnnotationConstantExpression::new).collect(Collectors.toList())));
231-
node.getAnnotations().removeAll(next.getValue());
234+
collector.addMember("value", listX(entry.getValue().stream().map(AnnotationConstantExpression::new).collect(toList())));
235+
node.getAnnotations().removeAll(entry.getValue());
232236
node.addAnnotation(collector);
233237
}
234238
}

base/org.codehaus.groovy40/src/org/codehaus/groovy/classgen/ExtendedVerifier.java

Lines changed: 27 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@
3434
import org.codehaus.groovy.ast.expr.ClassExpression;
3535
import org.codehaus.groovy.ast.expr.DeclarationExpression;
3636
import org.codehaus.groovy.ast.expr.Expression;
37-
import org.codehaus.groovy.ast.expr.ListExpression;
37+
import org.codehaus.groovy.ast.expr.PropertyExpression;
3838
import org.codehaus.groovy.ast.expr.VariableExpression;
3939
import org.codehaus.groovy.ast.stmt.ReturnStatement;
4040
import org.codehaus.groovy.ast.stmt.Statement;
@@ -44,14 +44,13 @@
4444
import groovyjarjarasm.asm.Opcodes;
4545

4646
import java.lang.annotation.Retention;
47-
import java.lang.annotation.RetentionPolicy;
4847
import java.util.ArrayList;
4948
import java.util.Iterator;
5049
import java.util.LinkedHashMap;
5150
import java.util.List;
5251
import java.util.Map;
53-
import java.util.stream.Collectors;
5452

53+
import static java.util.stream.Collectors.toList;
5554
import static org.codehaus.groovy.ast.AnnotationNode.ANNOTATION_TARGET;
5655
import static org.codehaus.groovy.ast.AnnotationNode.CONSTRUCTOR_TARGET;
5756
import static org.codehaus.groovy.ast.AnnotationNode.FIELD_TARGET;
@@ -63,7 +62,9 @@
6362
import static org.codehaus.groovy.ast.AnnotationNode.TYPE_PARAMETER_TARGET;
6463
import static org.codehaus.groovy.ast.AnnotationNode.TYPE_TARGET;
6564
import static org.codehaus.groovy.ast.AnnotationNode.TYPE_USE_TARGET;
65+
import static org.codehaus.groovy.ast.ClassHelper.makeCached;
6666
import static org.codehaus.groovy.ast.tools.GeneralUtils.getInterfacesAndSuperInterfaces;
67+
import static org.codehaus.groovy.ast.tools.GeneralUtils.listX;
6768
import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpec;
6869
import static org.codehaus.groovy.ast.tools.GenericsUtils.correctToGenericsSpecRecurse;
6970
import static org.codehaus.groovy.ast.tools.GenericsUtils.createGenericsSpec;
@@ -349,10 +350,10 @@ private boolean isTypeUseScenario(AnnotationNode visited, int target) {
349350
}
350351

351352
private void processDuplicateAnnotationContainers(AnnotatedNode node, Map<String, List<AnnotationNode>> nonSourceAnnotations) {
352-
for (Map.Entry<String, List<AnnotationNode>> next : nonSourceAnnotations.entrySet()) {
353-
if (next.getValue().size() > 1) {
353+
for (Map.Entry<String, List<AnnotationNode>> entry : nonSourceAnnotations.entrySet()) {
354+
if (entry.getValue().size() > 1) {
354355
ClassNode repeatable = null;
355-
AnnotationNode repeatee = next.getValue().get(0);
356+
AnnotationNode repeatee = entry.getValue().get(0);
356357
for (AnnotationNode anno : repeatee.getClassNode().getAnnotations()) {
357358
if (anno.getClassNode().getName().equals("java.lang.annotation.Repeatable")) {
358359
Expression value = anno.getMember("value");
@@ -364,29 +365,32 @@ private void processDuplicateAnnotationContainers(AnnotatedNode node, Map<String
364365
}
365366
if (repeatable != null) {
366367
if (nonSourceAnnotations.containsKey(repeatable.getName())) {
367-
addError("Cannot specify duplicate annotation on the same member. Explicit " + repeatable.getName()
368-
+ " found when creating implicit container for " + next.getKey(), node);
368+
addError("Cannot specify duplicate annotation on the same member. Explicit " + repeatable.getName() + " found when creating implicit container for " + entry.getKey(), node);
369369
}
370370
AnnotationNode collector = new AnnotationNode(repeatable);
371-
if (repeatee.hasRuntimeRetention()) {
371+
if (repeatee.hasClassRetention()) {
372+
collector.setClassRetention(true);
373+
} else if (repeatee.hasRuntimeRetention()) {
372374
collector.setRuntimeRetention(true);
373-
} else if (repeatable.hasClass()) { // GRECLIPSE edit
374-
Class<?> repeatableType = repeatable.getTypeClass();
375-
Retention retention = repeatableType.getAnnotation(Retention.class);
376-
collector.setRuntimeRetention(retention != null && retention.value().equals(RetentionPolicy.RUNTIME));
377-
} else {
378-
for (AnnotationNode annotation : repeatable.getAnnotations()) {
379-
if (annotation.getClassNode().getName().equals("java.lang.annotation.Retention")) {
380-
Expression value = annotation.getMember("value"); assert value != null;
381-
Object retention = evaluateExpression(value, source.getConfiguration());
382-
collector.setRuntimeRetention(retention != null && retention.toString().equals("RUNTIME"));
383-
break;
375+
} else { // load retention policy from annotation definition
376+
List<AnnotationNode> retention = repeatable.getAnnotations(makeCached(Retention.class));
377+
if (!retention.isEmpty()) {
378+
Object policy;
379+
Expression value = retention.get(0).getMember("value");
380+
if (value instanceof PropertyExpression) {
381+
policy = ((PropertyExpression) value).getPropertyAsString();
382+
} else { // NOTE: it is risky to evaluate the expression from repeatable's source this way:
383+
policy = evaluateExpression(value, source.getConfiguration(), source.getClassLoader());
384+
}
385+
if ("CLASS".equals(policy)) {
386+
collector.setClassRetention(true);
387+
} else if ("RUNTIME".equals(policy)) {
388+
collector.setRuntimeRetention(true);
384389
}
385390
}
386391
}
387-
collector.addMember("value", new ListExpression(next.getValue().stream()
388-
.map(AnnotationConstantExpression::new).collect(Collectors.toList())));
389-
node.getAnnotations().removeAll(next.getValue());
392+
collector.addMember("value", listX(entry.getValue().stream().map(AnnotationConstantExpression::new).collect(toList())));
393+
node.getAnnotations().removeAll(entry.getValue());
390394
node.addAnnotation(collector);
391395
}
392396
}

0 commit comments

Comments
 (0)