• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2018 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.testing.compile.CompilationSubject.assertThat;
20 import static dagger.internal.codegen.Compilers.daggerCompiler;
21 
22 import com.google.testing.compile.Compilation;
23 import com.google.testing.compile.JavaFileObjects;
24 import javax.tools.JavaFileObject;
25 import org.junit.Test;
26 import org.junit.runner.RunWith;
27 import org.junit.runners.JUnit4;
28 
29 /**
30  * Tests that errors are reported for invalid members injection methods and {@link
31  * dagger.MembersInjector} dependency requests.
32  */
33 @RunWith(JUnit4.class)
34 public class MembersInjectionValidationTest {
35   @Test
membersInjectDependsOnUnboundedType()36   public void membersInjectDependsOnUnboundedType() {
37     JavaFileObject injectsUnboundedType =
38         JavaFileObjects.forSourceLines(
39             "test.InjectsUnboundedType",
40             "package test;",
41             "",
42             "import dagger.MembersInjector;",
43             "import java.util.ArrayList;",
44             "import javax.inject.Inject;",
45             "",
46             "class InjectsUnboundedType {",
47             "  @Inject MembersInjector<ArrayList<?>> listInjector;",
48             "}");
49 
50     Compilation compilation = daggerCompiler().compile(injectsUnboundedType);
51     assertThat(compilation).failed();
52     assertThat(compilation)
53         .hadErrorContaining(
54             "Cannot inject members into types with unbounded type arguments: "
55                 + "java.util.ArrayList<?>")
56         .inFile(injectsUnboundedType)
57         .onLineContaining("@Inject MembersInjector<ArrayList<?>> listInjector;");
58   }
59 
60   @Test
membersInjectPrimitive()61   public void membersInjectPrimitive() {
62     JavaFileObject component =
63         JavaFileObjects.forSourceLines(
64             "test.TestComponent",
65             "package test;",
66             "",
67             "import dagger.Component;",
68             "",
69             "@Component",
70             "interface TestComponent {",
71             "  void inject(int primitive);",
72             "}");
73     Compilation compilation = daggerCompiler().compile(component);
74     assertThat(compilation).failed();
75     assertThat(compilation)
76         .hadErrorContaining("Cannot inject members into int")
77         .inFile(component)
78         .onLineContaining("void inject(int primitive);");
79   }
80 
81   @Test
membersInjectArray()82   public void membersInjectArray() {
83     JavaFileObject component =
84         JavaFileObjects.forSourceLines(
85             "test.TestComponent",
86             "package test;",
87             "",
88             "import dagger.Component;",
89             "",
90             "@Component",
91             "interface TestComponent {",
92             "  void inject(Object[] array);",
93             "}");
94     Compilation compilation = daggerCompiler().compile(component);
95     assertThat(compilation).failed();
96     assertThat(compilation)
97         .hadErrorContaining("Cannot inject members into java.lang.Object[]")
98         .inFile(component)
99         .onLineContaining("void inject(Object[] array);");
100   }
101 
102   @Test
membersInjectorOfArray()103   public void membersInjectorOfArray() {
104     JavaFileObject component =
105         JavaFileObjects.forSourceLines(
106             "test.TestComponent",
107             "package test;",
108             "",
109             "import dagger.Component;",
110             "import dagger.MembersInjector;",
111             "",
112             "@Component",
113             "interface TestComponent {",
114             "  MembersInjector<Object[]> objectArrayInjector();",
115             "}");
116     Compilation compilation = daggerCompiler().compile(component);
117     assertThat(compilation).failed();
118     assertThat(compilation)
119         .hadErrorContaining("Cannot inject members into java.lang.Object[]")
120         .inFile(component)
121         .onLineContaining("objectArrayInjector();");
122   }
123 
124   @Test
membersInjectRawType()125   public void membersInjectRawType() {
126     JavaFileObject component =
127         JavaFileObjects.forSourceLines(
128             "test.TestComponent",
129             "package test;",
130             "",
131             "import dagger.Component;",
132             "import java.util.Set;",
133             "",
134             "@Component",
135             "interface TestComponent {",
136             "  void inject(Set rawSet);",
137             "}");
138     Compilation compilation = daggerCompiler().compile(component);
139     assertThat(compilation).failed();
140     assertThat(compilation).hadErrorContaining("Cannot inject members into raw type java.util.Set");
141   }
142 
143   @Test
qualifiedMembersInjector()144   public void qualifiedMembersInjector() {
145     JavaFileObject component =
146         JavaFileObjects.forSourceLines(
147             "test.TestComponent",
148             "package test;",
149             "",
150             "import dagger.Component;",
151             "import dagger.MembersInjector;",
152             "import javax.inject.Named;",
153             "",
154             "@Component",
155             "interface TestComponent {",
156             "  @Named(\"foo\") MembersInjector<Object> objectInjector();",
157             "}");
158     Compilation compilation = daggerCompiler().compile(component);
159     assertThat(compilation).failed();
160     assertThat(compilation)
161         .hadErrorContaining("Cannot inject members into qualified types")
162         .inFile(component)
163         .onLineContaining("objectInjector();");
164   }
165 
166   @Test
qualifiedMembersInjectionMethod()167   public void qualifiedMembersInjectionMethod() {
168     JavaFileObject component =
169         JavaFileObjects.forSourceLines(
170             "test.TestComponent",
171             "package test;",
172             "",
173             "import dagger.Component;",
174             "import dagger.MembersInjector;",
175             "import javax.inject.Named;",
176             "",
177             "@Component",
178             "interface TestComponent {",
179             "  @Named(\"foo\") void injectObject(Object object);",
180             "}");
181     Compilation compilation = daggerCompiler().compile(component);
182     assertThat(compilation).failed();
183     assertThat(compilation)
184         .hadErrorContaining("Cannot inject members into qualified types")
185         .inFile(component)
186         .onLineContaining("injectObject(Object object);");
187   }
188 
189   @Test
qualifiedMembersInjectionMethodParameter()190   public void qualifiedMembersInjectionMethodParameter() {
191     JavaFileObject component =
192         JavaFileObjects.forSourceLines(
193             "test.TestComponent",
194             "package test;",
195             "",
196             "import dagger.Component;",
197             "import dagger.MembersInjector;",
198             "import javax.inject.Named;",
199             "",
200             "@Component",
201             "interface TestComponent {",
202             "  void injectObject(@Named(\"foo\") Object object);",
203             "}");
204     Compilation compilation = daggerCompiler().compile(component);
205     assertThat(compilation).failed();
206     assertThat(compilation)
207         .hadErrorContaining("Cannot inject members into qualified types")
208         .inFile(component)
209         .onLineContaining("injectObject(@Named(\"foo\") Object object);");
210   }
211 
212   @Test
staticFieldInjection()213   public void staticFieldInjection() {
214     JavaFileObject injected =
215         JavaFileObjects.forSourceLines(
216             "test.Injected",
217             "package test;",
218             "",
219             "import javax.inject.Inject;",
220             "",
221             "final class Injected {",
222             "  @Inject static Object object;",
223             "}");
224     JavaFileObject component =
225         JavaFileObjects.forSourceLines(
226             "test.TestComponent",
227             "package test;",
228             "",
229             "import dagger.Component;",
230             "",
231             "@Component",
232             "interface TestComponent {",
233             "  void inject(Injected injected);",
234             "}");
235     Compilation compilation = daggerCompiler().compile(injected, component);
236     assertThat(compilation).failed();
237     assertThat(compilation).hadErrorContaining("static fields").inFile(injected).onLine(6);
238   }
239 
240   @Test
missingMembersInjectorForKotlinProperty()241   public void missingMembersInjectorForKotlinProperty() {
242     JavaFileObject component =
243         JavaFileObjects.forSourceLines(
244             "test.TestComponent",
245             "package test;",
246             "",
247             "import dagger.Component;",
248             "import dagger.internal.codegen.KotlinInjectedQualifier;",
249             "",
250             "@Component(modules = TestModule.class)",
251             "interface TestComponent {",
252             "  void inject(KotlinInjectedQualifier injected);",
253             "}");
254     JavaFileObject module =
255         JavaFileObjects.forSourceLines(
256             "test.TestModule",
257             "package test;",
258             "",
259             "import dagger.Module;",
260             "import dagger.Provides;",
261             "import javax.inject.Named;",
262             "",
263             "@Module",
264             "class TestModule {",
265             "  @Provides",
266             "  @Named(\"TheString\")",
267             "  String theString() { return \"\"; }",
268             "}");
269     Compilation compilation = daggerCompiler().compile(component, module);
270     assertThat(compilation).failed();
271     assertThat(compilation)
272         .hadErrorContaining("Unable to read annotations on an injected Kotlin property.");
273   }
274 
275   @Test
memberInjectionForKotlinObjectFails()276   public void memberInjectionForKotlinObjectFails() {
277     JavaFileObject component =
278         JavaFileObjects.forSourceLines(
279             "test.TestComponent",
280             "package test;",
281             "",
282             "import dagger.Component;",
283             "import dagger.internal.codegen.KotlinObjectWithMemberInjection;",
284             "",
285             "@Component(modules = TestModule.class)",
286             "interface TestComponent {",
287             "  void inject(KotlinObjectWithMemberInjection injected);",
288             "}");
289     Compilation compilation = daggerCompiler().compile(component, testModule);
290     assertThat(compilation).failed();
291     assertThat(compilation)
292         .hadErrorContaining("Dagger does not support injection into Kotlin objects");
293   }
294 
295   @Test
setterMemberInjectionForKotlinObjectFails()296   public void setterMemberInjectionForKotlinObjectFails() {
297     JavaFileObject component =
298         JavaFileObjects.forSourceLines(
299             "test.TestComponent",
300             "package test;",
301             "",
302             "import dagger.Component;",
303             "import dagger.internal.codegen.KotlinObjectWithSetterMemberInjection;",
304             "",
305             "@Component(modules = TestModule.class)",
306             "interface TestComponent {",
307             "  void inject(KotlinObjectWithSetterMemberInjection injected);",
308             "}");
309     Compilation compilation = daggerCompiler().compile(component, testModule);
310     assertThat(compilation).failed();
311     assertThat(compilation)
312         .hadErrorContaining("Dagger does not support injection into Kotlin objects");
313   }
314 
315   @Test
memberInjectionForKotlinClassWithCompanionObjectFails()316   public void memberInjectionForKotlinClassWithCompanionObjectFails() {
317     JavaFileObject component =
318         JavaFileObjects.forSourceLines(
319             "test.TestComponent",
320             "package test;",
321             "",
322             "import dagger.Component;",
323             "import dagger.internal.codegen.KotlinClassWithMemberInjectedCompanion;",
324             "",
325             "@Component(modules = TestModule.class)",
326             "interface TestComponent {",
327             "  void inject(KotlinClassWithMemberInjectedCompanion injected);",
328             "  void injectCompanion(KotlinClassWithMemberInjectedCompanion.Companion injected);",
329             "}");
330     Compilation compilation = daggerCompiler().compile(component, testModule);
331     assertThat(compilation).failed();
332     assertThat(compilation)
333         .hadErrorContaining("Dagger does not support injection into static fields");
334   }
335 
336   @Test
setterMemberInjectionForKotlinClassWithCompanionObjectFails()337   public void setterMemberInjectionForKotlinClassWithCompanionObjectFails() {
338     JavaFileObject component =
339         JavaFileObjects.forSourceLines(
340             "test.TestComponent",
341             "package test;",
342             "",
343             "import dagger.Component;",
344             "import dagger.internal.codegen.KotlinClassWithSetterMemberInjectedCompanion;",
345             "",
346             "@Component(modules = TestModule.class)",
347             "interface TestComponent {",
348             "  void inject(KotlinClassWithSetterMemberInjectedCompanion.Companion injected);",
349             "}");
350     Compilation compilation = daggerCompiler().compile(component, testModule);
351     assertThat(compilation).failed();
352     assertThat(compilation)
353         .hadErrorContaining("Dagger does not support injection into Kotlin objects");
354   }
355 
356   @Test
memberInjectionForKotlinClassWithNamedCompanionObjectFails()357   public void memberInjectionForKotlinClassWithNamedCompanionObjectFails() {
358     JavaFileObject component =
359         JavaFileObjects.forSourceLines(
360             "test.TestComponent",
361             "package test;",
362             "",
363             "import dagger.Component;",
364             "import dagger.internal.codegen.KotlinClassWithMemberInjectedNamedCompanion;",
365             "",
366             "@Component(modules = TestModule.class)",
367             "interface TestComponent {",
368             "  void inject(KotlinClassWithMemberInjectedNamedCompanion injected);",
369             "  void injectCompanion(KotlinClassWithMemberInjectedNamedCompanion.TheCompanion"
370                 + " injected);",
371             "}");
372     Compilation compilation = daggerCompiler().compile(component, testModule);
373     assertThat(compilation).failed();
374     assertThat(compilation)
375         .hadErrorContaining("Dagger does not support injection into static fields");
376   }
377 
378   @Test
setterMemberInjectionForKotlinClassWithNamedCompanionObjectFails()379   public void setterMemberInjectionForKotlinClassWithNamedCompanionObjectFails() {
380     JavaFileObject component =
381         JavaFileObjects.forSourceLines(
382             "test.TestComponent",
383             "package test;",
384             "",
385             "import dagger.Component;",
386             "import dagger.internal.codegen.KotlinClassWithSetterMemberInjectedNamedCompanion;",
387             "",
388             "@Component(modules = TestModule.class)",
389             "interface TestComponent {",
390             "  void inject(",
391             "      KotlinClassWithSetterMemberInjectedNamedCompanion.TheCompanion injected);",
392             "}");
393     Compilation compilation = daggerCompiler().compile(component, testModule);
394     assertThat(compilation).failed();
395     assertThat(compilation)
396         .hadErrorContaining("Dagger does not support injection into Kotlin objects");
397   }
398 
399   private final JavaFileObject testModule =
400       JavaFileObjects.forSourceLines(
401           "test.TestModule",
402           "package test;",
403           "",
404           "import dagger.Module;",
405           "import dagger.Provides;",
406           "",
407           "@Module",
408           "class TestModule {",
409           "  @Provides",
410           "  String theString() { return \"\"; }",
411           "}");
412 }
413