1*f585d8a3SJacky Wang /* 2*f585d8a3SJacky Wang * Copyright (C) 2018 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 com.google.common.truth.Truth.assertThat; 20*f585d8a3SJacky Wang 21*f585d8a3SJacky Wang import androidx.room.compiler.processing.XProcessingEnv; 22*f585d8a3SJacky Wang import androidx.room.compiler.processing.util.DiagnosticMessage; 23*f585d8a3SJacky Wang import androidx.room.compiler.processing.util.Source; 24*f585d8a3SJacky Wang import com.google.common.collect.ImmutableList; 25*f585d8a3SJacky Wang import dagger.testing.compile.CompilerTests; 26*f585d8a3SJacky Wang import java.util.List; 27*f585d8a3SJacky Wang import javax.tools.Diagnostic; 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 @RunWith(Parameterized.class) 34*f585d8a3SJacky Wang public class MissingBindingValidationTest { 35*f585d8a3SJacky Wang @Parameters(name = "{0}") parameters()36*f585d8a3SJacky Wang public static ImmutableList<Object[]> parameters() { 37*f585d8a3SJacky Wang return CompilerMode.TEST_PARAMETERS; 38*f585d8a3SJacky Wang } 39*f585d8a3SJacky Wang 40*f585d8a3SJacky Wang private final CompilerMode compilerMode; 41*f585d8a3SJacky Wang MissingBindingValidationTest(CompilerMode compilerMode)42*f585d8a3SJacky Wang public MissingBindingValidationTest(CompilerMode compilerMode) { 43*f585d8a3SJacky Wang this.compilerMode = compilerMode; 44*f585d8a3SJacky Wang } 45*f585d8a3SJacky Wang 46*f585d8a3SJacky Wang @Test dependOnInterface()47*f585d8a3SJacky Wang public void dependOnInterface() { 48*f585d8a3SJacky Wang Source component = 49*f585d8a3SJacky Wang CompilerTests.javaSource( 50*f585d8a3SJacky Wang "test.MyComponent", 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 MyComponent {", 57*f585d8a3SJacky Wang " Foo getFoo();", 58*f585d8a3SJacky Wang "}"); 59*f585d8a3SJacky Wang Source injectable = 60*f585d8a3SJacky Wang CompilerTests.javaSource( 61*f585d8a3SJacky Wang "test.Foo", 62*f585d8a3SJacky Wang "package test;", 63*f585d8a3SJacky Wang "", 64*f585d8a3SJacky Wang "import javax.inject.Inject;", 65*f585d8a3SJacky Wang "", 66*f585d8a3SJacky Wang "class Foo {", 67*f585d8a3SJacky Wang " @Inject Foo(Bar bar) {}", 68*f585d8a3SJacky Wang "}"); 69*f585d8a3SJacky Wang Source nonInjectable = 70*f585d8a3SJacky Wang CompilerTests.javaSource( 71*f585d8a3SJacky Wang "test.Bar", 72*f585d8a3SJacky Wang "package test;", 73*f585d8a3SJacky Wang "", 74*f585d8a3SJacky Wang "import javax.inject.Inject;", 75*f585d8a3SJacky Wang "", 76*f585d8a3SJacky Wang "interface Bar {}"); 77*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component, injectable, nonInjectable) 78*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 79*f585d8a3SJacky Wang .compile( 80*f585d8a3SJacky Wang subject -> { 81*f585d8a3SJacky Wang subject.hasErrorCount(1); 82*f585d8a3SJacky Wang subject.hasErrorContaining( 83*f585d8a3SJacky Wang "Bar cannot be provided without an @Provides-annotated method.") 84*f585d8a3SJacky Wang .onSource(component) 85*f585d8a3SJacky Wang .onLineContaining("interface MyComponent"); 86*f585d8a3SJacky Wang }); 87*f585d8a3SJacky Wang } 88*f585d8a3SJacky Wang 89*f585d8a3SJacky Wang @Test entryPointDependsOnInterface()90*f585d8a3SJacky Wang public void entryPointDependsOnInterface() { 91*f585d8a3SJacky Wang Source component = 92*f585d8a3SJacky Wang CompilerTests.javaSource( 93*f585d8a3SJacky Wang "test.TestClass", 94*f585d8a3SJacky Wang "package test;", 95*f585d8a3SJacky Wang "", 96*f585d8a3SJacky Wang "import dagger.Component;", 97*f585d8a3SJacky Wang "", 98*f585d8a3SJacky Wang "final class TestClass {", 99*f585d8a3SJacky Wang " interface A {}", 100*f585d8a3SJacky Wang "", 101*f585d8a3SJacky Wang " @Component()", 102*f585d8a3SJacky Wang " interface AComponent {", 103*f585d8a3SJacky Wang " A getA();", 104*f585d8a3SJacky Wang " }", 105*f585d8a3SJacky Wang "}"); 106*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component) 107*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 108*f585d8a3SJacky Wang .compile( 109*f585d8a3SJacky Wang subject -> { 110*f585d8a3SJacky Wang subject.hasErrorCount(1); 111*f585d8a3SJacky Wang subject.hasErrorContaining( 112*f585d8a3SJacky Wang "\033[1;31m[Dagger/MissingBinding]\033[0m TestClass.A cannot be provided " 113*f585d8a3SJacky Wang + "without an @Provides-annotated method.") 114*f585d8a3SJacky Wang .onSource(component) 115*f585d8a3SJacky Wang .onLineContaining("interface AComponent"); 116*f585d8a3SJacky Wang }); 117*f585d8a3SJacky Wang } 118*f585d8a3SJacky Wang 119*f585d8a3SJacky Wang @Test entryPointDependsOnQualifiedInterface()120*f585d8a3SJacky Wang public void entryPointDependsOnQualifiedInterface() { 121*f585d8a3SJacky Wang Source component = 122*f585d8a3SJacky Wang CompilerTests.javaSource( 123*f585d8a3SJacky Wang "test.TestClass", 124*f585d8a3SJacky Wang "package test;", 125*f585d8a3SJacky Wang "", 126*f585d8a3SJacky Wang "import dagger.Component;", 127*f585d8a3SJacky Wang "import javax.inject.Qualifier;", 128*f585d8a3SJacky Wang "", 129*f585d8a3SJacky Wang "final class TestClass {", 130*f585d8a3SJacky Wang " @Qualifier @interface Q {}", 131*f585d8a3SJacky Wang " interface A {}", 132*f585d8a3SJacky Wang "", 133*f585d8a3SJacky Wang " @Component()", 134*f585d8a3SJacky Wang " interface AComponent {", 135*f585d8a3SJacky Wang " @Q A qualifiedA();", 136*f585d8a3SJacky Wang " }", 137*f585d8a3SJacky Wang "}"); 138*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component) 139*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 140*f585d8a3SJacky Wang .compile( 141*f585d8a3SJacky Wang subject -> { 142*f585d8a3SJacky Wang subject.hasErrorCount(1); 143*f585d8a3SJacky Wang subject.hasErrorContaining( 144*f585d8a3SJacky Wang "\033[1;31m[Dagger/MissingBinding]\033[0m @TestClass.Q TestClass.A cannot be " 145*f585d8a3SJacky Wang + "provided without an @Provides-annotated method.") 146*f585d8a3SJacky Wang .onSource(component) 147*f585d8a3SJacky Wang .onLineContaining("interface AComponent"); 148*f585d8a3SJacky Wang }); 149*f585d8a3SJacky Wang } 150*f585d8a3SJacky Wang constructorInjectionWithoutAnnotation()151*f585d8a3SJacky Wang @Test public void constructorInjectionWithoutAnnotation() { 152*f585d8a3SJacky Wang Source component = 153*f585d8a3SJacky Wang CompilerTests.javaSource("test.TestClass", 154*f585d8a3SJacky Wang "package test;", 155*f585d8a3SJacky Wang "", 156*f585d8a3SJacky Wang "import dagger.Component;", 157*f585d8a3SJacky Wang "import dagger.Module;", 158*f585d8a3SJacky Wang "import dagger.Provides;", 159*f585d8a3SJacky Wang "import javax.inject.Inject;", 160*f585d8a3SJacky Wang "", 161*f585d8a3SJacky Wang "final class TestClass {", 162*f585d8a3SJacky Wang " static class A {", 163*f585d8a3SJacky Wang " A() {}", 164*f585d8a3SJacky Wang " }", 165*f585d8a3SJacky Wang "", 166*f585d8a3SJacky Wang " @Component()", 167*f585d8a3SJacky Wang " interface AComponent {", 168*f585d8a3SJacky Wang " A getA();", 169*f585d8a3SJacky Wang " }", 170*f585d8a3SJacky Wang "}"); 171*f585d8a3SJacky Wang 172*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component) 173*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 174*f585d8a3SJacky Wang .compile( 175*f585d8a3SJacky Wang subject -> { 176*f585d8a3SJacky Wang subject.hasErrorCount(1); 177*f585d8a3SJacky Wang subject.hasErrorContaining( 178*f585d8a3SJacky Wang "TestClass.A cannot be provided without an @Inject constructor or an " 179*f585d8a3SJacky Wang + "@Provides-annotated method.") 180*f585d8a3SJacky Wang .onSource(component) 181*f585d8a3SJacky Wang .onLineContaining("interface AComponent"); 182*f585d8a3SJacky Wang }); 183*f585d8a3SJacky Wang } 184*f585d8a3SJacky Wang membersInjectWithoutProvision()185*f585d8a3SJacky Wang @Test public void membersInjectWithoutProvision() { 186*f585d8a3SJacky Wang Source component = 187*f585d8a3SJacky Wang CompilerTests.javaSource( 188*f585d8a3SJacky Wang "test.TestClass", 189*f585d8a3SJacky Wang "package test;", 190*f585d8a3SJacky Wang "", 191*f585d8a3SJacky Wang "import dagger.Component;", 192*f585d8a3SJacky Wang "import dagger.Module;", 193*f585d8a3SJacky Wang "import dagger.Provides;", 194*f585d8a3SJacky Wang "import javax.inject.Inject;", 195*f585d8a3SJacky Wang "", 196*f585d8a3SJacky Wang "final class TestClass {", 197*f585d8a3SJacky Wang " static class A {", 198*f585d8a3SJacky Wang " @Inject A() {}", 199*f585d8a3SJacky Wang " }", 200*f585d8a3SJacky Wang "", 201*f585d8a3SJacky Wang " static class B {", 202*f585d8a3SJacky Wang " @Inject A a;", 203*f585d8a3SJacky Wang " }", 204*f585d8a3SJacky Wang "", 205*f585d8a3SJacky Wang " @Component()", 206*f585d8a3SJacky Wang " interface AComponent {", 207*f585d8a3SJacky Wang " B getB();", 208*f585d8a3SJacky Wang " }", 209*f585d8a3SJacky Wang "}"); 210*f585d8a3SJacky Wang 211*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component) 212*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 213*f585d8a3SJacky Wang .compile( 214*f585d8a3SJacky Wang subject -> { 215*f585d8a3SJacky Wang subject.hasErrorCount(1); 216*f585d8a3SJacky Wang subject.hasErrorContaining( 217*f585d8a3SJacky Wang "TestClass.B cannot be provided without an @Inject constructor or an " 218*f585d8a3SJacky Wang + "@Provides-annotated method. This type supports members injection but " 219*f585d8a3SJacky Wang + "cannot be implicitly provided.") 220*f585d8a3SJacky Wang .onSource(component) 221*f585d8a3SJacky Wang .onLineContaining("interface AComponent"); 222*f585d8a3SJacky Wang }); 223*f585d8a3SJacky Wang } 224*f585d8a3SJacky Wang 225*f585d8a3SJacky Wang @Test missingBindingWithSameKeyAsMembersInjectionMethod()226*f585d8a3SJacky Wang public void missingBindingWithSameKeyAsMembersInjectionMethod() { 227*f585d8a3SJacky Wang Source self = 228*f585d8a3SJacky Wang CompilerTests.javaSource( 229*f585d8a3SJacky Wang "test.Self", 230*f585d8a3SJacky Wang "package test;", 231*f585d8a3SJacky Wang "", 232*f585d8a3SJacky Wang "import javax.inject.Inject;", 233*f585d8a3SJacky Wang "import javax.inject.Provider;", 234*f585d8a3SJacky Wang "", 235*f585d8a3SJacky Wang "class Self {", 236*f585d8a3SJacky Wang " @Inject Provider<Self> selfProvider;", 237*f585d8a3SJacky Wang "}"); 238*f585d8a3SJacky Wang Source component = 239*f585d8a3SJacky Wang CompilerTests.javaSource( 240*f585d8a3SJacky Wang "test.SelfComponent", 241*f585d8a3SJacky Wang "package test;", 242*f585d8a3SJacky Wang "", 243*f585d8a3SJacky Wang "import dagger.Component;", 244*f585d8a3SJacky Wang "", 245*f585d8a3SJacky Wang "@Component", 246*f585d8a3SJacky Wang "interface SelfComponent {", 247*f585d8a3SJacky Wang " void inject(Self target);", 248*f585d8a3SJacky Wang "}"); 249*f585d8a3SJacky Wang 250*f585d8a3SJacky Wang CompilerTests.daggerCompiler(self, component) 251*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 252*f585d8a3SJacky Wang .compile( 253*f585d8a3SJacky Wang subject -> { 254*f585d8a3SJacky Wang subject.hasErrorCount(1); 255*f585d8a3SJacky Wang subject.hasErrorContaining("Self cannot be provided without an @Inject constructor") 256*f585d8a3SJacky Wang .onSource(component) 257*f585d8a3SJacky Wang .onLineContaining("interface SelfComponent"); 258*f585d8a3SJacky Wang }); 259*f585d8a3SJacky Wang } 260*f585d8a3SJacky Wang 261*f585d8a3SJacky Wang @Test genericInjectClassWithWildcardDependencies()262*f585d8a3SJacky Wang public void genericInjectClassWithWildcardDependencies() { 263*f585d8a3SJacky Wang Source component = 264*f585d8a3SJacky Wang CompilerTests.javaSource( 265*f585d8a3SJacky Wang "test.TestComponent", 266*f585d8a3SJacky Wang "package test;", 267*f585d8a3SJacky Wang "", 268*f585d8a3SJacky Wang "import dagger.Component;", 269*f585d8a3SJacky Wang "", 270*f585d8a3SJacky Wang "@Component", 271*f585d8a3SJacky Wang "interface TestComponent {", 272*f585d8a3SJacky Wang " Foo<? extends Number> foo();", 273*f585d8a3SJacky Wang "}"); 274*f585d8a3SJacky Wang Source foo = 275*f585d8a3SJacky Wang CompilerTests.javaSource( 276*f585d8a3SJacky Wang "test.Foo", 277*f585d8a3SJacky Wang "package test;", 278*f585d8a3SJacky Wang "", 279*f585d8a3SJacky Wang "import javax.inject.Inject;", 280*f585d8a3SJacky Wang "", 281*f585d8a3SJacky Wang "final class Foo<T> {", 282*f585d8a3SJacky Wang " @Inject Foo(T t) {}", 283*f585d8a3SJacky Wang "}"); 284*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component, foo) 285*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 286*f585d8a3SJacky Wang .compile( 287*f585d8a3SJacky Wang subject -> { 288*f585d8a3SJacky Wang subject.hasErrorCount(1); 289*f585d8a3SJacky Wang subject.hasErrorContaining( 290*f585d8a3SJacky Wang "Foo<? extends Number> cannot be provided " 291*f585d8a3SJacky Wang + "without an @Provides-annotated method"); 292*f585d8a3SJacky Wang }); 293*f585d8a3SJacky Wang } 294*f585d8a3SJacky Wang longChainOfDependencies()295*f585d8a3SJacky Wang @Test public void longChainOfDependencies() { 296*f585d8a3SJacky Wang Source component = 297*f585d8a3SJacky Wang CompilerTests.javaSource( 298*f585d8a3SJacky Wang "test.TestClass", 299*f585d8a3SJacky Wang "package test;", 300*f585d8a3SJacky Wang "", 301*f585d8a3SJacky Wang "import dagger.Component;", 302*f585d8a3SJacky Wang "import dagger.Lazy;", 303*f585d8a3SJacky Wang "import dagger.Module;", 304*f585d8a3SJacky Wang "import dagger.Provides;", 305*f585d8a3SJacky Wang "import javax.inject.Inject;", 306*f585d8a3SJacky Wang "import javax.inject.Named;", 307*f585d8a3SJacky Wang "import javax.inject.Provider;", 308*f585d8a3SJacky Wang "", 309*f585d8a3SJacky Wang "final class TestClass {", 310*f585d8a3SJacky Wang " interface A {}", 311*f585d8a3SJacky Wang "", 312*f585d8a3SJacky Wang " static class B {", 313*f585d8a3SJacky Wang " @Inject B(A a) {}", 314*f585d8a3SJacky Wang " }", 315*f585d8a3SJacky Wang "", 316*f585d8a3SJacky Wang " static class C {", 317*f585d8a3SJacky Wang " @Inject B b;", 318*f585d8a3SJacky Wang " @Inject C(X x) {}", 319*f585d8a3SJacky Wang " }", 320*f585d8a3SJacky Wang "", 321*f585d8a3SJacky Wang " interface D { }", 322*f585d8a3SJacky Wang "", 323*f585d8a3SJacky Wang " static class DImpl implements D {", 324*f585d8a3SJacky Wang " @Inject DImpl(C c, B b) {}", 325*f585d8a3SJacky Wang " }", 326*f585d8a3SJacky Wang "", 327*f585d8a3SJacky Wang " static class X {", 328*f585d8a3SJacky Wang " @Inject X() {}", 329*f585d8a3SJacky Wang " }", 330*f585d8a3SJacky Wang "", 331*f585d8a3SJacky Wang " @Module", 332*f585d8a3SJacky Wang " static class DModule {", 333*f585d8a3SJacky Wang " @Provides @Named(\"slim shady\") D d(X x1, DImpl impl, X x2) { return impl; }", 334*f585d8a3SJacky Wang " }", 335*f585d8a3SJacky Wang "", 336*f585d8a3SJacky Wang " @Component(modules = { DModule.class })", 337*f585d8a3SJacky Wang " interface AComponent {", 338*f585d8a3SJacky Wang " @Named(\"slim shady\") D getFoo();", 339*f585d8a3SJacky Wang " C injectC(C c);", 340*f585d8a3SJacky Wang " Provider<C> cProvider();", 341*f585d8a3SJacky Wang " Lazy<C> lazyC();", 342*f585d8a3SJacky Wang " Provider<Lazy<C>> lazyCProvider();", 343*f585d8a3SJacky Wang " }", 344*f585d8a3SJacky Wang "}"); 345*f585d8a3SJacky Wang 346*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component) 347*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 348*f585d8a3SJacky Wang .compile( 349*f585d8a3SJacky Wang subject -> { 350*f585d8a3SJacky Wang subject.hasErrorCount(1); 351*f585d8a3SJacky Wang subject.hasErrorContaining( 352*f585d8a3SJacky Wang String.join( 353*f585d8a3SJacky Wang "\n", 354*f585d8a3SJacky Wang "TestClass.A cannot be provided without an @Provides-annotated method.", 355*f585d8a3SJacky Wang "", 356*f585d8a3SJacky Wang " TestClass.A is injected at", 357*f585d8a3SJacky Wang " [TestClass.AComponent] TestClass.B(a)", 358*f585d8a3SJacky Wang " TestClass.B is injected at", 359*f585d8a3SJacky Wang " [TestClass.AComponent] TestClass.C.b", 360*f585d8a3SJacky Wang " TestClass.C is injected at", 361*f585d8a3SJacky Wang " [TestClass.AComponent] TestClass.AComponent.injectC(TestClass.C)", 362*f585d8a3SJacky Wang "The following other entry points also depend on it:", 363*f585d8a3SJacky Wang " TestClass.AComponent.getFoo()", 364*f585d8a3SJacky Wang " TestClass.AComponent.cProvider()", 365*f585d8a3SJacky Wang " TestClass.AComponent.lazyC()", 366*f585d8a3SJacky Wang " TestClass.AComponent.lazyCProvider()")) 367*f585d8a3SJacky Wang .onSource(component) 368*f585d8a3SJacky Wang .onLineContaining("interface AComponent"); 369*f585d8a3SJacky Wang }); 370*f585d8a3SJacky Wang } 371*f585d8a3SJacky Wang 372*f585d8a3SJacky Wang @Test bindsMethodAppearsInTrace()373*f585d8a3SJacky Wang public void bindsMethodAppearsInTrace() { 374*f585d8a3SJacky Wang Source component = 375*f585d8a3SJacky Wang CompilerTests.javaSource( 376*f585d8a3SJacky Wang "TestComponent", 377*f585d8a3SJacky Wang "import dagger.Component;", 378*f585d8a3SJacky Wang "", 379*f585d8a3SJacky Wang "@Component(modules = TestModule.class)", 380*f585d8a3SJacky Wang "interface TestComponent {", 381*f585d8a3SJacky Wang " TestInterface testInterface();", 382*f585d8a3SJacky Wang "}"); 383*f585d8a3SJacky Wang Source interfaceFile = 384*f585d8a3SJacky Wang CompilerTests.javaSource("TestInterface", "interface TestInterface {}"); 385*f585d8a3SJacky Wang Source implementationFile = 386*f585d8a3SJacky Wang CompilerTests.javaSource( 387*f585d8a3SJacky Wang "TestImplementation", 388*f585d8a3SJacky Wang "import javax.inject.Inject;", 389*f585d8a3SJacky Wang "", 390*f585d8a3SJacky Wang "final class TestImplementation implements TestInterface {", 391*f585d8a3SJacky Wang " @Inject TestImplementation(String missingBinding) {}", 392*f585d8a3SJacky Wang "}"); 393*f585d8a3SJacky Wang Source module = 394*f585d8a3SJacky Wang CompilerTests.javaSource( 395*f585d8a3SJacky Wang "TestModule", 396*f585d8a3SJacky Wang "import dagger.Binds;", 397*f585d8a3SJacky Wang "import dagger.Module;", 398*f585d8a3SJacky Wang "", 399*f585d8a3SJacky Wang "@Module", 400*f585d8a3SJacky Wang "interface TestModule {", 401*f585d8a3SJacky Wang " @Binds abstract TestInterface bindTestInterface(TestImplementation implementation);", 402*f585d8a3SJacky Wang "}"); 403*f585d8a3SJacky Wang 404*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component, module, interfaceFile, implementationFile) 405*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 406*f585d8a3SJacky Wang .compile( 407*f585d8a3SJacky Wang subject -> { 408*f585d8a3SJacky Wang subject.hasErrorCount(1); 409*f585d8a3SJacky Wang subject.hasErrorContaining( 410*f585d8a3SJacky Wang String.join( 411*f585d8a3SJacky Wang "\n", 412*f585d8a3SJacky Wang "String cannot be provided without an @Inject constructor or an " 413*f585d8a3SJacky Wang + "@Provides-annotated method.", 414*f585d8a3SJacky Wang "", 415*f585d8a3SJacky Wang " String is injected at", 416*f585d8a3SJacky Wang " [TestComponent] TestImplementation(missingBinding)", 417*f585d8a3SJacky Wang " TestImplementation is injected at", 418*f585d8a3SJacky Wang " [TestComponent] TestModule.bindTestInterface(implementation)", 419*f585d8a3SJacky Wang " TestInterface is requested at", 420*f585d8a3SJacky Wang " [TestComponent] TestComponent.testInterface()")) 421*f585d8a3SJacky Wang .onSource(component) 422*f585d8a3SJacky Wang .onLineContaining("interface TestComponent"); 423*f585d8a3SJacky Wang }); 424*f585d8a3SJacky Wang } 425*f585d8a3SJacky Wang resolvedParametersInDependencyTrace()426*f585d8a3SJacky Wang @Test public void resolvedParametersInDependencyTrace() { 427*f585d8a3SJacky Wang Source generic = 428*f585d8a3SJacky Wang CompilerTests.javaSource("test.Generic", 429*f585d8a3SJacky Wang "package test;", 430*f585d8a3SJacky Wang "", 431*f585d8a3SJacky Wang "import javax.inject.Inject;", 432*f585d8a3SJacky Wang "import javax.inject.Provider;", 433*f585d8a3SJacky Wang "", 434*f585d8a3SJacky Wang "final class Generic<T> {", 435*f585d8a3SJacky Wang " @Inject Generic(T t) {}", 436*f585d8a3SJacky Wang "}"); 437*f585d8a3SJacky Wang Source testClass = 438*f585d8a3SJacky Wang CompilerTests.javaSource("test.TestClass", 439*f585d8a3SJacky Wang "package test;", 440*f585d8a3SJacky Wang "", 441*f585d8a3SJacky Wang "import javax.inject.Inject;", 442*f585d8a3SJacky Wang "import java.util.List;", 443*f585d8a3SJacky Wang "", 444*f585d8a3SJacky Wang "final class TestClass {", 445*f585d8a3SJacky Wang " @Inject TestClass(List list) {}", 446*f585d8a3SJacky Wang "}"); 447*f585d8a3SJacky Wang Source usesTest = 448*f585d8a3SJacky Wang CompilerTests.javaSource("test.UsesTest", 449*f585d8a3SJacky Wang "package test;", 450*f585d8a3SJacky Wang "", 451*f585d8a3SJacky Wang "import javax.inject.Inject;", 452*f585d8a3SJacky Wang "", 453*f585d8a3SJacky Wang "final class UsesTest {", 454*f585d8a3SJacky Wang " @Inject UsesTest(Generic<TestClass> genericTestClass) {}", 455*f585d8a3SJacky Wang "}"); 456*f585d8a3SJacky Wang Source component = 457*f585d8a3SJacky Wang CompilerTests.javaSource("test.TestComponent", 458*f585d8a3SJacky Wang "package test;", 459*f585d8a3SJacky Wang "", 460*f585d8a3SJacky Wang "import dagger.Component;", 461*f585d8a3SJacky Wang "", 462*f585d8a3SJacky Wang "@Component", 463*f585d8a3SJacky Wang "interface TestComponent {", 464*f585d8a3SJacky Wang " UsesTest usesTest();", 465*f585d8a3SJacky Wang "}"); 466*f585d8a3SJacky Wang 467*f585d8a3SJacky Wang CompilerTests.daggerCompiler(generic, testClass, usesTest, component) 468*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 469*f585d8a3SJacky Wang .compile( 470*f585d8a3SJacky Wang subject -> { 471*f585d8a3SJacky Wang subject.hasErrorCount(1); 472*f585d8a3SJacky Wang subject.hasErrorContaining( 473*f585d8a3SJacky Wang String.join( 474*f585d8a3SJacky Wang "\n", 475*f585d8a3SJacky Wang "List cannot be provided without an @Provides-annotated method.", 476*f585d8a3SJacky Wang "", 477*f585d8a3SJacky Wang " List is injected at", 478*f585d8a3SJacky Wang " [TestComponent] TestClass(list)", 479*f585d8a3SJacky Wang " TestClass is injected at", 480*f585d8a3SJacky Wang " [TestComponent] Generic(t)", 481*f585d8a3SJacky Wang " Generic<TestClass> is injected at", 482*f585d8a3SJacky Wang " [TestComponent] UsesTest(genericTestClass)", 483*f585d8a3SJacky Wang " UsesTest is requested at", 484*f585d8a3SJacky Wang " [TestComponent] TestComponent.usesTest()")); 485*f585d8a3SJacky Wang }); 486*f585d8a3SJacky Wang } 487*f585d8a3SJacky Wang resolvedVariablesInDependencyTrace()488*f585d8a3SJacky Wang @Test public void resolvedVariablesInDependencyTrace() { 489*f585d8a3SJacky Wang Source generic = 490*f585d8a3SJacky Wang CompilerTests.javaSource( 491*f585d8a3SJacky Wang "test.Generic", 492*f585d8a3SJacky Wang "package test;", 493*f585d8a3SJacky Wang "", 494*f585d8a3SJacky Wang "import javax.inject.Inject;", 495*f585d8a3SJacky Wang "import javax.inject.Provider;", 496*f585d8a3SJacky Wang "", 497*f585d8a3SJacky Wang "final class Generic<T> {", 498*f585d8a3SJacky Wang " @Inject T t;", 499*f585d8a3SJacky Wang " @Inject Generic() {}", 500*f585d8a3SJacky Wang "}"); 501*f585d8a3SJacky Wang Source testClass = 502*f585d8a3SJacky Wang CompilerTests.javaSource( 503*f585d8a3SJacky Wang "test.TestClass", 504*f585d8a3SJacky Wang "package test;", 505*f585d8a3SJacky Wang "", 506*f585d8a3SJacky Wang "import javax.inject.Inject;", 507*f585d8a3SJacky Wang "import java.util.List;", 508*f585d8a3SJacky Wang "", 509*f585d8a3SJacky Wang "final class TestClass {", 510*f585d8a3SJacky Wang " @Inject TestClass(List list) {}", 511*f585d8a3SJacky Wang "}"); 512*f585d8a3SJacky Wang Source usesTest = 513*f585d8a3SJacky Wang CompilerTests.javaSource( 514*f585d8a3SJacky Wang "test.UsesTest", 515*f585d8a3SJacky Wang "package test;", 516*f585d8a3SJacky Wang "", 517*f585d8a3SJacky Wang "import javax.inject.Inject;", 518*f585d8a3SJacky Wang "", 519*f585d8a3SJacky Wang "final class UsesTest {", 520*f585d8a3SJacky Wang " @Inject UsesTest(Generic<TestClass> genericTestClass) {}", 521*f585d8a3SJacky Wang "}"); 522*f585d8a3SJacky Wang Source component = 523*f585d8a3SJacky Wang CompilerTests.javaSource( 524*f585d8a3SJacky Wang "test.TestComponent", 525*f585d8a3SJacky Wang "package test;", 526*f585d8a3SJacky Wang "", 527*f585d8a3SJacky Wang "import dagger.Component;", 528*f585d8a3SJacky Wang "", 529*f585d8a3SJacky Wang "@Component", 530*f585d8a3SJacky Wang "interface TestComponent {", 531*f585d8a3SJacky Wang " UsesTest usesTest();", 532*f585d8a3SJacky Wang "}"); 533*f585d8a3SJacky Wang 534*f585d8a3SJacky Wang CompilerTests.daggerCompiler(generic, testClass, usesTest, component) 535*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 536*f585d8a3SJacky Wang .compile( 537*f585d8a3SJacky Wang subject -> { 538*f585d8a3SJacky Wang subject.hasErrorCount(1); 539*f585d8a3SJacky Wang subject.hasErrorContaining( 540*f585d8a3SJacky Wang String.join( 541*f585d8a3SJacky Wang "\n", 542*f585d8a3SJacky Wang "List cannot be provided without an @Provides-annotated method.", 543*f585d8a3SJacky Wang "", 544*f585d8a3SJacky Wang " List is injected at", 545*f585d8a3SJacky Wang " [TestComponent] TestClass(list)", 546*f585d8a3SJacky Wang " TestClass is injected at", 547*f585d8a3SJacky Wang " [TestComponent] Generic.t", 548*f585d8a3SJacky Wang " Generic<TestClass> is injected at", 549*f585d8a3SJacky Wang " [TestComponent] UsesTest(genericTestClass)", 550*f585d8a3SJacky Wang " UsesTest is requested at", 551*f585d8a3SJacky Wang " [TestComponent] TestComponent.usesTest()")); 552*f585d8a3SJacky Wang }); 553*f585d8a3SJacky Wang } 554*f585d8a3SJacky Wang 555*f585d8a3SJacky Wang @Test bindingUsedOnlyInSubcomponentDependsOnBindingOnlyInSubcomponent()556*f585d8a3SJacky Wang public void bindingUsedOnlyInSubcomponentDependsOnBindingOnlyInSubcomponent() { 557*f585d8a3SJacky Wang Source parent = 558*f585d8a3SJacky Wang CompilerTests.javaSource( 559*f585d8a3SJacky Wang "Parent", 560*f585d8a3SJacky Wang "import dagger.Component;", 561*f585d8a3SJacky Wang "", 562*f585d8a3SJacky Wang "@Component(modules = ParentModule.class)", 563*f585d8a3SJacky Wang "interface Parent {", 564*f585d8a3SJacky Wang " Child child();", 565*f585d8a3SJacky Wang "}"); 566*f585d8a3SJacky Wang Source parentModule = 567*f585d8a3SJacky Wang CompilerTests.javaSource( 568*f585d8a3SJacky Wang "ParentModule", 569*f585d8a3SJacky Wang "import dagger.Module;", 570*f585d8a3SJacky Wang "import dagger.Provides;", 571*f585d8a3SJacky Wang "", 572*f585d8a3SJacky Wang "@Module", 573*f585d8a3SJacky Wang "class ParentModule {", 574*f585d8a3SJacky Wang " @Provides static Object needsString(String string) {", 575*f585d8a3SJacky Wang " return \"needs string: \" + string;", 576*f585d8a3SJacky Wang " }", 577*f585d8a3SJacky Wang "}"); 578*f585d8a3SJacky Wang Source child = 579*f585d8a3SJacky Wang CompilerTests.javaSource( 580*f585d8a3SJacky Wang "Child", 581*f585d8a3SJacky Wang "import dagger.Subcomponent;", 582*f585d8a3SJacky Wang "", 583*f585d8a3SJacky Wang "@Subcomponent(modules = ChildModule.class)", 584*f585d8a3SJacky Wang "interface Child {", 585*f585d8a3SJacky Wang " String string();", 586*f585d8a3SJacky Wang " Object needsString();", 587*f585d8a3SJacky Wang "}"); 588*f585d8a3SJacky Wang Source childModule = 589*f585d8a3SJacky Wang CompilerTests.javaSource( 590*f585d8a3SJacky Wang "ChildModule", 591*f585d8a3SJacky Wang "import dagger.Module;", 592*f585d8a3SJacky Wang "import dagger.Provides;", 593*f585d8a3SJacky Wang "", 594*f585d8a3SJacky Wang "@Module", 595*f585d8a3SJacky Wang "class ChildModule {", 596*f585d8a3SJacky Wang " @Provides static String string() {", 597*f585d8a3SJacky Wang " return \"child string\";", 598*f585d8a3SJacky Wang " }", 599*f585d8a3SJacky Wang "}"); 600*f585d8a3SJacky Wang 601*f585d8a3SJacky Wang CompilerTests.daggerCompiler(parent, parentModule, child, childModule) 602*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 603*f585d8a3SJacky Wang .compile( 604*f585d8a3SJacky Wang subject -> { 605*f585d8a3SJacky Wang subject.hasErrorCount(1); 606*f585d8a3SJacky Wang subject.hasErrorContaining("String cannot be provided"); 607*f585d8a3SJacky Wang subject.hasErrorContaining("[Child] Child.needsString()") 608*f585d8a3SJacky Wang .onSource(parent) 609*f585d8a3SJacky Wang .onLineContaining("interface Parent"); 610*f585d8a3SJacky Wang }); 611*f585d8a3SJacky Wang } 612*f585d8a3SJacky Wang 613*f585d8a3SJacky Wang @Test multibindingContributionBetweenAncestorComponentAndEntrypointComponent()614*f585d8a3SJacky Wang public void multibindingContributionBetweenAncestorComponentAndEntrypointComponent() { 615*f585d8a3SJacky Wang Source parent = 616*f585d8a3SJacky Wang CompilerTests.javaSource( 617*f585d8a3SJacky Wang "Parent", 618*f585d8a3SJacky Wang "import dagger.Component;", 619*f585d8a3SJacky Wang "", 620*f585d8a3SJacky Wang "@Component(modules = ParentModule.class)", 621*f585d8a3SJacky Wang "interface Parent {", 622*f585d8a3SJacky Wang " Child child();", 623*f585d8a3SJacky Wang "}"); 624*f585d8a3SJacky Wang Source child = 625*f585d8a3SJacky Wang CompilerTests.javaSource( 626*f585d8a3SJacky Wang "Child", 627*f585d8a3SJacky Wang "import dagger.Subcomponent;", 628*f585d8a3SJacky Wang "", 629*f585d8a3SJacky Wang "@Subcomponent(modules = ChildModule.class)", 630*f585d8a3SJacky Wang "interface Child {", 631*f585d8a3SJacky Wang " Grandchild grandchild();", 632*f585d8a3SJacky Wang "}"); 633*f585d8a3SJacky Wang Source grandchild = 634*f585d8a3SJacky Wang CompilerTests.javaSource( 635*f585d8a3SJacky Wang "Grandchild", 636*f585d8a3SJacky Wang "import dagger.Subcomponent;", 637*f585d8a3SJacky Wang "", 638*f585d8a3SJacky Wang "@Subcomponent", 639*f585d8a3SJacky Wang "interface Grandchild {", 640*f585d8a3SJacky Wang " Object object();", 641*f585d8a3SJacky Wang "}"); 642*f585d8a3SJacky Wang 643*f585d8a3SJacky Wang Source parentModule = 644*f585d8a3SJacky Wang CompilerTests.javaSource( 645*f585d8a3SJacky Wang "ParentModule", 646*f585d8a3SJacky Wang "import dagger.Module;", 647*f585d8a3SJacky Wang "import dagger.Provides;", 648*f585d8a3SJacky Wang "import dagger.multibindings.IntoSet;", 649*f585d8a3SJacky Wang "import java.util.Set;", 650*f585d8a3SJacky Wang "", 651*f585d8a3SJacky Wang "@Module", 652*f585d8a3SJacky Wang "class ParentModule {", 653*f585d8a3SJacky Wang " @Provides static Object dependsOnSet(Set<String> strings) {", 654*f585d8a3SJacky Wang " return \"needs strings: \" + strings;", 655*f585d8a3SJacky Wang " }", 656*f585d8a3SJacky Wang "", 657*f585d8a3SJacky Wang " @Provides @IntoSet static String contributesToSet() {", 658*f585d8a3SJacky Wang " return \"parent string\";", 659*f585d8a3SJacky Wang " }", 660*f585d8a3SJacky Wang "", 661*f585d8a3SJacky Wang " @Provides int missingDependency(double dub) {", 662*f585d8a3SJacky Wang " return 4;", 663*f585d8a3SJacky Wang " }", 664*f585d8a3SJacky Wang "}"); 665*f585d8a3SJacky Wang Source childModule = 666*f585d8a3SJacky Wang CompilerTests.javaSource( 667*f585d8a3SJacky Wang "ChildModule", 668*f585d8a3SJacky Wang "import dagger.Module;", 669*f585d8a3SJacky Wang "import dagger.Provides;", 670*f585d8a3SJacky Wang "import dagger.multibindings.IntoSet;", 671*f585d8a3SJacky Wang "", 672*f585d8a3SJacky Wang "@Module", 673*f585d8a3SJacky Wang "class ChildModule {", 674*f585d8a3SJacky Wang " @Provides @IntoSet static String contributesToSet(int i) {", 675*f585d8a3SJacky Wang " return \"\" + i;", 676*f585d8a3SJacky Wang " }", 677*f585d8a3SJacky Wang "}"); 678*f585d8a3SJacky Wang CompilerTests.daggerCompiler(parent, parentModule, child, childModule, grandchild) 679*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 680*f585d8a3SJacky Wang .compile( 681*f585d8a3SJacky Wang subject -> { 682*f585d8a3SJacky Wang subject.hasErrorCount(1); 683*f585d8a3SJacky Wang // TODO(b/243720787): Replace with CompilationResultSubject#hasErrorContainingMatch() 684*f585d8a3SJacky Wang subject.hasErrorContaining( 685*f585d8a3SJacky Wang String.join( 686*f585d8a3SJacky Wang "\n", 687*f585d8a3SJacky Wang "Double cannot be provided without an @Inject constructor or an " 688*f585d8a3SJacky Wang + "@Provides-annotated method.", 689*f585d8a3SJacky Wang "", 690*f585d8a3SJacky Wang " Double is injected at", 691*f585d8a3SJacky Wang " [Parent] ParentModule.missingDependency(dub)", 692*f585d8a3SJacky Wang " Integer is injected at", 693*f585d8a3SJacky Wang " [Child] ChildModule.contributesToSet(i)", 694*f585d8a3SJacky Wang " Set<String> is injected at", 695*f585d8a3SJacky Wang " [Child] ParentModule.dependsOnSet(strings)", 696*f585d8a3SJacky Wang " Object is requested at", 697*f585d8a3SJacky Wang " [Grandchild] Grandchild.object() [Parent → Child → Grandchild]")) 698*f585d8a3SJacky Wang .onSource(parent) 699*f585d8a3SJacky Wang .onLineContaining("interface Parent"); 700*f585d8a3SJacky Wang }); 701*f585d8a3SJacky Wang } 702*f585d8a3SJacky Wang 703*f585d8a3SJacky Wang @Test manyDependencies()704*f585d8a3SJacky Wang public void manyDependencies() { 705*f585d8a3SJacky Wang Source component = 706*f585d8a3SJacky Wang CompilerTests.javaSource( 707*f585d8a3SJacky Wang "test.TestComponent", 708*f585d8a3SJacky Wang "package test;", 709*f585d8a3SJacky Wang "", 710*f585d8a3SJacky Wang "import dagger.Component;", 711*f585d8a3SJacky Wang "", 712*f585d8a3SJacky Wang "@Component(modules = TestModule.class)", 713*f585d8a3SJacky Wang "interface TestComponent {", 714*f585d8a3SJacky Wang " Object object();", 715*f585d8a3SJacky Wang " String string();", 716*f585d8a3SJacky Wang "}"); 717*f585d8a3SJacky Wang Source module = 718*f585d8a3SJacky Wang CompilerTests.javaSource( 719*f585d8a3SJacky Wang "test.TestModule", 720*f585d8a3SJacky Wang "package test;", 721*f585d8a3SJacky Wang "", 722*f585d8a3SJacky Wang "import dagger.Binds;", 723*f585d8a3SJacky Wang "import dagger.Module;", 724*f585d8a3SJacky Wang "import dagger.Provides;", 725*f585d8a3SJacky Wang "", 726*f585d8a3SJacky Wang "@Module", 727*f585d8a3SJacky Wang "abstract class TestModule {", 728*f585d8a3SJacky Wang " @Binds abstract Object object(NotBound notBound);", 729*f585d8a3SJacky Wang "", 730*f585d8a3SJacky Wang " @Provides static String string(NotBound notBound, Object object) {", 731*f585d8a3SJacky Wang " return notBound.toString();", 732*f585d8a3SJacky Wang " }", 733*f585d8a3SJacky Wang "}"); 734*f585d8a3SJacky Wang Source notBound = 735*f585d8a3SJacky Wang CompilerTests.javaSource( 736*f585d8a3SJacky Wang "test.NotBound", // 737*f585d8a3SJacky Wang "package test;", 738*f585d8a3SJacky Wang "", 739*f585d8a3SJacky Wang "interface NotBound {}"); 740*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component, module, notBound) 741*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 742*f585d8a3SJacky Wang .compile( 743*f585d8a3SJacky Wang subject -> { 744*f585d8a3SJacky Wang subject.hasErrorCount(1); 745*f585d8a3SJacky Wang subject.hasErrorContaining( 746*f585d8a3SJacky Wang String.join( 747*f585d8a3SJacky Wang "\n", 748*f585d8a3SJacky Wang "NotBound cannot be provided without an @Provides-annotated method.", 749*f585d8a3SJacky Wang "", 750*f585d8a3SJacky Wang " NotBound is injected at", 751*f585d8a3SJacky Wang " [TestComponent] TestModule.object(notBound)", 752*f585d8a3SJacky Wang " Object is requested at", 753*f585d8a3SJacky Wang " [TestComponent] TestComponent.object()", 754*f585d8a3SJacky Wang "It is also requested at:", 755*f585d8a3SJacky Wang " TestModule.string(notBound, …)", 756*f585d8a3SJacky Wang "The following other entry points also depend on it:", 757*f585d8a3SJacky Wang " TestComponent.string()")) 758*f585d8a3SJacky Wang .onSource(component) 759*f585d8a3SJacky Wang .onLineContaining("interface TestComponent"); 760*f585d8a3SJacky Wang }); 761*f585d8a3SJacky Wang } 762*f585d8a3SJacky Wang 763*f585d8a3SJacky Wang @Test tooManyRequests()764*f585d8a3SJacky Wang public void tooManyRequests() { 765*f585d8a3SJacky Wang Source foo = 766*f585d8a3SJacky Wang CompilerTests.javaSource( 767*f585d8a3SJacky Wang "test.Foo", 768*f585d8a3SJacky Wang "package test;", 769*f585d8a3SJacky Wang "", 770*f585d8a3SJacky Wang "import javax.inject.Inject;", 771*f585d8a3SJacky Wang "", 772*f585d8a3SJacky Wang "final class Foo {", 773*f585d8a3SJacky Wang " @Inject Foo(", 774*f585d8a3SJacky Wang " String one,", 775*f585d8a3SJacky Wang " String two,", 776*f585d8a3SJacky Wang " String three,", 777*f585d8a3SJacky Wang " String four,", 778*f585d8a3SJacky Wang " String five,", 779*f585d8a3SJacky Wang " String six,", 780*f585d8a3SJacky Wang " String seven,", 781*f585d8a3SJacky Wang " String eight,", 782*f585d8a3SJacky Wang " String nine,", 783*f585d8a3SJacky Wang " String ten,", 784*f585d8a3SJacky Wang " String eleven,", 785*f585d8a3SJacky Wang " String twelve,", 786*f585d8a3SJacky Wang " String thirteen) {", 787*f585d8a3SJacky Wang " }", 788*f585d8a3SJacky Wang "}"); 789*f585d8a3SJacky Wang Source component = 790*f585d8a3SJacky Wang CompilerTests.javaSource( 791*f585d8a3SJacky Wang "test.TestComponent", 792*f585d8a3SJacky Wang "package test;", 793*f585d8a3SJacky Wang "", 794*f585d8a3SJacky Wang "import dagger.Component;", 795*f585d8a3SJacky Wang "", 796*f585d8a3SJacky Wang "@Component", 797*f585d8a3SJacky Wang "interface TestComponent {", 798*f585d8a3SJacky Wang " String string();", 799*f585d8a3SJacky Wang " Foo foo();", 800*f585d8a3SJacky Wang "}"); 801*f585d8a3SJacky Wang 802*f585d8a3SJacky Wang CompilerTests.daggerCompiler(foo, component) 803*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 804*f585d8a3SJacky Wang .compile( 805*f585d8a3SJacky Wang subject -> { 806*f585d8a3SJacky Wang subject.hasErrorCount(1); 807*f585d8a3SJacky Wang subject.hasErrorContaining( 808*f585d8a3SJacky Wang String.join( 809*f585d8a3SJacky Wang "\n", 810*f585d8a3SJacky Wang "String cannot be provided without an @Inject constructor or an " 811*f585d8a3SJacky Wang + "@Provides-annotated method.", 812*f585d8a3SJacky Wang "", 813*f585d8a3SJacky Wang " String is requested at", 814*f585d8a3SJacky Wang " [TestComponent] TestComponent.string()", 815*f585d8a3SJacky Wang "It is also requested at:", 816*f585d8a3SJacky Wang " Foo(one, …)", 817*f585d8a3SJacky Wang " Foo(…, two, …)", 818*f585d8a3SJacky Wang " Foo(…, three, …)", 819*f585d8a3SJacky Wang " Foo(…, four, …)", 820*f585d8a3SJacky Wang " Foo(…, five, …)", 821*f585d8a3SJacky Wang " Foo(…, six, …)", 822*f585d8a3SJacky Wang " Foo(…, seven, …)", 823*f585d8a3SJacky Wang " Foo(…, eight, …)", 824*f585d8a3SJacky Wang " Foo(…, nine, …)", 825*f585d8a3SJacky Wang " Foo(…, ten, …)", 826*f585d8a3SJacky Wang " and 3 others", 827*f585d8a3SJacky Wang "The following other entry points also depend on it:", 828*f585d8a3SJacky Wang " TestComponent.foo()")) 829*f585d8a3SJacky Wang .onSource(component) 830*f585d8a3SJacky Wang .onLineContaining("interface TestComponent"); 831*f585d8a3SJacky Wang }); 832*f585d8a3SJacky Wang } 833*f585d8a3SJacky Wang 834*f585d8a3SJacky Wang @Test tooManyEntryPoints()835*f585d8a3SJacky Wang public void tooManyEntryPoints() { 836*f585d8a3SJacky Wang Source component = 837*f585d8a3SJacky Wang CompilerTests.javaSource( 838*f585d8a3SJacky Wang "test.TestComponent", 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 TestComponent {", 845*f585d8a3SJacky Wang " String string1();", 846*f585d8a3SJacky Wang " String string2();", 847*f585d8a3SJacky Wang " String string3();", 848*f585d8a3SJacky Wang " String string4();", 849*f585d8a3SJacky Wang " String string5();", 850*f585d8a3SJacky Wang " String string6();", 851*f585d8a3SJacky Wang " String string7();", 852*f585d8a3SJacky Wang " String string8();", 853*f585d8a3SJacky Wang " String string9();", 854*f585d8a3SJacky Wang " String string10();", 855*f585d8a3SJacky Wang " String string11();", 856*f585d8a3SJacky Wang " String string12();", 857*f585d8a3SJacky Wang "}"); 858*f585d8a3SJacky Wang 859*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component) 860*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 861*f585d8a3SJacky Wang .compile( 862*f585d8a3SJacky Wang subject -> { 863*f585d8a3SJacky Wang subject.hasErrorCount(1); 864*f585d8a3SJacky Wang subject.hasErrorContaining( 865*f585d8a3SJacky Wang String.join( 866*f585d8a3SJacky Wang "\n", 867*f585d8a3SJacky Wang "String cannot be provided without an @Inject constructor or an " 868*f585d8a3SJacky Wang + "@Provides-annotated method.", 869*f585d8a3SJacky Wang "", 870*f585d8a3SJacky Wang " String is requested at", 871*f585d8a3SJacky Wang " [TestComponent] TestComponent.string1()", 872*f585d8a3SJacky Wang "The following other entry points also depend on it:", 873*f585d8a3SJacky Wang " TestComponent.string2()", 874*f585d8a3SJacky Wang " TestComponent.string3()", 875*f585d8a3SJacky Wang " TestComponent.string4()", 876*f585d8a3SJacky Wang " TestComponent.string5()", 877*f585d8a3SJacky Wang " TestComponent.string6()", 878*f585d8a3SJacky Wang " TestComponent.string7()", 879*f585d8a3SJacky Wang " TestComponent.string8()", 880*f585d8a3SJacky Wang " TestComponent.string9()", 881*f585d8a3SJacky Wang " TestComponent.string10()", 882*f585d8a3SJacky Wang " TestComponent.string11()", 883*f585d8a3SJacky Wang " and 1 other")) 884*f585d8a3SJacky Wang .onSource(component) 885*f585d8a3SJacky Wang .onLineContaining("interface TestComponent"); 886*f585d8a3SJacky Wang }); 887*f585d8a3SJacky Wang } 888*f585d8a3SJacky Wang 889*f585d8a3SJacky Wang @Test missingBindingInAllComponentsAndEntryPoints()890*f585d8a3SJacky Wang public void missingBindingInAllComponentsAndEntryPoints() { 891*f585d8a3SJacky Wang Source parent = 892*f585d8a3SJacky Wang CompilerTests.javaSource( 893*f585d8a3SJacky Wang "Parent", 894*f585d8a3SJacky Wang "import dagger.Component;", 895*f585d8a3SJacky Wang "", 896*f585d8a3SJacky Wang "@Component", 897*f585d8a3SJacky Wang "interface Parent {", 898*f585d8a3SJacky Wang " Foo foo();", 899*f585d8a3SJacky Wang " Bar bar();", 900*f585d8a3SJacky Wang " Child child();", 901*f585d8a3SJacky Wang "}"); 902*f585d8a3SJacky Wang Source child = 903*f585d8a3SJacky Wang CompilerTests.javaSource( 904*f585d8a3SJacky Wang "Child", 905*f585d8a3SJacky Wang "import dagger.Subcomponent;", 906*f585d8a3SJacky Wang "", 907*f585d8a3SJacky Wang "@Subcomponent", 908*f585d8a3SJacky Wang "interface Child {", 909*f585d8a3SJacky Wang " Foo foo();", 910*f585d8a3SJacky Wang " Baz baz();", 911*f585d8a3SJacky Wang "}"); 912*f585d8a3SJacky Wang Source foo = 913*f585d8a3SJacky Wang CompilerTests.javaSource( 914*f585d8a3SJacky Wang "Foo", 915*f585d8a3SJacky Wang "import javax.inject.Inject;", 916*f585d8a3SJacky Wang "", 917*f585d8a3SJacky Wang "class Foo {", 918*f585d8a3SJacky Wang " @Inject Foo(Bar bar) {}", 919*f585d8a3SJacky Wang "}"); 920*f585d8a3SJacky Wang Source bar = 921*f585d8a3SJacky Wang CompilerTests.javaSource( 922*f585d8a3SJacky Wang "Bar", 923*f585d8a3SJacky Wang "import javax.inject.Inject;", 924*f585d8a3SJacky Wang "", 925*f585d8a3SJacky Wang "class Bar {", 926*f585d8a3SJacky Wang " @Inject Bar(Baz baz) {}", 927*f585d8a3SJacky Wang "}"); 928*f585d8a3SJacky Wang Source baz = 929*f585d8a3SJacky Wang CompilerTests.javaSource("Baz", "class Baz {}"); 930*f585d8a3SJacky Wang 931*f585d8a3SJacky Wang CompilerTests.daggerCompiler(parent, child, foo, bar, baz) 932*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 933*f585d8a3SJacky Wang .compile( 934*f585d8a3SJacky Wang subject -> { 935*f585d8a3SJacky Wang subject.hasErrorCount(1); 936*f585d8a3SJacky Wang subject.hasErrorContaining( 937*f585d8a3SJacky Wang String.join( 938*f585d8a3SJacky Wang "\n", 939*f585d8a3SJacky Wang "Baz cannot be provided without an @Inject constructor or an " 940*f585d8a3SJacky Wang + "@Provides-annotated method.", 941*f585d8a3SJacky Wang "", 942*f585d8a3SJacky Wang " Baz is injected at", 943*f585d8a3SJacky Wang " [Parent] Bar(baz)", 944*f585d8a3SJacky Wang " Bar is requested at", 945*f585d8a3SJacky Wang " [Parent] Parent.bar()", 946*f585d8a3SJacky Wang "The following other entry points also depend on it:", 947*f585d8a3SJacky Wang " Parent.foo()", 948*f585d8a3SJacky Wang " Child.foo() [Parent → Child]", 949*f585d8a3SJacky Wang " Child.baz() [Parent → Child]")) 950*f585d8a3SJacky Wang .onSource(parent) 951*f585d8a3SJacky Wang .onLineContaining("interface Parent"); 952*f585d8a3SJacky Wang }); 953*f585d8a3SJacky Wang } 954*f585d8a3SJacky Wang 955*f585d8a3SJacky Wang // Regression test for b/147423208 where if the same subcomponent was used 956*f585d8a3SJacky Wang // in two different parts of the hierarchy and only one side had a missing binding 957*f585d8a3SJacky Wang // incorrect caching during binding graph conversion might cause validation to pass 958*f585d8a3SJacky Wang // incorrectly. 959*f585d8a3SJacky Wang @Test sameSubcomponentUsedInDifferentHierarchies()960*f585d8a3SJacky Wang public void sameSubcomponentUsedInDifferentHierarchies() { 961*f585d8a3SJacky Wang Source parent = 962*f585d8a3SJacky Wang CompilerTests.javaSource("test.Parent", 963*f585d8a3SJacky Wang "package test;", 964*f585d8a3SJacky Wang "", 965*f585d8a3SJacky Wang "import dagger.Component;", 966*f585d8a3SJacky Wang "", 967*f585d8a3SJacky Wang "@Component", 968*f585d8a3SJacky Wang "interface Parent {", 969*f585d8a3SJacky Wang " Child1 getChild1();", 970*f585d8a3SJacky Wang " Child2 getChild2();", 971*f585d8a3SJacky Wang "}"); 972*f585d8a3SJacky Wang Source child1 = 973*f585d8a3SJacky Wang CompilerTests.javaSource("test.Child1", 974*f585d8a3SJacky Wang "package test;", 975*f585d8a3SJacky Wang "", 976*f585d8a3SJacky Wang "import dagger.Subcomponent;", 977*f585d8a3SJacky Wang "", 978*f585d8a3SJacky Wang "@Subcomponent(modules = LongModule.class)", 979*f585d8a3SJacky Wang "interface Child1 {", 980*f585d8a3SJacky Wang " RepeatedSub getSub();", 981*f585d8a3SJacky Wang "}"); 982*f585d8a3SJacky Wang Source child2 = 983*f585d8a3SJacky Wang CompilerTests.javaSource("test.Child2", 984*f585d8a3SJacky Wang "package test;", 985*f585d8a3SJacky Wang "", 986*f585d8a3SJacky Wang "import dagger.Subcomponent;", 987*f585d8a3SJacky Wang "", 988*f585d8a3SJacky Wang "@Subcomponent", 989*f585d8a3SJacky Wang "interface Child2 {", 990*f585d8a3SJacky Wang " RepeatedSub getSub();", 991*f585d8a3SJacky Wang "}"); 992*f585d8a3SJacky Wang Source repeatedSub = 993*f585d8a3SJacky Wang CompilerTests.javaSource("test.RepeatedSub", 994*f585d8a3SJacky Wang "package test;", 995*f585d8a3SJacky Wang "", 996*f585d8a3SJacky Wang "import dagger.Subcomponent;", 997*f585d8a3SJacky Wang "", 998*f585d8a3SJacky Wang "@Subcomponent", 999*f585d8a3SJacky Wang "interface RepeatedSub {", 1000*f585d8a3SJacky Wang " Foo getFoo();", 1001*f585d8a3SJacky Wang "}"); 1002*f585d8a3SJacky Wang Source injectable = 1003*f585d8a3SJacky Wang CompilerTests.javaSource("test.Foo", 1004*f585d8a3SJacky Wang "package test;", 1005*f585d8a3SJacky Wang "", 1006*f585d8a3SJacky Wang "import javax.inject.Inject;", 1007*f585d8a3SJacky Wang "", 1008*f585d8a3SJacky Wang "class Foo {", 1009*f585d8a3SJacky Wang " @Inject Foo(Long value) {}", 1010*f585d8a3SJacky Wang "}"); 1011*f585d8a3SJacky Wang Source module = 1012*f585d8a3SJacky Wang CompilerTests.javaSource("test.LongModule", 1013*f585d8a3SJacky Wang "package test;", 1014*f585d8a3SJacky Wang "", 1015*f585d8a3SJacky Wang "import dagger.Module;", 1016*f585d8a3SJacky Wang "import dagger.Provides;", 1017*f585d8a3SJacky Wang "", 1018*f585d8a3SJacky Wang "@Module", 1019*f585d8a3SJacky Wang "interface LongModule {", 1020*f585d8a3SJacky Wang " @Provides static Long provideLong() {", 1021*f585d8a3SJacky Wang " return 0L;", 1022*f585d8a3SJacky Wang " }", 1023*f585d8a3SJacky Wang "}"); 1024*f585d8a3SJacky Wang CompilerTests.daggerCompiler(parent, child1, child2, repeatedSub, injectable, module) 1025*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 1026*f585d8a3SJacky Wang .compile( 1027*f585d8a3SJacky Wang subject -> { 1028*f585d8a3SJacky Wang subject.hasErrorCount(1); 1029*f585d8a3SJacky Wang subject.hasErrorContaining("Long cannot be provided without an @Inject constructor") 1030*f585d8a3SJacky Wang .onSource(parent) 1031*f585d8a3SJacky Wang .onLineContaining("interface Parent"); 1032*f585d8a3SJacky Wang }); 1033*f585d8a3SJacky Wang } 1034*f585d8a3SJacky Wang 1035*f585d8a3SJacky Wang @Test requestUnusedBindingInDifferentComponent()1036*f585d8a3SJacky Wang public void requestUnusedBindingInDifferentComponent() { 1037*f585d8a3SJacky Wang Source parent = 1038*f585d8a3SJacky Wang CompilerTests.javaSource( 1039*f585d8a3SJacky Wang "test.Parent", 1040*f585d8a3SJacky Wang "package test;", 1041*f585d8a3SJacky Wang "", 1042*f585d8a3SJacky Wang "import dagger.Component;", 1043*f585d8a3SJacky Wang "", 1044*f585d8a3SJacky Wang "@Component", 1045*f585d8a3SJacky Wang "interface Parent {", 1046*f585d8a3SJacky Wang " Child1 getChild1();", 1047*f585d8a3SJacky Wang " Child2 getChild2();", 1048*f585d8a3SJacky Wang "}"); 1049*f585d8a3SJacky Wang Source child1 = 1050*f585d8a3SJacky Wang CompilerTests.javaSource( 1051*f585d8a3SJacky Wang "test.Child1", 1052*f585d8a3SJacky Wang "package test;", 1053*f585d8a3SJacky Wang "", 1054*f585d8a3SJacky Wang "import dagger.Subcomponent;", 1055*f585d8a3SJacky Wang "", 1056*f585d8a3SJacky Wang "@Subcomponent", 1057*f585d8a3SJacky Wang "interface Child1 {", 1058*f585d8a3SJacky Wang " Object getObject();", 1059*f585d8a3SJacky Wang "}"); 1060*f585d8a3SJacky Wang Source child2 = 1061*f585d8a3SJacky Wang CompilerTests.javaSource( 1062*f585d8a3SJacky Wang "test.Child2", 1063*f585d8a3SJacky Wang "package test;", 1064*f585d8a3SJacky Wang "", 1065*f585d8a3SJacky Wang "import dagger.Subcomponent;", 1066*f585d8a3SJacky Wang "", 1067*f585d8a3SJacky Wang "@Subcomponent(modules = Child2Module.class)", 1068*f585d8a3SJacky Wang "interface Child2 {}"); 1069*f585d8a3SJacky Wang Source child2Module = 1070*f585d8a3SJacky Wang CompilerTests.javaSource( 1071*f585d8a3SJacky Wang "test.Child2Module", 1072*f585d8a3SJacky Wang "package test;", 1073*f585d8a3SJacky Wang "", 1074*f585d8a3SJacky Wang "import dagger.Module;", 1075*f585d8a3SJacky Wang "import dagger.Provides;", 1076*f585d8a3SJacky Wang "", 1077*f585d8a3SJacky Wang "@Module", 1078*f585d8a3SJacky Wang "interface Child2Module {", 1079*f585d8a3SJacky Wang " @Provides", 1080*f585d8a3SJacky Wang " static Object provideObject() {", 1081*f585d8a3SJacky Wang " return new Object();", 1082*f585d8a3SJacky Wang " }", 1083*f585d8a3SJacky Wang "}"); 1084*f585d8a3SJacky Wang 1085*f585d8a3SJacky Wang CompilerTests.daggerCompiler(parent, child1, child2, child2Module) 1086*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 1087*f585d8a3SJacky Wang .compile( 1088*f585d8a3SJacky Wang subject -> { 1089*f585d8a3SJacky Wang subject.hasErrorCount(1); 1090*f585d8a3SJacky Wang subject.hasErrorContaining( 1091*f585d8a3SJacky Wang String.join( 1092*f585d8a3SJacky Wang "\n", 1093*f585d8a3SJacky Wang "Object cannot be provided without an @Inject constructor or an " 1094*f585d8a3SJacky Wang + "@Provides-annotated method.", 1095*f585d8a3SJacky Wang "", 1096*f585d8a3SJacky Wang " Object is requested at", 1097*f585d8a3SJacky Wang " [Child1] Child1.getObject() [Parent → Child1]", 1098*f585d8a3SJacky Wang "", 1099*f585d8a3SJacky Wang "Note: Object is provided in the following other components:", 1100*f585d8a3SJacky Wang " [Child2] Child2Module.provideObject()")); 1101*f585d8a3SJacky Wang }); 1102*f585d8a3SJacky Wang } 1103*f585d8a3SJacky Wang 1104*f585d8a3SJacky Wang @Test sameSubcomponentUsedInDifferentHierarchiesMissingBindingFromOneSide()1105*f585d8a3SJacky Wang public void sameSubcomponentUsedInDifferentHierarchiesMissingBindingFromOneSide() { 1106*f585d8a3SJacky Wang Source parent = 1107*f585d8a3SJacky Wang CompilerTests.javaSource( 1108*f585d8a3SJacky Wang "test.Parent", 1109*f585d8a3SJacky Wang "package test;", 1110*f585d8a3SJacky Wang "", 1111*f585d8a3SJacky Wang "import dagger.Component;", 1112*f585d8a3SJacky Wang "", 1113*f585d8a3SJacky Wang "@Component", 1114*f585d8a3SJacky Wang "interface Parent {", 1115*f585d8a3SJacky Wang " Child1 getChild1();", 1116*f585d8a3SJacky Wang " Child2 getChild2();", 1117*f585d8a3SJacky Wang "}"); 1118*f585d8a3SJacky Wang Source child1 = 1119*f585d8a3SJacky Wang CompilerTests.javaSource( 1120*f585d8a3SJacky Wang "test.Child1", 1121*f585d8a3SJacky Wang "package test;", 1122*f585d8a3SJacky Wang "", 1123*f585d8a3SJacky Wang "import dagger.Subcomponent;", 1124*f585d8a3SJacky Wang "", 1125*f585d8a3SJacky Wang "@Subcomponent(modules = Child1Module.class)", 1126*f585d8a3SJacky Wang "interface Child1 {", 1127*f585d8a3SJacky Wang " RepeatedSub getSub();", 1128*f585d8a3SJacky Wang "}"); 1129*f585d8a3SJacky Wang Source child2 = 1130*f585d8a3SJacky Wang CompilerTests.javaSource( 1131*f585d8a3SJacky Wang "test.Child2", 1132*f585d8a3SJacky Wang "package test;", 1133*f585d8a3SJacky Wang "", 1134*f585d8a3SJacky Wang "import dagger.Subcomponent;", 1135*f585d8a3SJacky Wang "", 1136*f585d8a3SJacky Wang "@Subcomponent(modules = Child2Module.class)", 1137*f585d8a3SJacky Wang "interface Child2 {", 1138*f585d8a3SJacky Wang " RepeatedSub getSub();", 1139*f585d8a3SJacky Wang "}"); 1140*f585d8a3SJacky Wang Source repeatedSub = 1141*f585d8a3SJacky Wang CompilerTests.javaSource( 1142*f585d8a3SJacky Wang "test.RepeatedSub", 1143*f585d8a3SJacky Wang "package test;", 1144*f585d8a3SJacky Wang "", 1145*f585d8a3SJacky Wang "import dagger.Subcomponent;", 1146*f585d8a3SJacky Wang "", 1147*f585d8a3SJacky Wang "@Subcomponent(modules = RepeatedSubModule.class)", 1148*f585d8a3SJacky Wang "interface RepeatedSub {", 1149*f585d8a3SJacky Wang " Object getObject();", 1150*f585d8a3SJacky Wang "}"); 1151*f585d8a3SJacky Wang Source child1Module = 1152*f585d8a3SJacky Wang CompilerTests.javaSource( 1153*f585d8a3SJacky Wang "test.Child1Module", 1154*f585d8a3SJacky Wang "package test;", 1155*f585d8a3SJacky Wang "", 1156*f585d8a3SJacky Wang "import dagger.Module;", 1157*f585d8a3SJacky Wang "import dagger.Provides;", 1158*f585d8a3SJacky Wang "import java.util.Set;", 1159*f585d8a3SJacky Wang "import dagger.multibindings.Multibinds;", 1160*f585d8a3SJacky Wang "", 1161*f585d8a3SJacky Wang "@Module", 1162*f585d8a3SJacky Wang "interface Child1Module {", 1163*f585d8a3SJacky Wang " @Multibinds Set<Integer> multibindIntegerSet();", 1164*f585d8a3SJacky Wang "}"); 1165*f585d8a3SJacky Wang Source child2Module = 1166*f585d8a3SJacky Wang CompilerTests.javaSource( 1167*f585d8a3SJacky Wang "test.Child2Module", 1168*f585d8a3SJacky Wang "package test;", 1169*f585d8a3SJacky Wang "", 1170*f585d8a3SJacky Wang "import dagger.Module;", 1171*f585d8a3SJacky Wang "import dagger.Provides;", 1172*f585d8a3SJacky Wang "import java.util.Set;", 1173*f585d8a3SJacky Wang "import dagger.multibindings.Multibinds;", 1174*f585d8a3SJacky Wang "", 1175*f585d8a3SJacky Wang "@Module", 1176*f585d8a3SJacky Wang "interface Child2Module {", 1177*f585d8a3SJacky Wang " @Multibinds Set<Integer> multibindIntegerSet();", 1178*f585d8a3SJacky Wang "", 1179*f585d8a3SJacky Wang " @Provides", 1180*f585d8a3SJacky Wang " static Object provideObject(Set<Integer> intSet) {", 1181*f585d8a3SJacky Wang " return new Object();", 1182*f585d8a3SJacky Wang " }", 1183*f585d8a3SJacky Wang "}"); 1184*f585d8a3SJacky Wang Source repeatedSubModule = 1185*f585d8a3SJacky Wang CompilerTests.javaSource( 1186*f585d8a3SJacky Wang "test.RepeatedSubModule", 1187*f585d8a3SJacky Wang "package test;", 1188*f585d8a3SJacky Wang "", 1189*f585d8a3SJacky Wang "import dagger.Module;", 1190*f585d8a3SJacky Wang "import dagger.Provides;", 1191*f585d8a3SJacky Wang "import dagger.multibindings.IntoSet;", 1192*f585d8a3SJacky Wang "import java.util.Set;", 1193*f585d8a3SJacky Wang "import dagger.multibindings.Multibinds;", 1194*f585d8a3SJacky Wang "", 1195*f585d8a3SJacky Wang "@Module", 1196*f585d8a3SJacky Wang "interface RepeatedSubModule {", 1197*f585d8a3SJacky Wang " @Provides", 1198*f585d8a3SJacky Wang " @IntoSet", 1199*f585d8a3SJacky Wang " static Integer provideInt() {", 1200*f585d8a3SJacky Wang " return 9;", 1201*f585d8a3SJacky Wang " }", 1202*f585d8a3SJacky Wang "}"); 1203*f585d8a3SJacky Wang 1204*f585d8a3SJacky Wang CompilerTests.daggerCompiler( 1205*f585d8a3SJacky Wang parent, child1, child2, repeatedSub, child1Module, child2Module, repeatedSubModule) 1206*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 1207*f585d8a3SJacky Wang .compile( 1208*f585d8a3SJacky Wang subject -> { 1209*f585d8a3SJacky Wang subject.hasErrorCount(1); 1210*f585d8a3SJacky Wang subject.hasErrorContaining( 1211*f585d8a3SJacky Wang String.join( 1212*f585d8a3SJacky Wang "\n", 1213*f585d8a3SJacky Wang "Object cannot be provided without an @Inject constructor or an " 1214*f585d8a3SJacky Wang + "@Provides-annotated method.", 1215*f585d8a3SJacky Wang "", 1216*f585d8a3SJacky Wang " Object is requested at", 1217*f585d8a3SJacky Wang " [RepeatedSub] RepeatedSub.getObject() " 1218*f585d8a3SJacky Wang + "[Parent → Child1 → RepeatedSub]", 1219*f585d8a3SJacky Wang "", 1220*f585d8a3SJacky Wang "Note: Object is provided in the following other components:", 1221*f585d8a3SJacky Wang " [Child2] Child2Module.provideObject(…)")); 1222*f585d8a3SJacky Wang }); 1223*f585d8a3SJacky Wang } 1224*f585d8a3SJacky Wang 1225*f585d8a3SJacky Wang @Test differentComponentPkgSameSimpleNameMissingBinding()1226*f585d8a3SJacky Wang public void differentComponentPkgSameSimpleNameMissingBinding() { 1227*f585d8a3SJacky Wang Source parent = 1228*f585d8a3SJacky Wang CompilerTests.javaSource( 1229*f585d8a3SJacky Wang "test.Parent", 1230*f585d8a3SJacky Wang "package test;", 1231*f585d8a3SJacky Wang "", 1232*f585d8a3SJacky Wang "import dagger.Component;", 1233*f585d8a3SJacky Wang "", 1234*f585d8a3SJacky Wang "@Component", 1235*f585d8a3SJacky Wang "interface Parent {", 1236*f585d8a3SJacky Wang " Child1 getChild1();", 1237*f585d8a3SJacky Wang " Child2 getChild2();", 1238*f585d8a3SJacky Wang "}"); 1239*f585d8a3SJacky Wang Source child1 = 1240*f585d8a3SJacky Wang CompilerTests.javaSource( 1241*f585d8a3SJacky Wang "test.Child1", 1242*f585d8a3SJacky Wang "package test;", 1243*f585d8a3SJacky Wang "", 1244*f585d8a3SJacky Wang "import dagger.Subcomponent;", 1245*f585d8a3SJacky Wang "", 1246*f585d8a3SJacky Wang "@Subcomponent(modules = Child1Module.class)", 1247*f585d8a3SJacky Wang "interface Child1 {", 1248*f585d8a3SJacky Wang " foo.Sub getSub();", 1249*f585d8a3SJacky Wang "}"); 1250*f585d8a3SJacky Wang Source child2 = 1251*f585d8a3SJacky Wang CompilerTests.javaSource( 1252*f585d8a3SJacky Wang "test.Child2", 1253*f585d8a3SJacky Wang "package test;", 1254*f585d8a3SJacky Wang "", 1255*f585d8a3SJacky Wang "import dagger.Subcomponent;", 1256*f585d8a3SJacky Wang "", 1257*f585d8a3SJacky Wang "@Subcomponent(modules = Child2Module.class)", 1258*f585d8a3SJacky Wang "interface Child2 {", 1259*f585d8a3SJacky Wang " bar.Sub getSub();", 1260*f585d8a3SJacky Wang "}"); 1261*f585d8a3SJacky Wang Source sub1 = 1262*f585d8a3SJacky Wang CompilerTests.javaSource( 1263*f585d8a3SJacky Wang "foo.Sub", 1264*f585d8a3SJacky Wang "package foo;", 1265*f585d8a3SJacky Wang "", 1266*f585d8a3SJacky Wang "import dagger.Subcomponent;", 1267*f585d8a3SJacky Wang "", 1268*f585d8a3SJacky Wang "@Subcomponent(modules = test.RepeatedSubModule.class)", 1269*f585d8a3SJacky Wang "public interface Sub {", 1270*f585d8a3SJacky Wang " Object getObject();", 1271*f585d8a3SJacky Wang "}"); 1272*f585d8a3SJacky Wang Source sub2 = 1273*f585d8a3SJacky Wang CompilerTests.javaSource( 1274*f585d8a3SJacky Wang "bar.Sub", 1275*f585d8a3SJacky Wang "package bar;", 1276*f585d8a3SJacky Wang "", 1277*f585d8a3SJacky Wang "import dagger.Subcomponent;", 1278*f585d8a3SJacky Wang "", 1279*f585d8a3SJacky Wang "@Subcomponent(modules = test.RepeatedSubModule.class)", 1280*f585d8a3SJacky Wang "public interface Sub {", 1281*f585d8a3SJacky Wang " Object getObject();", 1282*f585d8a3SJacky Wang "}"); 1283*f585d8a3SJacky Wang Source child1Module = 1284*f585d8a3SJacky Wang CompilerTests.javaSource( 1285*f585d8a3SJacky Wang "test.Child1Module", 1286*f585d8a3SJacky Wang "package test;", 1287*f585d8a3SJacky Wang "", 1288*f585d8a3SJacky Wang "import dagger.Module;", 1289*f585d8a3SJacky Wang "import dagger.Provides;", 1290*f585d8a3SJacky Wang "import java.util.Set;", 1291*f585d8a3SJacky Wang "import dagger.multibindings.Multibinds;", 1292*f585d8a3SJacky Wang "", 1293*f585d8a3SJacky Wang "@Module", 1294*f585d8a3SJacky Wang "interface Child1Module {", 1295*f585d8a3SJacky Wang " @Multibinds Set<Integer> multibindIntegerSet();", 1296*f585d8a3SJacky Wang "}"); 1297*f585d8a3SJacky Wang Source child2Module = 1298*f585d8a3SJacky Wang CompilerTests.javaSource( 1299*f585d8a3SJacky Wang "test.Child2Module", 1300*f585d8a3SJacky Wang "package test;", 1301*f585d8a3SJacky Wang "", 1302*f585d8a3SJacky Wang "import dagger.Module;", 1303*f585d8a3SJacky Wang "import dagger.Provides;", 1304*f585d8a3SJacky Wang "import java.util.Set;", 1305*f585d8a3SJacky Wang "import dagger.multibindings.Multibinds;", 1306*f585d8a3SJacky Wang "", 1307*f585d8a3SJacky Wang "@Module", 1308*f585d8a3SJacky Wang "interface Child2Module {", 1309*f585d8a3SJacky Wang " @Multibinds Set<Integer> multibindIntegerSet();", 1310*f585d8a3SJacky Wang "", 1311*f585d8a3SJacky Wang " @Provides", 1312*f585d8a3SJacky Wang " static Object provideObject(Set<Integer> intSet) {", 1313*f585d8a3SJacky Wang " return new Object();", 1314*f585d8a3SJacky Wang " }", 1315*f585d8a3SJacky Wang "}"); 1316*f585d8a3SJacky Wang Source repeatedSubModule = 1317*f585d8a3SJacky Wang CompilerTests.javaSource( 1318*f585d8a3SJacky Wang "test.RepeatedSubModule", 1319*f585d8a3SJacky Wang "package test;", 1320*f585d8a3SJacky Wang "", 1321*f585d8a3SJacky Wang "import dagger.Module;", 1322*f585d8a3SJacky Wang "import dagger.Provides;", 1323*f585d8a3SJacky Wang "import dagger.multibindings.IntoSet;", 1324*f585d8a3SJacky Wang "import java.util.Set;", 1325*f585d8a3SJacky Wang "import dagger.multibindings.Multibinds;", 1326*f585d8a3SJacky Wang "", 1327*f585d8a3SJacky Wang "@Module", 1328*f585d8a3SJacky Wang "public interface RepeatedSubModule {", 1329*f585d8a3SJacky Wang " @Provides", 1330*f585d8a3SJacky Wang " @IntoSet", 1331*f585d8a3SJacky Wang " static Integer provideInt() {", 1332*f585d8a3SJacky Wang " return 9;", 1333*f585d8a3SJacky Wang " }", 1334*f585d8a3SJacky Wang "}"); 1335*f585d8a3SJacky Wang 1336*f585d8a3SJacky Wang CompilerTests.daggerCompiler( 1337*f585d8a3SJacky Wang parent, child1, child2, sub1, sub2, child1Module, child2Module, repeatedSubModule) 1338*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 1339*f585d8a3SJacky Wang .compile( 1340*f585d8a3SJacky Wang subject -> { 1341*f585d8a3SJacky Wang subject.hasErrorCount(1); 1342*f585d8a3SJacky Wang subject.hasErrorContaining( 1343*f585d8a3SJacky Wang String.join( 1344*f585d8a3SJacky Wang "\n", 1345*f585d8a3SJacky Wang "Object cannot be provided without an @Inject constructor or an " 1346*f585d8a3SJacky Wang + "@Provides-annotated method.", 1347*f585d8a3SJacky Wang "", 1348*f585d8a3SJacky Wang " Object is requested at", 1349*f585d8a3SJacky Wang " [Sub] Sub.getObject() [Parent → Child1 → Sub]", 1350*f585d8a3SJacky Wang "", 1351*f585d8a3SJacky Wang "Note: Object is provided in the following other components:", 1352*f585d8a3SJacky Wang " [Child2] Child2Module.provideObject(…)")); 1353*f585d8a3SJacky Wang }); 1354*f585d8a3SJacky Wang } 1355*f585d8a3SJacky Wang 1356*f585d8a3SJacky Wang @Test requestWildcardTypeWithNonWildcardTypeBindingProvided_failsWithMissingBinding()1357*f585d8a3SJacky Wang public void requestWildcardTypeWithNonWildcardTypeBindingProvided_failsWithMissingBinding() { 1358*f585d8a3SJacky Wang Source component = 1359*f585d8a3SJacky Wang CompilerTests.javaSource( 1360*f585d8a3SJacky Wang "test.MyComponent", 1361*f585d8a3SJacky Wang "package test;", 1362*f585d8a3SJacky Wang "", 1363*f585d8a3SJacky Wang "import dagger.Component;", 1364*f585d8a3SJacky Wang "import java.util.Set;", 1365*f585d8a3SJacky Wang "", 1366*f585d8a3SJacky Wang "@Component(modules = TestModule.class)", 1367*f585d8a3SJacky Wang "interface MyComponent {", 1368*f585d8a3SJacky Wang " Foo getFoo();", 1369*f585d8a3SJacky Wang " Child getChild();", 1370*f585d8a3SJacky Wang "}"); 1371*f585d8a3SJacky Wang Source child = 1372*f585d8a3SJacky Wang CompilerTests.javaSource( 1373*f585d8a3SJacky Wang "test.Child", 1374*f585d8a3SJacky Wang "package test;", 1375*f585d8a3SJacky Wang "", 1376*f585d8a3SJacky Wang "import dagger.Subcomponent;", 1377*f585d8a3SJacky Wang "", 1378*f585d8a3SJacky Wang "@Subcomponent(modules = ChildModule.class)", 1379*f585d8a3SJacky Wang "interface Child {}"); 1380*f585d8a3SJacky Wang Source childModule = 1381*f585d8a3SJacky Wang CompilerTests.javaSource( 1382*f585d8a3SJacky Wang "test.ChildModule", 1383*f585d8a3SJacky Wang "package test;", 1384*f585d8a3SJacky Wang "", 1385*f585d8a3SJacky Wang "import dagger.Module;", 1386*f585d8a3SJacky Wang "import dagger.Provides;", 1387*f585d8a3SJacky Wang "import java.util.Set;", 1388*f585d8a3SJacky Wang "import java.util.HashSet;", 1389*f585d8a3SJacky Wang "", 1390*f585d8a3SJacky Wang "@Module", 1391*f585d8a3SJacky Wang "interface ChildModule {", 1392*f585d8a3SJacky Wang " @Provides", 1393*f585d8a3SJacky Wang " static Set<? extends Bar> provideBar() {", 1394*f585d8a3SJacky Wang " return new HashSet<Bar>();", 1395*f585d8a3SJacky Wang " }", 1396*f585d8a3SJacky Wang "}"); 1397*f585d8a3SJacky Wang Source fooSrc = 1398*f585d8a3SJacky Wang CompilerTests.javaSource( 1399*f585d8a3SJacky Wang "test.Foo", 1400*f585d8a3SJacky Wang "package test;", 1401*f585d8a3SJacky Wang "", 1402*f585d8a3SJacky Wang "import javax.inject.Inject;", 1403*f585d8a3SJacky Wang "import java.util.Set;", 1404*f585d8a3SJacky Wang "", 1405*f585d8a3SJacky Wang "class Foo {", 1406*f585d8a3SJacky Wang " @Inject Foo(Set<? extends Bar> bar) {}", 1407*f585d8a3SJacky Wang "}"); 1408*f585d8a3SJacky Wang Source barSrc = 1409*f585d8a3SJacky Wang CompilerTests.javaSource("test.Bar", "package test;", "", "public interface Bar {}"); 1410*f585d8a3SJacky Wang Source moduleSrc = 1411*f585d8a3SJacky Wang CompilerTests.javaSource( 1412*f585d8a3SJacky Wang "test.TestModule", 1413*f585d8a3SJacky Wang "package test;", 1414*f585d8a3SJacky Wang "", 1415*f585d8a3SJacky Wang "import dagger.Module;", 1416*f585d8a3SJacky Wang "import dagger.Provides;", 1417*f585d8a3SJacky Wang "import dagger.multibindings.ElementsIntoSet;", 1418*f585d8a3SJacky Wang "import java.util.Set;", 1419*f585d8a3SJacky Wang "import java.util.HashSet;", 1420*f585d8a3SJacky Wang "", 1421*f585d8a3SJacky Wang "@Module", 1422*f585d8a3SJacky Wang "public class TestModule {", 1423*f585d8a3SJacky Wang " @ElementsIntoSet", 1424*f585d8a3SJacky Wang " @Provides", 1425*f585d8a3SJacky Wang " Set<Bar> provideBars() {", 1426*f585d8a3SJacky Wang " return new HashSet<Bar>();", 1427*f585d8a3SJacky Wang " }", 1428*f585d8a3SJacky Wang "}"); 1429*f585d8a3SJacky Wang 1430*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component, child, childModule, fooSrc, barSrc, moduleSrc) 1431*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 1432*f585d8a3SJacky Wang .compile( 1433*f585d8a3SJacky Wang subject -> { 1434*f585d8a3SJacky Wang subject.hasErrorCount(1); 1435*f585d8a3SJacky Wang subject 1436*f585d8a3SJacky Wang .hasErrorContaining( 1437*f585d8a3SJacky Wang String.join( 1438*f585d8a3SJacky Wang "\n", 1439*f585d8a3SJacky Wang "Set<? extends Bar> cannot be provided without an @Provides-annotated " 1440*f585d8a3SJacky Wang + "method.", 1441*f585d8a3SJacky Wang "", 1442*f585d8a3SJacky Wang " Set<? extends Bar> is injected at", 1443*f585d8a3SJacky Wang " [MyComponent] Foo(bar)", 1444*f585d8a3SJacky Wang " Foo is requested at", 1445*f585d8a3SJacky Wang " [MyComponent] MyComponent.getFoo()", 1446*f585d8a3SJacky Wang "", 1447*f585d8a3SJacky Wang "Note: Set<? extends Bar> is provided in the following other components:", 1448*f585d8a3SJacky Wang " [Child] ChildModule.provideBar()", 1449*f585d8a3SJacky Wang "", 1450*f585d8a3SJacky Wang "Note: A similar binding is provided in the following other components:", 1451*f585d8a3SJacky Wang " Set<Bar> is provided at:", 1452*f585d8a3SJacky Wang " [MyComponent] Dagger-generated binding for Set<Bar>")) 1453*f585d8a3SJacky Wang .onSource(component) 1454*f585d8a3SJacky Wang .onLineContaining("interface MyComponent"); 1455*f585d8a3SJacky Wang }); 1456*f585d8a3SJacky Wang } 1457*f585d8a3SJacky Wang 1458*f585d8a3SJacky Wang @Test 1459*f585d8a3SJacky Wang public void injectParameterDoesNotSuppressWildcardGeneration_conflictsWithNonWildcardTypeBinding()1460*f585d8a3SJacky Wang injectParameterDoesNotSuppressWildcardGeneration_conflictsWithNonWildcardTypeBinding() { 1461*f585d8a3SJacky Wang Source component = 1462*f585d8a3SJacky Wang CompilerTests.javaSource( 1463*f585d8a3SJacky Wang "test.MyComponent", 1464*f585d8a3SJacky Wang "package test;", 1465*f585d8a3SJacky Wang "", 1466*f585d8a3SJacky Wang "import dagger.Component;", 1467*f585d8a3SJacky Wang "import java.util.Set;", 1468*f585d8a3SJacky Wang "", 1469*f585d8a3SJacky Wang "@Component(modules = TestModule.class)", 1470*f585d8a3SJacky Wang "interface MyComponent {", 1471*f585d8a3SJacky Wang " Foo getFoo();", 1472*f585d8a3SJacky Wang "}"); 1473*f585d8a3SJacky Wang Source fooSrc = 1474*f585d8a3SJacky Wang CompilerTests.kotlinSource( 1475*f585d8a3SJacky Wang "Foo.kt", 1476*f585d8a3SJacky Wang "package test", 1477*f585d8a3SJacky Wang "", 1478*f585d8a3SJacky Wang "import javax.inject.Inject", 1479*f585d8a3SJacky Wang "", 1480*f585d8a3SJacky Wang "class Foo @Inject constructor(val bar: Set<Bar>) {}"); 1481*f585d8a3SJacky Wang Source barSrc = 1482*f585d8a3SJacky Wang CompilerTests.javaSource("test.Bar", "package test;", "", "public interface Bar {}"); 1483*f585d8a3SJacky Wang Source moduleSrc = 1484*f585d8a3SJacky Wang CompilerTests.javaSource( 1485*f585d8a3SJacky Wang "test.TestModule", 1486*f585d8a3SJacky Wang "package test;", 1487*f585d8a3SJacky Wang "", 1488*f585d8a3SJacky Wang "import dagger.Module;", 1489*f585d8a3SJacky Wang "import dagger.Provides;", 1490*f585d8a3SJacky Wang "import dagger.multibindings.ElementsIntoSet;", 1491*f585d8a3SJacky Wang "import java.util.Set;", 1492*f585d8a3SJacky Wang "import java.util.HashSet;", 1493*f585d8a3SJacky Wang "", 1494*f585d8a3SJacky Wang "@Module", 1495*f585d8a3SJacky Wang "public class TestModule {", 1496*f585d8a3SJacky Wang " @ElementsIntoSet", 1497*f585d8a3SJacky Wang " @Provides", 1498*f585d8a3SJacky Wang " Set<Bar> provideBars() {", 1499*f585d8a3SJacky Wang " return new HashSet<Bar>();", 1500*f585d8a3SJacky Wang " }", 1501*f585d8a3SJacky Wang "}"); 1502*f585d8a3SJacky Wang 1503*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component, fooSrc, barSrc, moduleSrc) 1504*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 1505*f585d8a3SJacky Wang .compile( 1506*f585d8a3SJacky Wang subject -> { 1507*f585d8a3SJacky Wang subject.hasErrorCount(1); 1508*f585d8a3SJacky Wang subject 1509*f585d8a3SJacky Wang .hasErrorContaining( 1510*f585d8a3SJacky Wang String.join( 1511*f585d8a3SJacky Wang "\n", 1512*f585d8a3SJacky Wang "Set<? extends Bar> cannot be provided without an @Provides-annotated " 1513*f585d8a3SJacky Wang + "method.", 1514*f585d8a3SJacky Wang "", 1515*f585d8a3SJacky Wang " Set<? extends Bar> is injected at", 1516*f585d8a3SJacky Wang " [MyComponent] Foo(bar)", 1517*f585d8a3SJacky Wang " Foo is requested at", 1518*f585d8a3SJacky Wang " [MyComponent] MyComponent.getFoo()", 1519*f585d8a3SJacky Wang "", 1520*f585d8a3SJacky Wang "Note: A similar binding is provided in the following other components:", 1521*f585d8a3SJacky Wang " Set<Bar> is provided at:", 1522*f585d8a3SJacky Wang " [MyComponent] Dagger-generated binding for Set<Bar>")) 1523*f585d8a3SJacky Wang .onSource(component) 1524*f585d8a3SJacky Wang .onLineContaining("interface MyComponent"); 1525*f585d8a3SJacky Wang }); 1526*f585d8a3SJacky Wang } 1527*f585d8a3SJacky Wang 1528*f585d8a3SJacky Wang @Test injectWildcardTypeWithNonWildcardTypeBindingProvided_failsWithMissingBinding()1529*f585d8a3SJacky Wang public void injectWildcardTypeWithNonWildcardTypeBindingProvided_failsWithMissingBinding() { 1530*f585d8a3SJacky Wang Source component = 1531*f585d8a3SJacky Wang CompilerTests.javaSource( 1532*f585d8a3SJacky Wang "test.MyComponent", 1533*f585d8a3SJacky Wang "package test;", 1534*f585d8a3SJacky Wang "", 1535*f585d8a3SJacky Wang "import dagger.Component;", 1536*f585d8a3SJacky Wang "import java.util.Set;", 1537*f585d8a3SJacky Wang "", 1538*f585d8a3SJacky Wang "@Component(modules = TestModule.class)", 1539*f585d8a3SJacky Wang "interface MyComponent {", 1540*f585d8a3SJacky Wang " Foo getFoo();", 1541*f585d8a3SJacky Wang "}"); 1542*f585d8a3SJacky Wang Source fooSrc = 1543*f585d8a3SJacky Wang CompilerTests.javaSource( 1544*f585d8a3SJacky Wang "test.Foo", 1545*f585d8a3SJacky Wang "package test;", 1546*f585d8a3SJacky Wang "", 1547*f585d8a3SJacky Wang "import javax.inject.Inject;", 1548*f585d8a3SJacky Wang "import java.util.Set;", 1549*f585d8a3SJacky Wang "", 1550*f585d8a3SJacky Wang "class Foo {", 1551*f585d8a3SJacky Wang " @Inject Set<? extends Bar> bar;", 1552*f585d8a3SJacky Wang " @Inject Foo() {}", 1553*f585d8a3SJacky Wang "}"); 1554*f585d8a3SJacky Wang Source barSrc = 1555*f585d8a3SJacky Wang CompilerTests.javaSource("test.Bar", "package test;", "", "public interface Bar {}"); 1556*f585d8a3SJacky Wang Source moduleSrc = 1557*f585d8a3SJacky Wang CompilerTests.javaSource( 1558*f585d8a3SJacky Wang "test.TestModule", 1559*f585d8a3SJacky Wang "package test;", 1560*f585d8a3SJacky Wang "", 1561*f585d8a3SJacky Wang "import dagger.Module;", 1562*f585d8a3SJacky Wang "import dagger.Provides;", 1563*f585d8a3SJacky Wang "import dagger.multibindings.ElementsIntoSet;", 1564*f585d8a3SJacky Wang "import java.util.Set;", 1565*f585d8a3SJacky Wang "import java.util.HashSet;", 1566*f585d8a3SJacky Wang "", 1567*f585d8a3SJacky Wang "@Module", 1568*f585d8a3SJacky Wang "public class TestModule {", 1569*f585d8a3SJacky Wang " @ElementsIntoSet", 1570*f585d8a3SJacky Wang " @Provides", 1571*f585d8a3SJacky Wang " Set<Bar> provideBars() {", 1572*f585d8a3SJacky Wang " return new HashSet<Bar>();", 1573*f585d8a3SJacky Wang " }", 1574*f585d8a3SJacky Wang "}"); 1575*f585d8a3SJacky Wang 1576*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component, fooSrc, barSrc, moduleSrc) 1577*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 1578*f585d8a3SJacky Wang .compile( 1579*f585d8a3SJacky Wang subject -> { 1580*f585d8a3SJacky Wang subject.hasErrorCount(1); 1581*f585d8a3SJacky Wang subject 1582*f585d8a3SJacky Wang .hasErrorContaining( 1583*f585d8a3SJacky Wang String.join( 1584*f585d8a3SJacky Wang "\n", 1585*f585d8a3SJacky Wang "Set<? extends Bar> cannot be provided without an @Provides-annotated " 1586*f585d8a3SJacky Wang + "method.", 1587*f585d8a3SJacky Wang "", 1588*f585d8a3SJacky Wang " Set<? extends Bar> is injected at", 1589*f585d8a3SJacky Wang " [MyComponent] Foo.bar", 1590*f585d8a3SJacky Wang " Foo is requested at", 1591*f585d8a3SJacky Wang " [MyComponent] MyComponent.getFoo()", 1592*f585d8a3SJacky Wang "", 1593*f585d8a3SJacky Wang "Note: A similar binding is provided in the following other components:", 1594*f585d8a3SJacky Wang " Set<Bar> is provided at:", 1595*f585d8a3SJacky Wang " [MyComponent] Dagger-generated binding for Set<Bar>")) 1596*f585d8a3SJacky Wang .onSource(component) 1597*f585d8a3SJacky Wang .onLineContaining("interface MyComponent"); 1598*f585d8a3SJacky Wang }); 1599*f585d8a3SJacky Wang } 1600*f585d8a3SJacky Wang 1601*f585d8a3SJacky Wang @Test requestFinalClassWithWildcardAnnotation_missingWildcardTypeBinding()1602*f585d8a3SJacky Wang public void requestFinalClassWithWildcardAnnotation_missingWildcardTypeBinding() { 1603*f585d8a3SJacky Wang Source component = 1604*f585d8a3SJacky Wang CompilerTests.javaSource( 1605*f585d8a3SJacky Wang "test.MyComponent", 1606*f585d8a3SJacky Wang "package test;", 1607*f585d8a3SJacky Wang "", 1608*f585d8a3SJacky Wang "import dagger.Component;", 1609*f585d8a3SJacky Wang "import java.util.Set;", 1610*f585d8a3SJacky Wang "", 1611*f585d8a3SJacky Wang "@Component(modules = TestModule.class)", 1612*f585d8a3SJacky Wang "interface MyComponent {", 1613*f585d8a3SJacky Wang " Foo getFoo();", 1614*f585d8a3SJacky Wang "}"); 1615*f585d8a3SJacky Wang Source fooSrc = 1616*f585d8a3SJacky Wang CompilerTests.kotlinSource( 1617*f585d8a3SJacky Wang "test.Foo.kt", 1618*f585d8a3SJacky Wang "package test", 1619*f585d8a3SJacky Wang "", 1620*f585d8a3SJacky Wang "import javax.inject.Inject", 1621*f585d8a3SJacky Wang "", 1622*f585d8a3SJacky Wang "class Foo @Inject constructor(val bar: List<Bar>) {}"); 1623*f585d8a3SJacky Wang Source barSrc = 1624*f585d8a3SJacky Wang CompilerTests.javaSource("test.Bar", "package test;", "", "public final class Bar {}"); 1625*f585d8a3SJacky Wang Source moduleSrc = 1626*f585d8a3SJacky Wang CompilerTests.kotlinSource( 1627*f585d8a3SJacky Wang "test.TestModule.kt", 1628*f585d8a3SJacky Wang "package test", 1629*f585d8a3SJacky Wang "", 1630*f585d8a3SJacky Wang "import dagger.Module", 1631*f585d8a3SJacky Wang "import dagger.Provides", 1632*f585d8a3SJacky Wang "import dagger.multibindings.ElementsIntoSet", 1633*f585d8a3SJacky Wang "", 1634*f585d8a3SJacky Wang "@Module", 1635*f585d8a3SJacky Wang "object TestModule {", 1636*f585d8a3SJacky Wang " @Provides fun provideBars(): List<@JvmWildcard Bar> = setOf()", 1637*f585d8a3SJacky Wang "}"); 1638*f585d8a3SJacky Wang 1639*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component, fooSrc, barSrc, moduleSrc) 1640*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 1641*f585d8a3SJacky Wang .compile( 1642*f585d8a3SJacky Wang subject -> { 1643*f585d8a3SJacky Wang subject.hasErrorCount(1); 1644*f585d8a3SJacky Wang subject 1645*f585d8a3SJacky Wang .hasErrorContaining( 1646*f585d8a3SJacky Wang String.join( 1647*f585d8a3SJacky Wang "\n", 1648*f585d8a3SJacky Wang "List<Bar> cannot be provided without an @Provides-annotated method.", 1649*f585d8a3SJacky Wang "", 1650*f585d8a3SJacky Wang " List<Bar> is injected at", 1651*f585d8a3SJacky Wang " [MyComponent] Foo(bar)", 1652*f585d8a3SJacky Wang " Foo is requested at", 1653*f585d8a3SJacky Wang " [MyComponent] MyComponent.getFoo()", 1654*f585d8a3SJacky Wang "", 1655*f585d8a3SJacky Wang "Note: A similar binding is provided in the following other components:", 1656*f585d8a3SJacky Wang " List<? extends Bar> is provided at:", 1657*f585d8a3SJacky Wang " [MyComponent] TestModule.provideBars()")) 1658*f585d8a3SJacky Wang .onSource(component) 1659*f585d8a3SJacky Wang .onLineContaining("interface MyComponent"); 1660*f585d8a3SJacky Wang }); 1661*f585d8a3SJacky Wang } 1662*f585d8a3SJacky Wang 1663*f585d8a3SJacky Wang @Test multipleTypeParameters_notSuppressWildcardType_failsWithMissingBinding()1664*f585d8a3SJacky Wang public void multipleTypeParameters_notSuppressWildcardType_failsWithMissingBinding() { 1665*f585d8a3SJacky Wang Source component = 1666*f585d8a3SJacky Wang CompilerTests.javaSource( 1667*f585d8a3SJacky Wang "test.MyComponent", 1668*f585d8a3SJacky Wang "package test;", 1669*f585d8a3SJacky Wang "", 1670*f585d8a3SJacky Wang "import dagger.Component;", 1671*f585d8a3SJacky Wang "import java.util.Set;", 1672*f585d8a3SJacky Wang "", 1673*f585d8a3SJacky Wang "@Component(modules = TestModule.class)", 1674*f585d8a3SJacky Wang "interface MyComponent {", 1675*f585d8a3SJacky Wang " Foo getFoo();", 1676*f585d8a3SJacky Wang "}"); 1677*f585d8a3SJacky Wang Source fooSrc = 1678*f585d8a3SJacky Wang CompilerTests.kotlinSource( 1679*f585d8a3SJacky Wang "test.Foo.kt", 1680*f585d8a3SJacky Wang "package test", 1681*f585d8a3SJacky Wang "", 1682*f585d8a3SJacky Wang "import javax.inject.Inject", 1683*f585d8a3SJacky Wang "", 1684*f585d8a3SJacky Wang "class Foo @Inject constructor(val bar: Bar<Baz, Baz, Set<Baz>>) {}"); 1685*f585d8a3SJacky Wang Source barSrc = 1686*f585d8a3SJacky Wang CompilerTests.kotlinSource( 1687*f585d8a3SJacky Wang "test.Bar.kt", "package test", "", "class Bar<out T1, T2, T3> {}"); 1688*f585d8a3SJacky Wang 1689*f585d8a3SJacky Wang Source bazSrc = 1690*f585d8a3SJacky Wang CompilerTests.javaSource("test.Baz", "package test;", "", "public interface Baz {}"); 1691*f585d8a3SJacky Wang 1692*f585d8a3SJacky Wang Source moduleSrc = 1693*f585d8a3SJacky Wang CompilerTests.javaSource( 1694*f585d8a3SJacky Wang "test.TestModule", 1695*f585d8a3SJacky Wang "package test;", 1696*f585d8a3SJacky Wang "", 1697*f585d8a3SJacky Wang "import dagger.Module;", 1698*f585d8a3SJacky Wang "import dagger.Provides;", 1699*f585d8a3SJacky Wang "import java.util.Set;", 1700*f585d8a3SJacky Wang "", 1701*f585d8a3SJacky Wang "@Module", 1702*f585d8a3SJacky Wang "public class TestModule {", 1703*f585d8a3SJacky Wang " @Provides", 1704*f585d8a3SJacky Wang " Bar<Baz, Baz, Set<Baz>> provideBar() {", 1705*f585d8a3SJacky Wang " return new Bar<Baz, Baz, Set<Baz>>();", 1706*f585d8a3SJacky Wang " }", 1707*f585d8a3SJacky Wang "}"); 1708*f585d8a3SJacky Wang 1709*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component, fooSrc, barSrc, bazSrc, moduleSrc) 1710*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 1711*f585d8a3SJacky Wang .compile( 1712*f585d8a3SJacky Wang subject -> { 1713*f585d8a3SJacky Wang subject.hasErrorCount(1); 1714*f585d8a3SJacky Wang subject 1715*f585d8a3SJacky Wang .hasErrorContaining( 1716*f585d8a3SJacky Wang String.join( 1717*f585d8a3SJacky Wang "\n", 1718*f585d8a3SJacky Wang // TODO(b/324325095): Align KSP and KAPT error message. 1719*f585d8a3SJacky Wang CompilerTests.backend(subject) == XProcessingEnv.Backend.KSP 1720*f585d8a3SJacky Wang ? "Bar<? extends Baz,Baz,Set<Baz>> cannot be provided without an " 1721*f585d8a3SJacky Wang + "@Inject constructor or an @Provides-annotated method." 1722*f585d8a3SJacky Wang : "Bar<? extends Baz,Baz,Set<Baz>> cannot be provided without an " 1723*f585d8a3SJacky Wang + "@Provides-annotated method.", 1724*f585d8a3SJacky Wang "", 1725*f585d8a3SJacky Wang " Bar<? extends Baz,Baz,Set<Baz>> is injected at", 1726*f585d8a3SJacky Wang " [MyComponent] Foo(bar)", 1727*f585d8a3SJacky Wang " Foo is requested at", 1728*f585d8a3SJacky Wang " [MyComponent] MyComponent.getFoo()", 1729*f585d8a3SJacky Wang "", 1730*f585d8a3SJacky Wang "Note: A similar binding is provided in the following other components:", 1731*f585d8a3SJacky Wang " Bar<Baz,Baz,Set<Baz>> is provided at:", 1732*f585d8a3SJacky Wang " [MyComponent] TestModule.provideBar()")) 1733*f585d8a3SJacky Wang .onSource(component) 1734*f585d8a3SJacky Wang .onLineContaining("interface MyComponent"); 1735*f585d8a3SJacky Wang }); 1736*f585d8a3SJacky Wang } 1737*f585d8a3SJacky Wang 1738*f585d8a3SJacky Wang @Test missingBindingWithoutQualifier_warnAboutSimilarTypeWithQualifierExists()1739*f585d8a3SJacky Wang public void missingBindingWithoutQualifier_warnAboutSimilarTypeWithQualifierExists() { 1740*f585d8a3SJacky Wang Source qualifierSrc = 1741*f585d8a3SJacky Wang CompilerTests.javaSource( 1742*f585d8a3SJacky Wang "test.MyQualifier", 1743*f585d8a3SJacky Wang "package test;", 1744*f585d8a3SJacky Wang "", 1745*f585d8a3SJacky Wang "import javax.inject.Qualifier;", 1746*f585d8a3SJacky Wang "", 1747*f585d8a3SJacky Wang "@Qualifier", 1748*f585d8a3SJacky Wang "@interface MyQualifier {}"); 1749*f585d8a3SJacky Wang Source component = 1750*f585d8a3SJacky Wang CompilerTests.javaSource( 1751*f585d8a3SJacky Wang "test.MyComponent", 1752*f585d8a3SJacky Wang "package test;", 1753*f585d8a3SJacky Wang "", 1754*f585d8a3SJacky Wang "import dagger.Component;", 1755*f585d8a3SJacky Wang "import java.util.Set;", 1756*f585d8a3SJacky Wang "", 1757*f585d8a3SJacky Wang "@Component(modules = TestModule.class)", 1758*f585d8a3SJacky Wang "interface MyComponent {", 1759*f585d8a3SJacky Wang " Foo getFoo();", 1760*f585d8a3SJacky Wang "}"); 1761*f585d8a3SJacky Wang Source fooSrc = 1762*f585d8a3SJacky Wang CompilerTests.kotlinSource( 1763*f585d8a3SJacky Wang "Foo.kt", 1764*f585d8a3SJacky Wang "package test", 1765*f585d8a3SJacky Wang "", 1766*f585d8a3SJacky Wang "import javax.inject.Inject", 1767*f585d8a3SJacky Wang "", 1768*f585d8a3SJacky Wang "class Foo @Inject constructor(val bar: Set<Bar>) {}"); 1769*f585d8a3SJacky Wang Source barSrc = 1770*f585d8a3SJacky Wang CompilerTests.javaSource("test.Bar", "package test;", "", "public interface Bar {}"); 1771*f585d8a3SJacky Wang Source moduleSrc = 1772*f585d8a3SJacky Wang CompilerTests.javaSource( 1773*f585d8a3SJacky Wang "test.TestModule", 1774*f585d8a3SJacky Wang "package test;", 1775*f585d8a3SJacky Wang "", 1776*f585d8a3SJacky Wang "import dagger.Module;", 1777*f585d8a3SJacky Wang "import dagger.Provides;", 1778*f585d8a3SJacky Wang "import dagger.multibindings.ElementsIntoSet;", 1779*f585d8a3SJacky Wang "import java.util.Set;", 1780*f585d8a3SJacky Wang "import java.util.HashSet;", 1781*f585d8a3SJacky Wang "", 1782*f585d8a3SJacky Wang "@Module", 1783*f585d8a3SJacky Wang "public class TestModule {", 1784*f585d8a3SJacky Wang " @ElementsIntoSet", 1785*f585d8a3SJacky Wang " @Provides", 1786*f585d8a3SJacky Wang " @MyQualifier", 1787*f585d8a3SJacky Wang " Set<Bar> provideBars() {", 1788*f585d8a3SJacky Wang " return new HashSet<Bar>();", 1789*f585d8a3SJacky Wang " }", 1790*f585d8a3SJacky Wang "}"); 1791*f585d8a3SJacky Wang 1792*f585d8a3SJacky Wang CompilerTests.daggerCompiler(qualifierSrc, component, fooSrc, barSrc, moduleSrc) 1793*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 1794*f585d8a3SJacky Wang .compile( 1795*f585d8a3SJacky Wang subject -> { 1796*f585d8a3SJacky Wang subject.hasErrorCount(1); 1797*f585d8a3SJacky Wang subject.hasErrorContaining("MissingBinding"); 1798*f585d8a3SJacky Wang List<DiagnosticMessage> diagnostics = 1799*f585d8a3SJacky Wang subject.getCompilationResult().getDiagnostics().get(Diagnostic.Kind.ERROR); 1800*f585d8a3SJacky Wang assertThat(diagnostics).hasSize(1); 1801*f585d8a3SJacky Wang assertThat(diagnostics.get(0).getMsg()) 1802*f585d8a3SJacky Wang .doesNotContain("bindings with similar types exists in the graph"); 1803*f585d8a3SJacky Wang }); 1804*f585d8a3SJacky Wang } 1805*f585d8a3SJacky Wang 1806*f585d8a3SJacky Wang @Test missingWildcardTypeWithObjectBound_providedRawType_warnAboutSimilarTypeExists()1807*f585d8a3SJacky Wang public void missingWildcardTypeWithObjectBound_providedRawType_warnAboutSimilarTypeExists() { 1808*f585d8a3SJacky Wang Source component = 1809*f585d8a3SJacky Wang CompilerTests.javaSource( 1810*f585d8a3SJacky Wang "test.MyComponent", 1811*f585d8a3SJacky Wang "package test;", 1812*f585d8a3SJacky Wang "", 1813*f585d8a3SJacky Wang "import dagger.Component;", 1814*f585d8a3SJacky Wang "import java.util.Set;", 1815*f585d8a3SJacky Wang "", 1816*f585d8a3SJacky Wang "@Component(modules = TestModule.class)", 1817*f585d8a3SJacky Wang "interface MyComponent {", 1818*f585d8a3SJacky Wang " Foo getFoo();", 1819*f585d8a3SJacky Wang "}"); 1820*f585d8a3SJacky Wang Source fooSrc = 1821*f585d8a3SJacky Wang CompilerTests.kotlinSource( 1822*f585d8a3SJacky Wang "test.Foo.kt", 1823*f585d8a3SJacky Wang "package test", 1824*f585d8a3SJacky Wang "", 1825*f585d8a3SJacky Wang "import javax.inject.Inject", 1826*f585d8a3SJacky Wang "", 1827*f585d8a3SJacky Wang "class Foo @Inject constructor(val bar: Bar<Object>) {}"); 1828*f585d8a3SJacky Wang Source barSrc = 1829*f585d8a3SJacky Wang CompilerTests.kotlinSource("test.Bar.kt", "package test", "", "class Bar<out T1> {}"); 1830*f585d8a3SJacky Wang Source moduleSrc = 1831*f585d8a3SJacky Wang CompilerTests.javaSource( 1832*f585d8a3SJacky Wang "test.TestModule", 1833*f585d8a3SJacky Wang "package test;", 1834*f585d8a3SJacky Wang "", 1835*f585d8a3SJacky Wang "import dagger.Module;", 1836*f585d8a3SJacky Wang "import dagger.Provides;", 1837*f585d8a3SJacky Wang "import java.util.Set;", 1838*f585d8a3SJacky Wang "", 1839*f585d8a3SJacky Wang "@Module", 1840*f585d8a3SJacky Wang "public class TestModule {", 1841*f585d8a3SJacky Wang " @Provides", 1842*f585d8a3SJacky Wang " Bar provideBar() {", 1843*f585d8a3SJacky Wang " return new Bar<Object>();", 1844*f585d8a3SJacky Wang " }", 1845*f585d8a3SJacky Wang "}"); 1846*f585d8a3SJacky Wang 1847*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component, fooSrc, barSrc, moduleSrc) 1848*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 1849*f585d8a3SJacky Wang .compile( 1850*f585d8a3SJacky Wang subject -> { 1851*f585d8a3SJacky Wang subject.hasErrorCount(1); 1852*f585d8a3SJacky Wang subject.hasErrorContaining( 1853*f585d8a3SJacky Wang String.join( 1854*f585d8a3SJacky Wang "\n", 1855*f585d8a3SJacky Wang // TODO(b/324325095): Align KSP and KAPT error message. 1856*f585d8a3SJacky Wang CompilerTests.backend(subject) == XProcessingEnv.Backend.KSP 1857*f585d8a3SJacky Wang ? "Bar<?> cannot be provided without an @Inject constructor or an " 1858*f585d8a3SJacky Wang + "@Provides-annotated method." 1859*f585d8a3SJacky Wang : "Bar<?> cannot be provided without an @Provides-annotated method.", 1860*f585d8a3SJacky Wang "", 1861*f585d8a3SJacky Wang " Bar<?> is injected at", 1862*f585d8a3SJacky Wang " [MyComponent] Foo(bar)", 1863*f585d8a3SJacky Wang " Foo is requested at", 1864*f585d8a3SJacky Wang " [MyComponent] MyComponent.getFoo()", 1865*f585d8a3SJacky Wang "", 1866*f585d8a3SJacky Wang "Note: A similar binding is provided in the following other components:", 1867*f585d8a3SJacky Wang " Bar is provided at:", 1868*f585d8a3SJacky Wang " [MyComponent] TestModule.provideBar()")); 1869*f585d8a3SJacky Wang }); 1870*f585d8a3SJacky Wang } 1871*f585d8a3SJacky Wang 1872*f585d8a3SJacky Wang @Test missingWildcardType_providedRawType_warnAboutSimilarTypeExists()1873*f585d8a3SJacky Wang public void missingWildcardType_providedRawType_warnAboutSimilarTypeExists() { 1874*f585d8a3SJacky Wang Source component = 1875*f585d8a3SJacky Wang CompilerTests.javaSource( 1876*f585d8a3SJacky Wang "test.MyComponent", 1877*f585d8a3SJacky Wang "package test;", 1878*f585d8a3SJacky Wang "", 1879*f585d8a3SJacky Wang "import dagger.Component;", 1880*f585d8a3SJacky Wang "import java.util.Set;", 1881*f585d8a3SJacky Wang "", 1882*f585d8a3SJacky Wang "@Component(modules = TestModule.class)", 1883*f585d8a3SJacky Wang "interface MyComponent {", 1884*f585d8a3SJacky Wang " Foo getFoo();", 1885*f585d8a3SJacky Wang "}"); 1886*f585d8a3SJacky Wang Source fooSrc = 1887*f585d8a3SJacky Wang CompilerTests.kotlinSource( 1888*f585d8a3SJacky Wang "test.Foo.kt", 1889*f585d8a3SJacky Wang "package test", 1890*f585d8a3SJacky Wang "", 1891*f585d8a3SJacky Wang "import javax.inject.Inject", 1892*f585d8a3SJacky Wang "", 1893*f585d8a3SJacky Wang "class Foo @Inject constructor(val bar: Bar<String>) {}"); 1894*f585d8a3SJacky Wang Source barSrc = 1895*f585d8a3SJacky Wang CompilerTests.kotlinSource("test.Bar.kt", "package test", "", "class Bar<out T1> {}"); 1896*f585d8a3SJacky Wang Source moduleSrc = 1897*f585d8a3SJacky Wang CompilerTests.javaSource( 1898*f585d8a3SJacky Wang "test.TestModule", 1899*f585d8a3SJacky Wang "package test;", 1900*f585d8a3SJacky Wang "", 1901*f585d8a3SJacky Wang "import dagger.Module;", 1902*f585d8a3SJacky Wang "import dagger.Provides;", 1903*f585d8a3SJacky Wang "import java.util.Set;", 1904*f585d8a3SJacky Wang "", 1905*f585d8a3SJacky Wang "@Module", 1906*f585d8a3SJacky Wang "public class TestModule {", 1907*f585d8a3SJacky Wang " @Provides", 1908*f585d8a3SJacky Wang " Bar provideBar() {", 1909*f585d8a3SJacky Wang " return new Bar<Object>();", 1910*f585d8a3SJacky Wang " }", 1911*f585d8a3SJacky Wang "}"); 1912*f585d8a3SJacky Wang 1913*f585d8a3SJacky Wang CompilerTests.daggerCompiler(component, fooSrc, barSrc, moduleSrc) 1914*f585d8a3SJacky Wang .withProcessingOptions(compilerMode.processorOptions()) 1915*f585d8a3SJacky Wang .compile( 1916*f585d8a3SJacky Wang subject -> { 1917*f585d8a3SJacky Wang subject.hasErrorCount(1); 1918*f585d8a3SJacky Wang subject.hasErrorContaining("MissingBinding"); 1919*f585d8a3SJacky Wang List<DiagnosticMessage> diagnostics = 1920*f585d8a3SJacky Wang subject.getCompilationResult().getDiagnostics().get(Diagnostic.Kind.ERROR); 1921*f585d8a3SJacky Wang assertThat(diagnostics).hasSize(1); 1922*f585d8a3SJacky Wang assertThat(diagnostics.get(0).getMsg()) 1923*f585d8a3SJacky Wang .doesNotContain("bindings with similar types exists in the graph"); 1924*f585d8a3SJacky Wang }); 1925*f585d8a3SJacky Wang } 1926*f585d8a3SJacky Wang } 1927