• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 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.model;
18 
19 import static com.google.auto.common.AnnotationMirrors.getAnnotationValuesWithDefaults;
20 import static java.util.stream.Collectors.joining;
21 
22 import com.google.common.base.Joiner;
23 import com.google.common.collect.ImmutableMap;
24 import com.squareup.javapoet.CodeBlock;
25 import java.util.List;
26 import javax.lang.model.element.AnnotationMirror;
27 import javax.lang.model.element.AnnotationValue;
28 import javax.lang.model.element.ExecutableElement;
29 import javax.lang.model.util.SimpleAnnotationValueVisitor8;
30 
31 /** Utility class for qualifier transformations */
32 final class MoreAnnotationMirrors {
33   /**
34    * Returns a String rendering of an {@link AnnotationMirror} that includes attributes in the order
35    * defined in the annotation type.
36    */
toStableString(DaggerAnnotation qualifier)37   public static String toStableString(DaggerAnnotation qualifier) {
38     return stableAnnotationMirrorToString(qualifier.javac());
39   }
40 
41   /**
42    * Returns a String rendering of an {@link AnnotationMirror} that includes attributes in the order
43    * defined in the annotation type. This will produce the same output for {@linkplain
44    * com.google.auto.common.AnnotationMirrors#equivalence() equal} {@link AnnotationMirror}s even if
45    * default values are omitted or their attributes were written in different orders, e.g.
46    * {@code @A(b = "b", c = "c")} and {@code @A(c = "c", b = "b", attributeWithDefaultValue =
47    * "default value")}.
48    */
49   // TODO(ronshapiro): move this to auto-common
stableAnnotationMirrorToString(AnnotationMirror qualifier)50   private static String stableAnnotationMirrorToString(AnnotationMirror qualifier) {
51     StringBuilder builder = new StringBuilder("@").append(qualifier.getAnnotationType());
52     ImmutableMap<ExecutableElement, AnnotationValue> elementValues =
53         getAnnotationValuesWithDefaults(qualifier);
54     if (!elementValues.isEmpty()) {
55       ImmutableMap.Builder<String, String> namedValuesBuilder = ImmutableMap.builder();
56       elementValues.forEach(
57           (key, value) ->
58               namedValuesBuilder.put(
59                   key.getSimpleName().toString(), stableAnnotationValueToString(value)));
60       ImmutableMap<String, String> namedValues = namedValuesBuilder.build();
61       builder.append('(');
62       if (namedValues.size() == 1 && namedValues.containsKey("value")) {
63         // Omit "value ="
64         builder.append(namedValues.get("value"));
65       } else {
66         builder.append(Joiner.on(", ").withKeyValueSeparator("=").join(namedValues));
67       }
68       builder.append(')');
69     }
70     return builder.toString();
71   }
72 
stableAnnotationValueToString(AnnotationValue annotationValue)73   private static String stableAnnotationValueToString(AnnotationValue annotationValue) {
74     return annotationValue.accept(
75         new SimpleAnnotationValueVisitor8<String, Void>() {
76           @Override
77           protected String defaultAction(Object value, Void ignore) {
78             return value.toString();
79           }
80 
81           @Override
82           public String visitString(String value, Void ignore) {
83             return CodeBlock.of("$S", value).toString();
84           }
85 
86           @Override
87           public String visitAnnotation(AnnotationMirror value, Void ignore) {
88             return stableAnnotationMirrorToString(value);
89           }
90 
91           @Override
92           public String visitArray(List<? extends AnnotationValue> value, Void ignore) {
93             return value.stream()
94                 .map(MoreAnnotationMirrors::stableAnnotationValueToString)
95                 .collect(joining(", ", "{", "}"));
96           }
97         },
98         null);
99   }
100 
101   private MoreAnnotationMirrors() {}
102 }
103