Skip to content

Commit d4f314e

Browse files
committed
#3: Do not ignore missing TypeMirror silently
Due to a bug in javac (JDK-8229535) for an annotation with Class values, instead of returning a TypeMirror with TypeKind#ERROR the compiler returns the string "<error>". Eclipse doesn't have this problem currently.
1 parent 39a1657 commit d4f314e

1 file changed

Lines changed: 76 additions & 50 deletions

File tree

api/src/main/java/org/mapstruct/tools/gem/GemValue.java

Lines changed: 76 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -5,13 +5,14 @@
55
*/
66
package org.mapstruct.tools.gem;
77

8+
import java.util.ArrayList;
89
import java.util.List;
910
import java.util.function.Function;
10-
import java.util.stream.Collectors;
11-
import java.util.stream.Stream;
1211
import javax.lang.model.element.AnnotationMirror;
1312
import javax.lang.model.element.AnnotationValue;
13+
import javax.lang.model.element.AnnotationValueVisitor;
1414
import javax.lang.model.element.VariableElement;
15+
import javax.lang.model.util.SimpleAnnotationValueVisitor8;
1516

1617
/**
1718
* Class representing a annotation value
@@ -22,85 +23,66 @@ public class GemValue<T> {
2223

2324
public static <V> GemValue<V> create(AnnotationValue annotationValue,
2425
AnnotationValue annotationDefaultValue, Class<V> valueClass) {
25-
V value = annotationValue == null ? null : valueClass.cast( annotationValue.getValue() );
26-
V defaultValue = annotationDefaultValue == null ? null : valueClass.cast( annotationDefaultValue.getValue() );
26+
ValueAnnotationValueVisitor<V, V> visitor = new ValueAnnotationValueVisitor<>( Function.identity() );
27+
V value = visit( annotationValue, visitor, valueClass );
28+
V defaultValue = visit( annotationDefaultValue, visitor, valueClass );
2729
return new GemValue<>( value, defaultValue, annotationValue );
2830
}
2931

3032
public static <V> GemValue<List<V>> createArray(AnnotationValue annotationValue,
3133
AnnotationValue annotationDefaultValue, Class<V> valueClass) {
32-
List<V> value = extractListValues( annotationValue, valueClass, Function.identity() );
33-
List<V> defaultValue = extractListValues( annotationDefaultValue, valueClass, Function.identity() );
34+
ValueAnnotationValueListVisitor<V, V> visitor = new ValueAnnotationValueListVisitor<>( Function.identity() );
35+
List<V> value = visitList( annotationValue, visitor, valueClass );
36+
List<V> defaultValue = visitList( annotationDefaultValue, visitor, valueClass );
3437

3538
return new GemValue<>( value, defaultValue, annotationValue );
3639
}
3740

3841
public static GemValue<String> createEnum(AnnotationValue annotationValue,
3942
AnnotationValue annotationDefaultValue) {
40-
String value = annotationValue == null ? null :
41-
( (VariableElement) annotationValue.getValue() ).getSimpleName().toString();
42-
String defaultValue = annotationDefaultValue == null ? null :
43-
( (VariableElement) annotationDefaultValue.getValue() ).getSimpleName().toString();
43+
ValueAnnotationValueVisitor<VariableElement, String> visitor = new ValueAnnotationValueVisitor<>(
44+
variableElement -> variableElement.getSimpleName().toString() );
45+
String value = visit( annotationValue, visitor, VariableElement.class );
46+
String defaultValue = visit( annotationDefaultValue, visitor, VariableElement.class );
4447
return new GemValue<>( value, defaultValue, annotationValue );
4548
}
4649

4750
public static GemValue<List<String>> createEnumArray(AnnotationValue annotationValue,
4851
AnnotationValue annotationDefaultValue) {
49-
List<String> value = extractListValues(
50-
annotationValue,
51-
VariableElement.class,
52-
variableElement -> variableElement.getSimpleName().toString()
53-
);
54-
List<String> defaultValue = extractListValues(
55-
annotationDefaultValue,
56-
VariableElement.class,
57-
variableElement -> variableElement.getSimpleName().toString()
58-
);
52+
ValueAnnotationValueListVisitor<VariableElement, String> visitor = new ValueAnnotationValueListVisitor<>(
53+
variableElement -> variableElement.getSimpleName().toString() );
54+
List<String> value = visitList( annotationValue, visitor, VariableElement.class );
55+
List<String> defaultValue = visitList( annotationDefaultValue, visitor, VariableElement.class );
5956

6057
return new GemValue<>( value, defaultValue, annotationValue );
6158
}
6259

6360
public static <V> GemValue<V> create(AnnotationValue annotationValue, AnnotationValue annotationDefaultValue,
6461
Function<AnnotationMirror, V> creator) {
65-
V value = annotationValue == null ? null : creator.apply( (AnnotationMirror) annotationValue.getValue() );
66-
V defaultValue = annotationDefaultValue == null ? null :
67-
creator.apply( (AnnotationMirror) annotationDefaultValue.getValue() );
62+
ValueAnnotationValueVisitor<AnnotationMirror, V> visitor = new ValueAnnotationValueVisitor<>( creator );
63+
V value = visit( annotationValue, visitor, AnnotationMirror.class );
64+
V defaultValue = visit( annotationDefaultValue, visitor, AnnotationMirror.class );
6865
return new GemValue<>( value, defaultValue, annotationValue );
6966
}
7067

7168
public static <V> GemValue<List<V>> createArray(AnnotationValue annotationValue,
72-
AnnotationValue annotationDefaultValue,
73-
Function<AnnotationMirror, V> creator) {
74-
List<V> value = extractListValues( annotationValue, AnnotationMirror.class, creator );
75-
List<V> defaultValue = extractListValues( annotationDefaultValue, AnnotationMirror.class, creator );
69+
AnnotationValue annotationDefaultValue,
70+
Function<AnnotationMirror, V> creator) {
71+
ValueAnnotationValueListVisitor<AnnotationMirror, V> visitor = new ValueAnnotationValueListVisitor<>( creator );
72+
List<V> value = visitList( annotationValue, visitor, AnnotationMirror.class );
73+
List<V> defaultValue = visitList( annotationDefaultValue, visitor, AnnotationMirror.class );
7674
return new GemValue<>( value, defaultValue, annotationValue );
7775
}
7876

79-
private static <V, R> List<R> extractListValues(AnnotationValue annotationValue, Class<V> valueClass,
80-
Function<V, R> mapper) {
81-
List<R> value;
82-
if ( annotationValue != null ) {
83-
Object definedValue = annotationValue.getValue();
84-
if ( definedValue instanceof List ) {
85-
value = toStream( (List) definedValue, valueClass ).map( mapper ).collect( Collectors.toList() );
86-
}
87-
else {
88-
value = null;
89-
}
90-
}
91-
else {
92-
value = null;
93-
}
94-
return value;
77+
private static <V, R> R visit(AnnotationValue annotationValue,
78+
AnnotationValueVisitor<R, Class<V>> visitor, Class<V> vClass) {
79+
return annotationValue == null ? null : annotationValue.accept( visitor, vClass );
9580
}
9681

97-
private static <T> Stream<T> toStream(List<?> annotationValues, Class<T> clz) {
98-
return annotationValues.stream()
99-
.filter( AnnotationValue.class::isInstance )
100-
.map( AnnotationValue.class::cast )
101-
.map( AnnotationValue::getValue )
102-
.filter( clz::isInstance )
103-
.map( clz::cast );
82+
private static <V, R> List<R> visitList(AnnotationValue annotationValue,
83+
AnnotationValueVisitor<List<R>, Class<V>> visitor,
84+
Class<V> vClass) {
85+
return annotationValue == null ? null : annotationValue.accept( visitor, vClass );
10486
}
10587

10688
private final T value;
@@ -165,4 +147,48 @@ public boolean isValid() {
165147
return value != null || defaultValue != null;
166148
}
167149

150+
private static class ValueAnnotationValueVisitor<V, R> extends SimpleAnnotationValueVisitor8<R, Class<V>> {
151+
152+
private final Function<V, R> valueMapper;
153+
154+
private ValueAnnotationValueVisitor(Function<V, R> valueMapper) {
155+
this.valueMapper = valueMapper;
156+
}
157+
158+
@Override
159+
protected R defaultAction(Object o, Class<V> vClass) {
160+
if ( o == null ) {
161+
return null;
162+
}
163+
else if ( vClass.isInstance( o ) ) {
164+
return valueMapper.apply( vClass.cast( o ) );
165+
}
166+
else {
167+
return null;
168+
}
169+
}
170+
}
171+
172+
private static class ValueAnnotationValueListVisitor<V, R>
173+
extends SimpleAnnotationValueVisitor8<List<R>, Class<V>> {
174+
175+
private final ValueAnnotationValueVisitor<V, R> arrayVisitor;
176+
177+
private ValueAnnotationValueListVisitor(Function<V, R> valueMapper) {
178+
arrayVisitor = new ValueAnnotationValueVisitor<>( valueMapper );
179+
}
180+
181+
@Override
182+
public List<R> visitArray(List<? extends AnnotationValue> vals, Class<V> vClass) {
183+
boolean valid = true;
184+
List<R> values = new ArrayList<>( vals.size() );
185+
for ( AnnotationValue val : vals ) {
186+
R value = val.accept( arrayVisitor, vClass );
187+
values.add( value );
188+
}
189+
190+
return values;
191+
}
192+
}
193+
168194
}

0 commit comments

Comments
 (0)