• 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;
18 
19 import static androidx.room.compiler.processing.util.ProcessorTestExtKt.runProcessorTest;
20 import static com.google.common.truth.Truth.assertThat;
21 import static dagger.internal.codegen.extension.DaggerCollectors.onlyElement;
22 import static dagger.internal.codegen.xprocessing.XTypes.stripVariances;
23 
24 import androidx.room.compiler.processing.XMethodElement;
25 import androidx.room.compiler.processing.XProcessingEnvConfig;
26 import androidx.room.compiler.processing.XTypeElement;
27 import androidx.room.compiler.processing.util.Source;
28 import androidx.room.compiler.processing.util.XTestInvocation;
29 import com.google.common.collect.ImmutableList;
30 import com.google.common.collect.ImmutableMap;
31 import com.squareup.javapoet.TypeName;
32 import dagger.testing.compile.CompilerTests;
33 import java.util.function.Function;
34 import org.junit.Test;
35 import org.junit.runner.RunWith;
36 import org.junit.runners.JUnit4;
37 
38 @RunWith(JUnit4.class)
39 public class XTypesStripTypeNameTest {
40   @Test
fooExtendsBar()41   public void fooExtendsBar() {
42     assertStrippedWildcardTypeNameEquals(
43         /* source = */
44         CompilerTests.javaSource(
45             "Subject",
46             "interface Subject {",
47             "  Foo<? extends Bar<? extends Baz>> method();",
48             "",
49             "  interface Foo<T> {}",
50             "  interface Bar<T> {}",
51             "  interface Baz {}",
52             "}"),
53         /* strippedTypeName = */ "Foo<Bar<Baz>>");
54   }
55 
56   @Test
fooSuperBar()57   public void fooSuperBar() {
58     assertStrippedWildcardTypeNameEquals(
59         /* source = */
60         CompilerTests.javaSource(
61             "Subject",
62             "interface Subject {",
63             "  Foo<? super Bar<? super Baz>> method();",
64             "",
65             "  interface Foo<T> {}",
66             "  interface Bar<T> {}",
67             "  interface Baz {}",
68             "}"),
69         /* strippedTypeName = */ "Foo<Bar<Baz>>");
70   }
71 
72   @Test
multipleParameters()73   public void multipleParameters() {
74     assertStrippedWildcardTypeNameEquals(
75         /* source = */
76         CompilerTests.javaSource(
77             "Subject",
78             "interface Subject {",
79             "  Foo<Bar<? extends Baz>, Bar<? super Baz>> method();",
80             "",
81             "  interface Foo<T1, T2> {}",
82             "  interface Bar<T> {}",
83             "  interface Baz {}",
84             "}"),
85         /* strippedTypeName = */ "Foo<Bar<Baz>, Bar<Baz>>");
86   }
87 
88   @Test
multipleParametersSameArgument()89   public void multipleParametersSameArgument() {
90     assertStrippedWildcardTypeNameEquals(
91         /* source = */
92         CompilerTests.javaSource(
93             "Subject",
94             "interface Subject {",
95             "  Foo<Bar<? extends Baz>, Bar<? extends Baz>> method();",
96             "",
97             "  interface Foo<T1, T2> {}",
98             "  interface Bar<T> {}",
99             "  interface Baz {}",
100             "}"),
101         /* strippedTypeName = */ "Foo<Bar<Baz>, Bar<Baz>>");
102   }
103 
104   @Test
multipleParametersCrossReferencing()105   public void multipleParametersCrossReferencing() {
106     assertStrippedWildcardTypeNameEquals(
107         /* source = */
108         CompilerTests.javaSource(
109             "Subject",
110             "interface Subject {",
111             "  Foo<Bar<? extends Baz>, Bar<? extends Bar<? extends Baz>>> method();",
112             "",
113             "  interface Foo<T1, T2 extends Bar<? extends T1>> {}",
114             "  interface Bar<T> {}",
115             "  interface Baz {}",
116             "}"),
117         /* strippedTypeName = */ "Foo<Bar<Baz>, Bar<Bar<Baz>>>");
118   }
119 
120   @Test
selfReferencing()121   public void selfReferencing() {
122     assertStrippedWildcardTypeNameEquals(
123         /* source = */
124         CompilerTests.javaSource(
125             "Subject",
126             "interface Subject {",
127             "  <T extends Foo<T>> Foo<T> method();",
128             "",
129             "  interface Foo<T extends Foo<T>> {}",
130             "}"),
131         /* strippedTypeName = */ "Foo<T>");
132   }
133 
134   @Test
arrayType()135   public void arrayType() {
136     assertStrippedWildcardTypeNameEquals(
137         /* source = */
138         CompilerTests.javaSource(
139             "Subject",
140             "interface Subject {",
141             "  Foo<? extends Bar<? extends Baz>>[] method();",
142             "",
143             "  interface Foo<T> {}",
144             "  interface Bar<T> {}",
145             "  interface Baz {}",
146             "}"),
147         /* strippedTypeName = */ "Foo<Bar<Baz>>[]");
148   }
149 
150   @Test
typeVariableSameVariableName()151   public void typeVariableSameVariableName() {
152     runTest(
153         CompilerTests.javaSource(
154             "Subject",
155             "interface Subject {",
156             "  <T extends Bar> Foo<T> method1();",
157             "  <T extends Baz> Foo<T> method2();",
158             "",
159             "  interface Foo<T> {}",
160             "  interface Bar {}",
161             "  interface Baz {}",
162             "}"),
163         invocation -> {
164           XTypeElement subject = invocation.getProcessingEnv().requireTypeElement("Subject");
165           TypeName method1ReturnTypeName =
166               getDeclaredMethod(subject, "method1").getReturnType().getTypeName();
167           TypeName method2ReturnTypeName =
168               getDeclaredMethod(subject, "method2").getReturnType().getTypeName();
169           assertThat(method1ReturnTypeName).isEqualTo(method2ReturnTypeName);
170           return null;
171         });
172   }
173 
assertStrippedWildcardTypeNameEquals(Source source, String strippedTypeName)174   private static void assertStrippedWildcardTypeNameEquals(Source source, String strippedTypeName) {
175     runTest(
176         source,
177         invocation -> {
178           XTypeElement subject = invocation.getProcessingEnv().requireTypeElement("Subject");
179           TypeName returnTypeName =
180               getDeclaredMethod(subject, "method").getReturnType().getTypeName();
181           assertThat(stripVariances(returnTypeName).toString().replace("Subject.", ""))
182               .isEqualTo(strippedTypeName);
183           return null;
184         });
185   }
186 
runTest(Source source, Function<XTestInvocation, Void> handler)187   private static void runTest(Source source, Function<XTestInvocation, Void> handler) {
188     runProcessorTest(
189         ImmutableList.of(source),
190         /* classpath = */ ImmutableList.of(),
191         /* options = */ ImmutableMap.of(),
192         /* javacArguments = */ ImmutableList.of(),
193         /* kotlincArguments = */ ImmutableList.of(),
194         /* config = */ new XProcessingEnvConfig.Builder().build(),
195         /* handler = */ invocation -> {
196           handler.apply(invocation);
197           return null;
198         });
199   }
200 
getDeclaredMethod(XTypeElement typeElement, String jvmName)201   private static XMethodElement getDeclaredMethod(XTypeElement typeElement, String jvmName) {
202     return typeElement.getDeclaredMethods().stream()
203         .filter(method -> method.getJvmName().contentEquals(jvmName))
204         .collect(onlyElement());
205   }
206 }
207