xref: /aosp_15_r20/external/dagger2/javatests/dagger/internal/codegen/UnresolvableDependencyTest.java (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
1 /*
2  * Copyright (C) 2021 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 com.google.common.truth.Truth.assertThat;
20 
21 import androidx.room.compiler.processing.XProcessingEnv;
22 import androidx.room.compiler.processing.util.Source;
23 import com.google.common.collect.ImmutableMap;
24 import dagger.testing.compile.CompilerTests;
25 import org.junit.Test;
26 import org.junit.runner.RunWith;
27 import org.junit.runners.JUnit4;
28 
29 @RunWith(JUnit4.class)
30 public final class UnresolvableDependencyTest {
31 
32   @Test
referencesUnresolvableDependency()33   public void referencesUnresolvableDependency() {
34     Source fooComponent =
35         CompilerTests.javaSource(
36             "test.FooComponent",
37             "package test;",
38             "",
39             "import dagger.Component;",
40             "",
41             "@Component",
42             "interface FooComponent {",
43             "  Foo foo();",
44             "}");
45 
46     Source foo =
47         CompilerTests.javaSource(
48             "test.Foo",
49             "package test;",
50             "",
51             "import javax.inject.Inject;",
52             "",
53             "class Foo {",
54             "  @Inject",
55             "  Foo(Bar bar) {}",
56             "}");
57 
58     Source bar =
59         CompilerTests.javaSource(
60             "test.Bar",
61             "package test;",
62             "",
63             "import javax.inject.Inject;",
64             "",
65             "class Bar {",
66             "  @Inject",
67             "  Bar(UnresolvableDependency dep) {}",
68             "}");
69 
70     // Only include a minimal portion of the stacktrace to minimize breaking tests due to refactors.
71     String stacktraceErrorMessage =
72         "dagger.internal.codegen.base"
73             + ".DaggerSuperficialValidation$ValidationException$KnownErrorType";
74     CompilerTests.daggerCompiler(fooComponent, foo, bar)
75         .compile(
76             subject -> {
77               switch (CompilerTests.backend(subject)) {
78                 case JAVAC:
79                   subject.hasErrorCount(3);
80                   subject.hasErrorContaining(
81                       "cannot find symbol"
82                           + "\n  symbol:   class UnresolvableDependency"
83                           + "\n  location: class test.Bar");
84                   break;
85                 case KSP:
86                   subject.hasErrorCount(2);
87                   break;
88               }
89               // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
90               boolean isJavac = CompilerTests.backend(subject) == XProcessingEnv.Backend.JAVAC;
91               String trace = "\n  "
92                   + "\n  Dependency trace:"
93                   + "\n      => element (CLASS): test.Bar"
94                   + "\n      => element (CONSTRUCTOR): Bar(%1$s)"
95                   + "\n      => type (EXECUTABLE constructor): (%1$s)void"
96                   + "\n      => type (ERROR parameter type): %1$s";
97               subject.hasErrorContaining(
98                   String.format(
99                       "InjectProcessingStep was unable to process 'Bar(%1$s)' because '%1$s' could "
100                           + "not be resolved." + trace,
101                       isJavac ? "UnresolvableDependency" : "error.NonExistentClass"));
102               subject.hasErrorContaining(
103                   String.format(
104                       "ComponentProcessingStep was unable to process 'test.FooComponent' because "
105                           + "'%1$s' could not be resolved." + trace,
106                       isJavac ? "UnresolvableDependency" : "error.NonExistentClass"));
107 
108               // Check that the stacktrace is not included in the error message by default.
109               assertThat(subject.getCompilationResult().rawOutput())
110                   .doesNotContain(stacktraceErrorMessage);
111             });
112 
113 
114     CompilerTests.daggerCompiler(fooComponent, foo, bar)
115         .withProcessingOptions(
116             ImmutableMap.of("dagger.includeStacktraceWithDeferredErrorMessages", "ENABLED"))
117         .compile(
118             subject -> {
119               switch (CompilerTests.backend(subject)) {
120                 case JAVAC:
121                   subject.hasErrorCount(3);
122                   break;
123                 case KSP:
124                   subject.hasErrorCount(2);
125                   break;
126               }
127               subject.hasErrorContaining(stacktraceErrorMessage);
128             });
129   }
130 
131   @Test
referencesUnresolvableAnnotationOnType()132   public void referencesUnresolvableAnnotationOnType() {
133     Source fooComponent =
134         CompilerTests.javaSource(
135             "test.FooComponent",
136             "package test;",
137             "",
138             "import dagger.Component;",
139             "",
140             "@Component",
141             "interface FooComponent {",
142             "  Foo foo();",
143             "}");
144 
145     Source foo =
146         CompilerTests.javaSource(
147             "test.Foo",
148             "package test;",
149             "",
150             "import javax.inject.Inject;",
151             "",
152             "class Foo {",
153             "  @Inject",
154             "  Foo(Bar bar) {}",
155             "}");
156 
157     Source bar =
158         CompilerTests.javaSource(
159             "test.Bar",
160             "package test;",
161             "",
162             "import javax.inject.Inject;",
163             "",
164             "@UnresolvableAnnotation",
165             "class Bar {",
166             "  @Inject",
167             "  Bar(String dep) {}",
168             "}");
169 
170     CompilerTests.daggerCompiler(fooComponent, foo, bar)
171         .compile(
172             subject -> {
173               switch (CompilerTests.backend(subject)) {
174                 case JAVAC:
175                   subject.hasErrorCount(3);
176                   subject.hasErrorContaining(
177                       "cannot find symbol"
178                           + "\n  symbol: class UnresolvableAnnotation");
179                   break;
180                 case KSP:
181                   subject.hasErrorCount(2);
182                   break;
183               }
184               // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
185               boolean isJavac = CompilerTests.backend(subject) == XProcessingEnv.Backend.JAVAC;
186               String trace = "\n  "
187                   + "\n  Dependency trace:"
188                   + "\n      => element (CLASS): test.Bar"
189                   + "\n      => annotation: @UnresolvableAnnotation"
190                   + "\n      => type (ERROR annotation type): %1$s";
191               subject.hasErrorContaining(
192                   String.format(
193                       "InjectProcessingStep was unable to process 'Bar(java.lang.String)' because "
194                           + "'%1$s' could not be resolved." + trace,
195                       isJavac ? "UnresolvableAnnotation" : "error.NonExistentClass"));
196               subject.hasErrorContaining(
197                   String.format(
198                       "ComponentProcessingStep was unable to process 'test.FooComponent' because "
199                           + "'%1$s' could not be resolved." + trace,
200                       isJavac ? "UnresolvableAnnotation" : "error.NonExistentClass"));
201             });
202   }
203 
204   @Test
referencesUnresolvableAnnotationOnTypeOnParameter()205   public void referencesUnresolvableAnnotationOnTypeOnParameter() {
206     Source fooComponent =
207         CompilerTests.javaSource(
208             "test.FooComponent",
209             "package test;",
210             "",
211             "import dagger.Component;",
212             "",
213             "@Component",
214             "interface FooComponent {",
215             "  Foo foo();",
216             "}");
217 
218     Source foo =
219         CompilerTests.javaSource(
220             "test.Foo",
221             "package test;",
222             "",
223             "import javax.inject.Inject;",
224             "",
225             "class Foo {",
226             "  @Inject",
227             "  Foo(Bar bar) {}",
228             "}");
229 
230     Source bar =
231         CompilerTests.javaSource(
232             "test.Bar",
233             "package test;",
234             "",
235             "import javax.inject.Inject;",
236             "",
237             "class Bar {",
238             "  @Inject",
239             "  Bar(@UnresolvableAnnotation String dep) {}",
240             "}");
241 
242     CompilerTests.daggerCompiler(fooComponent, foo, bar)
243         .compile(
244             subject -> {
245               switch (CompilerTests.backend(subject)) {
246                 case JAVAC:
247                   subject.hasErrorCount(3);
248                   subject.hasErrorContaining(
249                       "cannot find symbol"
250                           + "\n  symbol:   class UnresolvableAnnotation"
251                           + "\n  location: class test.Bar");
252                   break;
253                 case KSP:
254                   subject.hasErrorCount(2);
255                   break;
256               }
257               // TODO(b/248552462): Javac and KSP should match once this bug is fixed.
258               boolean isJavac = CompilerTests.backend(subject) == XProcessingEnv.Backend.JAVAC;
259               String trace = "\n  "
260                   + "\n  Dependency trace:"
261                   + "\n      => element (CLASS): test.Bar"
262                   + "\n      => element (CONSTRUCTOR): Bar(java.lang.String)"
263                   + "\n      => element (PARAMETER): dep"
264                   + "\n      => annotation: @UnresolvableAnnotation"
265                   + "\n      => type (ERROR annotation type): %1$s";
266               subject.hasErrorContaining(
267                   String.format(
268                       "InjectProcessingStep was unable to process 'Bar(java.lang.String)' because "
269                           + "'%1$s' could not be resolved." + trace,
270                       isJavac ? "UnresolvableAnnotation" : "error.NonExistentClass"));
271               subject.hasErrorContaining(
272                   String.format(
273                       "ComponentProcessingStep was unable to process 'test.FooComponent' because "
274                           + "'%1$s' could not be resolved." + trace,
275                       isJavac ? "UnresolvableAnnotation" : "error.NonExistentClass"));
276             });
277   }
278 }
279