1 /* 2 * Copyright (C) 2015 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.collect.ImmutableList; 19 import com.google.testing.compile.JavaFileObjects; 20 import javax.tools.JavaFileObject; 21 import org.junit.Test; 22 import org.junit.runner.RunWith; 23 import org.junit.runners.JUnit4; 24 25 import static com.google.common.truth.Truth.assertAbout; 26 import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; 27 import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources; 28 29 /** Tests for {@link dagger.Component.Builder} */ 30 @RunWith(JUnit4.class) 31 public class ComponentBuilderTest { 32 33 private static final ErrorMessages.ComponentBuilderMessages MSGS = 34 ErrorMessages.ComponentBuilderMessages.INSTANCE; 35 36 @Test testEmptyBuilder()37 public void testEmptyBuilder() { 38 JavaFileObject injectableTypeFile = JavaFileObjects.forSourceLines("test.SomeInjectableType", 39 "package test;", 40 "", 41 "import javax.inject.Inject;", 42 "", 43 "final class SomeInjectableType {", 44 " @Inject SomeInjectableType() {}", 45 "}"); 46 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 47 "package test;", 48 "", 49 "import dagger.Component;", 50 "", 51 "import javax.inject.Provider;", 52 "", 53 "@Component", 54 "interface SimpleComponent {", 55 " SomeInjectableType someInjectableType();", 56 "", 57 " @Component.Builder", 58 " static interface Builder {", 59 " SimpleComponent build();", 60 " }", 61 "}"); 62 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 63 "test.DaggerSimpleComponent", 64 "package test;", 65 "", 66 "import javax.annotation.Generated;", 67 "import test.SimpleComponent", 68 "", 69 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 70 "public final class DaggerSimpleComponent implements SimpleComponent {", 71 " private DaggerSimpleComponent(Builder builder) {", 72 " assert builder != null;", 73 " initialize(builder);", 74 " }", 75 "", 76 " public static SimpleComponent.Builder builder() {", 77 " return new Builder();", 78 " }", 79 "", 80 " public static SimpleComponent create() {", 81 " return builder().build();", 82 " }", 83 "", 84 " @SuppressWarnings(\"unchecked\")", 85 " private void initialize(final Builder builder) {", 86 " }", 87 "", 88 " @Override", 89 " public SomeInjectableType someInjectableType() {", 90 " return SomeInjectableType_Factory.create().get();", 91 " }", 92 "", 93 " private static final class Builder implements SimpleComponent.Builder {", 94 " @Override", 95 " public SimpleComponent build() {", 96 " return new DaggerSimpleComponent(this);", 97 " }", 98 " }", 99 "}"); 100 assertAbout(javaSources()).that(ImmutableList.of(injectableTypeFile, componentFile)) 101 .processedWith(new ComponentProcessor()) 102 .compilesWithoutError() 103 .and().generatesSources(generatedComponent); 104 } 105 106 @Test testUsesBuildAndSetterNames()107 public void testUsesBuildAndSetterNames() { 108 JavaFileObject moduleFile = JavaFileObjects.forSourceLines("test.TestModule", 109 "package test;", 110 "", 111 "import dagger.Module;", 112 "import dagger.Provides;", 113 "", 114 "@Module", 115 "final class TestModule {", 116 " @Provides String string() { return null; }", 117 "}"); 118 119 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent", 120 "package test;", 121 "", 122 "import dagger.Component;", 123 "", 124 "@Component(modules = TestModule.class)", 125 "interface TestComponent {", 126 " String string();", 127 "", 128 " @Component.Builder", 129 " interface Builder {", 130 " Builder setTestModule(TestModule testModule);", 131 " TestComponent create();", 132 " }", 133 "}"); 134 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 135 "test.DaggerTestComponent", 136 "package test;", 137 "", 138 "import javax.annotation.Generated;", 139 "import javax.inject.Provider;", 140 "import test.TestComponent;", 141 "", 142 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 143 "public final class DaggerTestComponent implements TestComponent {", 144 " private Provider<String> stringProvider;", 145 "", 146 " private DaggerTestComponent(Builder builder) {", 147 " assert builder != null;", 148 " initialize(builder);", 149 " }", 150 "", 151 " public static TestComponent.Builder builder() {", 152 " return new Builder();", 153 " }", 154 "", 155 " public static TestComponent create() {", 156 " return builder().create();", 157 " }", 158 "", 159 " @SuppressWarnings(\"unchecked\")", 160 " private void initialize(final Builder builder) {", 161 " this.stringProvider = TestModule_StringFactory.create(builder.testModule);", 162 " }", 163 "", 164 " @Override", 165 " public String string() {", 166 " return stringProvider.get();", 167 " }", 168 "", 169 " private static final class Builder implements TestComponent.Builder {", 170 " private TestModule testModule;", 171 "", 172 " @Override", 173 " public TestComponent create() {", 174 " if (testModule == null) {", 175 " this.testModule = new TestModule();", 176 " }", 177 " return new DaggerTestComponent(this);", 178 " }", 179 "", 180 " @Override", 181 " public Builder setTestModule(TestModule testModule) {", 182 " if (testModule == null) {", 183 " throw new NullPointerException();", 184 " }", 185 " this.testModule = testModule;", 186 " return this;", 187 " }", 188 " }", 189 "}"); 190 assertAbout(javaSources()) 191 .that(ImmutableList.of(moduleFile, componentFile)) 192 .processedWith(new ComponentProcessor()) 193 .compilesWithoutError() 194 .and().generatesSources(generatedComponent); 195 } 196 197 @Test testIgnoresModulesNotInApi()198 public void testIgnoresModulesNotInApi() { 199 JavaFileObject module1 = JavaFileObjects.forSourceLines("test.TestModule1", 200 "package test;", 201 "", 202 "import dagger.Module;", 203 "import dagger.Provides;", 204 "", 205 "@Module", 206 "final class TestModule1 {", 207 " @Provides String string() { return null; }", 208 "}"); 209 JavaFileObject module2 = JavaFileObjects.forSourceLines("test.TestModule2", 210 "package test;", 211 "", 212 "import dagger.Module;", 213 "import dagger.Provides;", 214 "", 215 "@Module", 216 "final class TestModule2 {", 217 " @Provides Integer integer() { return null; }", 218 "}"); 219 220 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent", 221 "package test;", 222 "", 223 "import dagger.Component;", 224 "", 225 "@Component(modules = {TestModule1.class, TestModule2.class})", 226 "interface TestComponent {", 227 " String string();", 228 " Integer integer();", 229 "", 230 " @Component.Builder", 231 " interface Builder {", 232 " Builder testModule1(TestModule1 testModule1);", 233 " TestComponent build();", 234 " }", 235 "}"); 236 JavaFileObject generatedComponent = JavaFileObjects.forSourceLines( 237 "test.DaggerTestComponent", 238 "package test;", 239 "", 240 "import javax.annotation.Generated;", 241 "import javax.inject.Provider;", 242 "import test.TestComponent;", 243 "", 244 "@Generated(\"dagger.internal.codegen.ComponentProcessor\")", 245 "public final class DaggerTestComponent implements TestComponent {", 246 " private Provider<String> stringProvider;", 247 " private Provider<Integer> integerProvider;", 248 "", 249 " private DaggerTestComponent(Builder builder) {", 250 " assert builder != null;", 251 " initialize(builder);", 252 " }", 253 "", 254 " public static TestComponent.Builder builder() {", 255 " return new Builder();", 256 " }", 257 "", 258 " public static TestComponent create() {", 259 " return builder().build();", 260 " }", 261 "", 262 " @SuppressWarnings(\"unchecked\")", 263 " private void initialize(final Builder builder) {", 264 " this.stringProvider = TestModule1_StringFactory.create(builder.testModule1);", 265 " this.integerProvider = TestModule2_IntegerFactory.create(builder.testModule2);", 266 " }", 267 "", 268 " @Override", 269 " public String string() {", 270 " return stringProvider.get();", 271 " }", 272 "", 273 " @Override", 274 " public Integer integer() {", 275 " return integerProvider.get();", 276 " }", 277 "", 278 " private static final class Builder implements TestComponent.Builder {", 279 " private TestModule1 testModule1;", 280 " private TestModule2 testModule2;", 281 "", 282 " @Override", 283 " public TestComponent build() {", 284 " if (testModule1 == null) {", 285 " this.testModule1 = new TestModule1();", 286 " }", 287 " if (testModule2 == null) {", 288 " this.testModule2 = new TestModule2();", 289 " }", 290 " return new DaggerTestComponent(this);", 291 " }", 292 "", 293 " @Override", 294 " public Builder testModule1(TestModule1 testModule1) {", 295 " if (testModule1 == null) {", 296 " throw new NullPointerException();", 297 " }", 298 " this.testModule1 = testModule1;", 299 " return this;", 300 " }", 301 " }", 302 "}"); 303 assertAbout(javaSources()) 304 .that(ImmutableList.of(module1, module2, componentFile)) 305 .processedWith(new ComponentProcessor()) 306 .compilesWithoutError() 307 .and().generatesSources(generatedComponent); 308 } 309 310 @Test testMoreThanOneBuilderFails()311 public void testMoreThanOneBuilderFails() { 312 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 313 "package test;", 314 "", 315 "import dagger.Component;", 316 "", 317 "import javax.inject.Provider;", 318 "", 319 "@Component", 320 "interface SimpleComponent {", 321 " @Component.Builder", 322 " static interface Builder {", 323 " SimpleComponent build();", 324 " }", 325 "", 326 " @Component.Builder", 327 " interface Builder2 {", 328 " SimpleComponent build();", 329 " }", 330 "}"); 331 assertAbout(javaSource()).that(componentFile) 332 .processedWith(new ComponentProcessor()) 333 .failsToCompile() 334 .withErrorContaining(String.format(MSGS.moreThanOne(), 335 "[test.SimpleComponent.Builder, test.SimpleComponent.Builder2]")) 336 .in(componentFile); 337 } 338 339 @Test testBuilderGenericsFails()340 public void testBuilderGenericsFails() { 341 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 342 "package test;", 343 "", 344 "import dagger.Component;", 345 "", 346 "import javax.inject.Provider;", 347 "", 348 "@Component", 349 "interface SimpleComponent {", 350 " @Component.Builder", 351 " interface Builder<T> {", 352 " SimpleComponent build();", 353 " }", 354 "}"); 355 assertAbout(javaSource()).that(componentFile) 356 .processedWith(new ComponentProcessor()) 357 .failsToCompile() 358 .withErrorContaining(MSGS.generics()) 359 .in(componentFile); 360 } 361 362 @Test testBuilderNotInComponentFails()363 public void testBuilderNotInComponentFails() { 364 JavaFileObject builder = JavaFileObjects.forSourceLines("test.Builder", 365 "package test;", 366 "", 367 "import dagger.Component;", 368 "", 369 "@Component.Builder", 370 "interface Builder {}"); 371 assertAbout(javaSource()).that(builder) 372 .processedWith(new ComponentProcessor()) 373 .failsToCompile() 374 .withErrorContaining(MSGS.mustBeInComponent()) 375 .in(builder); 376 } 377 378 @Test testBuilderMissingBuildMethodFails()379 public void testBuilderMissingBuildMethodFails() { 380 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 381 "package test;", 382 "", 383 "import dagger.Component;", 384 "", 385 "import javax.inject.Provider;", 386 "", 387 "@Component", 388 "interface SimpleComponent {", 389 " @Component.Builder", 390 " interface Builder {}", 391 "}"); 392 assertAbout(javaSource()).that(componentFile) 393 .processedWith(new ComponentProcessor()) 394 .failsToCompile() 395 .withErrorContaining(MSGS.missingBuildMethod()) 396 .in(componentFile); 397 } 398 399 @Test testPrivateBuilderFails()400 public void testPrivateBuilderFails() { 401 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 402 "package test;", 403 "", 404 "import dagger.Component;", 405 "", 406 "import javax.inject.Provider;", 407 "", 408 "@Component", 409 "abstract class SimpleComponent {", 410 " @Component.Builder", 411 " private interface Builder {}", 412 "}"); 413 assertAbout(javaSource()).that(componentFile) 414 .processedWith(new ComponentProcessor()) 415 .failsToCompile() 416 .withErrorContaining(MSGS.isPrivate()) 417 .in(componentFile); 418 } 419 420 @Test testNonStaticBuilderFails()421 public void testNonStaticBuilderFails() { 422 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 423 "package test;", 424 "", 425 "import dagger.Component;", 426 "", 427 "import javax.inject.Provider;", 428 "", 429 "@Component", 430 "abstract class SimpleComponent {", 431 " @Component.Builder", 432 " abstract class Builder {}", 433 "}"); 434 assertAbout(javaSource()).that(componentFile) 435 .processedWith(new ComponentProcessor()) 436 .failsToCompile() 437 .withErrorContaining(MSGS.mustBeStatic()) 438 .in(componentFile); 439 } 440 441 @Test testNonAbstractBuilderFails()442 public void testNonAbstractBuilderFails() { 443 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 444 "package test;", 445 "", 446 "import dagger.Component;", 447 "", 448 "import javax.inject.Provider;", 449 "", 450 "@Component", 451 "abstract class SimpleComponent {", 452 " @Component.Builder", 453 " static class Builder {}", 454 "}"); 455 assertAbout(javaSource()).that(componentFile) 456 .processedWith(new ComponentProcessor()) 457 .failsToCompile() 458 .withErrorContaining(MSGS.mustBeAbstract()); 459 } 460 461 @Test testBuilderOneCxtorWithArgsFails()462 public void testBuilderOneCxtorWithArgsFails() { 463 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 464 "package test;", 465 "", 466 "import dagger.Component;", 467 "", 468 "import javax.inject.Provider;", 469 "", 470 "@Component", 471 "abstract class SimpleComponent {", 472 " @Component.Builder", 473 " static abstract class Builder {", 474 " Builder(String unused) {}", 475 " }", 476 "}"); 477 assertAbout(javaSource()).that(componentFile) 478 .processedWith(new ComponentProcessor()) 479 .failsToCompile() 480 .withErrorContaining(MSGS.cxtorOnlyOneAndNoArgs()) 481 .in(componentFile); 482 } 483 484 @Test testBuilderMoreThanOneCxtorFails()485 public void testBuilderMoreThanOneCxtorFails() { 486 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 487 "package test;", 488 "", 489 "import dagger.Component;", 490 "", 491 "import javax.inject.Provider;", 492 "", 493 "@Component", 494 "abstract class SimpleComponent {", 495 " @Component.Builder", 496 " static abstract class Builder {", 497 " Builder() {}", 498 " Builder(String unused) {}", 499 " }", 500 "}"); 501 assertAbout(javaSource()).that(componentFile) 502 .processedWith(new ComponentProcessor()) 503 .failsToCompile() 504 .withErrorContaining(MSGS.cxtorOnlyOneAndNoArgs()) 505 .in(componentFile); 506 } 507 508 @Test testBuilderEnumFails()509 public void testBuilderEnumFails() { 510 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 511 "package test;", 512 "", 513 "import dagger.Component;", 514 "", 515 "import javax.inject.Provider;", 516 "", 517 "@Component", 518 "abstract class SimpleComponent {", 519 " @Component.Builder", 520 " enum Builder {}", 521 "}"); 522 assertAbout(javaSource()).that(componentFile) 523 .processedWith(new ComponentProcessor()) 524 .failsToCompile() 525 .withErrorContaining(MSGS.mustBeClassOrInterface()) 526 .in(componentFile); 527 } 528 529 @Test testBuilderBuildReturnsWrongTypeFails()530 public void testBuilderBuildReturnsWrongTypeFails() { 531 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 532 "package test;", 533 "", 534 "import dagger.Component;", 535 "", 536 "import javax.inject.Provider;", 537 "", 538 "@Component", 539 "abstract class SimpleComponent {", 540 " @Component.Builder", 541 " interface Builder {", 542 " String build();", 543 " }", 544 "}"); 545 assertAbout(javaSource()).that(componentFile) 546 .processedWith(new ComponentProcessor()) 547 .failsToCompile() 548 .withErrorContaining(MSGS.buildMustReturnComponentType()) 549 .in(componentFile).onLine(11); 550 } 551 552 @Test testInheritedBuilderBuildReturnsWrongTypeFails()553 public void testInheritedBuilderBuildReturnsWrongTypeFails() { 554 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 555 "package test;", 556 "", 557 "import dagger.Component;", 558 "", 559 "import javax.inject.Provider;", 560 "", 561 "@Component", 562 "abstract class SimpleComponent {", 563 " interface Parent {", 564 " String build();", 565 " }", 566 "", 567 " @Component.Builder", 568 " interface Builder extends Parent {}", 569 "}"); 570 assertAbout(javaSource()).that(componentFile) 571 .processedWith(new ComponentProcessor()) 572 .failsToCompile() 573 .withErrorContaining( 574 String.format(MSGS.inheritedBuildMustReturnComponentType(), "build")) 575 .in(componentFile).onLine(14); 576 } 577 578 @Test testTwoBuildMethodsFails()579 public void testTwoBuildMethodsFails() { 580 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 581 "package test;", 582 "", 583 "import dagger.Component;", 584 "", 585 "import javax.inject.Provider;", 586 "", 587 "@Component", 588 "abstract class SimpleComponent {", 589 " @Component.Builder", 590 " interface Builder {", 591 " SimpleComponent build();", 592 " SimpleComponent create();", 593 " }", 594 "}"); 595 assertAbout(javaSource()).that(componentFile) 596 .processedWith(new ComponentProcessor()) 597 .failsToCompile() 598 .withErrorContaining(String.format(MSGS.twoBuildMethods(), "build()")) 599 .in(componentFile).onLine(12); 600 } 601 602 @Test testInheritedTwoBuildMethodsFails()603 public void testInheritedTwoBuildMethodsFails() { 604 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 605 "package test;", 606 "", 607 "import dagger.Component;", 608 "", 609 "import javax.inject.Provider;", 610 "", 611 "@Component", 612 "abstract class SimpleComponent {", 613 " interface Parent {", 614 " SimpleComponent build();", 615 " SimpleComponent create();", 616 " }", 617 "", 618 " @Component.Builder", 619 " interface Builder extends Parent {}", 620 "}"); 621 assertAbout(javaSource()).that(componentFile) 622 .processedWith(new ComponentProcessor()) 623 .failsToCompile() 624 .withErrorContaining( 625 String.format(MSGS.inheritedTwoBuildMethods(), "create()", "build()")) 626 .in(componentFile).onLine(15); 627 } 628 629 @Test testMoreThanOneArgFails()630 public void testMoreThanOneArgFails() { 631 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 632 "package test;", 633 "", 634 "import dagger.Component;", 635 "", 636 "import javax.inject.Provider;", 637 "", 638 "@Component", 639 "abstract class SimpleComponent {", 640 " @Component.Builder", 641 " interface Builder {", 642 " SimpleComponent build();", 643 " Builder set(String s, Integer i);", 644 " Builder set(Number n, Double d);", 645 " }", 646 "}"); 647 assertAbout(javaSource()).that(componentFile) 648 .processedWith(new ComponentProcessor()) 649 .failsToCompile() 650 .withErrorContaining(MSGS.methodsMustTakeOneArg()) 651 .in(componentFile).onLine(12) 652 .and().withErrorContaining(MSGS.methodsMustTakeOneArg()) 653 .in(componentFile).onLine(13); 654 } 655 656 @Test testInheritedMoreThanOneArgFails()657 public void testInheritedMoreThanOneArgFails() { 658 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 659 "package test;", 660 "", 661 "import dagger.Component;", 662 "", 663 "import javax.inject.Provider;", 664 "", 665 "@Component", 666 "abstract class SimpleComponent {", 667 " interface Parent {", 668 " SimpleComponent build();", 669 " Builder set1(String s, Integer i);", 670 " }", 671 "", 672 " @Component.Builder", 673 " interface Builder extends Parent {}", 674 "}"); 675 assertAbout(javaSource()).that(componentFile) 676 .processedWith(new ComponentProcessor()) 677 .failsToCompile() 678 .withErrorContaining( 679 String.format(MSGS.inheritedMethodsMustTakeOneArg(), 680 "set1(java.lang.String,java.lang.Integer)")) 681 .in(componentFile).onLine(15); 682 } 683 684 @Test testSetterReturningNonVoidOrBuilderFails()685 public void testSetterReturningNonVoidOrBuilderFails() { 686 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 687 "package test;", 688 "", 689 "import dagger.Component;", 690 "", 691 "import javax.inject.Provider;", 692 "", 693 "@Component", 694 "abstract class SimpleComponent {", 695 " @Component.Builder", 696 " interface Builder {", 697 " SimpleComponent build();", 698 " String set(Integer i);", 699 " }", 700 "}"); 701 assertAbout(javaSource()).that(componentFile) 702 .processedWith(new ComponentProcessor()) 703 .failsToCompile() 704 .withErrorContaining(MSGS.methodsMustReturnVoidOrBuilder()) 705 .in(componentFile).onLine(12); 706 } 707 708 @Test testInheritedSetterReturningNonVoidOrBuilderFails()709 public void testInheritedSetterReturningNonVoidOrBuilderFails() { 710 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 711 "package test;", 712 "", 713 "import dagger.Component;", 714 "", 715 "import javax.inject.Provider;", 716 "", 717 "@Component", 718 "abstract class SimpleComponent {", 719 " interface Parent {", 720 " SimpleComponent build();", 721 " String set(Integer i);", 722 " }", 723 "", 724 " @Component.Builder", 725 " interface Builder extends Parent {}", 726 "}"); 727 assertAbout(javaSource()).that(componentFile) 728 .processedWith(new ComponentProcessor()) 729 .failsToCompile() 730 .withErrorContaining( 731 String.format(MSGS.inheritedMethodsMustReturnVoidOrBuilder(), 732 "set(java.lang.Integer)")) 733 .in(componentFile).onLine(15); 734 } 735 736 @Test testGenericsOnSetterMethodFails()737 public void testGenericsOnSetterMethodFails() { 738 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 739 "package test;", 740 "", 741 "import dagger.Component;", 742 "", 743 "import javax.inject.Provider;", 744 "", 745 "@Component", 746 "abstract class SimpleComponent {", 747 " @Component.Builder", 748 " interface Builder {", 749 " SimpleComponent build();", 750 " <T> Builder set(T t);", 751 " }", 752 "}"); 753 assertAbout(javaSource()).that(componentFile) 754 .processedWith(new ComponentProcessor()) 755 .failsToCompile() 756 .withErrorContaining(MSGS.methodsMayNotHaveTypeParameters()) 757 .in(componentFile).onLine(12); 758 } 759 760 @Test testGenericsOnInheritedSetterMethodFails()761 public void testGenericsOnInheritedSetterMethodFails() { 762 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 763 "package test;", 764 "", 765 "import dagger.Component;", 766 "", 767 "import javax.inject.Provider;", 768 "", 769 "@Component", 770 "abstract class SimpleComponent {", 771 " interface Parent {", 772 " SimpleComponent build();", 773 " <T> Builder set(T t);", 774 " }", 775 "", 776 " @Component.Builder", 777 " interface Builder extends Parent {}", 778 "}"); 779 assertAbout(javaSource()).that(componentFile) 780 .processedWith(new ComponentProcessor()) 781 .failsToCompile() 782 .withErrorContaining( 783 String.format(MSGS.inheritedMethodsMayNotHaveTypeParameters(), "<T>set(T)")) 784 .in(componentFile).onLine(15); 785 } 786 787 @Test testMultipleSettersPerTypeFails()788 public void testMultipleSettersPerTypeFails() { 789 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 790 "package test;", 791 "", 792 "import dagger.Component;", 793 "", 794 "import javax.inject.Provider;", 795 "", 796 "@Component", 797 "abstract class SimpleComponent {", 798 " @Component.Builder", 799 " interface Builder {", 800 " SimpleComponent build();", 801 " void set1(String s);", 802 " void set2(String s);", 803 " }", 804 "}"); 805 assertAbout(javaSource()).that(componentFile) 806 .processedWith(new ComponentProcessor()) 807 .failsToCompile() 808 .withErrorContaining( 809 String.format(MSGS.manyMethodsForType(), 810 "java.lang.String", "[set1(java.lang.String), set2(java.lang.String)]")) 811 .in(componentFile).onLine(10); 812 } 813 814 @Test testMultipleSettersPerTypeIncludingResolvedGenericsFails()815 public void testMultipleSettersPerTypeIncludingResolvedGenericsFails() { 816 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 817 "package test;", 818 "", 819 "import dagger.Component;", 820 "", 821 "import javax.inject.Provider;", 822 "", 823 "@Component", 824 "abstract class SimpleComponent {", 825 " interface Parent<T> {", 826 " void set1(T t);", 827 " }", 828 "", 829 " @Component.Builder", 830 " interface Builder extends Parent<String> {", 831 " SimpleComponent build();", 832 " void set2(String s);", 833 " }", 834 "}"); 835 assertAbout(javaSource()).that(componentFile) 836 .processedWith(new ComponentProcessor()) 837 .failsToCompile() 838 .withErrorContaining( 839 String.format(MSGS.manyMethodsForType(), 840 "java.lang.String", "[set1(T), set2(java.lang.String)]")) 841 .in(componentFile).onLine(14); 842 } 843 844 @Test testExtraSettersFails()845 public void testExtraSettersFails() { 846 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.SimpleComponent", 847 "package test;", 848 "", 849 "import dagger.Component;", 850 "", 851 "import javax.inject.Provider;", 852 "", 853 "@Component", 854 "abstract class SimpleComponent {", 855 " @Component.Builder", 856 " interface Builder {", 857 " SimpleComponent build();", 858 " void set1(String s);", 859 " void set2(Integer s);", 860 " }", 861 "}"); 862 assertAbout(javaSource()).that(componentFile) 863 .processedWith(new ComponentProcessor()) 864 .failsToCompile() 865 .withErrorContaining( 866 String.format(MSGS.extraSetters(), 867 "[void test.SimpleComponent.Builder.set1(String)," 868 + " void test.SimpleComponent.Builder.set2(Integer)]")) 869 .in(componentFile).onLine(10); 870 871 } 872 873 @Test testMissingSettersFail()874 public void testMissingSettersFail() { 875 JavaFileObject moduleFile = JavaFileObjects.forSourceLines("test.TestModule", 876 "package test;", 877 "", 878 "import dagger.Module;", 879 "import dagger.Provides;", 880 "", 881 "@Module", 882 "final class TestModule {", 883 " TestModule(String unused) {}", 884 " @Provides String s() { return null; }", 885 "}"); 886 JavaFileObject module2File = JavaFileObjects.forSourceLines("test.Test2Module", 887 "package test;", 888 "", 889 "import dagger.Module;", 890 "import dagger.Provides;", 891 "", 892 "@Module", 893 "final class Test2Module {", 894 " @Provides Integer i() { return null; }", 895 "}"); 896 JavaFileObject module3File = JavaFileObjects.forSourceLines("test.Test3Module", 897 "package test;", 898 "", 899 "import dagger.Module;", 900 "import dagger.Provides;", 901 "", 902 "@Module", 903 "final class Test3Module {", 904 " Test3Module(String unused) {}", 905 " @Provides Double d() { return null; }", 906 "}"); 907 JavaFileObject componentFile = JavaFileObjects.forSourceLines("test.TestComponent", 908 "package test;", 909 "", 910 "import dagger.Component;", 911 "", 912 "@Component(modules = {TestModule.class, Test2Module.class, Test3Module.class},", 913 " dependencies = OtherComponent.class)", 914 "interface TestComponent {", 915 " String string();", 916 " Integer integer();", 917 "", 918 " @Component.Builder", 919 " interface Builder {", 920 " TestComponent create();", 921 " }", 922 "}"); 923 JavaFileObject otherComponent = JavaFileObjects.forSourceLines("test.OtherComponent", 924 "package test;", 925 "", 926 "import dagger.Component;", 927 "", 928 "@Component", 929 "interface OtherComponent {}"); 930 assertAbout(javaSources()) 931 .that(ImmutableList.of(moduleFile, module2File, module3File, componentFile, otherComponent)) 932 .processedWith(new ComponentProcessor()) 933 .failsToCompile() 934 .withErrorContaining( 935 // Ignores Test2Module because we can construct it ourselves. 936 // TODO(sameb): Ignore Test3Module because it's not used within transitive dependencies. 937 String.format(MSGS.missingSetters(), 938 "[test.TestModule, test.Test3Module, test.OtherComponent]")) 939 .in(componentFile).onLine(12); 940 } 941 } 942