xref: /aosp_15_r20/external/dagger2/javatests/dagger/internal/codegen/DaggerSuperficialValidationTest.java (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
1*f585d8a3SJacky Wang /*
2*f585d8a3SJacky Wang  * Copyright (C) 2021 The Dagger Authors.
3*f585d8a3SJacky Wang  *
4*f585d8a3SJacky Wang  * Licensed under the Apache License, Version 2.0 (the "License");
5*f585d8a3SJacky Wang  * you may not use this file except in compliance with the License.
6*f585d8a3SJacky Wang  * You may obtain a copy of the License at
7*f585d8a3SJacky Wang  *
8*f585d8a3SJacky Wang  * http://www.apache.org/licenses/LICENSE-2.0
9*f585d8a3SJacky Wang  *
10*f585d8a3SJacky Wang  * Unless required by applicable law or agreed to in writing, software
11*f585d8a3SJacky Wang  * distributed under the License is distributed on an "AS IS" BASIS,
12*f585d8a3SJacky Wang  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13*f585d8a3SJacky Wang  * See the License for the specific language governing permissions and
14*f585d8a3SJacky Wang  * limitations under the License.
15*f585d8a3SJacky Wang  */
16*f585d8a3SJacky Wang 
17*f585d8a3SJacky Wang package dagger.internal.codegen;
18*f585d8a3SJacky Wang 
19*f585d8a3SJacky Wang import static com.google.common.truth.Truth.assertThat;
20*f585d8a3SJacky Wang import static org.junit.Assert.assertThrows;
21*f585d8a3SJacky Wang 
22*f585d8a3SJacky Wang import androidx.room.compiler.processing.XConstructorElement;
23*f585d8a3SJacky Wang import androidx.room.compiler.processing.XElement;
24*f585d8a3SJacky Wang import androidx.room.compiler.processing.XMethodElement;
25*f585d8a3SJacky Wang import androidx.room.compiler.processing.XProcessingEnv;
26*f585d8a3SJacky Wang import androidx.room.compiler.processing.XProcessingStep;
27*f585d8a3SJacky Wang import androidx.room.compiler.processing.XTypeElement;
28*f585d8a3SJacky Wang import androidx.room.compiler.processing.XVariableElement;
29*f585d8a3SJacky Wang import androidx.room.compiler.processing.util.Source;
30*f585d8a3SJacky Wang import com.google.common.base.Joiner;
31*f585d8a3SJacky Wang import com.google.common.collect.ImmutableList;
32*f585d8a3SJacky Wang import com.google.common.collect.ImmutableSet;
33*f585d8a3SJacky Wang import dagger.BindsInstance;
34*f585d8a3SJacky Wang import dagger.Component;
35*f585d8a3SJacky Wang import dagger.internal.codegen.base.DaggerSuperficialValidation;
36*f585d8a3SJacky Wang import dagger.internal.codegen.base.DaggerSuperficialValidation.ValidationException;
37*f585d8a3SJacky Wang import dagger.testing.compile.CompilerTests;
38*f585d8a3SJacky Wang import java.util.Map;
39*f585d8a3SJacky Wang import java.util.Set;
40*f585d8a3SJacky Wang import javax.inject.Singleton;
41*f585d8a3SJacky Wang import org.junit.Test;
42*f585d8a3SJacky Wang import org.junit.runner.RunWith;
43*f585d8a3SJacky Wang import org.junit.runners.Parameterized;
44*f585d8a3SJacky Wang import org.junit.runners.Parameterized.Parameters;
45*f585d8a3SJacky Wang 
46*f585d8a3SJacky Wang @RunWith(Parameterized.class)
47*f585d8a3SJacky Wang public class DaggerSuperficialValidationTest {
48*f585d8a3SJacky Wang   enum SourceKind {
49*f585d8a3SJacky Wang     JAVA,
50*f585d8a3SJacky Wang     KOTLIN
51*f585d8a3SJacky Wang   }
52*f585d8a3SJacky Wang 
53*f585d8a3SJacky Wang   @Parameters(name = "sourceKind={0}")
parameters()54*f585d8a3SJacky Wang   public static ImmutableList<Object[]> parameters() {
55*f585d8a3SJacky Wang     return ImmutableList.of(new Object[] {SourceKind.JAVA}, new Object[] {SourceKind.KOTLIN});
56*f585d8a3SJacky Wang   }
57*f585d8a3SJacky Wang 
58*f585d8a3SJacky Wang   private final SourceKind sourceKind;
59*f585d8a3SJacky Wang 
DaggerSuperficialValidationTest(SourceKind sourceKind)60*f585d8a3SJacky Wang   public DaggerSuperficialValidationTest(SourceKind sourceKind) {
61*f585d8a3SJacky Wang     this.sourceKind = sourceKind;
62*f585d8a3SJacky Wang   }
63*f585d8a3SJacky Wang 
64*f585d8a3SJacky Wang   private static final Joiner NEW_LINES = Joiner.on("\n  ");
65*f585d8a3SJacky Wang 
66*f585d8a3SJacky Wang   @Test
missingReturnType()67*f585d8a3SJacky Wang   public void missingReturnType() {
68*f585d8a3SJacky Wang     runTest(
69*f585d8a3SJacky Wang         CompilerTests.javaSource(
70*f585d8a3SJacky Wang             "test.TestClass",
71*f585d8a3SJacky Wang             "package test;",
72*f585d8a3SJacky Wang             "",
73*f585d8a3SJacky Wang             "abstract class TestClass {",
74*f585d8a3SJacky Wang             "  abstract MissingType blah();",
75*f585d8a3SJacky Wang             "}"),
76*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
77*f585d8a3SJacky Wang             "test.TestClass.kt",
78*f585d8a3SJacky Wang             "package test",
79*f585d8a3SJacky Wang             "",
80*f585d8a3SJacky Wang             "abstract class TestClass {",
81*f585d8a3SJacky Wang             "  abstract fun blah(): MissingType",
82*f585d8a3SJacky Wang             "}"),
83*f585d8a3SJacky Wang         (processingEnv, superficialValidation) -> {
84*f585d8a3SJacky Wang           XTypeElement testClassElement = processingEnv.findTypeElement("test.TestClass");
85*f585d8a3SJacky Wang           ValidationException exception =
86*f585d8a3SJacky Wang               assertThrows(
87*f585d8a3SJacky Wang                   ValidationException.KnownErrorType.class,
88*f585d8a3SJacky Wang                   () -> superficialValidation.validateElement(testClassElement));
89*f585d8a3SJacky Wang           // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
90*f585d8a3SJacky Wang           boolean isJavac = processingEnv.getBackend() == XProcessingEnv.Backend.JAVAC;
91*f585d8a3SJacky Wang           assertThat(exception)
92*f585d8a3SJacky Wang               .hasMessageThat()
93*f585d8a3SJacky Wang               .contains(
94*f585d8a3SJacky Wang                   String.format(
95*f585d8a3SJacky Wang                       NEW_LINES.join(
96*f585d8a3SJacky Wang                           "Validation trace:",
97*f585d8a3SJacky Wang                           "  => element (CLASS): test.TestClass",
98*f585d8a3SJacky Wang                           "  => element (METHOD): blah()",
99*f585d8a3SJacky Wang                           "  => type (ERROR return type): %1$s"),
100*f585d8a3SJacky Wang                       isJavac ? "MissingType" : "error.NonExistentClass"));
101*f585d8a3SJacky Wang         });
102*f585d8a3SJacky Wang   }
103*f585d8a3SJacky Wang 
104*f585d8a3SJacky Wang   @Test
missingGenericReturnType()105*f585d8a3SJacky Wang   public void missingGenericReturnType() {
106*f585d8a3SJacky Wang     runTest(
107*f585d8a3SJacky Wang         CompilerTests.javaSource(
108*f585d8a3SJacky Wang             "test.TestClass",
109*f585d8a3SJacky Wang             "package test;",
110*f585d8a3SJacky Wang             "",
111*f585d8a3SJacky Wang             "abstract class TestClass {",
112*f585d8a3SJacky Wang             "  abstract MissingType<?> blah();",
113*f585d8a3SJacky Wang             "}"),
114*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
115*f585d8a3SJacky Wang             "test.TestClass.kt",
116*f585d8a3SJacky Wang             "package test",
117*f585d8a3SJacky Wang             "",
118*f585d8a3SJacky Wang             "abstract class TestClass {",
119*f585d8a3SJacky Wang             "  abstract fun blah(): MissingType<*>",
120*f585d8a3SJacky Wang             "}"),
121*f585d8a3SJacky Wang         (processingEnv, superficialValidation) -> {
122*f585d8a3SJacky Wang           XTypeElement testClassElement = processingEnv.findTypeElement("test.TestClass");
123*f585d8a3SJacky Wang           ValidationException exception =
124*f585d8a3SJacky Wang               assertThrows(
125*f585d8a3SJacky Wang                   ValidationException.KnownErrorType.class,
126*f585d8a3SJacky Wang                   () -> superficialValidation.validateElement(testClassElement));
127*f585d8a3SJacky Wang           // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
128*f585d8a3SJacky Wang           boolean isJavac = processingEnv.getBackend() == XProcessingEnv.Backend.JAVAC;
129*f585d8a3SJacky Wang           assertThat(exception)
130*f585d8a3SJacky Wang               .hasMessageThat()
131*f585d8a3SJacky Wang               .contains(
132*f585d8a3SJacky Wang                   String.format(
133*f585d8a3SJacky Wang                       NEW_LINES.join(
134*f585d8a3SJacky Wang                           "Validation trace:",
135*f585d8a3SJacky Wang                           "  => element (CLASS): test.TestClass",
136*f585d8a3SJacky Wang                           "  => element (METHOD): blah()",
137*f585d8a3SJacky Wang                           "  => type (ERROR return type): %1$s"),
138*f585d8a3SJacky Wang                       isJavac ? "<any>" : "error.NonExistentClass"));
139*f585d8a3SJacky Wang         });
140*f585d8a3SJacky Wang   }
141*f585d8a3SJacky Wang 
142*f585d8a3SJacky Wang   @Test
missingReturnTypeTypeParameter()143*f585d8a3SJacky Wang   public void missingReturnTypeTypeParameter() {
144*f585d8a3SJacky Wang     runTest(
145*f585d8a3SJacky Wang         CompilerTests.javaSource(
146*f585d8a3SJacky Wang             "test.TestClass",
147*f585d8a3SJacky Wang             "package test;",
148*f585d8a3SJacky Wang             "",
149*f585d8a3SJacky Wang             "import java.util.Map;",
150*f585d8a3SJacky Wang             "import java.util.Set;",
151*f585d8a3SJacky Wang             "",
152*f585d8a3SJacky Wang             "abstract class TestClass {",
153*f585d8a3SJacky Wang             "  abstract Map<Set<?>, MissingType<?>> blah();",
154*f585d8a3SJacky Wang             "}"),
155*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
156*f585d8a3SJacky Wang             "test.TestClass.kt",
157*f585d8a3SJacky Wang             "package test",
158*f585d8a3SJacky Wang             "",
159*f585d8a3SJacky Wang             "abstract class TestClass {",
160*f585d8a3SJacky Wang             "  abstract fun blah(): Map<Set<*>, MissingType<*>>",
161*f585d8a3SJacky Wang             "}"),
162*f585d8a3SJacky Wang         (processingEnv, superficialValidation) -> {
163*f585d8a3SJacky Wang           XTypeElement testClassElement = processingEnv.findTypeElement("test.TestClass");
164*f585d8a3SJacky Wang           ValidationException exception =
165*f585d8a3SJacky Wang               assertThrows(
166*f585d8a3SJacky Wang                   ValidationException.KnownErrorType.class,
167*f585d8a3SJacky Wang                   () -> superficialValidation.validateElement(testClassElement));
168*f585d8a3SJacky Wang           // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
169*f585d8a3SJacky Wang           boolean isJavac = processingEnv.getBackend() == XProcessingEnv.Backend.JAVAC;
170*f585d8a3SJacky Wang           assertThat(exception)
171*f585d8a3SJacky Wang               .hasMessageThat()
172*f585d8a3SJacky Wang               .contains(
173*f585d8a3SJacky Wang                   String.format(
174*f585d8a3SJacky Wang                       NEW_LINES.join(
175*f585d8a3SJacky Wang                           "Validation trace:",
176*f585d8a3SJacky Wang                           "  => element (CLASS): test.TestClass",
177*f585d8a3SJacky Wang                           "  => element (METHOD): blah()",
178*f585d8a3SJacky Wang                           "  => type (DECLARED return type): "
179*f585d8a3SJacky Wang                               + "java.util.Map<java.util.Set<?>,%1$s>",
180*f585d8a3SJacky Wang                           "  => type (ERROR type argument): %1$s"),
181*f585d8a3SJacky Wang                       isJavac ? "<any>" : "error.NonExistentClass"));
182*f585d8a3SJacky Wang         });
183*f585d8a3SJacky Wang   }
184*f585d8a3SJacky Wang 
185*f585d8a3SJacky Wang   @Test
missingTypeParameter()186*f585d8a3SJacky Wang   public void missingTypeParameter() {
187*f585d8a3SJacky Wang     runTest(
188*f585d8a3SJacky Wang         CompilerTests.javaSource(
189*f585d8a3SJacky Wang             "test.TestClass", //
190*f585d8a3SJacky Wang             "package test;",
191*f585d8a3SJacky Wang             "",
192*f585d8a3SJacky Wang             "class TestClass<T extends MissingType> {}"),
193*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
194*f585d8a3SJacky Wang             "test.TestClass.kt", //
195*f585d8a3SJacky Wang             "package test",
196*f585d8a3SJacky Wang             "",
197*f585d8a3SJacky Wang             "class TestClass<T : MissingType>"),
198*f585d8a3SJacky Wang         (processingEnv, superficialValidation) -> {
199*f585d8a3SJacky Wang           if (isKAPT(processingEnv)) {
200*f585d8a3SJacky Wang             // TODO(b/268536260): Figure out why XProcessing Testing infra fails when using KAPT.
201*f585d8a3SJacky Wang             return;
202*f585d8a3SJacky Wang           }
203*f585d8a3SJacky Wang           XTypeElement testClassElement = processingEnv.findTypeElement("test.TestClass");
204*f585d8a3SJacky Wang           ValidationException exception =
205*f585d8a3SJacky Wang               assertThrows(
206*f585d8a3SJacky Wang                   ValidationException.KnownErrorType.class,
207*f585d8a3SJacky Wang                   () -> superficialValidation.validateElement(testClassElement));
208*f585d8a3SJacky Wang           // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
209*f585d8a3SJacky Wang           boolean isJavac = processingEnv.getBackend() == XProcessingEnv.Backend.JAVAC;
210*f585d8a3SJacky Wang           assertThat(exception)
211*f585d8a3SJacky Wang               .hasMessageThat()
212*f585d8a3SJacky Wang               .contains(
213*f585d8a3SJacky Wang                   String.format(
214*f585d8a3SJacky Wang                       NEW_LINES.join(
215*f585d8a3SJacky Wang                           "Validation trace:",
216*f585d8a3SJacky Wang                           "  => element (CLASS): test.TestClass",
217*f585d8a3SJacky Wang                           "  => element (TYPE_PARAMETER): T",
218*f585d8a3SJacky Wang                           "  => type (ERROR bound type): %s"),
219*f585d8a3SJacky Wang                       isJavac ? "MissingType" : "error.NonExistentClass"));
220*f585d8a3SJacky Wang         });
221*f585d8a3SJacky Wang   }
222*f585d8a3SJacky Wang 
223*f585d8a3SJacky Wang   @Test
missingParameterType()224*f585d8a3SJacky Wang   public void missingParameterType() {
225*f585d8a3SJacky Wang     runTest(
226*f585d8a3SJacky Wang         CompilerTests.javaSource(
227*f585d8a3SJacky Wang             "test.TestClass",
228*f585d8a3SJacky Wang             "package test;",
229*f585d8a3SJacky Wang             "",
230*f585d8a3SJacky Wang             "abstract class TestClass {",
231*f585d8a3SJacky Wang             "  abstract void foo(MissingType param);",
232*f585d8a3SJacky Wang             "}"),
233*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
234*f585d8a3SJacky Wang             "test.TestClass.kt",
235*f585d8a3SJacky Wang             "package test",
236*f585d8a3SJacky Wang             "",
237*f585d8a3SJacky Wang             "abstract class TestClass {",
238*f585d8a3SJacky Wang             "  abstract fun foo(param: MissingType);",
239*f585d8a3SJacky Wang             "}"),
240*f585d8a3SJacky Wang         (processingEnv, superficialValidation) -> {
241*f585d8a3SJacky Wang           XTypeElement testClassElement = processingEnv.findTypeElement("test.TestClass");
242*f585d8a3SJacky Wang           ValidationException exception =
243*f585d8a3SJacky Wang               assertThrows(
244*f585d8a3SJacky Wang                   ValidationException.KnownErrorType.class,
245*f585d8a3SJacky Wang                   () -> superficialValidation.validateElement(testClassElement));
246*f585d8a3SJacky Wang           // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
247*f585d8a3SJacky Wang           boolean isJavac = processingEnv.getBackend() == XProcessingEnv.Backend.JAVAC;
248*f585d8a3SJacky Wang           assertThat(exception)
249*f585d8a3SJacky Wang               .hasMessageThat()
250*f585d8a3SJacky Wang               .contains(
251*f585d8a3SJacky Wang                   String.format(
252*f585d8a3SJacky Wang                       NEW_LINES.join(
253*f585d8a3SJacky Wang                           "Validation trace:",
254*f585d8a3SJacky Wang                           "  => element (CLASS): test.TestClass",
255*f585d8a3SJacky Wang                           "  => element (METHOD): foo(%1$s)",
256*f585d8a3SJacky Wang                           "  => element (PARAMETER): param",
257*f585d8a3SJacky Wang                           "  => type (ERROR parameter type): %1$s"),
258*f585d8a3SJacky Wang                       isJavac ? "MissingType" : "error.NonExistentClass"));
259*f585d8a3SJacky Wang         });
260*f585d8a3SJacky Wang   }
261*f585d8a3SJacky Wang 
262*f585d8a3SJacky Wang   @Test
missingAnnotation()263*f585d8a3SJacky Wang   public void missingAnnotation() {
264*f585d8a3SJacky Wang     runTest(
265*f585d8a3SJacky Wang         CompilerTests.javaSource(
266*f585d8a3SJacky Wang             "test.TestClass", //
267*f585d8a3SJacky Wang             "package test;",
268*f585d8a3SJacky Wang             "",
269*f585d8a3SJacky Wang             "@MissingAnnotation",
270*f585d8a3SJacky Wang             "class TestClass {}"),
271*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
272*f585d8a3SJacky Wang             "test.TestClass.kt", //
273*f585d8a3SJacky Wang             "package test",
274*f585d8a3SJacky Wang             "",
275*f585d8a3SJacky Wang             "@MissingAnnotation",
276*f585d8a3SJacky Wang             "class TestClass"),
277*f585d8a3SJacky Wang         (processingEnv, superficialValidation) -> {
278*f585d8a3SJacky Wang           XTypeElement testClassElement = processingEnv.findTypeElement("test.TestClass");
279*f585d8a3SJacky Wang           ValidationException exception =
280*f585d8a3SJacky Wang               assertThrows(
281*f585d8a3SJacky Wang                   ValidationException.KnownErrorType.class,
282*f585d8a3SJacky Wang                   () -> superficialValidation.validateElement(testClassElement));
283*f585d8a3SJacky Wang           // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
284*f585d8a3SJacky Wang           boolean isJavac = processingEnv.getBackend() == XProcessingEnv.Backend.JAVAC;
285*f585d8a3SJacky Wang           assertThat(exception)
286*f585d8a3SJacky Wang               .hasMessageThat()
287*f585d8a3SJacky Wang               .contains(
288*f585d8a3SJacky Wang                   String.format(
289*f585d8a3SJacky Wang                       NEW_LINES.join(
290*f585d8a3SJacky Wang                           "Validation trace:",
291*f585d8a3SJacky Wang                           "  => element (CLASS): test.TestClass",
292*f585d8a3SJacky Wang                           "  => annotation type: MissingAnnotation",
293*f585d8a3SJacky Wang                           "  => type (ERROR annotation type): %s"),
294*f585d8a3SJacky Wang                       isJavac ? "MissingAnnotation" : "error.NonExistentClass"));
295*f585d8a3SJacky Wang         });
296*f585d8a3SJacky Wang   }
297*f585d8a3SJacky Wang 
298*f585d8a3SJacky Wang   @Test
handlesRecursiveTypeParams()299*f585d8a3SJacky Wang   public void handlesRecursiveTypeParams() {
300*f585d8a3SJacky Wang     runSuccessfulTest(
301*f585d8a3SJacky Wang         CompilerTests.javaSource(
302*f585d8a3SJacky Wang             "test.TestClass", //
303*f585d8a3SJacky Wang             "package test;",
304*f585d8a3SJacky Wang             "",
305*f585d8a3SJacky Wang             "class TestClass<T extends Comparable<T>> {}"),
306*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
307*f585d8a3SJacky Wang             "test.TestClass.kt", //
308*f585d8a3SJacky Wang             "package test",
309*f585d8a3SJacky Wang             "",
310*f585d8a3SJacky Wang             "class TestClass<T : Comparable<T>>"),
311*f585d8a3SJacky Wang         (processingEnv, superficialValidation) ->
312*f585d8a3SJacky Wang             superficialValidation.validateElement(processingEnv.findTypeElement("test.TestClass")));
313*f585d8a3SJacky Wang   }
314*f585d8a3SJacky Wang 
315*f585d8a3SJacky Wang   @Test
handlesRecursiveType()316*f585d8a3SJacky Wang   public void handlesRecursiveType() {
317*f585d8a3SJacky Wang     runSuccessfulTest(
318*f585d8a3SJacky Wang         CompilerTests.javaSource(
319*f585d8a3SJacky Wang             "test.TestClass",
320*f585d8a3SJacky Wang             "package test;",
321*f585d8a3SJacky Wang             "",
322*f585d8a3SJacky Wang             "abstract class TestClass {",
323*f585d8a3SJacky Wang             "  abstract TestClass foo(TestClass x);",
324*f585d8a3SJacky Wang             "}"),
325*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
326*f585d8a3SJacky Wang             "test.TestClass.kt",
327*f585d8a3SJacky Wang             "package test",
328*f585d8a3SJacky Wang             "",
329*f585d8a3SJacky Wang             "abstract class TestClass {",
330*f585d8a3SJacky Wang             "  abstract fun foo(x: TestClass): TestClass",
331*f585d8a3SJacky Wang             "}"),
332*f585d8a3SJacky Wang         (processingEnv, superficialValidation) ->
333*f585d8a3SJacky Wang             superficialValidation.validateElement(processingEnv.findTypeElement("test.TestClass")));
334*f585d8a3SJacky Wang   }
335*f585d8a3SJacky Wang 
336*f585d8a3SJacky Wang   @Test
missingWildcardBound()337*f585d8a3SJacky Wang   public void missingWildcardBound() {
338*f585d8a3SJacky Wang     runTest(
339*f585d8a3SJacky Wang         CompilerTests.javaSource(
340*f585d8a3SJacky Wang             "test.TestClass",
341*f585d8a3SJacky Wang             "package test;",
342*f585d8a3SJacky Wang             "",
343*f585d8a3SJacky Wang             "import java.util.Set;",
344*f585d8a3SJacky Wang             "",
345*f585d8a3SJacky Wang             "class TestClass {",
346*f585d8a3SJacky Wang             "  static final class Foo<T> {}",
347*f585d8a3SJacky Wang             "",
348*f585d8a3SJacky Wang             "  Foo<? extends MissingType> extendsTest() {",
349*f585d8a3SJacky Wang             "    return null;",
350*f585d8a3SJacky Wang             "  }",
351*f585d8a3SJacky Wang             "",
352*f585d8a3SJacky Wang             "  Foo<? super MissingType> superTest() {",
353*f585d8a3SJacky Wang             "    return null;",
354*f585d8a3SJacky Wang             "  }",
355*f585d8a3SJacky Wang             "}"),
356*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
357*f585d8a3SJacky Wang             "test.TestClass.kt",
358*f585d8a3SJacky Wang             "package test",
359*f585d8a3SJacky Wang             "",
360*f585d8a3SJacky Wang             "class TestClass {",
361*f585d8a3SJacky Wang             "  class Foo<T>",
362*f585d8a3SJacky Wang             "",
363*f585d8a3SJacky Wang             "  fun extendsTest(): Foo<out MissingType> = TODO()",
364*f585d8a3SJacky Wang             "",
365*f585d8a3SJacky Wang             "  fun superTest(): Foo<in MissingType> = TODO()",
366*f585d8a3SJacky Wang             "}"),
367*f585d8a3SJacky Wang         (processingEnv, superficialValidation) -> {
368*f585d8a3SJacky Wang           XTypeElement testClassElement = processingEnv.findTypeElement("test.TestClass");
369*f585d8a3SJacky Wang           ValidationException exception =
370*f585d8a3SJacky Wang               assertThrows(
371*f585d8a3SJacky Wang                   ValidationException.KnownErrorType.class,
372*f585d8a3SJacky Wang                   () -> superficialValidation.validateElement(testClassElement));
373*f585d8a3SJacky Wang           // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
374*f585d8a3SJacky Wang           boolean isJavac = processingEnv.getBackend() == XProcessingEnv.Backend.JAVAC;
375*f585d8a3SJacky Wang           assertThat(exception)
376*f585d8a3SJacky Wang               .hasMessageThat()
377*f585d8a3SJacky Wang               .contains(
378*f585d8a3SJacky Wang                   String.format(
379*f585d8a3SJacky Wang                       NEW_LINES.join(
380*f585d8a3SJacky Wang                           "Validation trace:",
381*f585d8a3SJacky Wang                           "  => element (CLASS): test.TestClass",
382*f585d8a3SJacky Wang                           "  => element (METHOD): extendsTest()",
383*f585d8a3SJacky Wang                           "  => type (DECLARED return type): test.TestClass.Foo<? extends %1$s>",
384*f585d8a3SJacky Wang                           "  => type (WILDCARD type argument): ? extends %1$s",
385*f585d8a3SJacky Wang                           "  => type (ERROR extends bound type): %1$s"),
386*f585d8a3SJacky Wang                       isJavac ? "MissingType" : "error.NonExistentClass"));
387*f585d8a3SJacky Wang         });
388*f585d8a3SJacky Wang   }
389*f585d8a3SJacky Wang 
390*f585d8a3SJacky Wang   @Test
missingIntersection()391*f585d8a3SJacky Wang   public void missingIntersection() {
392*f585d8a3SJacky Wang     runTest(
393*f585d8a3SJacky Wang         CompilerTests.javaSource(
394*f585d8a3SJacky Wang             "test.TestClass",
395*f585d8a3SJacky Wang             "package test;",
396*f585d8a3SJacky Wang             "",
397*f585d8a3SJacky Wang             "class TestClass<T extends Number & Missing> {}"),
398*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
399*f585d8a3SJacky Wang             "test.TestClass.kt",
400*f585d8a3SJacky Wang             "package test",
401*f585d8a3SJacky Wang             "",
402*f585d8a3SJacky Wang             "class TestClass<T> where T: Number, T: Missing"),
403*f585d8a3SJacky Wang         (processingEnv, superficialValidation) -> {
404*f585d8a3SJacky Wang           if (isKAPT(processingEnv)) {
405*f585d8a3SJacky Wang             // TODO(b/268536260): Figure out why XProcessing Testing infra fails when using KAPT.
406*f585d8a3SJacky Wang             return;
407*f585d8a3SJacky Wang           }
408*f585d8a3SJacky Wang           XTypeElement testClassElement = processingEnv.findTypeElement("test.TestClass");
409*f585d8a3SJacky Wang           ValidationException exception =
410*f585d8a3SJacky Wang               assertThrows(
411*f585d8a3SJacky Wang                   ValidationException.KnownErrorType.class,
412*f585d8a3SJacky Wang                   () -> superficialValidation.validateElement(testClassElement));
413*f585d8a3SJacky Wang           // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
414*f585d8a3SJacky Wang           boolean isJavac = processingEnv.getBackend() == XProcessingEnv.Backend.JAVAC;
415*f585d8a3SJacky Wang           assertThat(exception)
416*f585d8a3SJacky Wang               .hasMessageThat()
417*f585d8a3SJacky Wang               .contains(
418*f585d8a3SJacky Wang                   String.format(
419*f585d8a3SJacky Wang                       NEW_LINES.join(
420*f585d8a3SJacky Wang                           "Validation trace:",
421*f585d8a3SJacky Wang                           "  => element (CLASS): test.TestClass",
422*f585d8a3SJacky Wang                           "  => element (TYPE_PARAMETER): T",
423*f585d8a3SJacky Wang                           "  => type (ERROR bound type): %s"),
424*f585d8a3SJacky Wang                       isJavac ? "Missing" : "error.NonExistentClass"));
425*f585d8a3SJacky Wang         });
426*f585d8a3SJacky Wang   }
427*f585d8a3SJacky Wang 
428*f585d8a3SJacky Wang   @Test
invalidAnnotationValue()429*f585d8a3SJacky Wang   public void invalidAnnotationValue() {
430*f585d8a3SJacky Wang     runTest(
431*f585d8a3SJacky Wang         CompilerTests.javaSource(
432*f585d8a3SJacky Wang             "test.Outer",
433*f585d8a3SJacky Wang             "package test;",
434*f585d8a3SJacky Wang             "",
435*f585d8a3SJacky Wang             "final class Outer {",
436*f585d8a3SJacky Wang             "  @interface TestAnnotation {",
437*f585d8a3SJacky Wang             "    Class[] classes();",
438*f585d8a3SJacky Wang             "  }",
439*f585d8a3SJacky Wang             "",
440*f585d8a3SJacky Wang             "  @TestAnnotation(classes = MissingType.class)",
441*f585d8a3SJacky Wang             "  static class TestClass {}",
442*f585d8a3SJacky Wang             "}"),
443*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
444*f585d8a3SJacky Wang             "test.Outer.kt",
445*f585d8a3SJacky Wang             "package test",
446*f585d8a3SJacky Wang             "",
447*f585d8a3SJacky Wang             "class Outer {",
448*f585d8a3SJacky Wang             "  annotation class TestAnnotation(",
449*f585d8a3SJacky Wang             "    val classes: Array<kotlin.reflect.KClass<*>>",
450*f585d8a3SJacky Wang             "  )",
451*f585d8a3SJacky Wang             "",
452*f585d8a3SJacky Wang             "  @TestAnnotation(classes = [MissingType::class])",
453*f585d8a3SJacky Wang             "  class TestClass {}",
454*f585d8a3SJacky Wang             "}"),
455*f585d8a3SJacky Wang         (processingEnv, superficialValidation) -> {
456*f585d8a3SJacky Wang           XTypeElement testClassElement = processingEnv.findTypeElement("test.Outer.TestClass");
457*f585d8a3SJacky Wang           if (processingEnv.getBackend() == XProcessingEnv.Backend.KSP
458*f585d8a3SJacky Wang               && sourceKind == SourceKind.KOTLIN) {
459*f585d8a3SJacky Wang             // TODO(b/269364338): When using kotlin source with KSP the MissingType annotation value
460*f585d8a3SJacky Wang             // appears to be missing so validating this element does not cause the expected failure.
461*f585d8a3SJacky Wang             superficialValidation.validateElement(testClassElement);
462*f585d8a3SJacky Wang             return;
463*f585d8a3SJacky Wang           }
464*f585d8a3SJacky Wang           ValidationException exception =
465*f585d8a3SJacky Wang               assertThrows(
466*f585d8a3SJacky Wang                   ValidationException.KnownErrorType.class,
467*f585d8a3SJacky Wang                   () -> superficialValidation.validateElement(testClassElement));
468*f585d8a3SJacky Wang           // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
469*f585d8a3SJacky Wang           boolean isJavac = processingEnv.getBackend() == XProcessingEnv.Backend.JAVAC;
470*f585d8a3SJacky Wang           assertThat(exception)
471*f585d8a3SJacky Wang               .hasMessageThat()
472*f585d8a3SJacky Wang               .contains(
473*f585d8a3SJacky Wang                   String.format(
474*f585d8a3SJacky Wang                       NEW_LINES.join(
475*f585d8a3SJacky Wang                           "Validation trace:",
476*f585d8a3SJacky Wang                           "  => element (CLASS): test.Outer.TestClass",
477*f585d8a3SJacky Wang                           "  => annotation type: test.Outer.TestAnnotation",
478*f585d8a3SJacky Wang                           "  => annotation: @test.Outer.TestAnnotation(classes={<%1$s>})",
479*f585d8a3SJacky Wang                           "  => annotation value (TYPE_ARRAY): classes={<%1$s>}",
480*f585d8a3SJacky Wang                           "  => annotation value (TYPE): classes=<%1$s>"),
481*f585d8a3SJacky Wang                       isJavac ? "error" : "Error"));
482*f585d8a3SJacky Wang         });
483*f585d8a3SJacky Wang   }
484*f585d8a3SJacky Wang 
485*f585d8a3SJacky Wang   @Test
invalidAnnotationValueOnParameter()486*f585d8a3SJacky Wang   public void invalidAnnotationValueOnParameter() {
487*f585d8a3SJacky Wang     runTest(
488*f585d8a3SJacky Wang         CompilerTests.javaSource(
489*f585d8a3SJacky Wang             "test.Outer",
490*f585d8a3SJacky Wang             "package test;",
491*f585d8a3SJacky Wang             "",
492*f585d8a3SJacky Wang             "final class Outer {",
493*f585d8a3SJacky Wang             "  @interface TestAnnotation {",
494*f585d8a3SJacky Wang             "    Class[] classes();",
495*f585d8a3SJacky Wang             "  }",
496*f585d8a3SJacky Wang             "",
497*f585d8a3SJacky Wang             "  static class TestClass {",
498*f585d8a3SJacky Wang             "    TestClass(@TestAnnotation(classes = MissingType.class) String strParam) {}",
499*f585d8a3SJacky Wang             "  }",
500*f585d8a3SJacky Wang             "}"),
501*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
502*f585d8a3SJacky Wang             "test.Outer.kt",
503*f585d8a3SJacky Wang             "package test",
504*f585d8a3SJacky Wang             "",
505*f585d8a3SJacky Wang             "class Outer {",
506*f585d8a3SJacky Wang             "  annotation class TestAnnotation(",
507*f585d8a3SJacky Wang             "    val classes: Array<kotlin.reflect.KClass<*>>",
508*f585d8a3SJacky Wang             "  )",
509*f585d8a3SJacky Wang             "",
510*f585d8a3SJacky Wang             "  class TestClass(",
511*f585d8a3SJacky Wang             "      @TestAnnotation(classes = [MissingType::class]) strParam: String",
512*f585d8a3SJacky Wang             "  )",
513*f585d8a3SJacky Wang             "}"),
514*f585d8a3SJacky Wang         (processingEnv, superficialValidation) -> {
515*f585d8a3SJacky Wang           if (sourceKind == SourceKind.KOTLIN) {
516*f585d8a3SJacky Wang             // TODO(b/268536260): Figure out why XProcessing Testing infra fails when using KAPT.
517*f585d8a3SJacky Wang             // TODO(b/269364338): When using kotlin source the MissingType annotation value appears
518*f585d8a3SJacky Wang             // to be missing so validating this element does not cause the expected failure.
519*f585d8a3SJacky Wang             return;
520*f585d8a3SJacky Wang           }
521*f585d8a3SJacky Wang           XTypeElement testClassElement = processingEnv.findTypeElement("test.Outer.TestClass");
522*f585d8a3SJacky Wang           XConstructorElement constructor = testClassElement.getConstructors().get(0);
523*f585d8a3SJacky Wang           XVariableElement parameter = constructor.getParameters().get(0);
524*f585d8a3SJacky Wang           ValidationException exception =
525*f585d8a3SJacky Wang               assertThrows(
526*f585d8a3SJacky Wang                   ValidationException.KnownErrorType.class,
527*f585d8a3SJacky Wang                   () -> superficialValidation.validateElement(parameter));
528*f585d8a3SJacky Wang           // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
529*f585d8a3SJacky Wang           boolean isJavac = processingEnv.getBackend() == XProcessingEnv.Backend.JAVAC;
530*f585d8a3SJacky Wang           assertThat(exception)
531*f585d8a3SJacky Wang               .hasMessageThat()
532*f585d8a3SJacky Wang               .contains(
533*f585d8a3SJacky Wang                   String.format(
534*f585d8a3SJacky Wang                       NEW_LINES.join(
535*f585d8a3SJacky Wang                           "Validation trace:",
536*f585d8a3SJacky Wang                           "  => element (CLASS): test.Outer.TestClass",
537*f585d8a3SJacky Wang                           "  => element (CONSTRUCTOR): TestClass(java.lang.String)",
538*f585d8a3SJacky Wang                           "  => element (PARAMETER): strParam",
539*f585d8a3SJacky Wang                           "  => annotation type: test.Outer.TestAnnotation",
540*f585d8a3SJacky Wang                           "  => annotation: @test.Outer.TestAnnotation(classes={<%1$s>})",
541*f585d8a3SJacky Wang                           "  => annotation value (TYPE_ARRAY): classes={<%1$s>}",
542*f585d8a3SJacky Wang                           "  => annotation value (TYPE): classes=<%1$s>"),
543*f585d8a3SJacky Wang                       isJavac ? "error" : "Error"));
544*f585d8a3SJacky Wang         });
545*f585d8a3SJacky Wang   }
546*f585d8a3SJacky Wang 
547*f585d8a3SJacky Wang   @Test
invalidSuperclassInTypeHierarchy()548*f585d8a3SJacky Wang   public void invalidSuperclassInTypeHierarchy() {
549*f585d8a3SJacky Wang     runTest(
550*f585d8a3SJacky Wang         CompilerTests.javaSource(
551*f585d8a3SJacky Wang             "test.Outer",
552*f585d8a3SJacky Wang             "package test;",
553*f585d8a3SJacky Wang             "",
554*f585d8a3SJacky Wang             "final class Outer {",
555*f585d8a3SJacky Wang             "  Child<Long> getChild() { return null; }",
556*f585d8a3SJacky Wang             "  static class Child<T> extends Parent<T> {}",
557*f585d8a3SJacky Wang             "  static class Parent<T> extends MissingType<T> {}",
558*f585d8a3SJacky Wang             "}"),
559*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
560*f585d8a3SJacky Wang             "test.Outer.kt",
561*f585d8a3SJacky Wang             "package test",
562*f585d8a3SJacky Wang             "",
563*f585d8a3SJacky Wang             "class Outer {",
564*f585d8a3SJacky Wang             "  fun getChild(): Child<Long> = TODO()",
565*f585d8a3SJacky Wang             "  class Child<T> : Parent<T>",
566*f585d8a3SJacky Wang             "  open class Parent<T> : MissingType<T>",
567*f585d8a3SJacky Wang             "}"),
568*f585d8a3SJacky Wang         (processingEnv, superficialValidation) -> {
569*f585d8a3SJacky Wang           XTypeElement outerElement = processingEnv.findTypeElement("test.Outer");
570*f585d8a3SJacky Wang           XMethodElement getChildMethod = outerElement.getDeclaredMethods().get(0);
571*f585d8a3SJacky Wang           ValidationException exception =
572*f585d8a3SJacky Wang               assertThrows(
573*f585d8a3SJacky Wang                   ValidationException.KnownErrorType.class,
574*f585d8a3SJacky Wang                   () ->
575*f585d8a3SJacky Wang                       superficialValidation.validateTypeHierarchyOf(
576*f585d8a3SJacky Wang                           "return type", getChildMethod, getChildMethod.getReturnType()));
577*f585d8a3SJacky Wang           // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
578*f585d8a3SJacky Wang           boolean isJavac = processingEnv.getBackend() == XProcessingEnv.Backend.JAVAC;
579*f585d8a3SJacky Wang           assertThat(exception)
580*f585d8a3SJacky Wang               .hasMessageThat()
581*f585d8a3SJacky Wang               .contains(
582*f585d8a3SJacky Wang                   String.format(
583*f585d8a3SJacky Wang                       NEW_LINES.join(
584*f585d8a3SJacky Wang                           "Validation trace:",
585*f585d8a3SJacky Wang                           "  => element (CLASS): test.Outer",
586*f585d8a3SJacky Wang                           "  => element (METHOD): getChild()",
587*f585d8a3SJacky Wang                           "  => type (DECLARED return type): test.Outer.Child<java.lang.Long>",
588*f585d8a3SJacky Wang                           "  => type (DECLARED supertype): test.Outer.Parent<java.lang.Long>",
589*f585d8a3SJacky Wang                           "  => type (ERROR supertype): %s"),
590*f585d8a3SJacky Wang                       isJavac ? "MissingType<T>" : "error.NonExistentClass"));
591*f585d8a3SJacky Wang         });
592*f585d8a3SJacky Wang   }
593*f585d8a3SJacky Wang 
594*f585d8a3SJacky Wang   @Test
invalidSuperclassTypeParameterInTypeHierarchy()595*f585d8a3SJacky Wang   public void invalidSuperclassTypeParameterInTypeHierarchy() {
596*f585d8a3SJacky Wang     runTest(
597*f585d8a3SJacky Wang         CompilerTests.javaSource(
598*f585d8a3SJacky Wang             "test.Outer",
599*f585d8a3SJacky Wang             "package test;",
600*f585d8a3SJacky Wang             "",
601*f585d8a3SJacky Wang             "final class Outer {",
602*f585d8a3SJacky Wang             "  Child getChild() { return null; }",
603*f585d8a3SJacky Wang             "  static class Child extends Parent<MissingType> {}",
604*f585d8a3SJacky Wang             "  static class Parent<T> {}",
605*f585d8a3SJacky Wang             "}"),
606*f585d8a3SJacky Wang         CompilerTests.kotlinSource(
607*f585d8a3SJacky Wang             "test.Outer.kt",
608*f585d8a3SJacky Wang             "package test",
609*f585d8a3SJacky Wang             "",
610*f585d8a3SJacky Wang             "class Outer {",
611*f585d8a3SJacky Wang             "  fun getChild(): Child = TODO()",
612*f585d8a3SJacky Wang             "  class Child : Parent<MissingType>()",
613*f585d8a3SJacky Wang             "  open class Parent<T>",
614*f585d8a3SJacky Wang             "}"),
615*f585d8a3SJacky Wang         (processingEnv, superficialValidation) -> {
616*f585d8a3SJacky Wang           XTypeElement outerElement = processingEnv.findTypeElement("test.Outer");
617*f585d8a3SJacky Wang           XMethodElement getChildMethod = outerElement.getDeclaredMethods().get(0);
618*f585d8a3SJacky Wang           if (isKAPT(processingEnv)) {
619*f585d8a3SJacky Wang             // https://youtrack.jetbrains.com/issue/KT-34193/Kapt-CorrectErrorTypes-doesnt-work-for-generics
620*f585d8a3SJacky Wang             // There's no way to work around this bug in KAPT so validation doesn't catch this case.
621*f585d8a3SJacky Wang             superficialValidation.validateTypeHierarchyOf(
622*f585d8a3SJacky Wang                 "return type", getChildMethod, getChildMethod.getReturnType());
623*f585d8a3SJacky Wang             return;
624*f585d8a3SJacky Wang           }
625*f585d8a3SJacky Wang           ValidationException exception =
626*f585d8a3SJacky Wang               assertThrows(
627*f585d8a3SJacky Wang                   ValidationException.KnownErrorType.class,
628*f585d8a3SJacky Wang                   () ->
629*f585d8a3SJacky Wang                       superficialValidation.validateTypeHierarchyOf(
630*f585d8a3SJacky Wang                           "return type", getChildMethod, getChildMethod.getReturnType()));
631*f585d8a3SJacky Wang           // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
632*f585d8a3SJacky Wang           boolean isJavac = processingEnv.getBackend() == XProcessingEnv.Backend.JAVAC;
633*f585d8a3SJacky Wang           assertThat(exception)
634*f585d8a3SJacky Wang               .hasMessageThat()
635*f585d8a3SJacky Wang               .contains(
636*f585d8a3SJacky Wang                   String.format(
637*f585d8a3SJacky Wang                       NEW_LINES.join(
638*f585d8a3SJacky Wang                           "Validation trace:",
639*f585d8a3SJacky Wang                           "  => element (CLASS): test.Outer",
640*f585d8a3SJacky Wang                           "  => element (METHOD): getChild()",
641*f585d8a3SJacky Wang                           "  => type (DECLARED return type): test.Outer.Child",
642*f585d8a3SJacky Wang                           "  => type (DECLARED supertype): test.Outer.Parent<%1$s>",
643*f585d8a3SJacky Wang                           "  => type (ERROR type argument): %1$s"),
644*f585d8a3SJacky Wang                       isJavac ? "MissingType" : "error.NonExistentClass"));
645*f585d8a3SJacky Wang         });
646*f585d8a3SJacky Wang   }
647*f585d8a3SJacky Wang 
runTest( Source.JavaSource javaSource, Source.KotlinSource kotlinSource, AssertionHandler assertionHandler)648*f585d8a3SJacky Wang   private void runTest(
649*f585d8a3SJacky Wang       Source.JavaSource javaSource,
650*f585d8a3SJacky Wang       Source.KotlinSource kotlinSource,
651*f585d8a3SJacky Wang       AssertionHandler assertionHandler) {
652*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(sourceKind == SourceKind.JAVA ? javaSource : kotlinSource)
653*f585d8a3SJacky Wang         .withProcessingSteps(() -> new AssertingStep(assertionHandler))
654*f585d8a3SJacky Wang         // We're expecting compiler errors that we assert on in the assertionHandler.
655*f585d8a3SJacky Wang         .compile(subject -> subject.hasError());
656*f585d8a3SJacky Wang   }
657*f585d8a3SJacky Wang 
runSuccessfulTest( Source.JavaSource javaSource, Source.KotlinSource kotlinSource, AssertionHandler assertionHandler)658*f585d8a3SJacky Wang   private void runSuccessfulTest(
659*f585d8a3SJacky Wang       Source.JavaSource javaSource,
660*f585d8a3SJacky Wang       Source.KotlinSource kotlinSource,
661*f585d8a3SJacky Wang       AssertionHandler assertionHandler) {
662*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(sourceKind == SourceKind.JAVA ? javaSource : kotlinSource)
663*f585d8a3SJacky Wang         .withProcessingSteps(() -> new AssertingStep(assertionHandler))
664*f585d8a3SJacky Wang         .compile(subject -> subject.hasErrorCount(0));
665*f585d8a3SJacky Wang   }
666*f585d8a3SJacky Wang 
isKAPT(XProcessingEnv processingEnv)667*f585d8a3SJacky Wang   private boolean isKAPT(XProcessingEnv processingEnv) {
668*f585d8a3SJacky Wang     return processingEnv.getBackend() == XProcessingEnv.Backend.JAVAC
669*f585d8a3SJacky Wang         && sourceKind == SourceKind.KOTLIN;
670*f585d8a3SJacky Wang   }
671*f585d8a3SJacky Wang 
672*f585d8a3SJacky Wang   private interface AssertionHandler {
runAssertions( XProcessingEnv processingEnv, DaggerSuperficialValidation superficialValidation)673*f585d8a3SJacky Wang     void runAssertions(
674*f585d8a3SJacky Wang         XProcessingEnv processingEnv, DaggerSuperficialValidation superficialValidation);
675*f585d8a3SJacky Wang   }
676*f585d8a3SJacky Wang 
677*f585d8a3SJacky Wang   private static final class AssertingStep implements XProcessingStep {
678*f585d8a3SJacky Wang     private final AssertionHandler assertionHandler;
679*f585d8a3SJacky Wang     private boolean processed = false;
680*f585d8a3SJacky Wang 
AssertingStep(AssertionHandler assertionHandler)681*f585d8a3SJacky Wang     AssertingStep(AssertionHandler assertionHandler) {
682*f585d8a3SJacky Wang       this.assertionHandler = assertionHandler;
683*f585d8a3SJacky Wang     }
684*f585d8a3SJacky Wang 
685*f585d8a3SJacky Wang     @Override
annotations()686*f585d8a3SJacky Wang     public final ImmutableSet<String> annotations() {
687*f585d8a3SJacky Wang       return ImmutableSet.of("*");
688*f585d8a3SJacky Wang     }
689*f585d8a3SJacky Wang 
690*f585d8a3SJacky Wang     @Override
process( XProcessingEnv env, Map<String, ? extends Set<? extends XElement>> elementsByAnnotation)691*f585d8a3SJacky Wang     public ImmutableSet<XElement> process(
692*f585d8a3SJacky Wang         XProcessingEnv env, Map<String, ? extends Set<? extends XElement>> elementsByAnnotation) {
693*f585d8a3SJacky Wang       if (!processed) {
694*f585d8a3SJacky Wang         processed = true; // only process once.
695*f585d8a3SJacky Wang         TestComponent component =
696*f585d8a3SJacky Wang             DaggerDaggerSuperficialValidationTest_TestComponent.factory().create(env);
697*f585d8a3SJacky Wang         assertionHandler.runAssertions(env, component.superficialValidation());
698*f585d8a3SJacky Wang       }
699*f585d8a3SJacky Wang       return ImmutableSet.of();
700*f585d8a3SJacky Wang     }
701*f585d8a3SJacky Wang 
702*f585d8a3SJacky Wang     @Override
processOver( XProcessingEnv env, Map<String, ? extends Set<? extends XElement>> elementsByAnnotation)703*f585d8a3SJacky Wang     public void processOver(
704*f585d8a3SJacky Wang         XProcessingEnv env, Map<String, ? extends Set<? extends XElement>> elementsByAnnotation) {}
705*f585d8a3SJacky Wang   }
706*f585d8a3SJacky Wang 
707*f585d8a3SJacky Wang   @Singleton
708*f585d8a3SJacky Wang   @Component(modules = ProcessingEnvironmentModule.class)
709*f585d8a3SJacky Wang   interface TestComponent {
superficialValidation()710*f585d8a3SJacky Wang     DaggerSuperficialValidation superficialValidation();
711*f585d8a3SJacky Wang 
712*f585d8a3SJacky Wang     @Component.Factory
713*f585d8a3SJacky Wang     interface Factory {
create(@indsInstance XProcessingEnv processingEnv)714*f585d8a3SJacky Wang       TestComponent create(@BindsInstance XProcessingEnv processingEnv);
715*f585d8a3SJacky Wang     }
716*f585d8a3SJacky Wang   }
717*f585d8a3SJacky Wang }
718