1 /* 2 * Copyright (C) 2014 The Dagger Authors. 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 17 package dagger.internal.codegen; 18 19 import static com.google.common.truth.Truth.assertAbout; 20 import static com.google.testing.compile.CompilationSubject.assertThat; 21 import static com.google.testing.compile.JavaSourceSubjectFactory.javaSource; 22 import static com.google.testing.compile.JavaSourcesSubjectFactory.javaSources; 23 import static dagger.internal.codegen.Compilers.compilerWithOptions; 24 import static dagger.internal.codegen.Compilers.daggerCompiler; 25 26 import com.google.common.collect.ImmutableList; 27 import com.google.testing.compile.Compilation; 28 import com.google.testing.compile.JavaFileObjects; 29 import javax.tools.JavaFileObject; 30 import org.junit.Test; 31 import org.junit.runner.RunWith; 32 import org.junit.runners.JUnit4; 33 34 @RunWith(JUnit4.class) 35 // TODO(gak): add tests for generation in the default package. 36 public final class InjectConstructorFactoryGeneratorTest { 37 private static final JavaFileObject QUALIFIER_A = 38 JavaFileObjects.forSourceLines("test.QualifierA", 39 "package test;", 40 "", 41 "import javax.inject.Qualifier;", 42 "", 43 "@Qualifier @interface QualifierA {}"); 44 private static final JavaFileObject QUALIFIER_B = 45 JavaFileObjects.forSourceLines("test.QualifierB", 46 "package test;", 47 "", 48 "import javax.inject.Qualifier;", 49 "", 50 "@Qualifier @interface QualifierB {}"); 51 private static final JavaFileObject SCOPE_A = 52 JavaFileObjects.forSourceLines("test.ScopeA", 53 "package test;", 54 "", 55 "import javax.inject.Scope;", 56 "", 57 "@Scope @interface ScopeA {}"); 58 private static final JavaFileObject SCOPE_B = 59 JavaFileObjects.forSourceLines("test.ScopeB", 60 "package test;", 61 "", 62 "import javax.inject.Scope;", 63 "", 64 "@Scope @interface ScopeB {}"); 65 injectOnPrivateConstructor()66 @Test public void injectOnPrivateConstructor() { 67 JavaFileObject file = JavaFileObjects.forSourceLines("test.PrivateConstructor", 68 "package test;", 69 "", 70 "import javax.inject.Inject;", 71 "", 72 "class PrivateConstructor {", 73 " @Inject private PrivateConstructor() {}", 74 "}"); 75 Compilation compilation = daggerCompiler().compile(file); 76 assertThat(compilation).failed(); 77 assertThat(compilation) 78 .hadErrorContaining("Dagger does not support injection into private constructors") 79 .inFile(file) 80 .onLine(6); 81 } 82 injectConstructorOnInnerClass()83 @Test public void injectConstructorOnInnerClass() { 84 JavaFileObject file = JavaFileObjects.forSourceLines("test.OuterClass", 85 "package test;", 86 "", 87 "import javax.inject.Inject;", 88 "", 89 "class OuterClass {", 90 " class InnerClass {", 91 " @Inject InnerClass() {}", 92 " }", 93 "}"); 94 Compilation compilation = daggerCompiler().compile(file); 95 assertThat(compilation).failed(); 96 assertThat(compilation) 97 .hadErrorContaining( 98 "@Inject constructors are invalid on inner classes. " 99 + "Did you mean to make the class static?") 100 .inFile(file) 101 .onLine(7); 102 } 103 injectConstructorOnAbstractClass()104 @Test public void injectConstructorOnAbstractClass() { 105 JavaFileObject file = JavaFileObjects.forSourceLines("test.AbstractClass", 106 "package test;", 107 "", 108 "import javax.inject.Inject;", 109 "", 110 "abstract class AbstractClass {", 111 " @Inject AbstractClass() {}", 112 "}"); 113 Compilation compilation = daggerCompiler().compile(file); 114 assertThat(compilation).failed(); 115 assertThat(compilation) 116 .hadErrorContaining("@Inject is nonsense on the constructor of an abstract class") 117 .inFile(file) 118 .onLine(6); 119 } 120 injectConstructorOnGenericClass()121 @Test public void injectConstructorOnGenericClass() { 122 JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericClass", 123 "package test;", 124 "", 125 "import javax.inject.Inject;", 126 "", 127 "class GenericClass<T> {", 128 " @Inject GenericClass(T t) {}", 129 "}"); 130 JavaFileObject expected = 131 JavaFileObjects.forSourceLines( 132 "test.GenericClass_Factory", 133 "package test;", 134 "", 135 GeneratedLines.generatedImports( 136 "import dagger.internal.Factory;", 137 "import javax.inject.Provider;"), 138 "", 139 GeneratedLines.generatedAnnotations(), 140 "public final class GenericClass_Factory<T> implements Factory<GenericClass<T>> {", 141 " private final Provider<T> tProvider;", 142 "", 143 " public GenericClass_Factory(Provider<T> tProvider) {", 144 " this.tProvider = tProvider;", 145 " }", 146 "", 147 " @Override", 148 " public GenericClass<T> get() {", 149 " return newInstance(tProvider.get());", 150 " }", 151 "", 152 " public static <T> GenericClass_Factory<T> create(Provider<T> tProvider) {", 153 " return new GenericClass_Factory<T>(tProvider);", 154 " }", 155 "", 156 " public static <T> GenericClass<T> newInstance(T t) {", 157 " return new GenericClass<T>(t);", 158 " }", 159 "}"); 160 assertAbout(javaSource()).that(file) 161 .processedWith(new ComponentProcessor()) 162 .compilesWithoutError() 163 .and().generatesSources(expected); 164 } 165 fieldAndMethodGenerics()166 @Test public void fieldAndMethodGenerics() { 167 JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericClass", 168 "package test;", 169 "", 170 "import javax.inject.Inject;", 171 "", 172 "class GenericClass<A, B> {", 173 " @Inject A a;", 174 "", 175 " @Inject GenericClass() {}", 176 "", 177 " @Inject void register(B b) {}", 178 "}"); 179 JavaFileObject expected = 180 JavaFileObjects.forSourceLines( 181 "test.GenericClass_Factory", 182 "package test;", 183 "", 184 GeneratedLines.generatedImports( 185 "import dagger.internal.Factory;", 186 "import javax.inject.Provider;"), 187 "", 188 GeneratedLines.generatedAnnotations(), 189 "public final class GenericClass_Factory<A, B> implements", 190 " Factory<GenericClass<A, B>> {", 191 " private final Provider<A> aProvider;", 192 " private final Provider<B> bProvider;", 193 "", 194 " public GenericClass_Factory(", 195 " Provider<A> aProvider, Provider<B> bProvider) {", 196 " this.aProvider = aProvider;", 197 " this.bProvider = bProvider;", 198 " }", 199 "", 200 " @Override", 201 " public GenericClass<A, B> get() {", 202 " GenericClass<A, B> instance = newInstance();", 203 " GenericClass_MembersInjector.injectA(instance, aProvider.get());", 204 " GenericClass_MembersInjector.injectRegister(instance, bProvider.get());", 205 " return instance;", 206 " }", 207 "", 208 " public static <A, B> GenericClass_Factory<A, B> create(", 209 " Provider<A> aProvider, Provider<B> bProvider) {", 210 " return new GenericClass_Factory<A, B>(aProvider, bProvider);", 211 " }", 212 "", 213 " public static <A, B> GenericClass<A, B> newInstance() {", 214 " return new GenericClass<A, B>();", 215 " }", 216 "}"); 217 assertAbout(javaSource()).that(file) 218 .processedWith(new ComponentProcessor()) 219 .compilesWithoutError() 220 .and().generatesSources(expected); 221 } 222 genericClassWithNoDependencies()223 @Test public void genericClassWithNoDependencies() { 224 JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericClass", 225 "package test;", 226 "", 227 "import javax.inject.Inject;", 228 "", 229 "class GenericClass<T> {", 230 " @Inject GenericClass() {}", 231 "}"); 232 JavaFileObject expected = 233 JavaFileObjects.forSourceLines( 234 "test.GenericClass_Factory", 235 "package test;", 236 "", 237 GeneratedLines.generatedImports("import dagger.internal.Factory;"), 238 "", 239 GeneratedLines.generatedAnnotations(), 240 "public final class GenericClass_Factory<T> implements Factory<GenericClass<T>> {", 241 " @Override", 242 " public GenericClass<T> get() {", 243 " return newInstance();", 244 " }", 245 "", 246 " @SuppressWarnings(\"unchecked\")", 247 " public static <T> GenericClass_Factory<T> create() {", 248 " return InstanceHolder.INSTANCE;", 249 " }", 250 "", 251 " public static <T> GenericClass<T> newInstance() {", 252 " return new GenericClass<T>();", 253 " }", 254 "", 255 " private static final class InstanceHolder {", 256 " @SuppressWarnings(\"rawtypes\")", 257 " private static final GenericClass_Factory INSTANCE = new GenericClass_Factory();", 258 " }", 259 "}"); 260 assertAbout(javaSource()).that(file) 261 .processedWith(new ComponentProcessor()) 262 .compilesWithoutError() 263 .and().generatesSources(expected); 264 } 265 twoGenericTypes()266 @Test public void twoGenericTypes() { 267 JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericClass", 268 "package test;", 269 "", 270 "import javax.inject.Inject;", 271 "", 272 "class GenericClass<A, B> {", 273 " @Inject GenericClass(A a, B b) {}", 274 "}"); 275 JavaFileObject expected = 276 JavaFileObjects.forSourceLines( 277 "test.GenericClass_Factory", 278 "package test;", 279 "", 280 GeneratedLines.generatedImports( 281 "import dagger.internal.Factory;", 282 "import javax.inject.Provider;"), 283 "", 284 GeneratedLines.generatedAnnotations(), 285 "public final class GenericClass_Factory<A, B>", 286 " implements Factory<GenericClass<A, B>> {", 287 " private final Provider<A> aProvider;", 288 " private final Provider<B> bProvider;", 289 "", 290 " public GenericClass_Factory(Provider<A> aProvider, Provider<B> bProvider) {", 291 " this.aProvider = aProvider;", 292 " this.bProvider = bProvider;", 293 " }", 294 "", 295 " @Override", 296 " public GenericClass<A, B> get() {", 297 " return newInstance(aProvider.get(), bProvider.get());", 298 " }", 299 "", 300 " public static <A, B> GenericClass_Factory<A, B> create(", 301 " Provider<A> aProvider, Provider<B> bProvider) {", 302 " return new GenericClass_Factory<A, B>(aProvider, bProvider);", 303 " }", 304 "", 305 " public static <A, B> GenericClass<A, B> newInstance(A a, B b) {", 306 " return new GenericClass<A, B>(a, b);", 307 " }", 308 "}"); 309 assertAbout(javaSource()).that(file) 310 .processedWith(new ComponentProcessor()) 311 .compilesWithoutError() 312 .and().generatesSources(expected); 313 } 314 boundedGenerics()315 @Test public void boundedGenerics() { 316 JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericClass", 317 "package test;", 318 "", 319 "import javax.inject.Inject;", 320 "import java.util.List;", 321 "", 322 "class GenericClass<A extends Number & Comparable<A>,", 323 " B extends List<? extends String>,", 324 " C extends List<? super String>> {", 325 " @Inject GenericClass(A a, B b, C c) {}", 326 "}"); 327 JavaFileObject expected = 328 JavaFileObjects.forSourceLines( 329 "test.GenericClass_Factory", 330 "package test;", 331 "", 332 GeneratedLines.generatedImports( 333 "import dagger.internal.Factory;", 334 "import java.util.List;", 335 "import javax.inject.Provider;"), 336 "", 337 GeneratedLines.generatedAnnotations(), 338 "public final class GenericClass_Factory<A extends Number & Comparable<A>,", 339 " B extends List<? extends String>,", 340 " C extends List<? super String>>", 341 " implements Factory<GenericClass<A, B, C>> {", 342 " private final Provider<A> aProvider;", 343 " private final Provider<B> bProvider;", 344 " private final Provider<C> cProvider;", 345 "", 346 " public GenericClass_Factory(Provider<A> aProvider,", 347 " Provider<B> bProvider,", 348 " Provider<C> cProvider) {", 349 " this.aProvider = aProvider;", 350 " this.bProvider = bProvider;", 351 " this.cProvider = cProvider;", 352 " }", 353 "", 354 " @Override", 355 " public GenericClass<A, B, C> get() {", 356 " return newInstance(aProvider.get(), bProvider.get(), cProvider.get());", 357 " }", 358 "", 359 " public static <A extends Number & Comparable<A>,", 360 " B extends List<? extends String>,", 361 " C extends List<? super String>> GenericClass_Factory<A, B, C> create(", 362 " Provider<A> aProvider, Provider<B> bProvider, Provider<C> cProvider) {", 363 " return new GenericClass_Factory<A, B, C>(aProvider, bProvider, cProvider);", 364 " }", 365 "", 366 " public static <", 367 " A extends Number & Comparable<A>,", 368 " B extends List<? extends String>,", 369 " C extends List<? super String>>", 370 " GenericClass<A, B, C> newInstance(A a, B b, C c) {", 371 " return new GenericClass<A, B, C>(a, b, c);", 372 " }", 373 "}"); 374 assertAbout(javaSource()).that(file) 375 .processedWith(new ComponentProcessor()) 376 .compilesWithoutError() 377 .and().generatesSources(expected); 378 } 379 multipleSameTypesWithGenericsAndQualifiersAndLazies()380 @Test public void multipleSameTypesWithGenericsAndQualifiersAndLazies() { 381 JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericClass", 382 "package test;", 383 "", 384 "import javax.inject.Inject;", 385 "import javax.inject.Provider;", 386 "import dagger.Lazy;", 387 "", 388 "class GenericClass<A, B> {", 389 " @Inject GenericClass(A a, A a2, Provider<A> pa, @QualifierA A qa, Lazy<A> la, ", 390 " String s, String s2, Provider<String> ps, ", 391 " @QualifierA String qs, Lazy<String> ls,", 392 " B b, B b2, Provider<B> pb, @QualifierA B qb, Lazy<B> lb) {}", 393 "}"); 394 JavaFileObject expected = 395 JavaFileObjects.forSourceLines( 396 "test.GenericClass_Factory", 397 "package test;", 398 "", 399 GeneratedLines.generatedImports( 400 "import dagger.Lazy;", 401 "import dagger.internal.DoubleCheck;", 402 "import dagger.internal.Factory;", 403 "import javax.inject.Provider;"), 404 "", 405 GeneratedLines.generatedAnnotations(), 406 "public final class GenericClass_Factory<A, B>", 407 " implements Factory<GenericClass<A, B>> {", 408 " private final Provider<A> aProvider;", 409 " private final Provider<A> a2Provider;", 410 " private final Provider<A> paProvider;", 411 " private final Provider<A> qaProvider;", 412 " private final Provider<A> laProvider;", 413 " private final Provider<String> sProvider;", 414 " private final Provider<String> s2Provider;", 415 " private final Provider<String> psProvider;", 416 " private final Provider<String> qsProvider;", 417 " private final Provider<String> lsProvider;", 418 " private final Provider<B> bProvider;", 419 " private final Provider<B> b2Provider;", 420 " private final Provider<B> pbProvider;", 421 " private final Provider<B> qbProvider;", 422 " private final Provider<B> lbProvider;", 423 "", 424 " public GenericClass_Factory(", 425 " Provider<A> aProvider,", 426 " Provider<A> a2Provider,", 427 " Provider<A> paProvider,", 428 " Provider<A> qaProvider,", 429 " Provider<A> laProvider,", 430 " Provider<String> sProvider,", 431 " Provider<String> s2Provider,", 432 " Provider<String> psProvider,", 433 " Provider<String> qsProvider,", 434 " Provider<String> lsProvider,", 435 " Provider<B> bProvider,", 436 " Provider<B> b2Provider,", 437 " Provider<B> pbProvider,", 438 " Provider<B> qbProvider,", 439 " Provider<B> lbProvider) {", 440 " this.aProvider = aProvider;", 441 " this.a2Provider = a2Provider;", 442 " this.paProvider = paProvider;", 443 " this.qaProvider = qaProvider;", 444 " this.laProvider = laProvider;", 445 " this.sProvider = sProvider;", 446 " this.s2Provider = s2Provider;", 447 " this.psProvider = psProvider;", 448 " this.qsProvider = qsProvider;", 449 " this.lsProvider = lsProvider;", 450 " this.bProvider = bProvider;", 451 " this.b2Provider = b2Provider;", 452 " this.pbProvider = pbProvider;", 453 " this.qbProvider = qbProvider;", 454 " this.lbProvider = lbProvider;", 455 " }", 456 "", 457 " @Override", 458 " public GenericClass<A, B> get() {", 459 " return newInstance(", 460 " aProvider.get(),", 461 " a2Provider.get(),", 462 " paProvider,", 463 " qaProvider.get(),", 464 " DoubleCheck.lazy(laProvider),", 465 " sProvider.get(),", 466 " s2Provider.get(),", 467 " psProvider,", 468 " qsProvider.get(),", 469 " DoubleCheck.lazy(lsProvider),", 470 " bProvider.get(),", 471 " b2Provider.get(),", 472 " pbProvider,", 473 " qbProvider.get(),", 474 " DoubleCheck.lazy(lbProvider));", 475 " }", 476 "", 477 " public static <A, B> GenericClass_Factory<A, B> create(", 478 " Provider<A> aProvider,", 479 " Provider<A> a2Provider,", 480 " Provider<A> paProvider,", 481 " Provider<A> qaProvider,", 482 " Provider<A> laProvider,", 483 " Provider<String> sProvider,", 484 " Provider<String> s2Provider,", 485 " Provider<String> psProvider,", 486 " Provider<String> qsProvider,", 487 " Provider<String> lsProvider,", 488 " Provider<B> bProvider,", 489 " Provider<B> b2Provider,", 490 " Provider<B> pbProvider,", 491 " Provider<B> qbProvider,", 492 " Provider<B> lbProvider) {", 493 " return new GenericClass_Factory<A, B>(", 494 " aProvider,", 495 " a2Provider,", 496 " paProvider,", 497 " qaProvider,", 498 " laProvider,", 499 " sProvider,", 500 " s2Provider,", 501 " psProvider,", 502 " qsProvider,", 503 " lsProvider,", 504 " bProvider,", 505 " b2Provider,", 506 " pbProvider,", 507 " qbProvider,", 508 " lbProvider);", 509 " }", 510 "", 511 " public static <A, B> GenericClass<A, B> newInstance(", 512 " A a,", 513 " A a2,", 514 " Provider<A> pa,", 515 " A qa,", 516 " Lazy<A> la,", 517 " String s,", 518 " String s2,", 519 " Provider<String> ps,", 520 " String qs,", 521 " Lazy<String> ls,", 522 " B b,", 523 " B b2,", 524 " Provider<B> pb,", 525 " B qb,", 526 " Lazy<B> lb) {", 527 " return new GenericClass<A, B>(", 528 " a, a2, pa, qa, la, s, s2, ps, qs, ls, b, b2, pb, qb, lb);", 529 " }", 530 "}"); 531 assertAbout(javaSources()).that(ImmutableList.of(file, QUALIFIER_A)) 532 .processedWith(new ComponentProcessor()) 533 .compilesWithoutError() 534 .and().generatesSources(expected); 535 } 536 multipleInjectConstructors()537 @Test public void multipleInjectConstructors() { 538 JavaFileObject file = JavaFileObjects.forSourceLines("test.TooManyInjectConstructors", 539 "package test;", 540 "", 541 "import javax.inject.Inject;", 542 "", 543 "class TooManyInjectConstructors {", 544 " @Inject TooManyInjectConstructors() {}", 545 " TooManyInjectConstructors(int i) {}", 546 " @Inject TooManyInjectConstructors(String s) {}", 547 "}"); 548 Compilation compilation = daggerCompiler().compile(file); 549 assertThat(compilation).failed(); 550 assertThat(compilation) 551 .hadErrorContaining("Types may only contain one injected constructor") 552 .inFile(file) 553 .onLine(6); 554 assertThat(compilation) 555 .hadErrorContaining("Types may only contain one injected constructor") 556 .inFile(file) 557 .onLine(8); 558 } 559 multipleQualifiersOnInjectConstructorParameter()560 @Test public void multipleQualifiersOnInjectConstructorParameter() { 561 JavaFileObject file = JavaFileObjects.forSourceLines("test.MultipleQualifierConstructorParam", 562 "package test;", 563 "", 564 "import javax.inject.Inject;", 565 "", 566 "class MultipleQualifierConstructorParam {", 567 " @Inject MultipleQualifierConstructorParam(@QualifierA @QualifierB String s) {}", 568 "}"); 569 Compilation compilation = daggerCompiler().compile(file, QUALIFIER_A, QUALIFIER_B); 570 assertThat(compilation).failed(); 571 // for whatever reason, javac only reports the error once on the constructor 572 assertThat(compilation) 573 .hadErrorContaining("A single dependency request may not use more than one @Qualifier") 574 .inFile(file) 575 .onLine(6); 576 } 577 injectConstructorOnClassWithMultipleScopes()578 @Test public void injectConstructorOnClassWithMultipleScopes() { 579 JavaFileObject file = JavaFileObjects.forSourceLines("test.MultipleScopeClass", 580 "package test;", 581 "", 582 "import javax.inject.Inject;", 583 "", 584 "@ScopeA @ScopeB class MultipleScopeClass {", 585 " @Inject MultipleScopeClass() {}", 586 "}"); 587 Compilation compilation = daggerCompiler().compile(file, SCOPE_A, SCOPE_B); 588 assertThat(compilation).failed(); 589 assertThat(compilation) 590 .hadErrorContaining("A single binding may not declare more than one @Scope") 591 .inFile(file) 592 .onLine(5) 593 .atColumn(1); 594 assertThat(compilation) 595 .hadErrorContaining("A single binding may not declare more than one @Scope") 596 .inFile(file) 597 .onLine(5) 598 .atColumn(9); 599 } 600 injectConstructorWithQualifier()601 @Test public void injectConstructorWithQualifier() { 602 JavaFileObject file = JavaFileObjects.forSourceLines("test.MultipleScopeClass", 603 "package test;", 604 "", 605 "import javax.inject.Inject;", 606 "", 607 "class MultipleScopeClass {", 608 " @Inject", 609 " @QualifierA", 610 " @QualifierB", 611 " MultipleScopeClass() {}", 612 "}"); 613 Compilation compilation = daggerCompiler().compile(file, QUALIFIER_A, QUALIFIER_B); 614 assertThat(compilation).failed(); 615 assertThat(compilation) 616 .hadErrorContaining("@Qualifier annotations are not allowed on @Inject constructors") 617 .inFile(file) 618 .onLine(7); 619 assertThat(compilation) 620 .hadErrorContaining("@Qualifier annotations are not allowed on @Inject constructors") 621 .inFile(file) 622 .onLine(8); 623 } 624 injectConstructorWithCheckedExceptionsError()625 @Test public void injectConstructorWithCheckedExceptionsError() { 626 JavaFileObject file = JavaFileObjects.forSourceLines("test.CheckedExceptionClass", 627 "package test;", 628 "", 629 "import javax.inject.Inject;", 630 "", 631 "class CheckedExceptionClass {", 632 " @Inject CheckedExceptionClass() throws Exception {}", 633 "}"); 634 Compilation compilation = daggerCompiler().compile(file); 635 assertThat(compilation).failed(); 636 assertThat(compilation) 637 .hadErrorContaining("Dagger does not support checked exceptions on @Inject constructors") 638 .inFile(file) 639 .onLine(6); 640 } 641 injectConstructorWithCheckedExceptionsWarning()642 @Test public void injectConstructorWithCheckedExceptionsWarning() { 643 JavaFileObject file = JavaFileObjects.forSourceLines("test.CheckedExceptionClass", 644 "package test;", 645 "", 646 "import javax.inject.Inject;", 647 "", 648 "class CheckedExceptionClass {", 649 " @Inject CheckedExceptionClass() throws Exception {}", 650 "}"); 651 Compilation compilation = 652 compilerWithOptions("-Adagger.privateMemberValidation=WARNING").compile(file); 653 assertThat(compilation).succeeded(); 654 assertThat(compilation) 655 .hadWarningContaining("Dagger does not support checked exceptions on @Inject constructors") 656 .inFile(file) 657 .onLine(6); 658 } 659 privateInjectClassError()660 @Test public void privateInjectClassError() { 661 JavaFileObject file = JavaFileObjects.forSourceLines("test.OuterClass", 662 "package test;", 663 "", 664 "import javax.inject.Inject;", 665 "", 666 "final class OuterClass {", 667 " private static final class InnerClass {", 668 " @Inject InnerClass() {}", 669 " }", 670 "}"); 671 Compilation compilation = daggerCompiler().compile(file); 672 assertThat(compilation).failed(); 673 assertThat(compilation) 674 .hadErrorContaining("Dagger does not support injection into private classes") 675 .inFile(file) 676 .onLine(7); 677 } 678 privateInjectClassWarning()679 @Test public void privateInjectClassWarning() { 680 JavaFileObject file = JavaFileObjects.forSourceLines("test.OuterClass", 681 "package test;", 682 "", 683 "import javax.inject.Inject;", 684 "", 685 "final class OuterClass {", 686 " private static final class InnerClass {", 687 " @Inject InnerClass() {}", 688 " }", 689 "}"); 690 Compilation compilation = 691 compilerWithOptions("-Adagger.privateMemberValidation=WARNING").compile(file); 692 assertThat(compilation).succeeded(); 693 assertThat(compilation) 694 .hadWarningContaining("Dagger does not support injection into private classes") 695 .inFile(file) 696 .onLine(7); 697 } 698 nestedInPrivateInjectClassError()699 @Test public void nestedInPrivateInjectClassError() { 700 JavaFileObject file = JavaFileObjects.forSourceLines("test.OuterClass", 701 "package test;", 702 "", 703 "import javax.inject.Inject;", 704 "", 705 "final class OuterClass {", 706 " private static final class MiddleClass {", 707 " static final class InnerClass {", 708 " @Inject InnerClass() {}", 709 " }", 710 " }", 711 "}"); 712 Compilation compilation = daggerCompiler().compile(file); 713 assertThat(compilation).failed(); 714 assertThat(compilation) 715 .hadErrorContaining("Dagger does not support injection into private classes") 716 .inFile(file) 717 .onLine(8); 718 } 719 nestedInPrivateInjectClassWarning()720 @Test public void nestedInPrivateInjectClassWarning() { 721 JavaFileObject file = JavaFileObjects.forSourceLines("test.OuterClass", 722 "package test;", 723 "", 724 "import javax.inject.Inject;", 725 "", 726 "final class OuterClass {", 727 " private static final class MiddleClass {", 728 " static final class InnerClass {", 729 " @Inject InnerClass() {}", 730 " }", 731 " }", 732 "}"); 733 Compilation compilation = 734 compilerWithOptions("-Adagger.privateMemberValidation=WARNING").compile(file); 735 assertThat(compilation).succeeded(); 736 assertThat(compilation) 737 .hadWarningContaining("Dagger does not support injection into private classes") 738 .inFile(file) 739 .onLine(8); 740 } 741 finalInjectField()742 @Test public void finalInjectField() { 743 JavaFileObject file = JavaFileObjects.forSourceLines("test.FinalInjectField", 744 "package test;", 745 "", 746 "import javax.inject.Inject;", 747 "", 748 "class FinalInjectField {", 749 " @Inject final String s;", 750 "}"); 751 Compilation compilation = daggerCompiler().compile(file); 752 assertThat(compilation).failed(); 753 assertThat(compilation) 754 .hadErrorContaining("@Inject fields may not be final") 755 .inFile(file) 756 .onLine(6); 757 } 758 privateInjectFieldError()759 @Test public void privateInjectFieldError() { 760 JavaFileObject file = JavaFileObjects.forSourceLines("test.PrivateInjectField", 761 "package test;", 762 "", 763 "import javax.inject.Inject;", 764 "", 765 "class PrivateInjectField {", 766 " @Inject private String s;", 767 "}"); 768 Compilation compilation = daggerCompiler().compile(file); 769 assertThat(compilation).failed(); 770 assertThat(compilation) 771 .hadErrorContaining("Dagger does not support injection into private fields") 772 .inFile(file) 773 .onLine(6); 774 } 775 privateInjectFieldWarning()776 @Test public void privateInjectFieldWarning() { 777 JavaFileObject file = JavaFileObjects.forSourceLines("test.PrivateInjectField", 778 "package test;", 779 "", 780 "import javax.inject.Inject;", 781 "", 782 "class PrivateInjectField {", 783 " @Inject private String s;", 784 "}"); 785 Compilation compilation = 786 compilerWithOptions("-Adagger.privateMemberValidation=WARNING").compile(file); 787 assertThat(compilation).succeeded(); // TODO: Verify warning message when supported 788 } 789 staticInjectFieldError()790 @Test public void staticInjectFieldError() { 791 JavaFileObject file = JavaFileObjects.forSourceLines("test.StaticInjectField", 792 "package test;", 793 "", 794 "import javax.inject.Inject;", 795 "", 796 "class StaticInjectField {", 797 " @Inject static String s;", 798 "}"); 799 Compilation compilation = daggerCompiler().compile(file); 800 assertThat(compilation).failed(); 801 assertThat(compilation) 802 .hadErrorContaining("Dagger does not support injection into static fields") 803 .inFile(file) 804 .onLine(6); 805 } 806 staticInjectFieldWarning()807 @Test public void staticInjectFieldWarning() { 808 JavaFileObject file = JavaFileObjects.forSourceLines("test.StaticInjectField", 809 "package test;", 810 "", 811 "import javax.inject.Inject;", 812 "", 813 "class StaticInjectField {", 814 " @Inject static String s;", 815 "}"); 816 Compilation compilation = 817 compilerWithOptions("-Adagger.staticMemberValidation=WARNING").compile(file); 818 assertThat(compilation).succeeded(); // TODO: Verify warning message when supported 819 } 820 multipleQualifiersOnField()821 @Test public void multipleQualifiersOnField() { 822 JavaFileObject file = JavaFileObjects.forSourceLines("test.MultipleQualifierInjectField", 823 "package test;", 824 "", 825 "import javax.inject.Inject;", 826 "", 827 "class MultipleQualifierInjectField {", 828 " @Inject @QualifierA @QualifierB String s;", 829 "}"); 830 Compilation compilation = daggerCompiler().compile(file, QUALIFIER_A, QUALIFIER_B); 831 assertThat(compilation).failed(); 832 assertThat(compilation) 833 .hadErrorContaining("A single dependency request may not use more than one @Qualifier") 834 .inFile(file) 835 .onLine(6) 836 .atColumn(11); 837 assertThat(compilation) 838 .hadErrorContaining("A single dependency request may not use more than one @Qualifier") 839 .inFile(file) 840 .onLine(6) 841 .atColumn(23); 842 } 843 abstractInjectMethod()844 @Test public void abstractInjectMethod() { 845 JavaFileObject file = JavaFileObjects.forSourceLines("test.AbstractInjectMethod", 846 "package test;", 847 "", 848 "import javax.inject.Inject;", 849 "", 850 "abstract class AbstractInjectMethod {", 851 " @Inject abstract void method();", 852 "}"); 853 Compilation compilation = daggerCompiler().compile(file); 854 assertThat(compilation).failed(); 855 assertThat(compilation) 856 .hadErrorContaining("Methods with @Inject may not be abstract") 857 .inFile(file) 858 .onLine(6); 859 } 860 privateInjectMethodError()861 @Test public void privateInjectMethodError() { 862 JavaFileObject file = JavaFileObjects.forSourceLines("test.PrivateInjectMethod", 863 "package test;", 864 "", 865 "import javax.inject.Inject;", 866 "", 867 "class PrivateInjectMethod {", 868 " @Inject private void method(){}", 869 "}"); 870 Compilation compilation = daggerCompiler().compile(file); 871 assertThat(compilation).failed(); 872 assertThat(compilation) 873 .hadErrorContaining("Dagger does not support injection into private methods") 874 .inFile(file) 875 .onLine(6); 876 } 877 privateInjectMethodWarning()878 @Test public void privateInjectMethodWarning() { 879 JavaFileObject file = JavaFileObjects.forSourceLines("test.PrivateInjectMethod", 880 "package test;", 881 "", 882 "import javax.inject.Inject;", 883 "", 884 "class PrivateInjectMethod {", 885 " @Inject private void method(){}", 886 "}"); 887 Compilation compilation = 888 compilerWithOptions("-Adagger.privateMemberValidation=WARNING").compile(file); 889 assertThat(compilation).succeeded(); // TODO: Verify warning message when supported 890 } 891 staticInjectMethodError()892 @Test public void staticInjectMethodError() { 893 JavaFileObject file = JavaFileObjects.forSourceLines("test.StaticInjectMethod", 894 "package test;", 895 "", 896 "import javax.inject.Inject;", 897 "", 898 "class StaticInjectMethod {", 899 " @Inject static void method(){}", 900 "}"); 901 Compilation compilation = daggerCompiler().compile(file); 902 assertThat(compilation).failed(); 903 assertThat(compilation) 904 .hadErrorContaining("Dagger does not support injection into static methods") 905 .inFile(file) 906 .onLine(6); 907 } 908 staticInjectMethodWarning()909 @Test public void staticInjectMethodWarning() { 910 JavaFileObject file = JavaFileObjects.forSourceLines("test.StaticInjectMethod", 911 "package test;", 912 "", 913 "import javax.inject.Inject;", 914 "", 915 "class StaticInjectMethod {", 916 " @Inject static void method(){}", 917 "}"); 918 Compilation compilation = 919 compilerWithOptions("-Adagger.staticMemberValidation=WARNING").compile(file); 920 assertThat(compilation).succeeded(); // TODO: Verify warning message when supported 921 } 922 genericInjectMethod()923 @Test public void genericInjectMethod() { 924 JavaFileObject file = JavaFileObjects.forSourceLines("test.GenericInjectMethod", 925 "package test;", 926 "", 927 "import javax.inject.Inject;", 928 "", 929 "class AbstractInjectMethod {", 930 " @Inject <T> void method();", 931 "}"); 932 Compilation compilation = daggerCompiler().compile(file); 933 assertThat(compilation).failed(); 934 assertThat(compilation) 935 .hadErrorContaining("Methods with @Inject may not declare type parameters") 936 .inFile(file) 937 .onLine(6); 938 } 939 multipleQualifiersOnInjectMethodParameter()940 @Test public void multipleQualifiersOnInjectMethodParameter() { 941 JavaFileObject file = JavaFileObjects.forSourceLines("test.MultipleQualifierMethodParam", 942 "package test;", 943 "", 944 "import javax.inject.Inject;", 945 "", 946 "class MultipleQualifierMethodParam {", 947 " @Inject void method(@QualifierA @QualifierB String s) {}", 948 "}"); 949 Compilation compilation = daggerCompiler().compile(file, QUALIFIER_A, QUALIFIER_B); 950 assertThat(compilation).failed(); 951 assertThat(compilation) 952 .hadErrorContaining("A single dependency request may not use more than one @Qualifier") 953 .inFile(file) 954 .onLine(6); 955 } 956 injectConstructorDependsOnProduced()957 @Test public void injectConstructorDependsOnProduced() { 958 JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A", 959 "package test;", 960 "", 961 "import dagger.producers.Produced;", 962 "import javax.inject.Inject;", 963 "", 964 "final class A {", 965 " @Inject A(Produced<String> str) {}", 966 "}"); 967 Compilation compilation = daggerCompiler().compile(aFile); 968 assertThat(compilation).failed(); 969 assertThat(compilation) 970 .hadErrorContaining("Produced may only be injected in @Produces methods"); 971 } 972 injectConstructorDependsOnProducer()973 @Test public void injectConstructorDependsOnProducer() { 974 JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A", 975 "package test;", 976 "", 977 "import dagger.producers.Producer;", 978 "import javax.inject.Inject;", 979 "", 980 "final class A {", 981 " @Inject A(Producer<String> str) {}", 982 "}"); 983 Compilation compilation = daggerCompiler().compile(aFile); 984 assertThat(compilation).failed(); 985 assertThat(compilation) 986 .hadErrorContaining("Producer may only be injected in @Produces methods"); 987 } 988 injectFieldDependsOnProduced()989 @Test public void injectFieldDependsOnProduced() { 990 JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A", 991 "package test;", 992 "", 993 "import dagger.producers.Produced;", 994 "import javax.inject.Inject;", 995 "", 996 "final class A {", 997 " @Inject Produced<String> str;", 998 "}"); 999 Compilation compilation = daggerCompiler().compile(aFile); 1000 assertThat(compilation).failed(); 1001 assertThat(compilation) 1002 .hadErrorContaining("Produced may only be injected in @Produces methods"); 1003 } 1004 injectFieldDependsOnProducer()1005 @Test public void injectFieldDependsOnProducer() { 1006 JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A", 1007 "package test;", 1008 "", 1009 "import dagger.producers.Producer;", 1010 "import javax.inject.Inject;", 1011 "", 1012 "final class A {", 1013 " @Inject Producer<String> str;", 1014 "}"); 1015 Compilation compilation = daggerCompiler().compile(aFile); 1016 assertThat(compilation).failed(); 1017 assertThat(compilation) 1018 .hadErrorContaining("Producer may only be injected in @Produces methods"); 1019 } 1020 injectMethodDependsOnProduced()1021 @Test public void injectMethodDependsOnProduced() { 1022 JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A", 1023 "package test;", 1024 "", 1025 "import dagger.producers.Produced;", 1026 "import javax.inject.Inject;", 1027 "", 1028 "final class A {", 1029 " @Inject void inject(Produced<String> str) {}", 1030 "}"); 1031 Compilation compilation = daggerCompiler().compile(aFile); 1032 assertThat(compilation).failed(); 1033 assertThat(compilation) 1034 .hadErrorContaining("Produced may only be injected in @Produces methods"); 1035 } 1036 injectMethodDependsOnProducer()1037 @Test public void injectMethodDependsOnProducer() { 1038 JavaFileObject aFile = JavaFileObjects.forSourceLines("test.A", 1039 "package test;", 1040 "", 1041 "import dagger.producers.Producer;", 1042 "import javax.inject.Inject;", 1043 "", 1044 "final class A {", 1045 " @Inject void inject(Producer<String> str) {}", 1046 "}"); 1047 Compilation compilation = daggerCompiler().compile(aFile); 1048 assertThat(compilation).failed(); 1049 assertThat(compilation) 1050 .hadErrorContaining("Producer may only be injected in @Produces methods"); 1051 } 1052 1053 injectConstructor()1054 @Test public void injectConstructor() { 1055 JavaFileObject file = JavaFileObjects.forSourceLines("test.InjectConstructor", 1056 "package test;", 1057 "", 1058 "import javax.inject.Inject;", 1059 "", 1060 "class InjectConstructor {", 1061 " @Inject InjectConstructor(String s) {}", 1062 "}"); 1063 JavaFileObject expected = 1064 JavaFileObjects.forSourceLines( 1065 "test.InjectConstructor_Factory", 1066 "package test;", 1067 "", 1068 GeneratedLines.generatedImports( 1069 "import dagger.internal.Factory;", 1070 "import javax.inject.Provider;"), 1071 "", 1072 GeneratedLines.generatedAnnotations(), 1073 "public final class InjectConstructor_Factory ", 1074 " implements Factory<InjectConstructor> {", 1075 "", 1076 " private final Provider<String> sProvider;", 1077 "", 1078 " public InjectConstructor_Factory(Provider<String> sProvider) {", 1079 " this.sProvider = sProvider;", 1080 " }", 1081 "", 1082 " @Override public InjectConstructor get() {", 1083 " return newInstance(sProvider.get());", 1084 " }", 1085 "", 1086 " public static InjectConstructor_Factory create(Provider<String> sProvider) {", 1087 " return new InjectConstructor_Factory(sProvider);", 1088 " }", 1089 "", 1090 " public static InjectConstructor newInstance(String s) {", 1091 " return new InjectConstructor(s);", 1092 " }", 1093 "}"); 1094 assertAbout(javaSource()).that(file).processedWith(new ComponentProcessor()) 1095 .compilesWithoutError() 1096 .and().generatesSources(expected); 1097 } 1098 injectConstructorAndMembersInjection()1099 @Test public void injectConstructorAndMembersInjection() { 1100 JavaFileObject file = JavaFileObjects.forSourceLines("test.AllInjections", 1101 "package test;", 1102 "", 1103 "import javax.inject.Inject;", 1104 "", 1105 "class AllInjections {", 1106 " @Inject String s;", 1107 " @Inject AllInjections(String s) {}", 1108 " @Inject void s(String s) {}", 1109 "}"); 1110 JavaFileObject expectedFactory = 1111 JavaFileObjects.forSourceLines( 1112 "test.AllInjections_Factory", 1113 "package test;", 1114 "", 1115 GeneratedLines.generatedImports( 1116 "import dagger.internal.Factory;", 1117 "import javax.inject.Provider;"), 1118 "", 1119 GeneratedLines.generatedAnnotations(), 1120 "public final class AllInjections_Factory implements Factory<AllInjections> {", 1121 " private final Provider<String> sProvider;", 1122 " private final Provider<String> sProvider2;", 1123 " private final Provider<String> sProvider3;", 1124 "", 1125 " public AllInjections_Factory(", 1126 " Provider<String> sProvider,", 1127 " Provider<String> sProvider2,", 1128 " Provider<String> sProvider3) {", 1129 " this.sProvider = sProvider;", 1130 " this.sProvider2 = sProvider2;", 1131 " this.sProvider3 = sProvider3;", 1132 " }", 1133 "", 1134 " @Override", 1135 " public AllInjections get() {", 1136 " AllInjections instance = newInstance(sProvider.get());", 1137 " AllInjections_MembersInjector.injectS(instance, sProvider2.get());", 1138 " AllInjections_MembersInjector.injectS2(instance, sProvider3.get());", 1139 " return instance;", 1140 " }", 1141 "", 1142 " public static AllInjections_Factory create(", 1143 " Provider<String> sProvider,", 1144 " Provider<String> sProvider2,", 1145 " Provider<String> sProvider3) {", 1146 " return new AllInjections_Factory(sProvider, sProvider2, sProvider3);", 1147 " }", 1148 "", 1149 " public static AllInjections newInstance(String s) {", 1150 " return new AllInjections(s);", 1151 " }", 1152 "}"); 1153 assertAbout(javaSource()).that(file).processedWith(new ComponentProcessor()) 1154 .compilesWithoutError() 1155 .and() 1156 .generatesSources(expectedFactory); 1157 } 1158 1159 @Test wildcardDependency()1160 public void wildcardDependency() { 1161 JavaFileObject file = JavaFileObjects.forSourceLines("test.InjectConstructor", 1162 "package test;", 1163 "", 1164 "import java.util.List;", 1165 "import javax.inject.Inject;", 1166 "", 1167 "class InjectConstructor {", 1168 " @Inject InjectConstructor(List<?> objects) {}", 1169 "}"); 1170 JavaFileObject expected = 1171 JavaFileObjects.forSourceLines( 1172 "test.InjectConstructor_Factory", 1173 "package test;", 1174 "", 1175 GeneratedLines.generatedImports( 1176 "import dagger.internal.Factory;", 1177 "import java.util.List;", 1178 "import javax.inject.Provider;"), 1179 "", 1180 GeneratedLines.generatedAnnotations(), 1181 "public final class InjectConstructor_Factory ", 1182 " implements Factory<InjectConstructor> {", 1183 "", 1184 " private final Provider<List<?>> objectsProvider;", 1185 "", 1186 " public InjectConstructor_Factory(Provider<List<?>> objectsProvider) {", 1187 " this.objectsProvider = objectsProvider;", 1188 " }", 1189 "", 1190 " @Override public InjectConstructor get() {", 1191 " return newInstance(objectsProvider.get());", 1192 " }", 1193 "", 1194 " public static InjectConstructor_Factory create(", 1195 " Provider<List<?>> objectsProvider) {", 1196 " return new InjectConstructor_Factory(objectsProvider);", 1197 " }", 1198 "", 1199 " public static InjectConstructor newInstance(List<?> objects) {", 1200 " return new InjectConstructor(objects);", 1201 " }", 1202 "}"); 1203 assertAbout(javaSource()).that(file).processedWith(new ComponentProcessor()) 1204 .compilesWithoutError() 1205 .and().generatesSources(expected); 1206 } 1207 1208 @Test basicNameCollision()1209 public void basicNameCollision() { 1210 JavaFileObject factoryFile = JavaFileObjects.forSourceLines("other.pkg.Factory", 1211 "package other.pkg;", 1212 "", 1213 "public class Factory {}"); 1214 JavaFileObject file = JavaFileObjects.forSourceLines("test.InjectConstructor", 1215 "package test;", 1216 "", 1217 "import javax.inject.Inject;", 1218 "import other.pkg.Factory;", 1219 "", 1220 "class InjectConstructor {", 1221 " @Inject InjectConstructor(Factory factory) {}", 1222 "}"); 1223 JavaFileObject expected = 1224 JavaFileObjects.forSourceLines( 1225 "test.InjectConstructor_Factory", 1226 "package test;", 1227 "", 1228 GeneratedLines.generatedImports( 1229 "import dagger.internal.Factory;", 1230 "import javax.inject.Provider;"), 1231 "", 1232 GeneratedLines.generatedAnnotations(), 1233 "public final class InjectConstructor_Factory ", 1234 " implements Factory<InjectConstructor> {", 1235 "", 1236 " private final Provider<other.pkg.Factory> factoryProvider;", 1237 "", 1238 " public InjectConstructor_Factory(Provider<other.pkg.Factory> factoryProvider) {", 1239 " this.factoryProvider = factoryProvider;", 1240 " }", 1241 "", 1242 " @Override public InjectConstructor get() {", 1243 " return newInstance(factoryProvider.get());", 1244 " }", 1245 "", 1246 " public static InjectConstructor_Factory create(", 1247 " Provider<other.pkg.Factory> factoryProvider) {", 1248 " return new InjectConstructor_Factory(factoryProvider);", 1249 " }", 1250 "", 1251 " public static InjectConstructor newInstance(", 1252 " other.pkg.Factory factory) {", 1253 " return new InjectConstructor(factory);", 1254 " }", 1255 "}"); 1256 assertAbout(javaSources()).that(ImmutableList.of(factoryFile, file)) 1257 .processedWith(new ComponentProcessor()) 1258 .compilesWithoutError() 1259 .and().generatesSources(expected); 1260 } 1261 1262 @Test nestedNameCollision()1263 public void nestedNameCollision() { 1264 JavaFileObject factoryFile = JavaFileObjects.forSourceLines("other.pkg.Outer", 1265 "package other.pkg;", 1266 "", 1267 "public class Outer {", 1268 " public class Factory {}", 1269 "}"); 1270 JavaFileObject file = JavaFileObjects.forSourceLines("test.InjectConstructor", 1271 "package test;", 1272 "", 1273 "import javax.inject.Inject;", 1274 "import other.pkg.Outer;", 1275 "", 1276 "class InjectConstructor {", 1277 " @Inject InjectConstructor(Outer.Factory factory) {}", 1278 "}"); 1279 JavaFileObject expected = 1280 JavaFileObjects.forSourceLines( 1281 "test.InjectConstructor_Factory", 1282 "package test;", 1283 "", 1284 GeneratedLines.generatedImports( 1285 "import dagger.internal.Factory;", 1286 "import javax.inject.Provider;", 1287 "import other.pkg.Outer;"), 1288 "", 1289 GeneratedLines.generatedAnnotations(), 1290 "public final class InjectConstructor_Factory ", 1291 " implements Factory<InjectConstructor> {", 1292 "", 1293 " private final Provider<Outer.Factory> factoryProvider;", 1294 "", 1295 " public InjectConstructor_Factory(Provider<Outer.Factory> factoryProvider) {", 1296 " this.factoryProvider = factoryProvider;", 1297 " }", 1298 "", 1299 " @Override public InjectConstructor get() {", 1300 " return newInstance(factoryProvider.get());", 1301 " }", 1302 "", 1303 " public static InjectConstructor_Factory create(", 1304 " Provider<Outer.Factory> factoryProvider) {", 1305 " return new InjectConstructor_Factory(factoryProvider);", 1306 " }", 1307 "", 1308 " public static InjectConstructor newInstance(", 1309 " Outer.Factory factory) {", 1310 " return new InjectConstructor(factory);", 1311 " }", 1312 "}"); 1313 assertAbout(javaSources()).that(ImmutableList.of(factoryFile, file)) 1314 .processedWith(new ComponentProcessor()) 1315 .compilesWithoutError() 1316 .and().generatesSources(expected); 1317 } 1318 1319 @Test samePackageNameCollision()1320 public void samePackageNameCollision() { 1321 JavaFileObject samePackageInterface = JavaFileObjects.forSourceLines("test.CommonName", 1322 "package test;", 1323 "", 1324 "public interface CommonName {}"); 1325 JavaFileObject differentPackageInterface = JavaFileObjects.forSourceLines( 1326 "other.pkg.CommonName", 1327 "package other.pkg;", 1328 "", 1329 "public interface CommonName {}"); 1330 JavaFileObject file = JavaFileObjects.forSourceLines("test.InjectConstructor", 1331 "package test;", 1332 "", 1333 "import javax.inject.Inject;", 1334 "", 1335 "class InjectConstructor implements CommonName {", 1336 " @Inject InjectConstructor(other.pkg.CommonName otherPackage, CommonName samePackage) {}", 1337 "}"); 1338 JavaFileObject expected = 1339 JavaFileObjects.forSourceLines( 1340 "test.InjectConstructor_Factory", 1341 "package test;", 1342 "", 1343 GeneratedLines.generatedImports( 1344 "import dagger.internal.Factory;", 1345 "import javax.inject.Provider;"), 1346 "", 1347 GeneratedLines.generatedAnnotations(), 1348 "public final class InjectConstructor_Factory ", 1349 " implements Factory<InjectConstructor> {", 1350 "", 1351 " private final Provider<other.pkg.CommonName> otherPackageProvider;", 1352 " private final Provider<CommonName> samePackageProvider;", 1353 "", 1354 " public InjectConstructor_Factory(", 1355 " Provider<other.pkg.CommonName> otherPackageProvider,", 1356 " Provider<CommonName> samePackageProvider) {", 1357 " this.otherPackageProvider = otherPackageProvider;", 1358 " this.samePackageProvider = samePackageProvider;", 1359 " }", 1360 "", 1361 " @Override public InjectConstructor get() {", 1362 " return newInstance(otherPackageProvider.get(), samePackageProvider.get());", 1363 " }", 1364 "", 1365 " public static InjectConstructor_Factory create(", 1366 " Provider<other.pkg.CommonName> otherPackageProvider,", 1367 " Provider<CommonName> samePackageProvider) {", 1368 " return new InjectConstructor_Factory(otherPackageProvider, samePackageProvider);", 1369 " }", 1370 "", 1371 " public static InjectConstructor newInstance(", 1372 " other.pkg.CommonName otherPackage, CommonName samePackage) {", 1373 " return new InjectConstructor(otherPackage, samePackage);", 1374 " }", 1375 "}"); 1376 assertAbout(javaSources()) 1377 .that(ImmutableList.of(samePackageInterface, differentPackageInterface, file)) 1378 .processedWith(new ComponentProcessor()) 1379 .compilesWithoutError() 1380 .and().generatesSources(expected); 1381 } 1382 1383 @Test noDeps()1384 public void noDeps() { 1385 JavaFileObject simpleType = JavaFileObjects.forSourceLines("test.SimpleType", 1386 "package test;", 1387 "", 1388 "import javax.inject.Inject;", 1389 "", 1390 "final class SimpleType {", 1391 " @Inject SimpleType() {}", 1392 "}"); 1393 JavaFileObject factory = 1394 JavaFileObjects.forSourceLines( 1395 "test.SimpleType_Factory", 1396 "package test;", 1397 "", 1398 GeneratedLines.generatedImports("import dagger.internal.Factory;"), 1399 "", 1400 GeneratedLines.generatedAnnotations(), 1401 "public final class SimpleType_Factory implements Factory<SimpleType> {", 1402 " @Override public SimpleType get() {", 1403 " return newInstance();", 1404 " }", 1405 "", 1406 " public static SimpleType_Factory create() {", 1407 " return InstanceHolder.INSTANCE;", 1408 " }", 1409 "", 1410 " public static SimpleType newInstance() {", 1411 " return new SimpleType();", 1412 " }", 1413 "", 1414 " private static final class InstanceHolder {", 1415 " private static final SimpleType_Factory INSTANCE = new SimpleType_Factory();", 1416 " }", 1417 "}"); 1418 assertAbout(javaSource()) 1419 .that(simpleType) 1420 .processedWith(new ComponentProcessor()) 1421 .compilesWithoutError() 1422 .and().generatesSources(factory); 1423 } 1424 simpleComponentWithNesting()1425 @Test public void simpleComponentWithNesting() { 1426 JavaFileObject nestedTypesFile = JavaFileObjects.forSourceLines("test.OuterType", 1427 "package test;", 1428 "", 1429 "import dagger.Component;", 1430 "import javax.inject.Inject;", 1431 "", 1432 "final class OuterType {", 1433 " static class A {", 1434 " @Inject A() {}", 1435 " }", 1436 " static class B {", 1437 " @Inject A a;", 1438 " }", 1439 "}"); 1440 JavaFileObject aFactory = 1441 JavaFileObjects.forSourceLines( 1442 "test.OuterType_A_Factory", 1443 "package test;", 1444 "", 1445 GeneratedLines.generatedImports("import dagger.internal.Factory;"), 1446 "", 1447 GeneratedLines.generatedAnnotations(), 1448 "public final class OuterType_A_Factory implements Factory<OuterType.A> {", 1449 " @Override public OuterType.A get() {", 1450 " return newInstance();", 1451 " }", 1452 "", 1453 " public static OuterType_A_Factory create() {", 1454 " return InstanceHolder.INSTANCE;", 1455 " }", 1456 "", 1457 " public static OuterType.A newInstance() {", 1458 " return new OuterType.A();", 1459 " }", 1460 "", 1461 " private static final class InstanceHolder {", 1462 " private static final OuterType_A_Factory INSTANCE = new OuterType_A_Factory();", 1463 " }", 1464 "}"); 1465 assertAbout(javaSources()).that(ImmutableList.of(nestedTypesFile)) 1466 .processedWith(new ComponentProcessor()) 1467 .compilesWithoutError() 1468 .and().generatesSources(aFactory); 1469 } 1470 } 1471