xref: /aosp_15_r20/external/dagger2/javatests/dagger/internal/codegen/ComponentBuilderTest.java (revision f585d8a307d0621d6060bd7e80091fdcbf94fe27)
1 /*
2  * Copyright (C) 2015 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 dagger.internal.codegen.base.ComponentCreatorAnnotation.COMPONENT_BUILDER;
20 import static dagger.internal.codegen.binding.ErrorMessages.creatorMessagesFor;
21 
22 import androidx.room.compiler.processing.util.Source;
23 import dagger.internal.codegen.binding.ErrorMessages;
24 import dagger.testing.compile.CompilerTests;
25 import dagger.testing.golden.GoldenFileRule;
26 import java.util.Collection;
27 import org.junit.Rule;
28 import org.junit.Test;
29 import org.junit.runner.RunWith;
30 import org.junit.runners.Parameterized;
31 import org.junit.runners.Parameterized.Parameters;
32 
33 /** Tests for {@link dagger.Component.Builder} */
34 @RunWith(Parameterized.class)
35 public class ComponentBuilderTest {
36   @Parameters(name = "{0}")
parameters()37   public static Collection<Object[]> parameters() {
38     return CompilerMode.TEST_PARAMETERS;
39   }
40 
41   @Rule public GoldenFileRule goldenFileRule = new GoldenFileRule();
42 
43   private final CompilerMode compilerMode;
44 
ComponentBuilderTest(CompilerMode compilerMode)45   public ComponentBuilderTest(CompilerMode compilerMode) {
46     this.compilerMode = compilerMode;
47   }
48 
49   private static final ErrorMessages.ComponentCreatorMessages MSGS =
50       creatorMessagesFor(COMPONENT_BUILDER);
51 
52   @Test
testUsesBuildAndSetterNames()53   public void testUsesBuildAndSetterNames() throws Exception {
54     Source moduleFile =
55         CompilerTests.javaSource(
56             "test.TestModule",
57             "package test;",
58             "",
59             "import dagger.Module;",
60             "import dagger.Provides;",
61             "",
62             "@Module",
63             "final class TestModule {",
64             "  @Provides String string() { return null; }",
65             "}");
66 
67     Source componentFile =
68         CompilerTests.javaSource(
69             "test.TestComponent",
70             "package test;",
71             "",
72             "import dagger.Component;",
73             "",
74             "@Component(modules = TestModule.class)",
75             "interface TestComponent {",
76             "  String string();",
77             "",
78             "  @Component.Builder",
79             "  interface Builder {",
80             "    Builder setTestModule(TestModule testModule);",
81             "    TestComponent create();",
82             "  }",
83             "}");
84 
85     CompilerTests.daggerCompiler(moduleFile, componentFile)
86         .withProcessingOptions(compilerMode.processorOptions())
87         .compile(
88             subject -> {
89               subject.hasErrorCount(0);
90               subject.generatedSource(goldenFileRule.goldenSource("test/DaggerTestComponent"));
91             });
92   }
93 
94   @Test
testSetterMethodWithMoreThanOneArgFails()95   public void testSetterMethodWithMoreThanOneArgFails() {
96     Source componentFile =
97         CompilerTests.javaSource(
98             "test.SimpleComponent",
99             "package test;",
100             "",
101             "import dagger.Component;",
102             "import javax.inject.Provider;",
103             "",
104             "@Component",
105             "abstract class SimpleComponent {",
106             "  @Component.Builder",
107             "  interface Builder {",
108             "    SimpleComponent build();",
109             "    Builder set(String s, Integer i);",
110             "    Builder set(Number n, Double d);",
111             "  }",
112             "}");
113 
114     CompilerTests.daggerCompiler(componentFile)
115         .withProcessingOptions(compilerMode.processorOptions())
116         .compile(
117             subject -> {
118               subject.hasErrorCount(2);
119               subject
120                   .hasErrorContaining(MSGS.setterMethodsMustTakeOneArg())
121                   .onSource(componentFile)
122                   .onLineContaining("Builder set(String s, Integer i);");
123               subject
124                   .hasErrorContaining(MSGS.setterMethodsMustTakeOneArg())
125                   .onSource(componentFile)
126                   .onLineContaining("Builder set(Number n, Double d);");
127             });
128   }
129 
130   @Test
testInheritedSetterMethodWithMoreThanOneArgFails()131   public void testInheritedSetterMethodWithMoreThanOneArgFails() {
132     Source componentFile =
133         CompilerTests.javaSource(
134             "test.SimpleComponent",
135             "package test;",
136             "",
137             "import dagger.Component;",
138             "import javax.inject.Provider;",
139             "",
140             "@Component",
141             "abstract class SimpleComponent {",
142             "  interface Parent {",
143             "    SimpleComponent build();",
144             "    Builder set1(String s, Integer i);",
145             "  }",
146             "",
147             "  @Component.Builder",
148             "  interface Builder extends Parent {}",
149             "}");
150 
151     CompilerTests.daggerCompiler(componentFile)
152         .withProcessingOptions(compilerMode.processorOptions())
153         .compile(
154             subject -> {
155               subject.hasErrorCount(1);
156               subject
157                   .hasErrorContaining(
158                       String.format(
159                           MSGS.inheritedSetterMethodsMustTakeOneArg(),
160                           "test.SimpleComponent.Builder test.SimpleComponent.Parent.set1("
161                               + "String, Integer)"))
162                   .onSource(componentFile)
163                   .onLineContaining("interface Builder");
164             });
165   }
166 
167   @Test
testSetterReturningNonVoidOrBuilderFails()168   public void testSetterReturningNonVoidOrBuilderFails() {
169     Source componentFile =
170         CompilerTests.javaSource(
171             "test.SimpleComponent",
172             "package test;",
173             "",
174             "import dagger.Component;",
175             "import javax.inject.Provider;",
176             "",
177             "@Component",
178             "abstract class SimpleComponent {",
179             "  @Component.Builder",
180             "  interface Builder {",
181             "    SimpleComponent build();",
182             "    String set(Integer i);",
183             "  }",
184             "}");
185 
186     CompilerTests.daggerCompiler(componentFile)
187         .withProcessingOptions(compilerMode.processorOptions())
188         .compile(
189             subject -> {
190               subject.hasErrorCount(1);
191               subject
192                   .hasErrorContaining(MSGS.setterMethodsMustReturnVoidOrBuilder())
193                   .onSource(componentFile)
194                   .onLineContaining("String set(Integer i);");
195             });
196   }
197 
198   @Test
testInheritedSetterReturningNonVoidOrBuilderFails()199   public void testInheritedSetterReturningNonVoidOrBuilderFails() {
200     Source componentFile =
201         CompilerTests.javaSource(
202             "test.SimpleComponent",
203             "package test;",
204             "",
205             "import dagger.Component;",
206             "import javax.inject.Provider;",
207             "",
208             "@Component",
209             "abstract class SimpleComponent {",
210             "  interface Parent {",
211             "    SimpleComponent build();",
212             "    String set(Integer i);",
213             "  }",
214             "",
215             "  @Component.Builder",
216             "  interface Builder extends Parent {}",
217             "}");
218 
219     CompilerTests.daggerCompiler(componentFile)
220         .withProcessingOptions(compilerMode.processorOptions())
221         .compile(
222             subject -> {
223               subject.hasErrorCount(1);
224               subject
225                   .hasErrorContaining(
226                       String.format(
227                           MSGS.inheritedSetterMethodsMustReturnVoidOrBuilder(),
228                           "String test.SimpleComponent.Parent.set(Integer)"))
229                   .onSource(componentFile)
230                   .onLineContaining("interface Builder");
231             });
232   }
233 
234   @Test
testGenericsOnSetterMethodFails()235   public void testGenericsOnSetterMethodFails() {
236     Source componentFile =
237         CompilerTests.javaSource(
238             "test.SimpleComponent",
239             "package test;",
240             "",
241             "import dagger.Component;",
242             "import javax.inject.Provider;",
243             "",
244             "@Component",
245             "abstract class SimpleComponent {",
246             "  @Component.Builder",
247             "  interface Builder {",
248             "    SimpleComponent build();",
249             "    <T> Builder set(T t);",
250             "  }",
251             "}");
252 
253     CompilerTests.daggerCompiler(componentFile)
254         .withProcessingOptions(compilerMode.processorOptions())
255         .compile(
256             subject -> {
257               subject.hasErrorCount(1);
258               subject
259                   .hasErrorContaining(MSGS.methodsMayNotHaveTypeParameters())
260                   .onSource(componentFile)
261                   .onLineContaining("<T> Builder set(T t);");
262             });
263   }
264 
265   @Test
testGenericsOnInheritedSetterMethodFails()266   public void testGenericsOnInheritedSetterMethodFails() {
267     Source componentFile =
268         CompilerTests.javaSource(
269             "test.SimpleComponent",
270             "package test;",
271             "",
272             "import dagger.Component;",
273             "import javax.inject.Provider;",
274             "",
275             "@Component",
276             "abstract class SimpleComponent {",
277             "  interface Parent {",
278             "    SimpleComponent build();",
279             "    <T> Builder set(T t);",
280             "  }",
281             "",
282             "  @Component.Builder",
283             "  interface Builder extends Parent {}",
284             "}");
285 
286     CompilerTests.daggerCompiler(componentFile)
287         .withProcessingOptions(compilerMode.processorOptions())
288         .compile(
289             subject -> {
290               subject.hasErrorCount(1);
291               subject
292                   .hasErrorContaining(
293                       String.format(
294                           MSGS.inheritedMethodsMayNotHaveTypeParameters(),
295                           "test.SimpleComponent.Builder test.SimpleComponent.Parent.set(T)"))
296                   .onSource(componentFile)
297                   .onLineContaining("interface Builder");
298             });
299   }
300 
301   @Test
testBindsInstanceNotAllowedOnBothSetterAndParameter()302   public void testBindsInstanceNotAllowedOnBothSetterAndParameter() {
303     Source componentFile =
304         CompilerTests.javaSource(
305             "test.SimpleComponent",
306             "package test;",
307             "",
308             "import dagger.BindsInstance;",
309             "import dagger.Component;",
310             "",
311             "@Component",
312             "abstract class SimpleComponent {",
313             "  abstract String s();",
314             "",
315             "  @Component.Builder",
316             "  interface Builder {",
317             "    @BindsInstance",
318             "    Builder s(@BindsInstance String s);",
319             "",
320             "    SimpleComponent build();",
321             "  }",
322             "}");
323 
324     CompilerTests.daggerCompiler(componentFile)
325         .withProcessingOptions(compilerMode.processorOptions())
326         .compile(
327             subject -> {
328               subject.hasErrorCount(1);
329               subject
330                   .hasErrorContaining(MSGS.bindsInstanceNotAllowedOnBothSetterMethodAndParameter())
331                   .onSource(componentFile)
332                   .onLineContaining("Builder s(");
333             });
334   }
335 
336   @Test
testBindsInstanceNotAllowedOnBothSetterAndParameter_inherited()337   public void testBindsInstanceNotAllowedOnBothSetterAndParameter_inherited() {
338     Source componentFile =
339         CompilerTests.javaSource(
340             "test.SimpleComponent",
341             "package test;",
342             "",
343             "import dagger.BindsInstance;",
344             "import dagger.Component;",
345             "",
346             "@Component",
347             "abstract class SimpleComponent {",
348             "  abstract String s();",
349             "",
350             "  interface BuilderParent<B extends BuilderParent> {",
351             "    @BindsInstance",
352             "    B s(@BindsInstance String s);",
353             "  }",
354             "",
355             "  @Component.Builder",
356             "  interface Builder extends BuilderParent<Builder> {",
357             "    SimpleComponent build();",
358             "  }",
359             "}");
360 
361     CompilerTests.daggerCompiler(componentFile)
362         .withProcessingOptions(compilerMode.processorOptions())
363         .compile(
364             subject -> {
365               subject.hasErrorCount(1);
366               subject
367                   .hasErrorContaining(
368                       String.format(
369                           MSGS.inheritedBindsInstanceNotAllowedOnBothSetterMethodAndParameter(),
370                           "@BindsInstance B test.SimpleComponent.BuilderParent.s(String)"))
371                   .onSource(componentFile)
372                   .onLineContaining("Builder extends BuilderParent<Builder>");
373             });
374   }
375 }
376