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 androidx.room.compiler.processing.util.Source; 20*f585d8a3SJacky Wang import com.squareup.javapoet.MethodSpec; 21*f585d8a3SJacky Wang import com.squareup.javapoet.TypeSpec; 22*f585d8a3SJacky Wang import dagger.internal.codegen.javapoet.TypeNames; 23*f585d8a3SJacky Wang import dagger.testing.compile.CompilerTests; 24*f585d8a3SJacky Wang import dagger.testing.golden.GoldenFileRule; 25*f585d8a3SJacky Wang import java.util.Collection; 26*f585d8a3SJacky Wang import org.junit.Rule; 27*f585d8a3SJacky Wang import org.junit.Test; 28*f585d8a3SJacky Wang import org.junit.runner.RunWith; 29*f585d8a3SJacky Wang import org.junit.runners.Parameterized; 30*f585d8a3SJacky Wang import org.junit.runners.Parameterized.Parameters; 31*f585d8a3SJacky Wang 32*f585d8a3SJacky Wang @RunWith(Parameterized.class) 33*f585d8a3SJacky Wang public class SubcomponentValidationTest { 34*f585d8a3SJacky Wang @Parameters(name = "{0}") parameters()35*f585d8a3SJacky Wang public static Collection<Object[]> parameters() { 36*f585d8a3SJacky Wang return CompilerMode.TEST_PARAMETERS; 37*f585d8a3SJacky Wang } 38*f585d8a3SJacky Wang 39*f585d8a3SJacky Wang private final CompilerMode compilerMode; 40*f585d8a3SJacky Wang SubcomponentValidationTest(CompilerMode compilerMode)41*f585d8a3SJacky Wang public SubcomponentValidationTest(CompilerMode compilerMode) { 42*f585d8a3SJacky Wang this.compilerMode = compilerMode; 43*f585d8a3SJacky Wang } 44*f585d8a3SJacky Wang 45*f585d8a3SJacky Wang @Rule public GoldenFileRule goldenFileRule = new GoldenFileRule(); 46*f585d8a3SJacky Wang factoryMethod_missingModulesWithParameters()47*f585d8a3SJacky Wang @Test public void factoryMethod_missingModulesWithParameters() { 48*f585d8a3SJacky Wang Source componentFile = 49*f585d8a3SJacky Wang CompilerTests.javaSource( 50*f585d8a3SJacky Wang "test.TestComponent", 51*f585d8a3SJacky Wang "package test;", 52*f585d8a3SJacky Wang "", 53*f585d8a3SJacky Wang "import dagger.Component;", 54*f585d8a3SJacky Wang "", 55*f585d8a3SJacky Wang "@Component", 56*f585d8a3SJacky Wang "interface TestComponent {", 57*f585d8a3SJacky Wang " ChildComponent newChildComponent();", 58*f585d8a3SJacky Wang "}"); 59*f585d8a3SJacky Wang Source childComponentFile = 60*f585d8a3SJacky Wang CompilerTests.javaSource( 61*f585d8a3SJacky Wang "test.ChildComponent", 62*f585d8a3SJacky Wang "package test;", 63*f585d8a3SJacky Wang "", 64*f585d8a3SJacky Wang "import dagger.Subcomponent;", 65*f585d8a3SJacky Wang "", 66*f585d8a3SJacky Wang "@Subcomponent(modules = ModuleWithParameters.class)", 67*f585d8a3SJacky Wang "interface ChildComponent {", 68*f585d8a3SJacky Wang " Object object();", 69*f585d8a3SJacky Wang "}"); 70*f585d8a3SJacky Wang Source moduleFile = 71*f585d8a3SJacky Wang CompilerTests.javaSource( 72*f585d8a3SJacky Wang "test.ModuleWithParameters", 73*f585d8a3SJacky Wang "package test;", 74*f585d8a3SJacky Wang "", 75*f585d8a3SJacky Wang "import dagger.Module;", 76*f585d8a3SJacky Wang "import dagger.Provides;", 77*f585d8a3SJacky Wang "", 78*f585d8a3SJacky Wang "@Module", 79*f585d8a3SJacky Wang "final class ModuleWithParameters {", 80*f585d8a3SJacky Wang " private final Object object;", 81*f585d8a3SJacky Wang "", 82*f585d8a3SJacky Wang " ModuleWithParameters(Object object) {", 83*f585d8a3SJacky Wang " this.object = object;", 84*f585d8a3SJacky Wang " }", 85*f585d8a3SJacky Wang "", 86*f585d8a3SJacky Wang " @Provides Object object() {", 87*f585d8a3SJacky Wang " return object;", 88*f585d8a3SJacky Wang " }", 89*f585d8a3SJacky Wang "}"); 90*f585d8a3SJacky Wang CompilerTests.daggerCompiler(componentFile, childComponentFile, moduleFile) 91*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 92*f585d8a3SJacky Wang .compile( 93*f585d8a3SJacky Wang subject -> { 94*f585d8a3SJacky Wang subject.hasErrorCount(1); 95*f585d8a3SJacky Wang subject.hasErrorContaining( 96*f585d8a3SJacky Wang "test.ChildComponent requires modules which have no visible default " 97*f585d8a3SJacky Wang + "constructors. Add the following modules as parameters to this method: " 98*f585d8a3SJacky Wang + "test.ModuleWithParameters") 99*f585d8a3SJacky Wang .onSource(componentFile) 100*f585d8a3SJacky Wang .onLineContaining("ChildComponent newChildComponent();"); 101*f585d8a3SJacky Wang }); 102*f585d8a3SJacky Wang } 103*f585d8a3SJacky Wang 104*f585d8a3SJacky Wang @Test factoryMethod_grandchild()105*f585d8a3SJacky Wang public void factoryMethod_grandchild() { 106*f585d8a3SJacky Wang Source component = 107*f585d8a3SJacky Wang CompilerTests.javaSource( 108*f585d8a3SJacky Wang "test.TestComponent", 109*f585d8a3SJacky Wang "package test;", 110*f585d8a3SJacky Wang "", 111*f585d8a3SJacky Wang "import dagger.Component;", 112*f585d8a3SJacky Wang "", 113*f585d8a3SJacky Wang "@Component", 114*f585d8a3SJacky Wang "interface TestComponent {", 115*f585d8a3SJacky Wang " ChildComponent newChildComponent();", 116*f585d8a3SJacky Wang "}"); 117*f585d8a3SJacky Wang Source childComponent = 118*f585d8a3SJacky Wang CompilerTests.javaSource( 119*f585d8a3SJacky Wang "test.ChildComponent", 120*f585d8a3SJacky Wang "package test;", 121*f585d8a3SJacky Wang "", 122*f585d8a3SJacky Wang "import dagger.Subcomponent;", 123*f585d8a3SJacky Wang "", 124*f585d8a3SJacky Wang "@Subcomponent", 125*f585d8a3SJacky Wang "interface ChildComponent {", 126*f585d8a3SJacky Wang " GrandchildComponent newGrandchildComponent();", 127*f585d8a3SJacky Wang "}"); 128*f585d8a3SJacky Wang Source grandchildComponent = 129*f585d8a3SJacky Wang CompilerTests.javaSource( 130*f585d8a3SJacky Wang "test.GrandchildComponent", 131*f585d8a3SJacky Wang "package test;", 132*f585d8a3SJacky Wang "", 133*f585d8a3SJacky Wang "import dagger.Subcomponent;", 134*f585d8a3SJacky Wang "", 135*f585d8a3SJacky Wang "@Subcomponent(modules = GrandchildModule.class)", 136*f585d8a3SJacky Wang "interface GrandchildComponent {", 137*f585d8a3SJacky Wang " Object object();", 138*f585d8a3SJacky Wang "}"); 139*f585d8a3SJacky Wang Source grandchildModule = 140*f585d8a3SJacky Wang CompilerTests.javaSource( 141*f585d8a3SJacky Wang "test.GrandchildModule", 142*f585d8a3SJacky Wang "package test;", 143*f585d8a3SJacky Wang "", 144*f585d8a3SJacky Wang "import dagger.Module;", 145*f585d8a3SJacky Wang "import dagger.Provides;", 146*f585d8a3SJacky Wang "", 147*f585d8a3SJacky Wang "@Module", 148*f585d8a3SJacky Wang "final class GrandchildModule {", 149*f585d8a3SJacky Wang " private final Object object;", 150*f585d8a3SJacky Wang "", 151*f585d8a3SJacky Wang " GrandchildModule(Object object) {", 152*f585d8a3SJacky Wang " this.object = object;", 153*f585d8a3SJacky Wang " }", 154*f585d8a3SJacky Wang "", 155*f585d8a3SJacky Wang " @Provides Object object() {", 156*f585d8a3SJacky Wang " return object;", 157*f585d8a3SJacky Wang " }", 158*f585d8a3SJacky Wang "}"); 159*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component, childComponent, grandchildComponent, grandchildModule) 160*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 161*f585d8a3SJacky Wang .compile( 162*f585d8a3SJacky Wang subject -> { 163*f585d8a3SJacky Wang subject.hasErrorCount(1); 164*f585d8a3SJacky Wang subject.hasErrorContaining( 165*f585d8a3SJacky Wang "[ChildComponent.newGrandchildComponent()] " 166*f585d8a3SJacky Wang + "GrandchildComponent requires modules which have no visible default " 167*f585d8a3SJacky Wang + "constructors. Add the following modules as parameters to this method: " 168*f585d8a3SJacky Wang + "GrandchildModule") 169*f585d8a3SJacky Wang .onSource(component) 170*f585d8a3SJacky Wang .onLineContaining("interface TestComponent"); 171*f585d8a3SJacky Wang }); 172*f585d8a3SJacky Wang } 173*f585d8a3SJacky Wang factoryMethod_nonModuleParameter()174*f585d8a3SJacky Wang @Test public void factoryMethod_nonModuleParameter() { 175*f585d8a3SJacky Wang Source componentFile = 176*f585d8a3SJacky Wang CompilerTests.javaSource("test.TestComponent", 177*f585d8a3SJacky Wang "package test;", 178*f585d8a3SJacky Wang "", 179*f585d8a3SJacky Wang "import dagger.Component;", 180*f585d8a3SJacky Wang "", 181*f585d8a3SJacky Wang "@Component", 182*f585d8a3SJacky Wang "interface TestComponent {", 183*f585d8a3SJacky Wang " ChildComponent newChildComponent(String someRandomString);", 184*f585d8a3SJacky Wang "}"); 185*f585d8a3SJacky Wang Source childComponentFile = 186*f585d8a3SJacky Wang CompilerTests.javaSource("test.ChildComponent", 187*f585d8a3SJacky Wang "package test;", 188*f585d8a3SJacky Wang "", 189*f585d8a3SJacky Wang "import dagger.Subcomponent;", 190*f585d8a3SJacky Wang "", 191*f585d8a3SJacky Wang "@Subcomponent", 192*f585d8a3SJacky Wang "interface ChildComponent {}"); 193*f585d8a3SJacky Wang CompilerTests.daggerCompiler(componentFile, childComponentFile) 194*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 195*f585d8a3SJacky Wang .compile( 196*f585d8a3SJacky Wang subject -> { 197*f585d8a3SJacky Wang subject.hasErrorCount(1); 198*f585d8a3SJacky Wang subject.hasErrorContaining( 199*f585d8a3SJacky Wang "Subcomponent factory methods may only accept modules, but java.lang.String " 200*f585d8a3SJacky Wang + "is not.") 201*f585d8a3SJacky Wang .onSource(componentFile) 202*f585d8a3SJacky Wang .onLine(7); 203*f585d8a3SJacky Wang }); 204*f585d8a3SJacky Wang } 205*f585d8a3SJacky Wang factoryMethod_duplicateParameter()206*f585d8a3SJacky Wang @Test public void factoryMethod_duplicateParameter() { 207*f585d8a3SJacky Wang Source moduleFile = 208*f585d8a3SJacky Wang CompilerTests.javaSource("test.TestModule", 209*f585d8a3SJacky Wang "package test;", 210*f585d8a3SJacky Wang "", 211*f585d8a3SJacky Wang "import dagger.Module;", 212*f585d8a3SJacky Wang "", 213*f585d8a3SJacky Wang "@Module", 214*f585d8a3SJacky Wang "final class TestModule {}"); 215*f585d8a3SJacky Wang Source componentFile = 216*f585d8a3SJacky Wang CompilerTests.javaSource("test.TestComponent", 217*f585d8a3SJacky Wang "package test;", 218*f585d8a3SJacky Wang "", 219*f585d8a3SJacky Wang "import dagger.Component;", 220*f585d8a3SJacky Wang "", 221*f585d8a3SJacky Wang "@Component", 222*f585d8a3SJacky Wang "interface TestComponent {", 223*f585d8a3SJacky Wang " ChildComponent newChildComponent(TestModule testModule1, TestModule testModule2);", 224*f585d8a3SJacky Wang "}"); 225*f585d8a3SJacky Wang Source childComponentFile = 226*f585d8a3SJacky Wang CompilerTests.javaSource("test.ChildComponent", 227*f585d8a3SJacky Wang "package test;", 228*f585d8a3SJacky Wang "", 229*f585d8a3SJacky Wang "import dagger.Subcomponent;", 230*f585d8a3SJacky Wang "", 231*f585d8a3SJacky Wang "@Subcomponent(modules = TestModule.class)", 232*f585d8a3SJacky Wang "interface ChildComponent {}"); 233*f585d8a3SJacky Wang CompilerTests.daggerCompiler(componentFile, childComponentFile, moduleFile) 234*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 235*f585d8a3SJacky Wang .compile( 236*f585d8a3SJacky Wang subject -> { 237*f585d8a3SJacky Wang subject.hasErrorCount(1); 238*f585d8a3SJacky Wang subject.hasErrorContaining( 239*f585d8a3SJacky Wang "A module may only occur once as an argument in a Subcomponent factory " 240*f585d8a3SJacky Wang + "method, but test.TestModule was already passed.") 241*f585d8a3SJacky Wang .onSource(componentFile) 242*f585d8a3SJacky Wang .onLine(7); 243*f585d8a3SJacky Wang }); 244*f585d8a3SJacky Wang } 245*f585d8a3SJacky Wang factoryMethod_superflouousModule()246*f585d8a3SJacky Wang @Test public void factoryMethod_superflouousModule() { 247*f585d8a3SJacky Wang Source moduleFile = 248*f585d8a3SJacky Wang CompilerTests.javaSource("test.TestModule", 249*f585d8a3SJacky Wang "package test;", 250*f585d8a3SJacky Wang "", 251*f585d8a3SJacky Wang "import dagger.Module;", 252*f585d8a3SJacky Wang "", 253*f585d8a3SJacky Wang "@Module", 254*f585d8a3SJacky Wang "final class TestModule {}"); 255*f585d8a3SJacky Wang Source componentFile = 256*f585d8a3SJacky Wang CompilerTests.javaSource("test.TestComponent", 257*f585d8a3SJacky Wang "package test;", 258*f585d8a3SJacky Wang "", 259*f585d8a3SJacky Wang "import dagger.Component;", 260*f585d8a3SJacky Wang "", 261*f585d8a3SJacky Wang "@Component", 262*f585d8a3SJacky Wang "interface TestComponent {", 263*f585d8a3SJacky Wang " ChildComponent newChildComponent(TestModule testModule);", 264*f585d8a3SJacky Wang "}"); 265*f585d8a3SJacky Wang Source childComponentFile = 266*f585d8a3SJacky Wang CompilerTests.javaSource("test.ChildComponent", 267*f585d8a3SJacky Wang "package test;", 268*f585d8a3SJacky Wang "", 269*f585d8a3SJacky Wang "import dagger.Subcomponent;", 270*f585d8a3SJacky Wang "", 271*f585d8a3SJacky Wang "@Subcomponent", 272*f585d8a3SJacky Wang "interface ChildComponent {}"); 273*f585d8a3SJacky Wang CompilerTests.daggerCompiler(moduleFile, componentFile, childComponentFile) 274*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 275*f585d8a3SJacky Wang .compile( 276*f585d8a3SJacky Wang subject -> { 277*f585d8a3SJacky Wang subject.hasErrorCount(1); 278*f585d8a3SJacky Wang subject.hasErrorContaining( 279*f585d8a3SJacky Wang "test.TestModule is present as an argument to the test.ChildComponent " 280*f585d8a3SJacky Wang + "factory method, but is not one of the modules used to implement the " 281*f585d8a3SJacky Wang + "subcomponent.") 282*f585d8a3SJacky Wang .onSource(componentFile) 283*f585d8a3SJacky Wang .onLine(7); 284*f585d8a3SJacky Wang }); 285*f585d8a3SJacky Wang } 286*f585d8a3SJacky Wang missingBinding()287*f585d8a3SJacky Wang @Test public void missingBinding() { 288*f585d8a3SJacky Wang Source moduleFile = 289*f585d8a3SJacky Wang CompilerTests.javaSource("test.TestModule", 290*f585d8a3SJacky Wang "package test;", 291*f585d8a3SJacky Wang "", 292*f585d8a3SJacky Wang "import dagger.Module;", 293*f585d8a3SJacky Wang "import dagger.Provides;", 294*f585d8a3SJacky Wang "", 295*f585d8a3SJacky Wang "@Module", 296*f585d8a3SJacky Wang "final class TestModule {", 297*f585d8a3SJacky Wang " @Provides String provideString(int i) {", 298*f585d8a3SJacky Wang " return Integer.toString(i);", 299*f585d8a3SJacky Wang " }", 300*f585d8a3SJacky Wang "}"); 301*f585d8a3SJacky Wang Source componentFile = 302*f585d8a3SJacky Wang CompilerTests.javaSource("test.TestComponent", 303*f585d8a3SJacky Wang "package test;", 304*f585d8a3SJacky Wang "", 305*f585d8a3SJacky Wang "import dagger.Component;", 306*f585d8a3SJacky Wang "", 307*f585d8a3SJacky Wang "@Component", 308*f585d8a3SJacky Wang "interface TestComponent {", 309*f585d8a3SJacky Wang " ChildComponent newChildComponent();", 310*f585d8a3SJacky Wang "}"); 311*f585d8a3SJacky Wang Source childComponentFile = 312*f585d8a3SJacky Wang CompilerTests.javaSource("test.ChildComponent", 313*f585d8a3SJacky Wang "package test;", 314*f585d8a3SJacky Wang "", 315*f585d8a3SJacky Wang "import dagger.Subcomponent;", 316*f585d8a3SJacky Wang "", 317*f585d8a3SJacky Wang "@Subcomponent(modules = TestModule.class)", 318*f585d8a3SJacky Wang "interface ChildComponent {", 319*f585d8a3SJacky Wang " String string();", 320*f585d8a3SJacky Wang "}"); 321*f585d8a3SJacky Wang CompilerTests.daggerCompiler(moduleFile, componentFile, childComponentFile) 322*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 323*f585d8a3SJacky Wang .compile( 324*f585d8a3SJacky Wang subject -> { 325*f585d8a3SJacky Wang subject.hasErrorCount(1); 326*f585d8a3SJacky Wang subject.hasErrorContaining( 327*f585d8a3SJacky Wang "Integer cannot be provided without an @Inject constructor or an " 328*f585d8a3SJacky Wang + "@Provides-annotated method") 329*f585d8a3SJacky Wang .onSource(componentFile) 330*f585d8a3SJacky Wang .onLineContaining("interface TestComponent"); 331*f585d8a3SJacky Wang }); 332*f585d8a3SJacky Wang } 333*f585d8a3SJacky Wang subcomponentOnConcreteType()334*f585d8a3SJacky Wang @Test public void subcomponentOnConcreteType() { 335*f585d8a3SJacky Wang Source subcomponentFile = 336*f585d8a3SJacky Wang CompilerTests.javaSource("test.NotASubcomponent", 337*f585d8a3SJacky Wang "package test;", 338*f585d8a3SJacky Wang "", 339*f585d8a3SJacky Wang "import dagger.Subcomponent;", 340*f585d8a3SJacky Wang "", 341*f585d8a3SJacky Wang "@Subcomponent", 342*f585d8a3SJacky Wang "final class NotASubcomponent {}"); 343*f585d8a3SJacky Wang CompilerTests.daggerCompiler(subcomponentFile) 344*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 345*f585d8a3SJacky Wang .compile( 346*f585d8a3SJacky Wang subject -> { 347*f585d8a3SJacky Wang subject.hasErrorCount(1); 348*f585d8a3SJacky Wang subject.hasErrorContaining("interface"); 349*f585d8a3SJacky Wang }); 350*f585d8a3SJacky Wang } 351*f585d8a3SJacky Wang scopeMismatch()352*f585d8a3SJacky Wang @Test public void scopeMismatch() { 353*f585d8a3SJacky Wang Source componentFile = 354*f585d8a3SJacky Wang CompilerTests.javaSource("test.ParentComponent", 355*f585d8a3SJacky Wang "package test;", 356*f585d8a3SJacky Wang "", 357*f585d8a3SJacky Wang "import dagger.Component;", 358*f585d8a3SJacky Wang "import javax.inject.Singleton;", 359*f585d8a3SJacky Wang "", 360*f585d8a3SJacky Wang "@Component", 361*f585d8a3SJacky Wang "@Singleton", 362*f585d8a3SJacky Wang "interface ParentComponent {", 363*f585d8a3SJacky Wang " ChildComponent childComponent();", 364*f585d8a3SJacky Wang "}"); 365*f585d8a3SJacky Wang Source subcomponentFile = 366*f585d8a3SJacky Wang CompilerTests.javaSource("test.ChildComponent", 367*f585d8a3SJacky Wang "package test;", 368*f585d8a3SJacky Wang "", 369*f585d8a3SJacky Wang "import dagger.Subcomponent;", 370*f585d8a3SJacky Wang "", 371*f585d8a3SJacky Wang "@Subcomponent(modules = ChildModule.class)", 372*f585d8a3SJacky Wang "interface ChildComponent {", 373*f585d8a3SJacky Wang " Object object();", 374*f585d8a3SJacky Wang "}"); 375*f585d8a3SJacky Wang Source moduleFile = 376*f585d8a3SJacky Wang CompilerTests.javaSource("test.ChildModule", 377*f585d8a3SJacky Wang "package test;", 378*f585d8a3SJacky Wang "", 379*f585d8a3SJacky Wang "import dagger.Module;", 380*f585d8a3SJacky Wang "import dagger.Provides;", 381*f585d8a3SJacky Wang "import javax.inject.Singleton;", 382*f585d8a3SJacky Wang "", 383*f585d8a3SJacky Wang "@Module", 384*f585d8a3SJacky Wang "final class ChildModule {", 385*f585d8a3SJacky Wang " @Provides @Singleton Object provideObject() { return null; }", 386*f585d8a3SJacky Wang "}"); 387*f585d8a3SJacky Wang CompilerTests.daggerCompiler(componentFile, subcomponentFile, moduleFile) 388*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 389*f585d8a3SJacky Wang .compile( 390*f585d8a3SJacky Wang subject -> { 391*f585d8a3SJacky Wang subject.hasErrorCount(1); 392*f585d8a3SJacky Wang subject.hasErrorContaining("@Singleton"); 393*f585d8a3SJacky Wang }); 394*f585d8a3SJacky Wang } 395*f585d8a3SJacky Wang 396*f585d8a3SJacky Wang @Test delegateFactoryNotCreatedForSubcomponentWhenProviderExistsInParent()397*f585d8a3SJacky Wang public void delegateFactoryNotCreatedForSubcomponentWhenProviderExistsInParent() 398*f585d8a3SJacky Wang throws Exception { 399*f585d8a3SJacky Wang Source parentComponentFile = 400*f585d8a3SJacky Wang CompilerTests.javaSource( 401*f585d8a3SJacky Wang "test.ParentComponent", 402*f585d8a3SJacky Wang "package test;", 403*f585d8a3SJacky Wang "", 404*f585d8a3SJacky Wang "import dagger.Component;", 405*f585d8a3SJacky Wang "import javax.inject.Singleton;", 406*f585d8a3SJacky Wang "", 407*f585d8a3SJacky Wang "@Singleton", 408*f585d8a3SJacky Wang "@Component", 409*f585d8a3SJacky Wang "interface ParentComponent {", 410*f585d8a3SJacky Wang " ChildComponent childComponent();", 411*f585d8a3SJacky Wang " Dep1 dep1();", 412*f585d8a3SJacky Wang " Dep2 dep2();", 413*f585d8a3SJacky Wang "}"); 414*f585d8a3SJacky Wang Source childComponentFile = 415*f585d8a3SJacky Wang CompilerTests.javaSource( 416*f585d8a3SJacky Wang "test.ChildComponent", 417*f585d8a3SJacky Wang "package test;", 418*f585d8a3SJacky Wang "", 419*f585d8a3SJacky Wang "import dagger.Subcomponent;", 420*f585d8a3SJacky Wang "", 421*f585d8a3SJacky Wang "@Subcomponent(modules = ChildModule.class)", 422*f585d8a3SJacky Wang "interface ChildComponent {", 423*f585d8a3SJacky Wang " Object object();", 424*f585d8a3SJacky Wang "}"); 425*f585d8a3SJacky Wang Source childModuleFile = 426*f585d8a3SJacky Wang CompilerTests.javaSource( 427*f585d8a3SJacky Wang "test.ChildModule", 428*f585d8a3SJacky Wang "package test;", 429*f585d8a3SJacky Wang "", 430*f585d8a3SJacky Wang "import dagger.Module;", 431*f585d8a3SJacky Wang "import dagger.Provides;", 432*f585d8a3SJacky Wang "", 433*f585d8a3SJacky Wang "@Module", 434*f585d8a3SJacky Wang "final class ChildModule {", 435*f585d8a3SJacky Wang " @Provides Object provideObject(A a) { return null; }", 436*f585d8a3SJacky Wang "}"); 437*f585d8a3SJacky Wang Source aFile = 438*f585d8a3SJacky Wang CompilerTests.javaSource( 439*f585d8a3SJacky Wang "test.A", 440*f585d8a3SJacky Wang "package test;", 441*f585d8a3SJacky Wang "", 442*f585d8a3SJacky Wang "import javax.inject.Inject;", 443*f585d8a3SJacky Wang "", 444*f585d8a3SJacky Wang "final class A {", 445*f585d8a3SJacky Wang " @Inject public A(NeedsDep1 a, Dep1 b, Dep2 c) { }", 446*f585d8a3SJacky Wang " @Inject public void methodA() { }", 447*f585d8a3SJacky Wang "}"); 448*f585d8a3SJacky Wang Source needsDep1File = 449*f585d8a3SJacky Wang CompilerTests.javaSource( 450*f585d8a3SJacky Wang "test.NeedsDep1", 451*f585d8a3SJacky Wang "package test;", 452*f585d8a3SJacky Wang "", 453*f585d8a3SJacky Wang "import javax.inject.Inject;", 454*f585d8a3SJacky Wang "", 455*f585d8a3SJacky Wang "final class NeedsDep1 {", 456*f585d8a3SJacky Wang " @Inject public NeedsDep1(Dep1 d) { }", 457*f585d8a3SJacky Wang "}"); 458*f585d8a3SJacky Wang Source dep1File = 459*f585d8a3SJacky Wang CompilerTests.javaSource( 460*f585d8a3SJacky Wang "test.Dep1", 461*f585d8a3SJacky Wang "package test;", 462*f585d8a3SJacky Wang "", 463*f585d8a3SJacky Wang "import javax.inject.Inject;", 464*f585d8a3SJacky Wang "import javax.inject.Singleton;", 465*f585d8a3SJacky Wang "", 466*f585d8a3SJacky Wang "@Singleton", 467*f585d8a3SJacky Wang "final class Dep1 {", 468*f585d8a3SJacky Wang " @Inject public Dep1() { }", 469*f585d8a3SJacky Wang " @Inject public void dep1Method() { }", 470*f585d8a3SJacky Wang "}"); 471*f585d8a3SJacky Wang Source dep2File = 472*f585d8a3SJacky Wang CompilerTests.javaSource( 473*f585d8a3SJacky Wang "test.Dep2", 474*f585d8a3SJacky Wang "package test;", 475*f585d8a3SJacky Wang "", 476*f585d8a3SJacky Wang "import javax.inject.Inject;", 477*f585d8a3SJacky Wang "import javax.inject.Singleton;", 478*f585d8a3SJacky Wang "", 479*f585d8a3SJacky Wang "@Singleton", 480*f585d8a3SJacky Wang "final class Dep2 {", 481*f585d8a3SJacky Wang " @Inject public Dep2() { }", 482*f585d8a3SJacky Wang " @Inject public void dep2Method() { }", 483*f585d8a3SJacky Wang "}"); 484*f585d8a3SJacky Wang 485*f585d8a3SJacky Wang CompilerTests.daggerCompiler( 486*f585d8a3SJacky Wang parentComponentFile, 487*f585d8a3SJacky Wang childComponentFile, 488*f585d8a3SJacky Wang childModuleFile, 489*f585d8a3SJacky Wang aFile, 490*f585d8a3SJacky Wang needsDep1File, 491*f585d8a3SJacky Wang dep1File, 492*f585d8a3SJacky Wang dep2File) 493*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 494*f585d8a3SJacky Wang .compile( 495*f585d8a3SJacky Wang subject -> { 496*f585d8a3SJacky Wang subject.hasErrorCount(0); 497*f585d8a3SJacky Wang subject.generatedSource( 498*f585d8a3SJacky Wang goldenFileRule.goldenSource("test/DaggerParentComponent")); 499*f585d8a3SJacky Wang }); 500*f585d8a3SJacky Wang } 501*f585d8a3SJacky Wang 502*f585d8a3SJacky Wang @Test multipleSubcomponentsWithSameSimpleNamesCanExistInSameComponent()503*f585d8a3SJacky Wang public void multipleSubcomponentsWithSameSimpleNamesCanExistInSameComponent() throws Exception { 504*f585d8a3SJacky Wang Source parent = 505*f585d8a3SJacky Wang CompilerTests.javaSource( 506*f585d8a3SJacky Wang "test.ParentComponent", 507*f585d8a3SJacky Wang "package test;", 508*f585d8a3SJacky Wang "", 509*f585d8a3SJacky Wang "import dagger.Component;", 510*f585d8a3SJacky Wang "", 511*f585d8a3SJacky Wang "@Component", 512*f585d8a3SJacky Wang "interface ParentComponent {", 513*f585d8a3SJacky Wang " Foo.Sub newInstanceSubcomponent();", 514*f585d8a3SJacky Wang " NoConflict newNoConflictSubcomponent();", 515*f585d8a3SJacky Wang "}"); 516*f585d8a3SJacky Wang Source foo = 517*f585d8a3SJacky Wang CompilerTests.javaSource( 518*f585d8a3SJacky Wang "test.Foo", 519*f585d8a3SJacky Wang "package test;", 520*f585d8a3SJacky Wang "", 521*f585d8a3SJacky Wang "import dagger.Subcomponent;", 522*f585d8a3SJacky Wang "", 523*f585d8a3SJacky Wang "interface Foo {", 524*f585d8a3SJacky Wang " @Subcomponent interface Sub {", 525*f585d8a3SJacky Wang " Bar.Sub newBarSubcomponent();", 526*f585d8a3SJacky Wang " }", 527*f585d8a3SJacky Wang "}"); 528*f585d8a3SJacky Wang Source bar = 529*f585d8a3SJacky Wang CompilerTests.javaSource( 530*f585d8a3SJacky Wang "test.Bar", 531*f585d8a3SJacky Wang "package test;", 532*f585d8a3SJacky Wang "", 533*f585d8a3SJacky Wang "import dagger.Subcomponent;", 534*f585d8a3SJacky Wang "", 535*f585d8a3SJacky Wang "interface Bar {", 536*f585d8a3SJacky Wang " @Subcomponent interface Sub {", 537*f585d8a3SJacky Wang " test.subpackage.Sub newSubcomponentInSubpackage();", 538*f585d8a3SJacky Wang " }", 539*f585d8a3SJacky Wang "}"); 540*f585d8a3SJacky Wang Source baz = 541*f585d8a3SJacky Wang CompilerTests.javaSource( 542*f585d8a3SJacky Wang "test.subpackage.Sub", 543*f585d8a3SJacky Wang "package test.subpackage;", 544*f585d8a3SJacky Wang "", 545*f585d8a3SJacky Wang "import dagger.Subcomponent;", 546*f585d8a3SJacky Wang "", 547*f585d8a3SJacky Wang "@Subcomponent public interface Sub {}"); 548*f585d8a3SJacky Wang Source noConflict = 549*f585d8a3SJacky Wang CompilerTests.javaSource( 550*f585d8a3SJacky Wang "test.NoConflict", 551*f585d8a3SJacky Wang "package test;", 552*f585d8a3SJacky Wang "", 553*f585d8a3SJacky Wang "import dagger.Subcomponent;", 554*f585d8a3SJacky Wang "", 555*f585d8a3SJacky Wang "@Subcomponent interface NoConflict {}"); 556*f585d8a3SJacky Wang 557*f585d8a3SJacky Wang CompilerTests.daggerCompiler(parent, foo, bar, baz, noConflict) 558*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 559*f585d8a3SJacky Wang .compile( 560*f585d8a3SJacky Wang subject -> { 561*f585d8a3SJacky Wang subject.hasErrorCount(0); 562*f585d8a3SJacky Wang subject.generatedSource( 563*f585d8a3SJacky Wang goldenFileRule.goldenSource("test/DaggerParentComponent")); 564*f585d8a3SJacky Wang }); 565*f585d8a3SJacky Wang } 566*f585d8a3SJacky Wang 567*f585d8a3SJacky Wang @Test subcomponentSimpleNamesDisambiguated()568*f585d8a3SJacky Wang public void subcomponentSimpleNamesDisambiguated() throws Exception { 569*f585d8a3SJacky Wang Source parent = 570*f585d8a3SJacky Wang CompilerTests.javaSource( 571*f585d8a3SJacky Wang "test.ParentComponent", 572*f585d8a3SJacky Wang "package test;", 573*f585d8a3SJacky Wang "", 574*f585d8a3SJacky Wang "import dagger.Component;", 575*f585d8a3SJacky Wang "", 576*f585d8a3SJacky Wang "@Component", 577*f585d8a3SJacky Wang "interface ParentComponent {", 578*f585d8a3SJacky Wang " Sub newSubcomponent();", 579*f585d8a3SJacky Wang "}"); 580*f585d8a3SJacky Wang Source sub = 581*f585d8a3SJacky Wang CompilerTests.javaSource( 582*f585d8a3SJacky Wang "test.Sub", 583*f585d8a3SJacky Wang "package test;", 584*f585d8a3SJacky Wang "", 585*f585d8a3SJacky Wang "import dagger.Subcomponent;", 586*f585d8a3SJacky Wang "", 587*f585d8a3SJacky Wang "@Subcomponent interface Sub {", 588*f585d8a3SJacky Wang " test.deep.many.levels.that.match.test.Sub newDeepSubcomponent();", 589*f585d8a3SJacky Wang "}"); 590*f585d8a3SJacky Wang Source deepSub = 591*f585d8a3SJacky Wang CompilerTests.javaSource( 592*f585d8a3SJacky Wang "test.deep.many.levels.that.match.test.Sub", 593*f585d8a3SJacky Wang "package test.deep.many.levels.that.match.test;", 594*f585d8a3SJacky Wang "", 595*f585d8a3SJacky Wang "import dagger.Subcomponent;", 596*f585d8a3SJacky Wang "", 597*f585d8a3SJacky Wang "@Subcomponent public interface Sub {}"); 598*f585d8a3SJacky Wang 599*f585d8a3SJacky Wang CompilerTests.daggerCompiler(parent, sub, deepSub) 600*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 601*f585d8a3SJacky Wang .compile( 602*f585d8a3SJacky Wang subject -> { 603*f585d8a3SJacky Wang subject.hasErrorCount(0); 604*f585d8a3SJacky Wang subject.generatedSource( 605*f585d8a3SJacky Wang goldenFileRule.goldenSource("test/DaggerParentComponent")); 606*f585d8a3SJacky Wang }); 607*f585d8a3SJacky Wang } 608*f585d8a3SJacky Wang 609*f585d8a3SJacky Wang @Test subcomponentSimpleNamesDisambiguatedInRoot()610*f585d8a3SJacky Wang public void subcomponentSimpleNamesDisambiguatedInRoot() throws Exception { 611*f585d8a3SJacky Wang Source parent = 612*f585d8a3SJacky Wang CompilerTests.javaSource( 613*f585d8a3SJacky Wang "ParentComponent", 614*f585d8a3SJacky Wang "import dagger.Component;", 615*f585d8a3SJacky Wang "", 616*f585d8a3SJacky Wang "@Component", 617*f585d8a3SJacky Wang "interface ParentComponent {", 618*f585d8a3SJacky Wang " Sub newSubcomponent();", 619*f585d8a3SJacky Wang "}"); 620*f585d8a3SJacky Wang Source sub = 621*f585d8a3SJacky Wang CompilerTests.javaSource( 622*f585d8a3SJacky Wang "Sub", 623*f585d8a3SJacky Wang "import dagger.Subcomponent;", 624*f585d8a3SJacky Wang "", 625*f585d8a3SJacky Wang "@Subcomponent interface Sub {", 626*f585d8a3SJacky Wang " test.deep.many.levels.that.match.test.Sub newDeepSubcomponent();", 627*f585d8a3SJacky Wang "}"); 628*f585d8a3SJacky Wang Source deepSub = 629*f585d8a3SJacky Wang CompilerTests.javaSource( 630*f585d8a3SJacky Wang "test.deep.many.levels.that.match.test.Sub", 631*f585d8a3SJacky Wang "package test.deep.many.levels.that.match.test;", 632*f585d8a3SJacky Wang "", 633*f585d8a3SJacky Wang "import dagger.Subcomponent;", 634*f585d8a3SJacky Wang "", 635*f585d8a3SJacky Wang "@Subcomponent public interface Sub {}"); 636*f585d8a3SJacky Wang 637*f585d8a3SJacky Wang CompilerTests.daggerCompiler(parent, sub, deepSub) 638*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 639*f585d8a3SJacky Wang .compile( 640*f585d8a3SJacky Wang subject -> { 641*f585d8a3SJacky Wang subject.hasErrorCount(0); 642*f585d8a3SJacky Wang subject.generatedSource( 643*f585d8a3SJacky Wang goldenFileRule.goldenSource("DaggerParentComponent")); 644*f585d8a3SJacky Wang }); 645*f585d8a3SJacky Wang } 646*f585d8a3SJacky Wang 647*f585d8a3SJacky Wang @Test subcomponentImplNameUsesFullyQualifiedClassNameIfNecessary()648*f585d8a3SJacky Wang public void subcomponentImplNameUsesFullyQualifiedClassNameIfNecessary() throws Exception { 649*f585d8a3SJacky Wang Source parent = 650*f585d8a3SJacky Wang CompilerTests.javaSource( 651*f585d8a3SJacky Wang "test.ParentComponent", 652*f585d8a3SJacky Wang "package test;", 653*f585d8a3SJacky Wang "", 654*f585d8a3SJacky Wang "import dagger.Component;", 655*f585d8a3SJacky Wang "", 656*f585d8a3SJacky Wang "@Component", 657*f585d8a3SJacky Wang "interface ParentComponent {", 658*f585d8a3SJacky Wang " top1.a.b.c.d.E.F.Sub top1();", 659*f585d8a3SJacky Wang " top2.a.b.c.d.E.F.Sub top2();", 660*f585d8a3SJacky Wang "}"); 661*f585d8a3SJacky Wang Source top1 = 662*f585d8a3SJacky Wang CompilerTests.javaSource( 663*f585d8a3SJacky Wang "top1.a.b.c.d.E", 664*f585d8a3SJacky Wang "package top1.a.b.c.d;", 665*f585d8a3SJacky Wang "", 666*f585d8a3SJacky Wang "import dagger.Subcomponent;", 667*f585d8a3SJacky Wang "", 668*f585d8a3SJacky Wang "public interface E {", 669*f585d8a3SJacky Wang " interface F {", 670*f585d8a3SJacky Wang " @Subcomponent interface Sub {}", 671*f585d8a3SJacky Wang " }", 672*f585d8a3SJacky Wang "}"); 673*f585d8a3SJacky Wang Source top2 = 674*f585d8a3SJacky Wang CompilerTests.javaSource( 675*f585d8a3SJacky Wang "top2.a.b.c.d.E", 676*f585d8a3SJacky Wang "package top2.a.b.c.d;", 677*f585d8a3SJacky Wang "", 678*f585d8a3SJacky Wang "import dagger.Subcomponent;", 679*f585d8a3SJacky Wang "", 680*f585d8a3SJacky Wang "public interface E {", 681*f585d8a3SJacky Wang " interface F {", 682*f585d8a3SJacky Wang " @Subcomponent interface Sub {}", 683*f585d8a3SJacky Wang " }", 684*f585d8a3SJacky Wang "}"); 685*f585d8a3SJacky Wang 686*f585d8a3SJacky Wang CompilerTests.daggerCompiler(parent, top1, top2) 687*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 688*f585d8a3SJacky Wang .compile( 689*f585d8a3SJacky Wang subject -> { 690*f585d8a3SJacky Wang subject.hasErrorCount(0); 691*f585d8a3SJacky Wang subject.generatedSource( 692*f585d8a3SJacky Wang goldenFileRule.goldenSource("test/DaggerParentComponent")); 693*f585d8a3SJacky Wang }); 694*f585d8a3SJacky Wang } 695*f585d8a3SJacky Wang 696*f585d8a3SJacky Wang @Test subcomponentNamesShouldNotConflictWithParent()697*f585d8a3SJacky Wang public void subcomponentNamesShouldNotConflictWithParent() 698*f585d8a3SJacky Wang throws Exception { 699*f585d8a3SJacky Wang Source parent = 700*f585d8a3SJacky Wang CompilerTests.javaSource( 701*f585d8a3SJacky Wang "test.C", 702*f585d8a3SJacky Wang "package test;", 703*f585d8a3SJacky Wang "", 704*f585d8a3SJacky Wang "import dagger.Component;", 705*f585d8a3SJacky Wang "", 706*f585d8a3SJacky Wang "@Component", 707*f585d8a3SJacky Wang "interface C {", 708*f585d8a3SJacky Wang " test.Foo.C newInstanceC();", 709*f585d8a3SJacky Wang "}"); 710*f585d8a3SJacky Wang Source subcomponentWithSameSimpleNameAsParent = 711*f585d8a3SJacky Wang CompilerTests.javaSource( 712*f585d8a3SJacky Wang "test.Foo", 713*f585d8a3SJacky Wang "package test;", 714*f585d8a3SJacky Wang "", 715*f585d8a3SJacky Wang "import dagger.Subcomponent;", 716*f585d8a3SJacky Wang "", 717*f585d8a3SJacky Wang "interface Foo {", 718*f585d8a3SJacky Wang " @Subcomponent interface C {}", 719*f585d8a3SJacky Wang "}"); 720*f585d8a3SJacky Wang 721*f585d8a3SJacky Wang CompilerTests.daggerCompiler(parent, subcomponentWithSameSimpleNameAsParent) 722*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 723*f585d8a3SJacky Wang .compile( 724*f585d8a3SJacky Wang subject -> { 725*f585d8a3SJacky Wang subject.hasErrorCount(0); 726*f585d8a3SJacky Wang subject.generatedSource( 727*f585d8a3SJacky Wang goldenFileRule.goldenSource("test/DaggerC")); 728*f585d8a3SJacky Wang }); 729*f585d8a3SJacky Wang } 730*f585d8a3SJacky Wang 731*f585d8a3SJacky Wang @Test subcomponentBuilderNamesShouldNotConflict()732*f585d8a3SJacky Wang public void subcomponentBuilderNamesShouldNotConflict() throws Exception { 733*f585d8a3SJacky Wang Source parent = 734*f585d8a3SJacky Wang CompilerTests.javaSource( 735*f585d8a3SJacky Wang "test.C", 736*f585d8a3SJacky Wang "package test;", 737*f585d8a3SJacky Wang "", 738*f585d8a3SJacky Wang "import dagger.Component;", 739*f585d8a3SJacky Wang "import dagger.Subcomponent;", 740*f585d8a3SJacky Wang "", 741*f585d8a3SJacky Wang "@Component", 742*f585d8a3SJacky Wang "interface C {", 743*f585d8a3SJacky Wang " Foo.Sub.Builder fooBuilder();", 744*f585d8a3SJacky Wang " Bar.Sub.Builder barBuilder();", 745*f585d8a3SJacky Wang "", 746*f585d8a3SJacky Wang " interface Foo {", 747*f585d8a3SJacky Wang " @Subcomponent", 748*f585d8a3SJacky Wang " interface Sub {", 749*f585d8a3SJacky Wang " @Subcomponent.Builder", 750*f585d8a3SJacky Wang " interface Builder {", 751*f585d8a3SJacky Wang " Sub build();", 752*f585d8a3SJacky Wang " }", 753*f585d8a3SJacky Wang " }", 754*f585d8a3SJacky Wang " }", 755*f585d8a3SJacky Wang "", 756*f585d8a3SJacky Wang " interface Bar {", 757*f585d8a3SJacky Wang " @Subcomponent", 758*f585d8a3SJacky Wang " interface Sub {", 759*f585d8a3SJacky Wang " @Subcomponent.Builder", 760*f585d8a3SJacky Wang " interface Builder {", 761*f585d8a3SJacky Wang " Sub build();", 762*f585d8a3SJacky Wang " }", 763*f585d8a3SJacky Wang " }", 764*f585d8a3SJacky Wang " }", 765*f585d8a3SJacky Wang "}"); 766*f585d8a3SJacky Wang 767*f585d8a3SJacky Wang CompilerTests.daggerCompiler(parent) 768*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 769*f585d8a3SJacky Wang .compile( 770*f585d8a3SJacky Wang subject -> { 771*f585d8a3SJacky Wang subject.hasErrorCount(0); 772*f585d8a3SJacky Wang subject.generatedSource( 773*f585d8a3SJacky Wang goldenFileRule.goldenSource("test/DaggerC")); 774*f585d8a3SJacky Wang }); 775*f585d8a3SJacky Wang } 776*f585d8a3SJacky Wang 777*f585d8a3SJacky Wang @Test duplicateBindingWithSubcomponentDeclaration()778*f585d8a3SJacky Wang public void duplicateBindingWithSubcomponentDeclaration() { 779*f585d8a3SJacky Wang Source module = 780*f585d8a3SJacky Wang CompilerTests.javaSource( 781*f585d8a3SJacky Wang "test.TestModule", 782*f585d8a3SJacky Wang "package test;", 783*f585d8a3SJacky Wang "", 784*f585d8a3SJacky Wang "import dagger.Module;", 785*f585d8a3SJacky Wang "import dagger.Provides;", 786*f585d8a3SJacky Wang "", 787*f585d8a3SJacky Wang "@Module(subcomponents = Sub.class)", 788*f585d8a3SJacky Wang "class TestModule {", 789*f585d8a3SJacky Wang " @Provides Sub.Builder providesConflictsWithModuleSubcomponents() { return null; }", 790*f585d8a3SJacky Wang " @Provides Object usesSubcomponentBuilder(Sub.Builder builder) {", 791*f585d8a3SJacky Wang " return new Builder().toString();", 792*f585d8a3SJacky Wang " }", 793*f585d8a3SJacky Wang "}"); 794*f585d8a3SJacky Wang 795*f585d8a3SJacky Wang Source subcomponent = 796*f585d8a3SJacky Wang CompilerTests.javaSource( 797*f585d8a3SJacky Wang "test.Sub", 798*f585d8a3SJacky Wang "package test;", 799*f585d8a3SJacky Wang "", 800*f585d8a3SJacky Wang "import dagger.Subcomponent;", 801*f585d8a3SJacky Wang "", 802*f585d8a3SJacky Wang "@Subcomponent", 803*f585d8a3SJacky Wang "interface Sub {", 804*f585d8a3SJacky Wang " @Subcomponent.Builder", 805*f585d8a3SJacky Wang " interface Builder {", 806*f585d8a3SJacky Wang " Sub build();", 807*f585d8a3SJacky Wang " }", 808*f585d8a3SJacky Wang "}"); 809*f585d8a3SJacky Wang 810*f585d8a3SJacky Wang Source component = 811*f585d8a3SJacky Wang CompilerTests.javaSource( 812*f585d8a3SJacky Wang "test.C", 813*f585d8a3SJacky Wang "package test;", 814*f585d8a3SJacky Wang "", 815*f585d8a3SJacky Wang "import dagger.Component;", 816*f585d8a3SJacky Wang "", 817*f585d8a3SJacky Wang "@Component(modules = TestModule.class)", 818*f585d8a3SJacky Wang "interface C {", 819*f585d8a3SJacky Wang " Object dependsOnBuilder();", 820*f585d8a3SJacky Wang "}"); 821*f585d8a3SJacky Wang 822*f585d8a3SJacky Wang CompilerTests.daggerCompiler(module, component, subcomponent) 823*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 824*f585d8a3SJacky Wang .compile( 825*f585d8a3SJacky Wang subject -> { 826*f585d8a3SJacky Wang subject.hasErrorCount(1); 827*f585d8a3SJacky Wang subject.hasErrorContaining("Sub.Builder is bound multiple times:"); 828*f585d8a3SJacky Wang subject.hasErrorContaining( 829*f585d8a3SJacky Wang "@Provides Sub.Builder TestModule.providesConflictsWithModuleSubcomponents()"); 830*f585d8a3SJacky Wang subject.hasErrorContaining("@Module(subcomponents = Sub.class) for TestModule"); 831*f585d8a3SJacky Wang }); 832*f585d8a3SJacky Wang } 833*f585d8a3SJacky Wang 834*f585d8a3SJacky Wang @Test subcomponentDependsOnGeneratedType()835*f585d8a3SJacky Wang public void subcomponentDependsOnGeneratedType() { 836*f585d8a3SJacky Wang Source parent = 837*f585d8a3SJacky Wang CompilerTests.javaSource( 838*f585d8a3SJacky Wang "test.Parent", 839*f585d8a3SJacky Wang "package test;", 840*f585d8a3SJacky Wang "", 841*f585d8a3SJacky Wang "import dagger.Component;", 842*f585d8a3SJacky Wang "", 843*f585d8a3SJacky Wang "@Component", 844*f585d8a3SJacky Wang "interface Parent {", 845*f585d8a3SJacky Wang " Child.Builder childBuilder();", 846*f585d8a3SJacky Wang "}"); 847*f585d8a3SJacky Wang Source child = 848*f585d8a3SJacky Wang CompilerTests.javaSource( 849*f585d8a3SJacky Wang "test.Child", 850*f585d8a3SJacky Wang "package test;", 851*f585d8a3SJacky Wang "", 852*f585d8a3SJacky Wang "import dagger.Subcomponent;", 853*f585d8a3SJacky Wang "", 854*f585d8a3SJacky Wang "@Subcomponent", 855*f585d8a3SJacky Wang "interface Child extends ChildSupertype {", 856*f585d8a3SJacky Wang " @Subcomponent.Builder", 857*f585d8a3SJacky Wang " interface Builder {", 858*f585d8a3SJacky Wang " Child build();", 859*f585d8a3SJacky Wang " }", 860*f585d8a3SJacky Wang "}"); 861*f585d8a3SJacky Wang Source childSupertype = 862*f585d8a3SJacky Wang CompilerTests.javaSource( 863*f585d8a3SJacky Wang "test.ChildSupertype", 864*f585d8a3SJacky Wang "package test;", 865*f585d8a3SJacky Wang "", 866*f585d8a3SJacky Wang "interface ChildSupertype {", 867*f585d8a3SJacky Wang " GeneratedInjectType generatedType();", 868*f585d8a3SJacky Wang "}"); 869*f585d8a3SJacky Wang TypeSpec generatedInjectType = 870*f585d8a3SJacky Wang TypeSpec.classBuilder("GeneratedInjectType") 871*f585d8a3SJacky Wang .addMethod( 872*f585d8a3SJacky Wang MethodSpec.constructorBuilder() 873*f585d8a3SJacky Wang .addAnnotation(TypeNames.INJECT_JAVAX) 874*f585d8a3SJacky Wang .build()) 875*f585d8a3SJacky Wang .build(); 876*f585d8a3SJacky Wang CompilerTests.daggerCompiler(parent, child, childSupertype) 877*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 878*f585d8a3SJacky Wang .withProcessingSteps(() -> new GeneratingProcessingStep("test", generatedInjectType)) 879*f585d8a3SJacky Wang .compile( 880*f585d8a3SJacky Wang subject -> { 881*f585d8a3SJacky Wang subject.hasErrorCount(0); 882*f585d8a3SJacky Wang subject.hasWarningCount(0); 883*f585d8a3SJacky Wang }); 884*f585d8a3SJacky Wang } 885*f585d8a3SJacky Wang } 886