• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2022 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.xprocessing;
18 
19 import static androidx.room.compiler.processing.compat.XConverters.getProcessingEnv;
20 import static androidx.room.compiler.processing.compat.XConverters.toJavac;
21 import static dagger.internal.codegen.extension.DaggerStreams.toImmutableList;
22 import static java.util.stream.Collectors.joining;
23 
24 import androidx.room.compiler.codegen.XTypeNameKt;
25 import androidx.room.compiler.processing.XConstructorType;
26 import androidx.room.compiler.processing.XExecutableElement;
27 import androidx.room.compiler.processing.XExecutableType;
28 import androidx.room.compiler.processing.XMethodType;
29 import androidx.room.compiler.processing.XProcessingEnv;
30 import androidx.room.compiler.processing.XType;
31 import com.google.common.collect.ImmutableList;
32 import com.squareup.javapoet.TypeName;
33 
34 /** A utility class for {@link XExecutableType} helper methods. */
35 // TODO(bcorso): Consider moving these methods into XProcessing library.
36 public final class XExecutableTypes {
37 
38   // TODO(b/271177465): Remove this method once XProcessing supports this feature.
isSubsignature(XExecutableElement method1, XExecutableElement method2)39   public static boolean isSubsignature(XExecutableElement method1, XExecutableElement method2) {
40     XProcessingEnv processingEnv = getProcessingEnv(method1);
41     switch (processingEnv.getBackend()) {
42       case JAVAC:
43         return isSubsignatureJavac(method1, method2, processingEnv);
44       case KSP:
45         return isSubsignatureKsp(method1, method2);
46     }
47     throw new AssertionError("Unexpected backend: " + processingEnv.getBackend());
48   }
49 
isSubsignatureKsp(XExecutableElement method1, XExecutableElement method2)50   private static boolean isSubsignatureKsp(XExecutableElement method1, XExecutableElement method2) {
51     if (method1.getParameters().size() != method2.getParameters().size()) {
52       return false;
53     }
54     ImmutableList<TypeName> method1Parameters = getParameters(method1);
55     ImmutableList<TypeName> method1TypeParameters = getTypeParameters(method1);
56     ImmutableList<TypeName> method2TypeParameters = getTypeParameters(method2);
57     return (method1TypeParameters.equals(method2TypeParameters)
58             && method1Parameters.equals(getParameters(method2)))
59         || (method1TypeParameters
60                 .isEmpty() // "The erasure of the signature of a generic method has no type
61             // parameters."
62             && method1Parameters.equals(
63                 method2.getExecutableType().getParameterTypes().stream()
64                     .map(XTypes::erasedTypeName)
65                     .collect(toImmutableList())));
66   }
67 
getParameters(XExecutableElement method)68   private static ImmutableList<TypeName> getParameters(XExecutableElement method) {
69     return method.getExecutableType().getParameterTypes().stream()
70         .map(XType::asTypeName)
71         .map(XTypeNameKt::toJavaPoet)
72         .collect(toImmutableList());
73   }
74 
getTypeParameters(XExecutableElement method)75   private static ImmutableList<TypeName> getTypeParameters(XExecutableElement method) {
76     return method.getTypeParameters().stream()
77         .map(it -> it.getBounds().get(0))
78         .map(XType::asTypeName)
79         .map(XTypeNameKt::toJavaPoet)
80         .collect(toImmutableList());
81   }
82 
isSubsignatureJavac( XExecutableElement method1, XExecutableElement method2, XProcessingEnv env)83   private static boolean isSubsignatureJavac(
84       XExecutableElement method1, XExecutableElement method2, XProcessingEnv env) {
85     return toJavac(env)
86         .getTypeUtils() // ALLOW_TYPES_ELEMENTS
87         .isSubsignature(toJavac(method1.getExecutableType()), toJavac(method2.getExecutableType()));
88   }
89 
isConstructorType(XExecutableType executableType)90   public static boolean isConstructorType(XExecutableType executableType) {
91     return executableType instanceof XConstructorType;
92   }
93 
isMethodType(XExecutableType executableType)94   public static boolean isMethodType(XExecutableType executableType) {
95     return executableType instanceof XMethodType;
96   }
97 
asMethodType(XExecutableType executableType)98   public static XMethodType asMethodType(XExecutableType executableType) {
99     return (XMethodType) executableType;
100   }
101 
getKindName(XExecutableType executableType)102   public static String getKindName(XExecutableType executableType) {
103     if (isMethodType(executableType)) {
104       return "METHOD";
105     } else if (isConstructorType(executableType)) {
106       return "CONSTRUCTOR";
107     }
108     return "UNKNOWN";
109   }
110 
111   /**
112    * Returns a string representation of {@link XExecutableType} that is independent of the backend
113    * (javac/ksp).
114    */
toStableString(XExecutableType executableType)115   public static String toStableString(XExecutableType executableType) {
116     try {
117       return String.format(
118           "(%s)%s",
119           executableType.getParameterTypes().stream()
120               .map(XTypes::toStableString)
121               .collect(joining(",")),
122           isMethodType(executableType)
123               ? XTypes.toStableString(asMethodType(executableType).getReturnType())
124               : TypeName.VOID);
125     } catch (TypeNotPresentException e) {
126       return e.typeName();
127     }
128   }
129 
XExecutableTypes()130   private XExecutableTypes() {}
131 }
132