• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2013 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 androidx.room.compiler.processing.XElementKt.isField;
20 import static androidx.room.compiler.processing.XElementKt.isMethodParameter;
21 import static androidx.room.compiler.processing.XElementKt.isTypeElement;
22 import static dagger.internal.codegen.xprocessing.XElements.asExecutable;
23 import static dagger.internal.codegen.xprocessing.XElements.asMethodParameter;
24 import static dagger.internal.codegen.xprocessing.XElements.asTypeElement;
25 import static dagger.internal.codegen.xprocessing.XElements.getSimpleName;
26 import static dagger.internal.codegen.xprocessing.XElements.isExecutable;
27 import static java.util.stream.Collectors.joining;
28 
29 import androidx.room.compiler.processing.XElement;
30 import androidx.room.compiler.processing.XExecutableElement;
31 import dagger.internal.codegen.xprocessing.XTypes;
32 import javax.inject.Inject;
33 
34 /**
35  * Formats elements into a useful string representation.
36  *
37  * <p>Elements directly enclosed by a type are preceded by the enclosing type's qualified name.
38  *
39  * <p>If the element is a parameter, the returned string will include the enclosing executable,
40  * with other parameters elided.
41  */
42 public final class ElementFormatter extends Formatter<XElement> {
43   @Inject
ElementFormatter()44   ElementFormatter() {}
45 
46   @Override
format(XElement element)47   public String format(XElement element) {
48     return elementToString(element);
49   }
50 
51   /**
52    * Returns a useful string form for an element.
53    *
54    * <p>Elements directly enclosed by a type are preceded by the enclosing type's qualified name.
55    *
56    * <p>If the element is a parameter, the returned string will include the enclosing executable,
57    * with other parameters elided.
58    */
elementToString(XElement element)59   public static String elementToString(XElement element) {
60     return elementToString(element, /* elideMethodParameterTypes= */ false);
61   }
62 
63   /**
64    * Returns a useful string form for an element.
65    *
66    * <p>Elements directly enclosed by a type are preceded by the enclosing type's qualified name.
67    *
68    * <p>Parameters are given with their enclosing executable, with other parameters elided.
69    */
elementToString(XElement element, boolean elideMethodParameterTypes)70   public static String elementToString(XElement element, boolean elideMethodParameterTypes) {
71     if (isExecutable(element)) {
72       return enclosingTypeAndMemberName(element)
73           .append(
74               elideMethodParameterTypes
75                   ? (asExecutable(element).getParameters().isEmpty() ? "()" : "(…)")
76                   : asExecutable(element).getParameters().stream()
77                       .map(parameter -> XTypes.toStableString(parameter.getType()))
78                       .collect(joining(", ", "(", ")")))
79           .toString();
80     } else if (isMethodParameter(element)) {
81       XExecutableElement methodOrConstructor = asMethodParameter(element).getEnclosingElement();
82       return enclosingTypeAndMemberName(methodOrConstructor)
83           .append('(')
84           .append(
85               formatArgumentInList(
86                   methodOrConstructor.getParameters().indexOf(element),
87                   methodOrConstructor.getParameters().size(),
88                   getSimpleName(element)))
89           .append(')')
90           .toString();
91     } else if (isField(element)) {
92       return enclosingTypeAndMemberName(element).toString();
93     } else if (isTypeElement(element)) {
94       return asTypeElement(element).getQualifiedName();
95     }
96     throw new UnsupportedOperationException("Can't determine string for element " + element);
97   }
98 
enclosingTypeAndMemberName(XElement element)99   private static StringBuilder enclosingTypeAndMemberName(XElement element) {
100     StringBuilder name = new StringBuilder(elementToString(element.getEnclosingElement()));
101     if (!getSimpleName(element).contentEquals("<init>")) {
102       name.append('.').append(getSimpleName(element));
103     }
104     return name;
105   }
106 }
107