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