1*f585d8a3SJacky Wang /*
2*f585d8a3SJacky Wang  * Copyright (C) 2015 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 dagger.internal.codegen.base.ComponentCreatorAnnotation.SUBCOMPONENT_BUILDER;
20*f585d8a3SJacky Wang import static dagger.internal.codegen.binding.ErrorMessages.creatorMessagesFor;
21*f585d8a3SJacky Wang 
22*f585d8a3SJacky Wang import androidx.room.compiler.processing.util.Source;
23*f585d8a3SJacky Wang import com.google.common.collect.ImmutableList;
24*f585d8a3SJacky Wang import dagger.internal.codegen.binding.ErrorMessages;
25*f585d8a3SJacky Wang import dagger.testing.compile.CompilerTests;
26*f585d8a3SJacky Wang import dagger.testing.golden.GoldenFileRule;
27*f585d8a3SJacky Wang import org.junit.Rule;
28*f585d8a3SJacky Wang import org.junit.Test;
29*f585d8a3SJacky Wang import org.junit.runner.RunWith;
30*f585d8a3SJacky Wang import org.junit.runners.Parameterized;
31*f585d8a3SJacky Wang import org.junit.runners.Parameterized.Parameters;
32*f585d8a3SJacky Wang 
33*f585d8a3SJacky Wang /** Tests for {@link dagger.Subcomponent.Builder} validation. */
34*f585d8a3SJacky Wang @RunWith(Parameterized.class)
35*f585d8a3SJacky Wang public class SubcomponentBuilderValidationTest {
36*f585d8a3SJacky Wang   @Parameters(name = "{0}")
parameters()37*f585d8a3SJacky Wang   public static ImmutableList<Object[]> parameters() {
38*f585d8a3SJacky Wang     return CompilerMode.TEST_PARAMETERS;
39*f585d8a3SJacky Wang   }
40*f585d8a3SJacky Wang 
41*f585d8a3SJacky Wang   @Rule public GoldenFileRule goldenFileRule = new GoldenFileRule();
42*f585d8a3SJacky Wang 
43*f585d8a3SJacky Wang   private final CompilerMode compilerMode;
44*f585d8a3SJacky Wang 
SubcomponentBuilderValidationTest(CompilerMode compilerMode)45*f585d8a3SJacky Wang   public SubcomponentBuilderValidationTest(CompilerMode compilerMode) {
46*f585d8a3SJacky Wang     this.compilerMode = compilerMode;
47*f585d8a3SJacky Wang   }
48*f585d8a3SJacky Wang 
49*f585d8a3SJacky Wang   private static final ErrorMessages.ComponentCreatorMessages MSGS =
50*f585d8a3SJacky Wang       creatorMessagesFor(SUBCOMPONENT_BUILDER);
51*f585d8a3SJacky Wang 
52*f585d8a3SJacky Wang   @Test
testMoreThanOneArgFails()53*f585d8a3SJacky Wang   public void testMoreThanOneArgFails() {
54*f585d8a3SJacky Wang     Source childComponentFile = CompilerTests.javaSource("test.ChildComponent",
55*f585d8a3SJacky Wang         "package test;",
56*f585d8a3SJacky Wang         "",
57*f585d8a3SJacky Wang         "import dagger.Subcomponent;",
58*f585d8a3SJacky Wang         "",
59*f585d8a3SJacky Wang         "@Subcomponent",
60*f585d8a3SJacky Wang         "abstract class ChildComponent {",
61*f585d8a3SJacky Wang         "  @Subcomponent.Builder",
62*f585d8a3SJacky Wang         "  interface Builder {",
63*f585d8a3SJacky Wang         "    ChildComponent build();",
64*f585d8a3SJacky Wang         "    Builder set(String s, Integer i);",
65*f585d8a3SJacky Wang         "    Builder set(Number n, Double d);",
66*f585d8a3SJacky Wang         "  }",
67*f585d8a3SJacky Wang         "}");
68*f585d8a3SJacky Wang 
69*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(childComponentFile)
70*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
71*f585d8a3SJacky Wang         .compile(
72*f585d8a3SJacky Wang             subject -> {
73*f585d8a3SJacky Wang               subject.hasErrorCount(2);
74*f585d8a3SJacky Wang               subject
75*f585d8a3SJacky Wang                   .hasErrorContaining(MSGS.setterMethodsMustTakeOneArg())
76*f585d8a3SJacky Wang                   .onSource(childComponentFile)
77*f585d8a3SJacky Wang                   .onLine(10);
78*f585d8a3SJacky Wang               subject
79*f585d8a3SJacky Wang                   .hasErrorContaining(MSGS.setterMethodsMustTakeOneArg())
80*f585d8a3SJacky Wang                   .onSource(childComponentFile)
81*f585d8a3SJacky Wang                   .onLine(11);
82*f585d8a3SJacky Wang             });
83*f585d8a3SJacky Wang   }
84*f585d8a3SJacky Wang 
85*f585d8a3SJacky Wang   @Test
testInheritedMoreThanOneArgFails()86*f585d8a3SJacky Wang   public void testInheritedMoreThanOneArgFails() {
87*f585d8a3SJacky Wang      Source childComponentFile = CompilerTests.javaSource("test.ChildComponent",
88*f585d8a3SJacky Wang         "package test;",
89*f585d8a3SJacky Wang         "",
90*f585d8a3SJacky Wang         "import dagger.Subcomponent;",
91*f585d8a3SJacky Wang         "",
92*f585d8a3SJacky Wang         "@Subcomponent",
93*f585d8a3SJacky Wang         "abstract class ChildComponent {",
94*f585d8a3SJacky Wang         "  interface Parent {",
95*f585d8a3SJacky Wang         "    ChildComponent build();",
96*f585d8a3SJacky Wang         "    Builder set1(String s, Integer i);",
97*f585d8a3SJacky Wang         "  }",
98*f585d8a3SJacky Wang         "",
99*f585d8a3SJacky Wang         "  @Subcomponent.Builder",
100*f585d8a3SJacky Wang         "  interface Builder extends Parent {}",
101*f585d8a3SJacky Wang         "}");
102*f585d8a3SJacky Wang 
103*f585d8a3SJacky Wang     String expectedErrorMsg =
104*f585d8a3SJacky Wang         String.format(
105*f585d8a3SJacky Wang             MSGS.inheritedSetterMethodsMustTakeOneArg(),
106*f585d8a3SJacky Wang             "test.ChildComponent.Builder test.ChildComponent.Parent.set1(String, Integer)");
107*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(childComponentFile)
108*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
109*f585d8a3SJacky Wang         .compile(
110*f585d8a3SJacky Wang             subject -> {
111*f585d8a3SJacky Wang               subject.hasErrorCount(1);
112*f585d8a3SJacky Wang               subject
113*f585d8a3SJacky Wang                   .hasErrorContaining(expectedErrorMsg)
114*f585d8a3SJacky Wang                   .onSource(childComponentFile)
115*f585d8a3SJacky Wang                   .onLine(13);
116*f585d8a3SJacky Wang             });
117*f585d8a3SJacky Wang   }
118*f585d8a3SJacky Wang 
119*f585d8a3SJacky Wang   @Test
testSetterReturningNonVoidOrBuilderFails()120*f585d8a3SJacky Wang   public void testSetterReturningNonVoidOrBuilderFails() {
121*f585d8a3SJacky Wang      Source childComponentFile = CompilerTests.javaSource("test.ChildComponent",
122*f585d8a3SJacky Wang         "package test;",
123*f585d8a3SJacky Wang         "",
124*f585d8a3SJacky Wang         "import dagger.Subcomponent;",
125*f585d8a3SJacky Wang         "",
126*f585d8a3SJacky Wang         "@Subcomponent",
127*f585d8a3SJacky Wang         "abstract class ChildComponent {",
128*f585d8a3SJacky Wang         "  @Subcomponent.Builder",
129*f585d8a3SJacky Wang         "  interface Builder {",
130*f585d8a3SJacky Wang         "    ChildComponent build();",
131*f585d8a3SJacky Wang         "    String set(Integer i);",
132*f585d8a3SJacky Wang         "  }",
133*f585d8a3SJacky Wang         "}");
134*f585d8a3SJacky Wang 
135*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(childComponentFile)
136*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
137*f585d8a3SJacky Wang         .compile(
138*f585d8a3SJacky Wang             subject -> {
139*f585d8a3SJacky Wang               subject.hasErrorCount(1);
140*f585d8a3SJacky Wang               subject
141*f585d8a3SJacky Wang                   .hasErrorContaining(MSGS.setterMethodsMustReturnVoidOrBuilder())
142*f585d8a3SJacky Wang                   .onSource(childComponentFile)
143*f585d8a3SJacky Wang                   .onLine(10);
144*f585d8a3SJacky Wang             });
145*f585d8a3SJacky Wang   }
146*f585d8a3SJacky Wang 
147*f585d8a3SJacky Wang   @Test
testInheritedSetterReturningNonVoidOrBuilderFails()148*f585d8a3SJacky Wang   public void testInheritedSetterReturningNonVoidOrBuilderFails() {
149*f585d8a3SJacky Wang      Source childComponentFile = CompilerTests.javaSource("test.ChildComponent",
150*f585d8a3SJacky Wang         "package test;",
151*f585d8a3SJacky Wang         "",
152*f585d8a3SJacky Wang         "import dagger.Subcomponent;",
153*f585d8a3SJacky Wang         "",
154*f585d8a3SJacky Wang         "@Subcomponent",
155*f585d8a3SJacky Wang         "abstract class ChildComponent {",
156*f585d8a3SJacky Wang         "  interface Parent {",
157*f585d8a3SJacky Wang         "    ChildComponent build();",
158*f585d8a3SJacky Wang         "    String set(Integer i);",
159*f585d8a3SJacky Wang         "  }",
160*f585d8a3SJacky Wang         "",
161*f585d8a3SJacky Wang         "  @Subcomponent.Builder",
162*f585d8a3SJacky Wang         "  interface Builder extends Parent {}",
163*f585d8a3SJacky Wang         "}");
164*f585d8a3SJacky Wang 
165*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(childComponentFile)
166*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
167*f585d8a3SJacky Wang         .compile(
168*f585d8a3SJacky Wang             subject -> {
169*f585d8a3SJacky Wang               subject.hasErrorCount(1);
170*f585d8a3SJacky Wang               subject
171*f585d8a3SJacky Wang                   .hasErrorContaining(
172*f585d8a3SJacky Wang                       String.format(
173*f585d8a3SJacky Wang                           MSGS.inheritedSetterMethodsMustReturnVoidOrBuilder(),
174*f585d8a3SJacky Wang                           "String test.ChildComponent.Parent.set(Integer)"))
175*f585d8a3SJacky Wang                   .onSource(childComponentFile)
176*f585d8a3SJacky Wang                   .onLine(13);
177*f585d8a3SJacky Wang             });
178*f585d8a3SJacky Wang   }
179*f585d8a3SJacky Wang 
180*f585d8a3SJacky Wang   @Test
testGenericsOnSetterMethodFails()181*f585d8a3SJacky Wang   public void testGenericsOnSetterMethodFails() {
182*f585d8a3SJacky Wang      Source childComponentFile = CompilerTests.javaSource("test.ChildComponent",
183*f585d8a3SJacky Wang         "package test;",
184*f585d8a3SJacky Wang         "",
185*f585d8a3SJacky Wang         "import dagger.Subcomponent;",
186*f585d8a3SJacky Wang         "",
187*f585d8a3SJacky Wang         "@Subcomponent",
188*f585d8a3SJacky Wang         "abstract class ChildComponent {",
189*f585d8a3SJacky Wang         "  @Subcomponent.Builder",
190*f585d8a3SJacky Wang         "  interface Builder {",
191*f585d8a3SJacky Wang         "    ChildComponent build();",
192*f585d8a3SJacky Wang         "    <T> Builder set(T t);",
193*f585d8a3SJacky Wang         "  }",
194*f585d8a3SJacky Wang         "}");
195*f585d8a3SJacky Wang 
196*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(childComponentFile)
197*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
198*f585d8a3SJacky Wang         .compile(
199*f585d8a3SJacky Wang             subject -> {
200*f585d8a3SJacky Wang               subject.hasErrorCount(1);
201*f585d8a3SJacky Wang               subject
202*f585d8a3SJacky Wang                   .hasErrorContaining(MSGS.methodsMayNotHaveTypeParameters())
203*f585d8a3SJacky Wang                   .onSource(childComponentFile)
204*f585d8a3SJacky Wang                   .onLine(10);
205*f585d8a3SJacky Wang             });
206*f585d8a3SJacky Wang   }
207*f585d8a3SJacky Wang 
208*f585d8a3SJacky Wang   @Test
testGenericsOnInheritedSetterMethodFails()209*f585d8a3SJacky Wang   public void testGenericsOnInheritedSetterMethodFails() {
210*f585d8a3SJacky Wang      Source childComponentFile = CompilerTests.javaSource("test.ChildComponent",
211*f585d8a3SJacky Wang         "package test;",
212*f585d8a3SJacky Wang         "",
213*f585d8a3SJacky Wang         "import dagger.Subcomponent;",
214*f585d8a3SJacky Wang         "",
215*f585d8a3SJacky Wang         "@Subcomponent",
216*f585d8a3SJacky Wang         "abstract class ChildComponent {",
217*f585d8a3SJacky Wang         "  interface Parent {",
218*f585d8a3SJacky Wang         "    ChildComponent build();",
219*f585d8a3SJacky Wang         "    <T> Builder set(T t);",
220*f585d8a3SJacky Wang         "  }",
221*f585d8a3SJacky Wang         "",
222*f585d8a3SJacky Wang         "  @Subcomponent.Builder",
223*f585d8a3SJacky Wang         "  interface Builder extends Parent {}",
224*f585d8a3SJacky Wang         "}");
225*f585d8a3SJacky Wang 
226*f585d8a3SJacky Wang     CompilerTests.daggerCompiler(childComponentFile)
227*f585d8a3SJacky Wang         .withProcessingOptions(compilerMode.processorOptions())
228*f585d8a3SJacky Wang         .compile(
229*f585d8a3SJacky Wang             subject -> {
230*f585d8a3SJacky Wang               subject.hasErrorCount(1);
231*f585d8a3SJacky Wang               subject
232*f585d8a3SJacky Wang                   .hasErrorContaining(
233*f585d8a3SJacky Wang                       String.format(
234*f585d8a3SJacky Wang                           MSGS.inheritedMethodsMayNotHaveTypeParameters(),
235*f585d8a3SJacky Wang                           "test.ChildComponent.Builder test.ChildComponent.Parent.set(T)"))
236*f585d8a3SJacky Wang                   .onSource(childComponentFile)
237*f585d8a3SJacky Wang                   .onLine(13);
238*f585d8a3SJacky Wang             });
239*f585d8a3SJacky Wang   }
240*f585d8a3SJacky Wang }
241