1 /* 2 * Copyright (C) 2014 Google, Inc. 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 package dagger.internal.codegen; 17 18 import com.google.common.base.Joiner; 19 import com.google.common.collect.ImmutableList; 20 import com.google.common.collect.ImmutableSet; 21 import com.google.testing.compile.JavaFileObjects; 22 import dagger.internal.codegen.writer.StringLiteral; 23 import java.io.IOException; 24 import java.io.Writer; 25 import java.util.Set; 26 import javax.annotation.processing.AbstractProcessor; 27 import javax.annotation.processing.Processor; 28 import javax.annotation.processing.RoundEnvironment; 29 import javax.lang.model.element.TypeElement; 30 import javax.tools.JavaFileObject; 31 import org.junit.Ignore; 32 import org.junit.Test; 33 import org.junit.runner.RunWith; 34 import org.junit.runners.JUnit4; 35 36 import static com.google.common.truth.Truth.assertAbout; 37 import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; 38 import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources; 39 import static dagger.internal.codegen.ErrorMessages.REFERENCED_MODULES_MUST_NOT_BE_ABSTRACT; 40 import static javax.tools.StandardLocation.SOURCE_OUTPUT; 41 42 @RunWith(JUnit4.class) 43 public class ComponentProcessorTest { 44 private static final StringLiteral NPE_LITERAL = 45 StringLiteral.forValue(ErrorMessages.CANNOT_RETURN_NULL_FROM_NON_NULLABLE_COMPONENT_METHOD); 46 componentOnConcreteClass()47 @Test public void componentOnConcreteClass() { 48 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.NotAComponent", 49 "package test;", 50 "", 51 "import dagger.Component;", 52 "", 53 "@Component", 54 "final class NotAComponent {}"); 55 assertAbout(javaSource()).that(componentFile) 56 .processedWith(new ComponentProcessor()) 57 .failsToCompile() 58 .withErrorContaining("interface"); 59 } 60 componentOnEnum()61 @Test public void componentOnEnum() { 62 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.NotAComponent", 63 "package test;", 64 "", 65 "import dagger.Component;", 66 "", 67 "@Component", 68 "enum NotAComponent {", 69 " INSTANCE", 70 "}"); 71 assertAbout(javaSource()).that(componentFile) 72 .processedWith(new ComponentProcessor()) 73 .failsToCompile() 74 .withErrorContaining("interface"); 75 } 76 componentOnAnnotation()77 @Test public void componentOnAnnotation() { 78 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.NotAComponent", 79 "package test;", 80 "", 81 "import dagger.Component;", 82 "", 83 "@Component", 84 "@interface NotAComponent {}"); 85 assertAbout(javaSource()).that(componentFile) 86 .processedWith(new ComponentProcessor()) 87 .failsToCompile() 88 .withErrorContaining("interface"); 89 } 90 nonModuleModule()91 @Test public void nonModuleModule() { 92 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.NotAComponent", 93 "package test;", 94 "", 95 "import dagger.Component;", 96 "", 97 "@Component(modules = Object.class)", 98 "interface NotAComponent {}"); 99 assertAbout(javaSource()).that(componentFile) 100 .processedWith(new ComponentProcessor()) 101 .failsToCompile() 102 .withErrorContaining("is not annotated with @Module"); 103 } 104 checkCannotReferToModuleOfType(String moduleType)105 private void checkCannotReferToModuleOfType(String moduleType) { 106 JavaFileObject moduleFile = JavaFileObjects.forSourceLines("test.TestModule", 107 "package test;", 108 "", 109 "import dagger.Module;", 110 "", 111 "@Module", 112 moduleType + " TestModule {}"); 113 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.BadComponent", 114 "package test;", 115 "", 116 "import dagger.Component;", 117 "", 118 "@Component(modules = TestModule.class)", 119 "interface BadComponent {}"); 120 assertAbout(javaSources()).that(ImmutableList.of(moduleFile, componentFile)) 121 .processedWith(new ComponentProcessor()) 122 .failsToCompile() 123 .withErrorContaining( 124 String.format(REFERENCED_MODULES_MUST_NOT_BE_ABSTRACT, "test.TestModule")); 125 } 126 cannotReferToAbstractClassModules()127 @Test public void cannotReferToAbstractClassModules() { 128 checkCannotReferToModuleOfType("abstract class"); 129 } 130 cannotReferToInterfaceModules()131 @Test public void cannotReferToInterfaceModules() { 132 checkCannotReferToModuleOfType("interface"); 133 } 134 doubleBindingFromResolvedModules()135 @Test public void doubleBindingFromResolvedModules() { 136 JavaFileObject parent = JavaFileObjects.forSourceLines("test.ParentModule", 137 "package test;", 138 "", 139 "import dagger.Module;", 140 "import dagger.Provides;", 141 "import java.util.List;", 142 "", 143 "@Module", 144 "abstract class ParentModule<A> {", 145 " @Provides List<A> provideListB(A a) { return null; }", 146 "}"); 147 JavaFileObject child = JavaFileObjects.forSourceLines("test.ChildModule", 148 "package test;", 149 "", 150 "import dagger.Module;", 151 "import dagger.Provides;", 152 "", 153 "@Module", 154 "class ChildNumberModule extends ParentModule<Integer> {", 155 " @Provides Integer provideInteger() { return null; }", 156 "}"); 157 JavaFileObject another = JavaFileObjects.forSourceLines("test.AnotherModule", 158 "package test;", 159 "", 160 "import dagger.Module;", 161 "import dagger.Provides;", 162 "import java.util.List;", 163 "", 164 "@Module", 165 "class AnotherModule {", 166 " @Provides List<Integer> provideListOfInteger() { return null; }", 167 "}"); 168 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.BadComponent", 169 "package test;", 170 "", 171 "import dagger.Component;", 172 "import java.util.List;", 173 "", 174 "@Component(modules = {ChildNumberModule.class, AnotherModule.class})", 175 "interface BadComponent {", 176 " List<Integer> listOfInteger();", 177 "}"); 178 assertAbout(javaSources()).that(ImmutableList.of(parent, child, another, componentFile)) 179 .processedWith(new ComponentProcessor()) 180 .failsToCompile().withErrorContaining( 181 "java.util.List<java.lang.Integer> is bound multiple times") 182 .and().withErrorContaining( 183 "@Provides List<Integer> test.ChildNumberModule.provideListB(Integer)") 184 .and().withErrorContaining( 185 "@Provides List<Integer> test.AnotherModule.provideListOfInteger()"); 186 } 187 simpleComponent()188 @Test public void simpleComponent() { 189 JavaFileObject injectableTypeFile = JavaFileObjects.forSourceLines("test.SomeInjectableType", 190 "package test;", 191 "", 192 "import javax.inject.Inject;", 193 "", 194 "final class SomeInjectableType {", 195 " @Inject SomeInjectableType() {}", 196 "}"); 197 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 198 "package test;", 199 "", 200 "import dagger.Component;", 201 "import dagger.Lazy;", 202 "", 203 "import javax.inject.Provider;", 204 "", 205 "@Component", 206 "interface SimpleComponent {", 207 " SomeInjectableType someInjectableType();", 208 " Lazy<SomeInjectableType> lazySomeInjectableType();", 209 " Provider<SomeInjectableType> someInjectableTypeProvider();", 210 "}"); 211 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 212 "test.DaggerSimpleComponent", 213 "package test;", 214 "", 215 "import dagger.Lazy;", 216 "import dagger.internal.DoubleCheckLazy;", 217 "import javax.annotation.Generated;", 218 "import javax.inject.Provider;", 219 "", 220 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 221 "public final class DaggerSimpleComponent implements SimpleComponent {", 222 " private DaggerSimpleComponent(Builder builder) {", 223 " assert builder != null;", 224 " initialize(builder);", 225 " }", 226 "", 227 " public static Builder builder() {", 228 " return new Builder();", 229 " }", 230 "", 231 " public static SimpleComponent create() {", 232 " return builder().build();", 233 " }", 234 "", 235 " @SuppressWarnings(\"unchecked\")", 236 " private void initialize(final Builder builder) {", 237 " }", 238 "", 239 " @Override", 240 " public SomeInjectableType someInjectableType() {", 241 " return SomeInjectableType_Factory.create().get();", 242 " }", 243 "", 244 " @Override", 245 " public Lazy<SomeInjectableType> lazySomeInjectableType() {", 246 " return DoubleCheckLazy.create(SomeInjectableType_Factory.create());", 247 " }", 248 "", 249 " @Override", 250 " public Provider<SomeInjectableType> someInjectableTypeProvider() {", 251 " return SomeInjectableType_Factory.create();", 252 " }", 253 "", 254 " public static final class Builder {", 255 " private Builder() {", 256 " }", 257 "", 258 " public SimpleComponent build() {", 259 " return new DaggerSimpleComponent(this);", 260 " }", 261 " }", 262 "}"); 263 assertAbout(javaSources()).that(ImmutableList.of(injectableTypeFile, componentFile)) 264 .processedWith(new ComponentProcessor()) 265 .compilesWithoutError() 266 .and().generatesSources(generatedComponent); 267 } 268 componentWithScope()269 @Test public void componentWithScope() { 270 JavaFileObject injectableTypeFile = JavaFileObjects.forSourceLines("test.SomeInjectableType", 271 "package test;", 272 "", 273 "import javax.inject.Inject;", 274 "import javax.inject.Singleton;", 275 "", 276 "@Singleton", 277 "final class SomeInjectableType {", 278 " @Inject SomeInjectableType() {}", 279 "}"); 280 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 281 "package test;", 282 "", 283 "import dagger.Component;", 284 "import dagger.Lazy;", 285 "import javax.inject.Provider;", 286 "import javax.inject.Singleton;", 287 "", 288 "@Singleton", 289 "@Component", 290 "interface SimpleComponent {", 291 " SomeInjectableType someInjectableType();", 292 " Lazy<SomeInjectableType> lazySomeInjectableType();", 293 " Provider<SomeInjectableType> someInjectableTypeProvider();", 294 "}"); 295 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 296 "test.DaggerSimpleComponent", 297 "package test;", 298 "", 299 "import dagger.Lazy;", 300 "import dagger.internal.DoubleCheckLazy;", 301 "import dagger.internal.ScopedProvider;", 302 "import javax.annotation.Generated;", 303 "import javax.inject.Provider;", 304 "", 305 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 306 "public final class DaggerSimpleComponent implements SimpleComponent {", 307 " private Provider<SomeInjectableType> someInjectableTypeProvider;", 308 "", 309 " private DaggerSimpleComponent(Builder builder) {", 310 " assert builder != null;", 311 " initialize(builder);", 312 " }", 313 "", 314 " public static Builder builder() {", 315 " return new Builder();", 316 " }", 317 "", 318 " public static SimpleComponent create() {", 319 " return builder().build();", 320 " }", 321 "", 322 " @SuppressWarnings(\"unchecked\")", 323 " private void initialize(final Builder builder) {", 324 " this.someInjectableTypeProvider =", 325 " ScopedProvider.create(SomeInjectableType_Factory.create());", 326 " }", 327 "", 328 " @Override", 329 " public SomeInjectableType someInjectableType() {", 330 " return someInjectableTypeProvider.get();", 331 " }", 332 "", 333 " @Override", 334 " public Lazy<SomeInjectableType> lazySomeInjectableType() {", 335 " return DoubleCheckLazy.create(someInjectableTypeProvider);", 336 " }", 337 "", 338 " @Override", 339 " public Provider<SomeInjectableType> someInjectableTypeProvider() {", 340 " return someInjectableTypeProvider;", 341 " }", 342 "", 343 " public static final class Builder {", 344 " private Builder() {", 345 " }", 346 "", 347 " public SimpleComponent build() {", 348 " return new DaggerSimpleComponent(this);", 349 " }", 350 " }", 351 "}"); 352 assertAbout(javaSources()).that(ImmutableList.of(injectableTypeFile, componentFile)) 353 .processedWith(new ComponentProcessor()) 354 .compilesWithoutError() 355 .and().generatesSources(generatedComponent); 356 } 357 simpleComponentWithNesting()358 @Test public void simpleComponentWithNesting() { 359 JavaFileObject nestedTypesFile = JavaFileObjects.forSourceLines("test.OuterType", 360 "package test;", 361 "", 362 "import dagger.Component;", 363 "import javax.inject.Inject;", 364 "", 365 "final class OuterType {", 366 " static class A {", 367 " @Inject A() {}", 368 " }", 369 " static class B {", 370 " @Inject A a;", 371 " }", 372 " @Component interface SimpleComponent {", 373 " A a();", 374 " void inject(B b);", 375 " }", 376 "}"); 377 378 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 379 "test.DaggerOuterType_SimpleComponent", 380 "package test;", 381 "", 382 "import dagger.MembersInjector;", 383 "import javax.annotation.Generated;", 384 "import test.OuterType.A;", 385 "import test.OuterType.B;", 386 "import test.OuterType.SimpleComponent;", 387 "", 388 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 389 "public final class DaggerOuterType_SimpleComponent implements SimpleComponent {", 390 " private MembersInjector<B> bMembersInjector;", 391 "", 392 " private DaggerOuterType_SimpleComponent(Builder builder) {", 393 " assert builder != null;", 394 " initialize(builder);", 395 " }", 396 "", 397 " public static Builder builder() {", 398 " return new Builder();", 399 " }", 400 "", 401 " public static SimpleComponent create() {", 402 " return builder().build();", 403 " }", 404 "", 405 " @SuppressWarnings(\"unchecked\")", 406 " private void initialize(final Builder builder) {", 407 " this.bMembersInjector =", 408 " OuterType$B_MembersInjector.create(OuterType$A_Factory.create());", 409 " }", 410 "", 411 " @Override", 412 " public A a() {", 413 " return OuterType$A_Factory.create().get();", 414 " }", 415 "", 416 " @Override", 417 " public void inject(B b) {", 418 " bMembersInjector.injectMembers(b);", 419 " }", 420 "", 421 " public static final class Builder {", 422 " private Builder() {", 423 " }", 424 "", 425 " public SimpleComponent build() {", 426 " return new DaggerOuterType_SimpleComponent(this);", 427 " }", 428 " }", 429 "}"); 430 assertAbout(javaSources()).that(ImmutableList.of(nestedTypesFile)) 431 .processedWith(new ComponentProcessor()) 432 .compilesWithoutError() 433 .and().generatesSources(generatedComponent); 434 } 435 componentWithModule()436 @Test public void componentWithModule() { 437 JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A", 438 "package test;", 439 "", 440 "import javax.inject.Inject;", 441 "", 442 "final class A {", 443 " @Inject A(B b) {}", 444 "}"); 445 JavaFileObject bFile = JavaFileObjects.forSourceLines("test.B", 446 "package test;", 447 "", 448 "interface B {}"); 449 JavaFileObject cFile = JavaFileObjects.forSourceLines("test.C", 450 "package test;", 451 "", 452 "import javax.inject.Inject;", 453 "", 454 "final class C {", 455 " @Inject C() {}", 456 "}"); 457 458 JavaFileObject moduleFile = JavaFileObjects.forSourceLines("test.TestModule", 459 "package test;", 460 "", 461 "import dagger.Module;", 462 "import dagger.Provides;", 463 "", 464 "@Module", 465 "final class TestModule {", 466 " @Provides B b(C c) { return null; }", 467 "}"); 468 469 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent", 470 "package test;", 471 "", 472 "import dagger.Component;", 473 "", 474 "import javax.inject.Provider;", 475 "", 476 "@Component(modules = TestModule.class)", 477 "interface TestComponent {", 478 " A a();", 479 "}"); 480 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 481 "test.DaggerTestComponent", 482 "package test;", 483 "", 484 "import javax.annotation.Generated;", 485 "import javax.inject.Provider;", 486 "", 487 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 488 "public final class DaggerTestComponent implements TestComponent {", 489 " private Provider<B> bProvider;", 490 " private Provider<A> aProvider;", 491 "", 492 " private DaggerTestComponent(Builder builder) {", 493 " assert builder != null;", 494 " initialize(builder);", 495 " }", 496 "", 497 " public static Builder builder() {", 498 " return new Builder();", 499 " }", 500 "", 501 " public static TestComponent create() {", 502 " return builder().build();", 503 " }", 504 "", 505 " @SuppressWarnings(\"unchecked\")", 506 " private void initialize(final Builder builder) {", 507 " this.bProvider = TestModule_BFactory.create(builder.testModule,", 508 " C_Factory.create());", 509 " this.aProvider = A_Factory.create(bProvider);", 510 " }", 511 "", 512 " @Override", 513 " public A a() {", 514 " return aProvider.get();", 515 " }", 516 "", 517 " public static final class Builder {", 518 " private TestModule testModule;", 519 "", 520 " private Builder() {", 521 " }", 522 "", 523 " public TestComponent build() {", 524 " if (testModule == null) {", 525 " this.testModule = new TestModule();", 526 " }", 527 " return new DaggerTestComponent(this);", 528 " }", 529 "", 530 " public Builder testModule(TestModule testModule) {", 531 " if (testModule == null) {", 532 " throw new NullPointerException();", 533 " }", 534 " this.testModule = testModule;", 535 " return this;", 536 " }", 537 " }", 538 "}"); 539 assertAbout(javaSources()) 540 .that(ImmutableList.of(aFile, bFile, cFile, moduleFile, componentFile)) 541 .processedWith(new ComponentProcessor()) 542 .compilesWithoutError() 543 .and().generatesSources(generatedComponent); 544 } 545 transitiveModuleDeps()546 @Test public void transitiveModuleDeps() { 547 JavaFileObject always = JavaFileObjects.forSourceLines("test.AlwaysIncluded", 548 "package test;", 549 "", 550 "import dagger.Module;", 551 "", 552 "@Module", 553 "final class AlwaysIncluded {}"); 554 JavaFileObject testModule = JavaFileObjects.forSourceLines("test.TestModule", 555 "package test;", 556 "", 557 "import dagger.Module;", 558 "", 559 "@Module(includes = {DepModule.class, AlwaysIncluded.class})", 560 "final class TestModule extends ParentTestModule {}"); 561 JavaFileObject parentTest = JavaFileObjects.forSourceLines("test.ParentTestModule", 562 "package test;", 563 "", 564 "import dagger.Module;", 565 "", 566 "@Module(includes = {ParentTestIncluded.class, AlwaysIncluded.class})", 567 "class ParentTestModule {}"); 568 JavaFileObject parentTestIncluded = JavaFileObjects.forSourceLines("test.ParentTestIncluded", 569 "package test;", 570 "", 571 "import dagger.Module;", 572 "", 573 "@Module(includes = AlwaysIncluded.class)", 574 "final class ParentTestIncluded {}"); 575 JavaFileObject depModule = JavaFileObjects.forSourceLines("test.TestModule", 576 "package test;", 577 "", 578 "import dagger.Module;", 579 "", 580 "@Module(includes = {RefByDep.class, AlwaysIncluded.class})", 581 "final class DepModule extends ParentDepModule {}"); 582 JavaFileObject refByDep = JavaFileObjects.forSourceLines("test.RefByDep", 583 "package test;", 584 "", 585 "import dagger.Module;", 586 "", 587 "@Module(includes = AlwaysIncluded.class)", 588 "final class RefByDep extends ParentDepModule {}"); 589 JavaFileObject parentDep = JavaFileObjects.forSourceLines("test.ParentDepModule", 590 "package test;", 591 "", 592 "import dagger.Module;", 593 "", 594 "@Module(includes = {ParentDepIncluded.class, AlwaysIncluded.class})", 595 "class ParentDepModule {}"); 596 JavaFileObject parentDepIncluded = JavaFileObjects.forSourceLines("test.ParentDepIncluded", 597 "package test;", 598 "", 599 "import dagger.Module;", 600 "", 601 "@Module(includes = AlwaysIncluded.class)", 602 "final class ParentDepIncluded {}"); 603 604 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent", 605 "package test;", 606 "", 607 "import dagger.Component;", 608 "", 609 "import javax.inject.Provider;", 610 "", 611 "@Component(modules = TestModule.class)", 612 "interface TestComponent {", 613 "}"); 614 // Generated code includes all includes, but excludes the parent modules. 615 // The "always" module should only be listed once. 616 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 617 "test.DaggerTestComponent", 618 "package test;", 619 "", 620 "import javax.annotation.Generated;", 621 "", 622 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 623 "public final class DaggerTestComponent implements TestComponent {", 624 "", 625 " private DaggerTestComponent(Builder builder) {", 626 " assert builder != null;", 627 " }", 628 "", 629 " public static Builder builder() {", 630 " return new Builder();", 631 " }", 632 "", 633 " public static TestComponent create() {", 634 " return builder().build();", 635 " }", 636 "", 637 " public static final class Builder {", 638 " private Builder() {", 639 " }", 640 "", 641 " public TestComponent build() {", 642 " return new DaggerTestComponent(this);", 643 " }", 644 "", 645 " @Deprecated", 646 " public Builder testModule(TestModule testModule) {", 647 " if (testModule == null) {", 648 " throw new NullPointerException();", 649 " }", 650 " return this;", 651 " }", 652 "", 653 " @Deprecated", 654 " public Builder parentTestIncluded(ParentTestIncluded parentTestIncluded) {", 655 " if (parentTestIncluded == null) {", 656 " throw new NullPointerException();", 657 " }", 658 " return this;", 659 " }", 660 "", 661 " @Deprecated", 662 " public Builder alwaysIncluded(AlwaysIncluded alwaysIncluded) {", 663 " if (alwaysIncluded == null) {", 664 " throw new NullPointerException();", 665 " }", 666 " return this;", 667 " }", 668 "", 669 " @Deprecated", 670 " public Builder depModule(DepModule depModule) {", 671 " if (depModule == null) {", 672 " throw new NullPointerException();", 673 " }", 674 " return this;", 675 " }", 676 "", 677 " @Deprecated", 678 " public Builder parentDepIncluded(ParentDepIncluded parentDepIncluded) {", 679 " if (parentDepIncluded == null) {", 680 " throw new NullPointerException();", 681 " }", 682 " return this;", 683 " }", 684 "", 685 " @Deprecated", 686 " public Builder refByDep(RefByDep refByDep) {", 687 " if (refByDep == null) {", 688 " throw new NullPointerException();", 689 " }", 690 " return this;", 691 " }", 692 " }", 693 "}"); 694 assertAbout(javaSources()) 695 .that(ImmutableList.of(always, 696 testModule, 697 parentTest, 698 parentTestIncluded, 699 depModule, 700 refByDep, 701 parentDep, 702 parentDepIncluded, 703 componentFile)) 704 .processedWith(new ComponentProcessor()) 705 .compilesWithoutError() 706 .and().generatesSources(generatedComponent); 707 } 708 709 @Test generatedTransitiveModule()710 public void generatedTransitiveModule() { 711 JavaFileObject rootModule = JavaFileObjects.forSourceLines("test.RootModule", 712 "package test;", 713 "", 714 "import dagger.Module;", 715 "", 716 "@Module(includes = GeneratedModule.class)", 717 "final class RootModule {}"); 718 JavaFileObject component = JavaFileObjects.forSourceLines("test.TestComponent", 719 "package test;", 720 "", 721 "import dagger.Component;", 722 "", 723 "@Component(modules = RootModule.class)", 724 "interface TestComponent {}"); 725 assertAbout(javaSources()) 726 .that(ImmutableList.of(rootModule, component)) 727 .processedWith(new ComponentProcessor()) 728 .failsToCompile(); 729 assertAbout(javaSources()) 730 .that(ImmutableList.of(rootModule, component)) 731 .processedWith( 732 new ComponentProcessor(), 733 new GeneratingProcessor( 734 "test.GeneratedModule", 735 "package test;", 736 "", 737 "import dagger.Module;", 738 "", 739 "@Module", 740 "final class GeneratedModule {}")) 741 .compilesWithoutError(); 742 } 743 744 @Test generatedModuleInSubcomponent()745 public void generatedModuleInSubcomponent() { 746 JavaFileObject subcomponent = 747 JavaFileObjects.forSourceLines( 748 "test.ChildComponent", 749 "package test;", 750 "", 751 "import dagger.Subcomponent;", 752 "", 753 "@Subcomponent(modules = GeneratedModule.class)", 754 "interface ChildComponent {}"); 755 JavaFileObject component = 756 JavaFileObjects.forSourceLines( 757 "test.TestComponent", 758 "package test;", 759 "", 760 "import dagger.Component;", 761 "", 762 "@Component", 763 "interface TestComponent {", 764 " ChildComponent childComponent();", 765 "}"); 766 assertAbout(javaSources()) 767 .that(ImmutableList.of(subcomponent, component)) 768 .processedWith(new ComponentProcessor()) 769 .failsToCompile(); 770 assertAbout(javaSources()) 771 .that(ImmutableList.of(subcomponent, component)) 772 .processedWith( 773 new ComponentProcessor(), 774 new GeneratingProcessor( 775 "test.GeneratedModule", 776 "package test;", 777 "", 778 "import dagger.Module;", 779 "", 780 "@Module", 781 "final class GeneratedModule {}")) 782 .compilesWithoutError(); 783 } 784 785 @Test subcomponentOmitsInheritedBindings()786 public void subcomponentOmitsInheritedBindings() { 787 JavaFileObject parent = 788 JavaFileObjects.forSourceLines( 789 "test.Parent", 790 "package test;", 791 "", 792 "import dagger.Component;", 793 "", 794 "@Component(modules = ParentModule.class)", 795 "interface Parent {", 796 " Child child();", 797 "}"); 798 JavaFileObject parentModule = 799 JavaFileObjects.forSourceLines( 800 "test.ParentModule", 801 "package test;", 802 "", 803 "import dagger.mapkeys.StringKey;", 804 "import dagger.Module;", 805 "import dagger.Provides;", 806 "", 807 "import static dagger.Provides.Type.SET;", 808 "import static dagger.Provides.Type.MAP;", 809 "", 810 "@Module", 811 "class ParentModule {", 812 " @Provides(type = SET) static Object parentObject() {", 813 " return \"parent object\";", 814 " }", 815 "", 816 " @Provides(type = MAP) @StringKey(\"parent key\") Object parentKeyObject() {", 817 " return \"parent value\";", 818 " }", 819 "}"); 820 JavaFileObject child = 821 JavaFileObjects.forSourceLines( 822 "test.Child", 823 "package test;", 824 "", 825 "import dagger.Subcomponent;", 826 "import java.util.Map;", 827 "import java.util.Set;", 828 "", 829 "@Subcomponent", 830 "interface Child {", 831 " Set<Object> objectSet();", 832 " Map<String, Object> objectMap();", 833 "}"); 834 JavaFileObject expected = 835 JavaFileObjects.forSourceLines( 836 "test.DaggerParent", 837 "package test;", 838 "", 839 "import dagger.internal.MapFactory;", 840 "import dagger.internal.MapProviderFactory;", 841 "import dagger.internal.SetFactory;", 842 "import java.util.Map;", 843 "import java.util.Set;", 844 "import javax.annotation.Generated;", 845 "import javax.inject.Provider;", 846 "", 847 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 848 "public final class DaggerParent implements Parent {", 849 " private Provider<Set<Object>> setOfObjectContribution1Provider;", 850 " private Provider<Set<Object>> setOfObjectProvider;", 851 " private Provider<Object> mapOfStringAndProviderOfObjectContribution1;", 852 " private Provider<Map<String, Provider<Object>>>", 853 " mapOfStringAndProviderOfObjectProvider;", 854 "", 855 " private DaggerParent(Builder builder) {", 856 " assert builder != null;", 857 " initialize(builder);", 858 " }", 859 "", 860 " public static Builder builder() {", 861 " return new Builder();", 862 " }", 863 "", 864 " public static Parent create() {", 865 " return builder().build();", 866 " }", 867 "", 868 " @SuppressWarnings(\"unchecked\")", 869 " private void initialize(final Builder builder) {", 870 " this.setOfObjectContribution1Provider =", 871 " ParentModule_ParentObjectFactory.create();", 872 " this.setOfObjectProvider = SetFactory.create(setOfObjectContribution1Provider);", 873 " this.mapOfStringAndProviderOfObjectContribution1 =", 874 " ParentModule_ParentKeyObjectFactory.create(builder.parentModule);", 875 " this.mapOfStringAndProviderOfObjectProvider =", 876 " MapProviderFactory.<String, Object>builder(1)", 877 " .put(\"parent key\", mapOfStringAndProviderOfObjectContribution1)", 878 " .build();", 879 " }", 880 "", 881 " @Override", 882 " public Child child() {", 883 " return new ChildImpl();", 884 " }", 885 "", 886 " public static final class Builder {", 887 " private ParentModule parentModule;", 888 "", 889 " private Builder() {}", 890 "", 891 " public Parent build() {", 892 " if (parentModule == null) {", 893 " this.parentModule = new ParentModule();", 894 " }", 895 " return new DaggerParent(this);", 896 " }", 897 "", 898 " public Builder parentModule(ParentModule parentModule) {", 899 " if (parentModule == null) {", 900 " throw new NullPointerException();", 901 " }", 902 " this.parentModule = parentModule;", 903 " return this;", 904 " }", 905 " }", 906 "", 907 " private final class ChildImpl implements Child {", 908 " private Provider<Map<String, Object>> mapOfStringAndObjectProvider;", 909 "", 910 " private ChildImpl() {", 911 " initialize();", 912 " }", 913 "", 914 " @SuppressWarnings(\"unchecked\")", 915 " private void initialize() {", 916 " this.mapOfStringAndObjectProvider = MapFactory.create(", 917 " DaggerParent.this.mapOfStringAndProviderOfObjectProvider);", 918 " }", 919 "", 920 " @Override", 921 " public Set<Object> objectSet() {", 922 " return DaggerParent.this.setOfObjectProvider.get();", 923 " }", 924 "", 925 " @Override", 926 " public Map<String, Object> objectMap() {", 927 " return mapOfStringAndObjectProvider.get();", 928 " }", 929 " }", 930 "}"); 931 assertAbout(javaSources()) 932 .that(ImmutableList.of(parent, parentModule, child)) 933 .processedWith(new ComponentProcessor()) 934 .compilesWithoutError() 935 .and() 936 .generatesSources(expected); 937 } 938 testDefaultPackage()939 @Test public void testDefaultPackage() { 940 JavaFileObject aClass = JavaFileObjects.forSourceLines("AClass", "class AClass {}"); 941 JavaFileObject bClass = JavaFileObjects.forSourceLines("BClass", 942 "import javax.inject.Inject;", 943 "", 944 "class BClass {", 945 " @Inject BClass(AClass a) {}", 946 "}"); 947 JavaFileObject aModule = JavaFileObjects.forSourceLines("AModule", 948 "import dagger.Module;", 949 "import dagger.Provides;", 950 "", 951 "@Module class AModule {", 952 " @Provides AClass aClass() {", 953 " return new AClass();", 954 " }", 955 "}"); 956 JavaFileObject component = JavaFileObjects.forSourceLines("SomeComponent", 957 "import dagger.Component;", 958 "", 959 "@Component(modules = AModule.class)", 960 "interface SomeComponent {", 961 " BClass bClass();", 962 "}"); 963 assertAbout(javaSources()) 964 .that(ImmutableList.of(aModule, aClass, bClass, component)) 965 .processedWith(new ComponentProcessor()) 966 .compilesWithoutError(); 967 } 968 setBindings()969 @Test public void setBindings() { 970 JavaFileObject emptySetModuleFile = JavaFileObjects.forSourceLines("test.EmptySetModule", 971 "package test;", 972 "", 973 "import static dagger.Provides.Type.SET_VALUES;", 974 "", 975 "import dagger.Module;", 976 "import dagger.Provides;", 977 "import java.util.Collections;", 978 "import java.util.Set;", 979 "", 980 "@Module", 981 "final class EmptySetModule {", 982 " @Provides(type = SET_VALUES) Set<String> emptySet() { return Collections.emptySet(); }", 983 "}"); 984 JavaFileObject setModuleFile = JavaFileObjects.forSourceLines("test.SetModule", 985 "package test;", 986 "", 987 "import static dagger.Provides.Type.SET;", 988 "", 989 "import dagger.Module;", 990 "import dagger.Provides;", 991 "", 992 "@Module", 993 "final class SetModule {", 994 " @Provides(type = SET) String string() { return \"\"; }", 995 "}"); 996 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent", 997 "package test;", 998 "", 999 "import dagger.Component;", 1000 "import java.util.Set;", 1001 "", 1002 "import javax.inject.Provider;", 1003 "", 1004 "@Component(modules = {EmptySetModule.class, SetModule.class})", 1005 "interface TestComponent {", 1006 " Set<String> strings();", 1007 "}"); 1008 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 1009 "test.DaggerTestComponent", 1010 "package test;", 1011 "", 1012 "import dagger.internal.SetFactory;", 1013 "import java.util.Set;", 1014 "import javax.annotation.Generated;", 1015 "import javax.inject.Provider;", 1016 "", 1017 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 1018 "public final class DaggerTestComponent implements TestComponent {", 1019 " private Provider<Set<String>> setOfStringContribution1Provider;", 1020 " private Provider<Set<String>> setOfStringContribution2Provider;", 1021 " private Provider<Set<String>> setOfStringProvider;", 1022 "", 1023 " private DaggerTestComponent(Builder builder) {", 1024 " assert builder != null;", 1025 " initialize(builder);", 1026 " }", 1027 "", 1028 " public static Builder builder() {", 1029 " return new Builder();", 1030 " }", 1031 "", 1032 " public static TestComponent create() {", 1033 " return builder().build();", 1034 " }", 1035 "", 1036 " @SuppressWarnings(\"unchecked\")", 1037 " private void initialize(final Builder builder) {", 1038 " this.setOfStringContribution1Provider =", 1039 " EmptySetModule_EmptySetFactory.create(builder.emptySetModule);", 1040 " this.setOfStringContribution2Provider =", 1041 " SetModule_StringFactory.create(builder.setModule);", 1042 " this.setOfStringProvider = SetFactory.create(", 1043 " setOfStringContribution1Provider, setOfStringContribution2Provider);", 1044 " }", 1045 "", 1046 " @Override", 1047 " public Set<String> strings() {", 1048 " return setOfStringProvider.get();", 1049 " }", 1050 "", 1051 " public static final class Builder {", 1052 " private EmptySetModule emptySetModule;", 1053 " private SetModule setModule;", 1054 "", 1055 " private Builder() {", 1056 " }", 1057 "", 1058 " public TestComponent build() {", 1059 " if (emptySetModule == null) {", 1060 " this.emptySetModule = new EmptySetModule();", 1061 " }", 1062 " if (setModule == null) {", 1063 " this.setModule = new SetModule();", 1064 " }", 1065 " return new DaggerTestComponent(this);", 1066 " }", 1067 "", 1068 " public Builder emptySetModule(EmptySetModule emptySetModule) {", 1069 " if (emptySetModule == null) {", 1070 " throw new NullPointerException();", 1071 " }", 1072 " this.emptySetModule = emptySetModule;", 1073 " return this;", 1074 " }", 1075 "", 1076 " public Builder setModule(SetModule setModule) {", 1077 " if (setModule == null) {", 1078 " throw new NullPointerException();", 1079 " }", 1080 " this.setModule = setModule;", 1081 " return this;", 1082 " }", 1083 " }", 1084 "}"); 1085 assertAbout(javaSources()) 1086 .that(ImmutableList.of(emptySetModuleFile, setModuleFile, componentFile)) 1087 .processedWith(new ComponentProcessor()) 1088 .compilesWithoutError() 1089 .and().generatesSources(generatedComponent); 1090 } 1091 membersInjection()1092 @Test public void membersInjection() { 1093 JavaFileObject injectableTypeFile = JavaFileObjects.forSourceLines("test.SomeInjectableType", 1094 "package test;", 1095 "", 1096 "import javax.inject.Inject;", 1097 "", 1098 "final class SomeInjectableType {", 1099 " @Inject SomeInjectableType() {}", 1100 "}"); 1101 JavaFileObject injectedTypeFile = JavaFileObjects.forSourceLines("test.SomeInjectedType", 1102 "package test;", 1103 "", 1104 "import javax.inject.Inject;", 1105 "", 1106 "final class SomeInjectedType {", 1107 " @Inject SomeInjectableType injectedField;", 1108 " SomeInjectedType() {}", 1109 "}"); 1110 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 1111 "package test;", 1112 "", 1113 "import dagger.Component;", 1114 "import dagger.Lazy;", 1115 "", 1116 "import javax.inject.Provider;", 1117 "", 1118 "@Component", 1119 "interface SimpleComponent {", 1120 " void inject(SomeInjectedType instance);", 1121 " SomeInjectedType injectAndReturn(SomeInjectedType instance);", 1122 "}"); 1123 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 1124 "test.DaggerSimpleComponent", 1125 "package test;", 1126 "", 1127 "import dagger.MembersInjector;", 1128 "import javax.annotation.Generated;", 1129 "", 1130 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 1131 "public final class DaggerSimpleComponent implements SimpleComponent {", 1132 " private MembersInjector<SomeInjectedType> someInjectedTypeMembersInjector;", 1133 "", 1134 " private DaggerSimpleComponent(Builder builder) {", 1135 " assert builder != null;", 1136 " initialize(builder);", 1137 " }", 1138 "", 1139 " public static Builder builder() {", 1140 " return new Builder();", 1141 " }", 1142 "", 1143 " public static SimpleComponent create() {", 1144 " return builder().build();", 1145 " }", 1146 "", 1147 " @SuppressWarnings(\"unchecked\")", 1148 " private void initialize(final Builder builder) {", 1149 " this.someInjectedTypeMembersInjector =", 1150 " SomeInjectedType_MembersInjector.create(SomeInjectableType_Factory.create());", 1151 " }", 1152 "", 1153 " @Override", 1154 " public void inject(SomeInjectedType instance) {", 1155 " someInjectedTypeMembersInjector.injectMembers(instance);", 1156 " }", 1157 "", 1158 " @Override", 1159 " public SomeInjectedType injectAndReturn(SomeInjectedType instance) {", 1160 " someInjectedTypeMembersInjector.injectMembers(instance);", 1161 " return instance;", 1162 " }", 1163 "", 1164 " public static final class Builder {", 1165 " private Builder() {", 1166 " }", 1167 "", 1168 " public SimpleComponent build() {", 1169 " return new DaggerSimpleComponent(this);", 1170 " }", 1171 " }", 1172 "}"); 1173 assertAbout(javaSources()) 1174 .that(ImmutableList.of(injectableTypeFile, injectedTypeFile, componentFile)) 1175 .processedWith(new ComponentProcessor()) 1176 .compilesWithoutError() 1177 .and().generatesSources(generatedComponent); 1178 } 1179 componentInjection()1180 @Test public void componentInjection() { 1181 JavaFileObject injectableTypeFile = JavaFileObjects.forSourceLines("test.SomeInjectableType", 1182 "package test;", 1183 "", 1184 "import javax.inject.Inject;", 1185 "", 1186 "final class SomeInjectableType {", 1187 " @Inject SomeInjectableType(SimpleComponent component) {}", 1188 "}"); 1189 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 1190 "package test;", 1191 "", 1192 "import dagger.Component;", 1193 "import dagger.Lazy;", 1194 "", 1195 "import javax.inject.Provider;", 1196 "", 1197 "@Component", 1198 "interface SimpleComponent {", 1199 " SomeInjectableType someInjectableType();", 1200 "}"); 1201 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 1202 "test.DaggerSimpleComponent", 1203 "package test;", 1204 "", 1205 "import dagger.internal.InstanceFactory;", 1206 "import javax.annotation.Generated;", 1207 "import javax.inject.Provider;", 1208 "", 1209 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 1210 "public final class DaggerSimpleComponent implements SimpleComponent {", 1211 " private Provider<SimpleComponent> simpleComponentProvider;", 1212 " private Provider<SomeInjectableType> someInjectableTypeProvider;", 1213 "", 1214 " private DaggerSimpleComponent(Builder builder) {", 1215 " assert builder != null;", 1216 " initialize(builder);", 1217 " }", 1218 "", 1219 " public static Builder builder() {", 1220 " return new Builder();", 1221 " }", 1222 "", 1223 " public static SimpleComponent create() {", 1224 " return builder().build();", 1225 " }", 1226 "", 1227 " @SuppressWarnings(\"unchecked\")", 1228 " private void initialize(final Builder builder) {", 1229 " this.simpleComponentProvider = InstanceFactory.<SimpleComponent>create(this);", 1230 " this.someInjectableTypeProvider =", 1231 " SomeInjectableType_Factory.create(simpleComponentProvider);", 1232 " }", 1233 "", 1234 " @Override", 1235 " public SomeInjectableType someInjectableType() {", 1236 " return someInjectableTypeProvider.get();", 1237 " }", 1238 "", 1239 " public static final class Builder {", 1240 " private Builder() {", 1241 " }", 1242 "", 1243 " public SimpleComponent build() {", 1244 " return new DaggerSimpleComponent(this);", 1245 " }", 1246 " }", 1247 "}"); 1248 assertAbout(javaSources()).that(ImmutableList.of(injectableTypeFile, componentFile)) 1249 .processedWith(new ComponentProcessor()) 1250 .compilesWithoutError() 1251 .and().generatesSources(generatedComponent); 1252 } 1253 membersInjectionInsideProvision()1254 @Test public void membersInjectionInsideProvision() { 1255 JavaFileObject injectableTypeFile = JavaFileObjects.forSourceLines("test.SomeInjectableType", 1256 "package test;", 1257 "", 1258 "import javax.inject.Inject;", 1259 "", 1260 "final class SomeInjectableType {", 1261 " @Inject SomeInjectableType() {}", 1262 "}"); 1263 JavaFileObject injectedTypeFile = JavaFileObjects.forSourceLines("test.SomeInjectedType", 1264 "package test;", 1265 "", 1266 "import javax.inject.Inject;", 1267 "", 1268 "final class SomeInjectedType {", 1269 " @Inject SomeInjectableType injectedField;", 1270 " @Inject SomeInjectedType() {}", 1271 "}"); 1272 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 1273 "package test;", 1274 "", 1275 "import dagger.Component;", 1276 "", 1277 "@Component", 1278 "interface SimpleComponent {", 1279 " SomeInjectedType createAndInject();", 1280 "}"); 1281 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 1282 "test.DaggerSimpleComponent", 1283 "package test;", 1284 "", 1285 "import dagger.MembersInjector;", 1286 "import javax.annotation.Generated;", 1287 "import javax.inject.Provider;", 1288 "", 1289 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 1290 "public final class DaggerSimpleComponent implements SimpleComponent {", 1291 " private MembersInjector<SomeInjectedType> someInjectedTypeMembersInjector;", 1292 " private Provider<SomeInjectedType> someInjectedTypeProvider;", 1293 "", 1294 " private DaggerSimpleComponent(Builder builder) {", 1295 " assert builder != null;", 1296 " initialize(builder);", 1297 " }", 1298 "", 1299 " public static Builder builder() {", 1300 " return new Builder();", 1301 " }", 1302 "", 1303 " public static SimpleComponent create() {", 1304 " return builder().build();", 1305 " }", 1306 "", 1307 " @SuppressWarnings(\"unchecked\")", 1308 " private void initialize(final Builder builder) {", 1309 " this.someInjectedTypeMembersInjector =", 1310 " SomeInjectedType_MembersInjector.create(SomeInjectableType_Factory.create());", 1311 " this.someInjectedTypeProvider =", 1312 " SomeInjectedType_Factory.create(someInjectedTypeMembersInjector);", 1313 " }", 1314 "", 1315 " @Override", 1316 " public SomeInjectedType createAndInject() {", 1317 " return someInjectedTypeProvider.get();", 1318 " }", 1319 "", 1320 " public static final class Builder {", 1321 " private Builder() {", 1322 " }", 1323 "", 1324 " public SimpleComponent build() {", 1325 " return new DaggerSimpleComponent(this);", 1326 " }", 1327 " }", 1328 "}"); 1329 assertAbout(javaSources()) 1330 .that(ImmutableList.of(injectableTypeFile, injectedTypeFile, componentFile)) 1331 .processedWith(new ComponentProcessor()) 1332 .compilesWithoutError() 1333 .and().generatesSources(generatedComponent); 1334 } 1335 injectionWithGenericBaseClass()1336 @Test public void injectionWithGenericBaseClass() { 1337 JavaFileObject genericType = JavaFileObjects.forSourceLines("test.AbstractGenericType", 1338 "package test;", 1339 "", 1340 "abstract class AbstractGenericType<T> {", 1341 "}"); 1342 JavaFileObject injectableTypeFile = JavaFileObjects.forSourceLines("test.SomeInjectableType", 1343 "package test;", 1344 "", 1345 "import javax.inject.Inject;", 1346 "", 1347 "final class SomeInjectableType extends AbstractGenericType<String> {", 1348 " @Inject SomeInjectableType() {}", 1349 "}"); 1350 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 1351 "package test;", 1352 "", 1353 "import dagger.Component;", 1354 "", 1355 "@Component", 1356 "interface SimpleComponent {", 1357 " SomeInjectableType someInjectableType();", 1358 "}"); 1359 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 1360 "test.DaggerSimpleComponent", 1361 "package test;", 1362 "", 1363 "import dagger.MembersInjector;", 1364 "import dagger.internal.MembersInjectors;", 1365 "import javax.annotation.Generated;", 1366 "import javax.inject.Provider;", 1367 "", 1368 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 1369 "public final class DaggerSimpleComponent implements SimpleComponent {", 1370 " private Provider<SomeInjectableType> someInjectableTypeProvider;", 1371 "", 1372 " private DaggerSimpleComponent(Builder builder) {", 1373 " assert builder != null;", 1374 " initialize(builder);", 1375 " }", 1376 "", 1377 " public static Builder builder() {", 1378 " return new Builder();", 1379 " }", 1380 "", 1381 " public static SimpleComponent create() {", 1382 " return builder().build();", 1383 " }", 1384 "", 1385 " @SuppressWarnings(\"unchecked\")", 1386 " private void initialize(final Builder builder) {", 1387 " this.someInjectableTypeProvider =", 1388 " SomeInjectableType_Factory.create((MembersInjector) MembersInjectors.noOp());", 1389 " }", 1390 "", 1391 " @Override", 1392 " public SomeInjectableType someInjectableType() {", 1393 " return someInjectableTypeProvider.get();", 1394 " }", 1395 "", 1396 " public static final class Builder {", 1397 " private Builder() {", 1398 " }", 1399 "", 1400 " public SimpleComponent build() {", 1401 " return new DaggerSimpleComponent(this);", 1402 " }", 1403 " }", 1404 "}"); 1405 assertAbout(javaSources()) 1406 .that(ImmutableList.of(genericType, injectableTypeFile, componentFile)) 1407 .processedWith(new ComponentProcessor()) 1408 .compilesWithoutError() 1409 .and().generatesSources(generatedComponent); 1410 } 1411 componentDependency()1412 @Test public void componentDependency() { 1413 JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A", 1414 "package test;", 1415 "", 1416 "import javax.inject.Inject;", 1417 "", 1418 "final class A {", 1419 " @Inject A() {}", 1420 "}"); 1421 JavaFileObject bFile = JavaFileObjects.forSourceLines("test.B", 1422 "package test;", 1423 "", 1424 "import javax.inject.Inject;", 1425 "", 1426 "final class B {", 1427 " @Inject B(A a) {}", 1428 "}"); 1429 JavaFileObject aComponentFile = JavaFileObjects.forSourceLines("test.AComponent", 1430 "package test;", 1431 "", 1432 "import dagger.Component;", 1433 "import dagger.Lazy;", 1434 "", 1435 "import javax.inject.Provider;", 1436 "", 1437 "@Component", 1438 "interface AComponent {", 1439 " A a();", 1440 "}"); 1441 JavaFileObject bComponentFile = JavaFileObjects.forSourceLines("test.AComponent", 1442 "package test;", 1443 "", 1444 "import dagger.Component;", 1445 "import dagger.Lazy;", 1446 "", 1447 "import javax.inject.Provider;", 1448 "", 1449 "@Component(dependencies = AComponent.class)", 1450 "interface BComponent {", 1451 " B b();", 1452 "}"); 1453 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 1454 "test.DaggerBComponent", 1455 "package test;", 1456 "", 1457 "import dagger.internal.Factory;", 1458 "import javax.annotation.Generated;", 1459 "import javax.inject.Provider;", 1460 "", 1461 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 1462 "public final class DaggerBComponent implements BComponent {", 1463 " private Provider<A> aProvider;", 1464 " private Provider<B> bProvider;", 1465 "", 1466 " private DaggerBComponent(Builder builder) {", 1467 " assert builder != null;", 1468 " initialize(builder);", 1469 " }", 1470 "", 1471 " public static Builder builder() {", 1472 " return new Builder();", 1473 " }", 1474 "", 1475 " @SuppressWarnings(\"unchecked\")", 1476 " private void initialize(final Builder builder) {", 1477 " this.aProvider = new Factory<A>() {", 1478 " private final AComponent aComponent = builder.aComponent;", 1479 " @Override public A get() {", 1480 " A provided = aComponent.a();", 1481 " if (provided == null) {", 1482 " throw new NullPointerException(" + NPE_LITERAL + ");", 1483 " }", 1484 " return provided;", 1485 " }", 1486 " };", 1487 " this.bProvider = B_Factory.create(aProvider);", 1488 " }", 1489 "", 1490 " @Override", 1491 " public B b() {", 1492 " return bProvider.get();", 1493 " }", 1494 "", 1495 " public static final class Builder {", 1496 " private AComponent aComponent;", 1497 "", 1498 " private Builder() {", 1499 " }", 1500 "", 1501 " public BComponent build() {", 1502 " if (aComponent == null) {", 1503 " throw new IllegalStateException(AComponent.class.getCanonicalName()", 1504 " + \" must be set\");", 1505 " }", 1506 " return new DaggerBComponent(this);", 1507 " }", 1508 "", 1509 " public Builder aComponent(AComponent aComponent) {", 1510 " if (aComponent == null) {", 1511 " throw new NullPointerException();", 1512 " }", 1513 " this.aComponent = aComponent;", 1514 " return this;", 1515 " }", 1516 " }", 1517 "}"); 1518 assertAbout(javaSources()) 1519 .that(ImmutableList.of(aFile, bFile, aComponentFile, bComponentFile)) 1520 .processedWith(new ComponentProcessor()) 1521 .compilesWithoutError() 1522 .and().generatesSources(generatedComponent); 1523 } 1524 moduleNameCollision()1525 @Test public void moduleNameCollision() { 1526 JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A", 1527 "package test;", 1528 "", 1529 "public final class A {}"); 1530 JavaFileObject otherAFile = JavaFileObjects.forSourceLines("other.test.A", 1531 "package other.test;", 1532 "", 1533 "public final class A {}"); 1534 1535 JavaFileObject moduleFile = JavaFileObjects.forSourceLines("test.TestModule", 1536 "package test;", 1537 "", 1538 "import dagger.Module;", 1539 "import dagger.Provides;", 1540 "", 1541 "@Module", 1542 "public final class TestModule {", 1543 " @Provides A a() { return null; }", 1544 "}"); 1545 JavaFileObject otherModuleFile = JavaFileObjects.forSourceLines("other.test.TestModule", 1546 "package other.test;", 1547 "", 1548 "import dagger.Module;", 1549 "import dagger.Provides;", 1550 "", 1551 "@Module", 1552 "public final class TestModule {", 1553 " @Provides A a() { return null; }", 1554 "}"); 1555 1556 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent", 1557 "package test;", 1558 "", 1559 "import dagger.Component;", 1560 "", 1561 "import javax.inject.Provider;", 1562 "", 1563 "@Component(modules = {TestModule.class, other.test.TestModule.class})", 1564 "interface TestComponent {", 1565 " A a();", 1566 " other.test.A otherA();", 1567 "}"); 1568 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 1569 "test.DaggerTestComponent", 1570 "package test;", 1571 "", 1572 "import javax.annotation.Generated;", 1573 "import javax.inject.Provider;", 1574 "import other.test.A;", 1575 "import other.test.TestModule;", 1576 "import other.test.TestModule_AFactory;", 1577 "", 1578 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 1579 "public final class DaggerTestComponent implements TestComponent {", 1580 " private Provider<test.A> aProvider;", 1581 " private Provider<A> aProvider1;", 1582 "", 1583 " private DaggerTestComponent(Builder builder) {", 1584 " assert builder != null;", 1585 " initialize(builder);", 1586 " }", 1587 "", 1588 " public static Builder builder() {", 1589 " return new Builder();", 1590 " }", 1591 "", 1592 " public static TestComponent create() {", 1593 " return builder().build();", 1594 " }", 1595 "", 1596 " @SuppressWarnings(\"unchecked\")", 1597 " private void initialize(final Builder builder) {", 1598 " this.aProvider = test.TestModule_AFactory.create(builder.testModule);", 1599 " this.aProvider1 = TestModule_AFactory.create(builder.testModule1);", 1600 " }", 1601 "", 1602 " @Override", 1603 " public test.A a() {", 1604 " return aProvider.get();", 1605 " }", 1606 "", 1607 " @Override", 1608 " public A otherA() {", 1609 " return aProvider1.get();", 1610 " }", 1611 "", 1612 " public static final class Builder {", 1613 " private test.TestModule testModule;", 1614 " private TestModule testModule1;", 1615 "", 1616 " private Builder() {", 1617 " }", 1618 "", 1619 " public TestComponent build() {", 1620 " if (testModule == null) {", 1621 " this.testModule = new test.TestModule();", 1622 " }", 1623 " if (testModule1 == null) {", 1624 " this.testModule1 = new TestModule();", 1625 " }", 1626 " return new DaggerTestComponent(this);", 1627 " }", 1628 "", 1629 " public Builder testModule(test.TestModule testModule) {", 1630 " if (testModule == null) {", 1631 " throw new NullPointerException();", 1632 " }", 1633 " this.testModule = testModule;", 1634 " return this;", 1635 " }", 1636 "", 1637 " public Builder testModule(TestModule testModule) {", 1638 " if (testModule == null) {", 1639 " throw new NullPointerException();", 1640 " }", 1641 " this.testModule1 = testModule;", 1642 " return this;", 1643 " }", 1644 " }", 1645 "}"); 1646 assertAbout(javaSources()) 1647 .that(ImmutableList.of(aFile, otherAFile, moduleFile, otherModuleFile, componentFile)) 1648 .processedWith(new ComponentProcessor()) 1649 .compilesWithoutError() 1650 .and().generatesSources(generatedComponent); 1651 } 1652 resolutionOrder()1653 @Test public void resolutionOrder() { 1654 JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A", 1655 "package test;", 1656 "", 1657 "import javax.inject.Inject;", 1658 "", 1659 "final class A {", 1660 " @Inject A(B b) {}", 1661 "}"); 1662 JavaFileObject bFile = JavaFileObjects.forSourceLines("test.B", 1663 "package test;", 1664 "", 1665 "import javax.inject.Inject;", 1666 "", 1667 "final class B {", 1668 " @Inject B(C c) {}", 1669 "}"); 1670 JavaFileObject cFile = JavaFileObjects.forSourceLines("test.C", 1671 "package test;", 1672 "", 1673 "import javax.inject.Inject;", 1674 "", 1675 "final class C {", 1676 " @Inject C() {}", 1677 "}"); 1678 JavaFileObject xFile = JavaFileObjects.forSourceLines("test.X", 1679 "package test;", 1680 "", 1681 "import javax.inject.Inject;", 1682 "", 1683 "final class X {", 1684 " @Inject X(C c) {}", 1685 "}"); 1686 1687 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent", 1688 "package test;", 1689 "", 1690 "import dagger.Component;", 1691 "", 1692 "import javax.inject.Provider;", 1693 "", 1694 "@Component", 1695 "interface TestComponent {", 1696 " A a();", 1697 " C c();", 1698 " X x();", 1699 "}"); 1700 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 1701 "test.DaggerTestComponent", 1702 "package test;", 1703 "", 1704 "import javax.annotation.Generated;", 1705 "import javax.inject.Provider;", 1706 "", 1707 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 1708 "public final class DaggerTestComponent implements TestComponent {", 1709 " private Provider<B> bProvider;", 1710 " private Provider<A> aProvider;", 1711 " private Provider<X> xProvider;", 1712 "", 1713 " private DaggerTestComponent(Builder builder) {", 1714 " assert builder != null;", 1715 " initialize(builder);", 1716 " }", 1717 "", 1718 " public static Builder builder() {", 1719 " return new Builder();", 1720 " }", 1721 "", 1722 " public static TestComponent create() {", 1723 " return builder().build();", 1724 " }", 1725 "", 1726 " @SuppressWarnings(\"unchecked\")", 1727 " private void initialize(final Builder builder) {", 1728 " this.bProvider = B_Factory.create(C_Factory.create());", 1729 " this.aProvider = A_Factory.create(bProvider);", 1730 " this.xProvider = X_Factory.create(C_Factory.create());", 1731 " }", 1732 "", 1733 " @Override", 1734 " public A a() {", 1735 " return aProvider.get();", 1736 " }", 1737 "", 1738 " @Override", 1739 " public C c() {", 1740 " return C_Factory.create().get();", 1741 " }", 1742 "", 1743 " @Override", 1744 " public X x() {", 1745 " return xProvider.get();", 1746 " }", 1747 "", 1748 " public static final class Builder {", 1749 " private Builder() {", 1750 " }", 1751 "", 1752 " public TestComponent build() {", 1753 " return new DaggerTestComponent(this);", 1754 " }", 1755 " }", 1756 "}"); 1757 assertAbout(javaSources()) 1758 .that(ImmutableList.of(aFile, bFile, cFile, xFile, componentFile)) 1759 .processedWith(new ComponentProcessor()) 1760 .compilesWithoutError() 1761 .and().generatesSources(generatedComponent); 1762 } 1763 simpleComponent_redundantComponentMethod()1764 @Test public void simpleComponent_redundantComponentMethod() { 1765 JavaFileObject injectableTypeFile = JavaFileObjects.forSourceLines("test.SomeInjectableType", 1766 "package test;", 1767 "", 1768 "import javax.inject.Inject;", 1769 "", 1770 "final class SomeInjectableType {", 1771 " @Inject SomeInjectableType() {}", 1772 "}"); 1773 JavaFileObject componentSupertypeAFile = JavaFileObjects.forSourceLines("test.SupertypeA", 1774 "package test;", 1775 "", 1776 "import dagger.Component;", 1777 "import dagger.Lazy;", 1778 "", 1779 "import javax.inject.Provider;", 1780 "", 1781 "@Component", 1782 "interface SupertypeA {", 1783 " SomeInjectableType someInjectableType();", 1784 "}"); 1785 JavaFileObject componentSupertypeBFile = JavaFileObjects.forSourceLines("test.SupertypeB", 1786 "package test;", 1787 "", 1788 "import dagger.Component;", 1789 "import dagger.Lazy;", 1790 "", 1791 "import javax.inject.Provider;", 1792 "", 1793 "@Component", 1794 "interface SupertypeB {", 1795 " SomeInjectableType someInjectableType();", 1796 "}"); 1797 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 1798 "package test;", 1799 "", 1800 "import dagger.Component;", 1801 "import dagger.Lazy;", 1802 "", 1803 "import javax.inject.Provider;", 1804 "", 1805 "@Component", 1806 "interface SimpleComponent extends SupertypeA, SupertypeB {", 1807 "}"); 1808 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 1809 "test.DaggerSimpleComponent", 1810 "package test;", 1811 "", 1812 "import javax.annotation.Generated;", 1813 "", 1814 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 1815 "public final class DaggerSimpleComponent implements SimpleComponent {", 1816 " private DaggerSimpleComponent(Builder builder) {", 1817 " assert builder != null;", 1818 " initialize(builder);", 1819 " }", 1820 "", 1821 " public static Builder builder() {", 1822 " return new Builder();", 1823 " }", 1824 "", 1825 " public static SimpleComponent create() {", 1826 " return builder().build();", 1827 " }", 1828 "", 1829 " @SuppressWarnings(\"unchecked\")", 1830 " private void initialize(final Builder builder) {}", 1831 "", 1832 " @Override", 1833 " public SomeInjectableType someInjectableType() {", 1834 " return SomeInjectableType_Factory.create().get();", 1835 " }", 1836 "", 1837 " public static final class Builder {", 1838 " private Builder() {", 1839 " }", 1840 "", 1841 " public SimpleComponent build() {", 1842 " return new DaggerSimpleComponent(this);", 1843 " }", 1844 " }", 1845 "}"); 1846 assertAbout(javaSources()).that(ImmutableList.of( 1847 injectableTypeFile, componentSupertypeAFile, componentSupertypeBFile, componentFile)) 1848 .processedWith(new ComponentProcessor()) 1849 .compilesWithoutError() 1850 .and().generatesSources(generatedComponent); 1851 } 1852 simpleComponent_inheritedComponentMethodDep()1853 @Test public void simpleComponent_inheritedComponentMethodDep() { 1854 JavaFileObject injectableTypeFile = JavaFileObjects.forSourceLines("test.SomeInjectableType", 1855 "package test;", 1856 "", 1857 "import javax.inject.Inject;", 1858 "", 1859 "final class SomeInjectableType {", 1860 " @Inject SomeInjectableType() {}", 1861 "}"); 1862 JavaFileObject componentSupertype = JavaFileObjects.forSourceLines("test.Supertype", 1863 "package test;", 1864 "", 1865 "import dagger.Component;", 1866 "import dagger.Lazy;", 1867 "", 1868 "import javax.inject.Provider;", 1869 "", 1870 "@Component", 1871 "interface Supertype {", 1872 " SomeInjectableType someInjectableType();", 1873 "}"); 1874 JavaFileObject depComponentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 1875 "package test;", 1876 "", 1877 "import dagger.Component;", 1878 "import dagger.Lazy;", 1879 "", 1880 "import javax.inject.Provider;", 1881 "", 1882 "@Component", 1883 "interface SimpleComponent extends Supertype {", 1884 "}"); 1885 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.ComponentWithDep", 1886 "package test;", 1887 "", 1888 "import dagger.Component;", 1889 "import dagger.Lazy;", 1890 "", 1891 "import javax.inject.Provider;", 1892 "", 1893 "@Component(dependencies = SimpleComponent.class)", 1894 "interface ComponentWithDep {", 1895 " SomeInjectableType someInjectableType();", 1896 "}"); 1897 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 1898 "test.DaggerSimpleComponent", 1899 "package test;", 1900 "", 1901 "import javax.annotation.Generated;", 1902 "", 1903 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 1904 "public final class DaggerSimpleComponent implements SimpleComponent {", 1905 " private DaggerSimpleComponent(Builder builder) {", 1906 " assert builder != null;", 1907 " initialize(builder);", 1908 " }", 1909 "", 1910 " public static Builder builder() {", 1911 " return new Builder();", 1912 " }", 1913 "", 1914 " public static SimpleComponent create() {", 1915 " return builder().build();", 1916 " }", 1917 "", 1918 " @SuppressWarnings(\"unchecked\")", 1919 " private void initialize(final Builder builder) {}", 1920 "", 1921 " @Override", 1922 " public SomeInjectableType someInjectableType() {", 1923 " return SomeInjectableType_Factory.create().get();", 1924 " }", 1925 "", 1926 " public static final class Builder {", 1927 " private Builder() {", 1928 " }", 1929 "", 1930 " public SimpleComponent build() {", 1931 " return new DaggerSimpleComponent(this);", 1932 " }", 1933 " }", 1934 "}"); 1935 assertAbout(javaSources()).that(ImmutableList.of( 1936 injectableTypeFile, componentSupertype, depComponentFile, componentFile)) 1937 .processedWith(new ComponentProcessor()) 1938 .compilesWithoutError() 1939 .and().generatesSources(generatedComponent); 1940 } 1941 wildcardGenericsRequiresAtProvides()1942 @Test public void wildcardGenericsRequiresAtProvides() { 1943 JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A", 1944 "package test;", 1945 "", 1946 "import javax.inject.Inject;", 1947 "", 1948 "final class A {", 1949 " @Inject A() {}", 1950 "}"); 1951 JavaFileObject bFile = JavaFileObjects.forSourceLines("test.B", 1952 "package test;", 1953 "", 1954 "import javax.inject.Inject;", 1955 "import javax.inject.Provider;", 1956 "", 1957 "final class B<T> {", 1958 " @Inject B(T t) {}", 1959 "}"); 1960 JavaFileObject cFile = JavaFileObjects.forSourceLines("test.C", 1961 "package test;", 1962 "", 1963 "import javax.inject.Inject;", 1964 "import javax.inject.Provider;", 1965 "", 1966 "final class C {", 1967 " @Inject C(B<? extends A> bA) {}", 1968 "}"); 1969 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 1970 "package test;", 1971 "", 1972 "import dagger.Component;", 1973 "import dagger.Lazy;", 1974 "", 1975 "import javax.inject.Provider;", 1976 "", 1977 "@Component", 1978 "interface SimpleComponent {", 1979 " C c();", 1980 "}"); 1981 assertAbout(javaSources()).that(ImmutableList.of(aFile, bFile, cFile, componentFile)) 1982 .processedWith(new ComponentProcessor()) 1983 .failsToCompile() 1984 .withErrorContaining( 1985 "test.B<? extends test.A> cannot be provided without an @Provides-annotated method"); 1986 } 1987 @Test componentImplicitlyDependsOnGeneratedType()1988 public void componentImplicitlyDependsOnGeneratedType() { 1989 JavaFileObject injectableTypeFile = JavaFileObjects.forSourceLines("test.SomeInjectableType", 1990 "package test;", 1991 "", 1992 "import javax.inject.Inject;", 1993 "", 1994 "final class SomeInjectableType {", 1995 " @Inject SomeInjectableType(GeneratedType generatedType) {}", 1996 "}"); 1997 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 1998 "package test;", 1999 "", 2000 "import dagger.Component;", 2001 "", 2002 "@Component", 2003 "interface SimpleComponent {", 2004 " SomeInjectableType someInjectableType();", 2005 "}"); 2006 assertAbout(javaSources()) 2007 .that(ImmutableList.of(injectableTypeFile, componentFile)) 2008 .processedWith( 2009 new ComponentProcessor(), 2010 new GeneratingProcessor( 2011 "test.GeneratedType", 2012 "package test;", 2013 "", 2014 "import javax.inject.Inject;", 2015 "", 2016 "final class GeneratedType {", 2017 " @Inject GeneratedType() {}", 2018 "}")) 2019 .compilesWithoutError() 2020 .and() 2021 .generatesFileNamed(SOURCE_OUTPUT, "test", "DaggerSimpleComponent.java"); 2022 } 2023 @Test componentSupertypeDependsOnGeneratedType()2024 public void componentSupertypeDependsOnGeneratedType() { 2025 JavaFileObject componentFile = 2026 JavaFileObjects.forSourceLines( 2027 "test.SimpleComponent", 2028 "package test;", 2029 "", 2030 "import dagger.Component;", 2031 "", 2032 "@Component", 2033 "interface SimpleComponent extends SimpleComponentInterface {}"); 2034 JavaFileObject interfaceFile = 2035 JavaFileObjects.forSourceLines( 2036 "test.SimpleComponentInterface", 2037 "package test;", 2038 "", 2039 "interface SimpleComponentInterface {", 2040 " GeneratedType generatedType();", 2041 "}"); 2042 assertAbout(javaSources()) 2043 .that(ImmutableList.of(componentFile, interfaceFile)) 2044 .processedWith( 2045 new ComponentProcessor(), 2046 new GeneratingProcessor( 2047 "test.GeneratedType", 2048 "package test;", 2049 "", 2050 "import javax.inject.Inject;", 2051 "", 2052 "final class GeneratedType {", 2053 " @Inject GeneratedType() {}", 2054 "}")) 2055 .compilesWithoutError() 2056 .and() 2057 .generatesFileNamed(SOURCE_OUTPUT, "test", "DaggerSimpleComponent.java"); 2058 } 2059 2060 @Test 2061 @Ignore // modify this test as necessary while debugging for your situation. 2062 @SuppressWarnings("unused") genericTestToLetMeDebugInEclipse()2063 public void genericTestToLetMeDebugInEclipse() { 2064 JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A", 2065 "package test;", 2066 "", 2067 "import javax.inject.Inject;", 2068 "", 2069 "public final class A {", 2070 " @Inject A() {}", 2071 "}"); 2072 JavaFileObject bFile = JavaFileObjects.forSourceLines("test.B", 2073 "package test;", 2074 "", 2075 "import javax.inject.Inject;", 2076 "import javax.inject.Provider;", 2077 "", 2078 "public class B<T> {", 2079 " @Inject B() {}", 2080 "}"); 2081 JavaFileObject dFile = JavaFileObjects.forSourceLines("test.sub.D", 2082 "package test.sub;", 2083 "", 2084 "import javax.inject.Inject;", 2085 "import javax.inject.Provider;", 2086 "import test.B;", 2087 "", 2088 "public class D {", 2089 " @Inject D(B<A.InA> ba) {}", 2090 "}"); 2091 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 2092 "package test;", 2093 "", 2094 "import dagger.Component;", 2095 "import dagger.Lazy;", 2096 "", 2097 "import javax.inject.Provider;", 2098 "", 2099 "@Component", 2100 "interface SimpleComponent {", 2101 " B<A> d();", 2102 " Provider<B<A>> d2();", 2103 "}"); 2104 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 2105 "test.DaggerSimpleComponent", 2106 "package test;", 2107 "", 2108 "import javax.annotation.Generated;", 2109 "import javax.inject.Provider;", 2110 "", 2111 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 2112 "public final class DaggerSimpleComponent implements SimpleComponent {", 2113 " private Provider<D> dProvider;", 2114 "", 2115 " private DaggerSimpleComponent(Builder builder) {", 2116 " assert builder != null;", 2117 " initialize(builder);", 2118 " }", 2119 "", 2120 " public static Builder builder() {", 2121 " return new Builder();", 2122 " }", 2123 "", 2124 " public static SimpleComponent create() {", 2125 " return builder().build();", 2126 " }", 2127 "", 2128 " @SuppressWarnings(\"unchecked\")", 2129 " private void initialize(final Builder builder) {", 2130 " this.dProvider = new D_Factory(B_Factory.INSTANCE);", 2131 " }", 2132 "", 2133 " @Override", 2134 " public D d() {", 2135 " return dProvider.get();", 2136 " }", 2137 "", 2138 " public static final class Builder {", 2139 " private Builder() {", 2140 " }", 2141 "", 2142 " public SimpleComponent build() {", 2143 " return new DaggerSimpleComponent(this);", 2144 " }", 2145 " }", 2146 "}"); 2147 assertAbout(javaSources()).that(ImmutableList.of(aFile, bFile, componentFile)) 2148 .processedWith(new ComponentProcessor()) 2149 .compilesWithoutError() 2150 .and().generatesSources(generatedComponent); 2151 } 2152 2153 /** 2154 * A simple {@link Processor} that generates one source file. 2155 */ 2156 private static final class GeneratingProcessor extends AbstractProcessor { 2157 private final String generatedClassName; 2158 private final String generatedSource; 2159 private boolean processed; 2160 GeneratingProcessor(String generatedClassName, String... source)2161 GeneratingProcessor(String generatedClassName, String... source) { 2162 this.generatedClassName = generatedClassName; 2163 this.generatedSource = Joiner.on("\n").join(source); 2164 } 2165 2166 @Override getSupportedAnnotationTypes()2167 public Set<String> getSupportedAnnotationTypes() { 2168 return ImmutableSet.of("*"); 2169 } 2170 2171 @Override process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv)2172 public boolean process(Set<? extends TypeElement> annotations, RoundEnvironment roundEnv) { 2173 if (!processed) { 2174 processed = true; 2175 try (Writer writer = 2176 processingEnv.getFiler().createSourceFile(generatedClassName).openWriter()) { 2177 writer.append(generatedSource); 2178 } catch (IOException e) { 2179 throw new RuntimeException(e); 2180 } 2181 } 2182 return false; 2183 } 2184 } 2185 } 2186