• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2016 The Dagger 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  * http://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 dagger.internal.codegen.base;
18 
19 import static com.google.common.base.Preconditions.checkArgument;
20 import static javax.lang.model.util.ElementFilter.methodsIn;
21 
22 import com.google.auto.common.MoreTypes;
23 import com.google.common.base.Functions;
24 import com.google.common.base.Joiner;
25 import com.google.common.collect.FluentIterable;
26 import com.google.common.collect.ImmutableMap;
27 import com.google.common.collect.Maps;
28 import java.util.Map;
29 import javax.lang.model.element.AnnotationMirror;
30 import javax.lang.model.element.AnnotationValue;
31 import javax.lang.model.element.ElementKind;
32 import javax.lang.model.element.ExecutableElement;
33 import javax.lang.model.element.TypeElement;
34 import javax.lang.model.type.DeclaredType;
35 
36 /** A representation of an annotation. */
37 public final class SimpleAnnotationMirror implements AnnotationMirror {
38   private final TypeElement annotationType;
39   private final ImmutableMap<String, ? extends AnnotationValue> namedValues;
40   private final ImmutableMap<ExecutableElement, ? extends AnnotationValue> elementValues;
41 
SimpleAnnotationMirror( TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues)42   private SimpleAnnotationMirror(
43       TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues) {
44     checkArgument(
45         annotationType.getKind().equals(ElementKind.ANNOTATION_TYPE),
46         "annotationType must be an annotation: %s",
47         annotationType);
48     checkArgument(
49         FluentIterable.from(methodsIn(annotationType.getEnclosedElements()))
50             .transform(element -> element.getSimpleName().toString())
51             .toSet()
52             .equals(namedValues.keySet()),
53         "namedValues must have values for exactly the members in %s: %s",
54         annotationType,
55         namedValues);
56     this.annotationType = annotationType;
57     this.namedValues = ImmutableMap.copyOf(namedValues);
58     this.elementValues =
59         Maps.toMap(
60             methodsIn(annotationType.getEnclosedElements()),
61             Functions.compose(
62                 Functions.forMap(namedValues), element -> element.getSimpleName().toString()));
63   }
64 
65   @Override
getAnnotationType()66   public DeclaredType getAnnotationType() {
67     return MoreTypes.asDeclared(annotationType.asType());
68   }
69 
70   @Override
getElementValues()71   public Map<ExecutableElement, ? extends AnnotationValue> getElementValues() {
72     return elementValues;
73   }
74 
75   @Override
toString()76   public String toString() {
77     StringBuilder builder = new StringBuilder("@").append(annotationType.getQualifiedName());
78     if (!namedValues.isEmpty()) {
79       builder
80           .append('(')
81           .append(Joiner.on(", ").withKeyValueSeparator(" = ").join(namedValues))
82           .append(')');
83     }
84     return builder.toString();
85   }
86 
87   /**
88    * An object representing an annotation instance.
89    *
90    * @param annotationType must be an annotation type with no members
91    */
of(TypeElement annotationType)92   public static AnnotationMirror of(TypeElement annotationType) {
93     return of(annotationType, ImmutableMap.<String, AnnotationValue>of());
94   }
95 
96   /**
97    * An object representing an annotation instance.
98    *
99    * @param annotationType must be an annotation type
100    * @param namedValues a value for every annotation member, including those with defaults, indexed
101    *     by simple name
102    */
of( TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues)103   private static AnnotationMirror of(
104       TypeElement annotationType, Map<String, ? extends AnnotationValue> namedValues) {
105     return new SimpleAnnotationMirror(annotationType, namedValues);
106   }
107 }
108