1 /* 2 * Copyright (C) 2023 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 androidx.room.compiler.processing.util.CompilationResultSubject; 20 import com.google.common.base.Joiner; 21 import com.google.common.collect.ImmutableList; 22 import com.google.common.collect.ImmutableMap; 23 import dagger.testing.compile.CompilerTests; 24 import java.util.function.Consumer; 25 import org.junit.Test; 26 import org.junit.runner.RunWith; 27 import org.junit.runners.Parameterized; 28 import org.junit.runners.Parameterized.Parameters; 29 30 @RunWith(Parameterized.class) 31 public class IgnoreProvisionKeyWildcardsTest { 32 enum SourceKind { JAVA, KOTLIN } 33 34 @Parameters(name = "sourceKind={0}, isIgnoreProvisionKeyWildcardsEnabled={1}") parameters()35 public static ImmutableList<Object[]> parameters() { 36 return ImmutableList.of( 37 new Object[] {SourceKind.JAVA, false}, 38 new Object[] {SourceKind.KOTLIN, false}, 39 new Object[] {SourceKind.JAVA, true}, 40 new Object[] {SourceKind.KOTLIN, true} 41 ); 42 } 43 44 private static final Joiner NEW_LINES = Joiner.on("\n"); 45 private static final Joiner NEW_LINES_FOR_ERROR_MSG = Joiner.on("\n "); 46 47 private final boolean isIgnoreProvisionKeyWildcardsEnabled; 48 private final SourceKind sourceKind; 49 private final ImmutableMap<String, String> processingOptions; 50 IgnoreProvisionKeyWildcardsTest( SourceKind sourceKind, boolean isIgnoreProvisionKeyWildcardsEnabled)51 public IgnoreProvisionKeyWildcardsTest( 52 SourceKind sourceKind, 53 boolean isIgnoreProvisionKeyWildcardsEnabled) { 54 this.sourceKind = sourceKind; 55 this.isIgnoreProvisionKeyWildcardsEnabled = isIgnoreProvisionKeyWildcardsEnabled; 56 processingOptions = 57 isIgnoreProvisionKeyWildcardsEnabled 58 ? ImmutableMap.of("dagger.ignoreProvisionKeyWildcards", "enabled") 59 : ImmutableMap.of("dagger.ignoreProvisionKeyWildcards", "disabled"); 60 } 61 62 @Test testProvidesUniqueBindingsWithDifferentTypeVariances()63 public void testProvidesUniqueBindingsWithDifferentTypeVariances() { 64 compile( 65 /* javaComponentClass = */ 66 NEW_LINES.join( 67 "@Component(modules = MyModule.class)", 68 "interface MyComponent {", 69 " Foo<? extends Bar> fooExtends();", 70 " Foo<Bar> foo();", 71 "}", 72 "@Module", 73 "interface MyModule {", 74 " @Provides static Foo<? extends Bar> fooExtends() { return null; }", 75 " @Provides static Foo<Bar> foo() { return null; }", 76 "}"), 77 /* kotlinComponentClass = */ 78 NEW_LINES.join( 79 "@Component(modules = [MyModule::class])", 80 "interface MyComponent {", 81 " fun fooExtends(): Foo<out Bar>", 82 " fun foo(): Foo<Bar>", 83 "}", 84 "@Module", 85 "object MyModule {", 86 " @Provides fun fooExtends(): Foo<out Bar> = TODO()", 87 " @Provides fun foo(): Foo<Bar> = TODO()", 88 "}"), 89 subject -> { 90 if (isIgnoreProvisionKeyWildcardsEnabled) { 91 subject.hasErrorCount(1); 92 subject.hasErrorContaining( 93 NEW_LINES_FOR_ERROR_MSG.join( 94 "Foo<? extends Bar> is bound multiple times:", 95 " @Provides Foo<Bar> MyModule.foo()", 96 " @Provides Foo<? extends Bar> MyModule.fooExtends()", 97 " in component: [MyComponent]")); 98 } else { 99 subject.hasErrorCount(0); 100 } 101 }); 102 } 103 104 @Test testProvidesUniqueBindingsWithMatchingWildcardArguments()105 public void testProvidesUniqueBindingsWithMatchingWildcardArguments() { 106 compile( 107 /* javaComponentClass = */ 108 NEW_LINES.join( 109 "@Component(modules = MyModule.class)", 110 "interface MyComponent {", 111 " Map<Foo<? extends Bar>, Foo<? extends Bar>> mapFooExtendsBarFooExtendsBar();", 112 " Map<Foo<? extends Bar>, Foo<Bar>> mapFooExtendsBarFooBar();", 113 " Map<Foo<Bar>, Foo<? extends Bar>> mapFooBarFooExtendsBar();", 114 " Map<Foo<Bar>, Foo<Bar>> mapFooBarFooBar();", 115 "}", 116 "@Module", 117 "class MyModule {", 118 " @Provides", 119 " Map<Foo<? extends Bar>, Foo<? extends Bar>> mapFooExtendsBarFooExtendsBar() {", 120 " return null; ", 121 " }", 122 " @Provides", 123 " Map<Foo<? extends Bar>, Foo<Bar>> mapFooExtendsBarFooBar() {", 124 " return null;", 125 " }", 126 " @Provides", 127 " Map<Foo<Bar>, Foo<? extends Bar>> mapFooBarFooExtendsBar() {", 128 " return null;", 129 " }", 130 " @Provides", 131 " Map<Foo<Bar>, Foo<Bar>> mapFooBarFooBar() {", 132 " return null;", 133 " }", 134 "}"), 135 /* kotlinComponentClass = */ 136 NEW_LINES.join( 137 "@Component(modules = [MyModule::class])", 138 "interface MyComponent {", 139 " fun mapFooExtendsBarFooExtendsBar(): Map<Foo<out Bar>, Foo<out Bar>>", 140 " fun mapFooExtendsBarFooBar(): Map<Foo<out Bar>, Foo<Bar>>", 141 " fun mapFooBarFooExtendsBar(): Map<Foo<Bar>, Foo<out Bar>>", 142 " fun mapFooBarFooBar(): Map<Foo<Bar>, Foo<Bar>>", 143 "}", 144 "@Module", 145 "class MyModule {", 146 " @Provides", 147 " fun mapFooExtendsBarFooExtendsBar(): Map<Foo<out Bar>, Foo<out Bar>> = TODO()", 148 " @Provides", 149 " fun mapFooExtendsBarFooBar(): Map<Foo<out Bar>, Foo<Bar>> = TODO()", 150 " @Provides", 151 " fun mapFooBarFooExtendsBar(): Map<Foo<Bar>, Foo<out Bar>> = TODO()", 152 " @Provides", 153 " fun mapFooBarFooBar(): Map<Foo<Bar>, Foo<Bar>> = TODO()", 154 "}"), 155 subject -> { 156 if (isIgnoreProvisionKeyWildcardsEnabled) { 157 subject.hasErrorCount(1); 158 subject.hasErrorContaining( 159 NEW_LINES_FOR_ERROR_MSG.join( 160 "Map<Foo<? extends Bar>,Foo<? extends Bar>> is bound multiple times:", 161 " @Provides Map<Foo<Bar>,Foo<Bar>> MyModule.mapFooBarFooBar()", 162 " @Provides Map<Foo<Bar>,Foo<? extends Bar>> " 163 + "MyModule.mapFooBarFooExtendsBar()", 164 " @Provides Map<Foo<? extends Bar>,Foo<Bar>> " 165 + "MyModule.mapFooExtendsBarFooBar()", 166 " @Provides Map<Foo<? extends Bar>,Foo<? extends Bar>> " 167 + "MyModule.mapFooExtendsBarFooExtendsBar()", 168 " in component: [MyComponent]")); 169 } else { 170 subject.hasErrorCount(0); 171 } 172 }); 173 } 174 175 @Test testProvidesMultibindsSetDeclarationsWithDifferentTypeVariances()176 public void testProvidesMultibindsSetDeclarationsWithDifferentTypeVariances() { 177 compile( 178 /* javaComponentClass = */ 179 NEW_LINES.join( 180 "@Component(modules = MyModule.class)", 181 "interface MyComponent {", 182 " Set<Foo<? extends Bar>> setExtends();", 183 " Set<Foo<Bar>> set();", 184 "}", 185 "@Module", 186 "interface MyModule {", 187 " @Multibinds Set<Foo<? extends Bar>> setExtends();", 188 " @Multibinds Set<Foo<Bar>> set();", 189 "}"), 190 /* kotlinComponentClass = */ 191 NEW_LINES.join( 192 "@Component(modules = [MyModule::class])", 193 "interface MyComponent {", 194 " fun setExtends(): Set<Foo<out Bar>>", 195 " fun set(): Set<Foo<Bar>>", 196 "}", 197 "@Module", 198 "interface MyModule {", 199 " @Multibinds fun setExtends(): Set<Foo<out Bar>>", 200 " @Multibinds fun set(): Set<Foo<Bar>>", 201 "}"), 202 subject -> { 203 if (isIgnoreProvisionKeyWildcardsEnabled) { 204 subject.hasErrorCount(1); 205 subject.hasErrorContaining( 206 NEW_LINES_FOR_ERROR_MSG.join( 207 "Set<Foo<? extends Bar>> has incompatible bindings or declarations:", 208 " Set bindings and declarations:", 209 " @Multibinds Set<Foo<Bar>> MyModule.set()", 210 " @Multibinds Set<Foo<? extends Bar>> MyModule.setExtends()", 211 " in component: [MyComponent]")); 212 } else { 213 subject.hasErrorCount(0); 214 } 215 }); 216 } 217 218 @Test testProvidesMultibindsSetContributionsWithDifferentTypeVariances()219 public void testProvidesMultibindsSetContributionsWithDifferentTypeVariances() { 220 compile( 221 /* javaComponentClass= */ NEW_LINES.join( 222 "@Component(modules = MyModule.class)", 223 "interface MyComponent {", 224 " Set<Foo<? extends Bar>> setExtends();", 225 " Set<Foo<Bar>> set();", 226 "}", 227 "@Module", 228 "interface MyModule {", 229 " @Provides @IntoSet static Foo<? extends Bar> setExtends() { return null; }", 230 " @Provides @IntoSet static Foo<Bar> set() { return null; }", 231 "}"), 232 /* kotlinComponentClass= */ NEW_LINES.join( 233 "@Component(modules = [MyModule::class])", 234 "interface MyComponent {", 235 " fun setExtends(): Set<Foo<out Bar>>", 236 " fun set(): Set<Foo<Bar>>", 237 "}", 238 "@Module", 239 "object MyModule {", 240 " @Provides @IntoSet fun setExtends(): Foo<out Bar> = TODO()", 241 " @Provides @IntoSet fun set(): Foo<Bar> = TODO()", 242 "}"), 243 subject -> { 244 if (isIgnoreProvisionKeyWildcardsEnabled) { 245 subject.hasErrorCount(1); 246 subject.hasErrorContaining( 247 NEW_LINES_FOR_ERROR_MSG.join( 248 "Set<Foo<? extends Bar>> has incompatible bindings or declarations:", 249 " Set bindings and declarations:", 250 " @Provides @IntoSet Foo<Bar> MyModule.set()", 251 " @Provides @IntoSet Foo<? extends Bar> MyModule.setExtends()", 252 " in component: [MyComponent]")); 253 } else { 254 subject.hasErrorCount(0); 255 } 256 }); 257 } 258 259 @Test testProvidesMultibindsSetContributionAndMultibindsWithDifferentVariances()260 public void testProvidesMultibindsSetContributionAndMultibindsWithDifferentVariances() { 261 compile( 262 /* javaComponentClass = */ 263 NEW_LINES.join( 264 "@Component(modules = MyModule.class)", 265 "interface MyComponent {", 266 " Set<Foo<? extends Bar>> setExtends();", 267 " Set<Foo<Bar>> set();", 268 "}", 269 "@Module", 270 "interface MyModule {", 271 " @Provides @IntoSet static Foo<? extends Bar> setExtends() { return null; }", 272 " @Multibinds Set<Foo<Bar>> mulitbindSet();", 273 "}"), 274 /* kotlinComponentClass = */ 275 NEW_LINES.join( 276 "@Component(modules = [MyModule::class])", 277 "interface MyComponent {", 278 " fun setExtends(): Set<Foo<out Bar>>", 279 " fun set(): Set<Foo<Bar>>", 280 "}", 281 "@Module", 282 "interface MyModule {", 283 " @Multibinds abstract fun mulitbindSet(): Set<Foo<Bar>>", 284 "", 285 " companion object {", 286 " @Provides @IntoSet fun setExtends(): Foo<out Bar> = TODO()", 287 " }", 288 "}"), 289 subject -> { 290 if (isIgnoreProvisionKeyWildcardsEnabled) { 291 subject.hasErrorCount(1); 292 subject.hasErrorContaining( 293 String.format( 294 NEW_LINES_FOR_ERROR_MSG.join( 295 "Set<Foo<? extends Bar>> has incompatible bindings or declarations:", 296 " Set bindings and declarations:", 297 " @Multibinds Set<Foo<Bar>> MyModule.mulitbindSet()", 298 " @Provides @IntoSet Foo<? extends Bar> %s.setExtends()", 299 " in component: [MyComponent]"), 300 sourceKind == SourceKind.KOTLIN ? "MyModule.Companion" : "MyModule")); 301 } else { 302 subject.hasErrorCount(0); 303 } 304 }); 305 } 306 307 @Test testProvidesIntoSetAndElementsIntoSetContributionsWithDifferentVariances()308 public void testProvidesIntoSetAndElementsIntoSetContributionsWithDifferentVariances() { 309 compile( 310 /* javaComponentClass= */ NEW_LINES.join( 311 "@Component(modules = MyModule.class)", 312 "interface MyComponent {", 313 " Set<Foo<? extends Bar>> setExtends();", 314 " Set<Foo<Bar>> set();", 315 "}", 316 "@Module", 317 "interface MyModule {", 318 " @Provides @IntoSet static Foo<? extends Bar> setExtends() { return null; }", 319 "", 320 " @Provides", 321 " @ElementsIntoSet", 322 " static Set<Foo<Bar>> set() { return null; }", 323 "}"), 324 /* kotlinComponentClass= */ NEW_LINES.join( 325 "@Component(modules = [MyModule::class])", 326 "interface MyComponent {", 327 " fun setExtends(): Set<Foo<out Bar>>", 328 " fun set(): Set<Foo<Bar>>", 329 "}", 330 "@Module", 331 "object MyModule {", 332 " @Provides @IntoSet fun setExtends(): Foo<out Bar> = TODO()", 333 " @Provides @ElementsIntoSet fun set(): Set<Foo<Bar>> = TODO()", 334 "}"), 335 subject -> { 336 if (isIgnoreProvisionKeyWildcardsEnabled) { 337 subject.hasErrorCount(1); 338 subject.hasErrorContaining( 339 NEW_LINES_FOR_ERROR_MSG.join( 340 "Set<Foo<? extends Bar>> has incompatible bindings or declarations:", 341 " Set bindings and declarations:", 342 " @Provides @ElementsIntoSet Set<Foo<Bar>> MyModule.set()", 343 " @Provides @IntoSet Foo<? extends Bar> MyModule.setExtends()", 344 " in component: [MyComponent]")); 345 } else { 346 subject.hasErrorCount(0); 347 } 348 }); 349 } 350 351 @Test testProvidesMultibindsSetContributionsWithSameTypeVariances()352 public void testProvidesMultibindsSetContributionsWithSameTypeVariances() { 353 compile( 354 /* javaComponentClass = */ 355 NEW_LINES.join( 356 "@Component(modules = MyModule.class)", 357 "interface MyComponent {", 358 " Set<Foo<Bar>> set();", 359 "}", 360 "@Module", 361 "interface MyModule {", 362 " @Provides @IntoSet static Foo<Bar> set1() { return null; }", 363 " @Provides @IntoSet static Foo<Bar> set2() { return null; }", 364 " @Provides @ElementsIntoSet static Set<Foo<Bar>> set3() { return null; }", 365 "}"), 366 /* kotlinComponentClass = */ 367 NEW_LINES.join( 368 "@Component(modules = [MyModule::class])", 369 "interface MyComponent {", 370 " fun set(): Set<Foo<Bar>>", 371 "}", 372 "@Module", 373 "object MyModule {", 374 " @Provides @IntoSet fun set1(): Foo<Bar> = TODO()", 375 " @Provides @IntoSet fun set2(): Foo<Bar> = TODO()", 376 " @Provides @ElementsIntoSet fun set3(): Set<Foo<Bar>> = TODO()", 377 "}"), 378 subject -> subject.hasErrorCount(0)); 379 } 380 381 @Test testProvidesMultibindsMapDeclarationValuesWithDifferentTypeVariances()382 public void testProvidesMultibindsMapDeclarationValuesWithDifferentTypeVariances() { 383 compile( 384 /* javaComponentClass = */ 385 NEW_LINES.join( 386 "@Component(modules = MyModule.class)", 387 "interface MyComponent {", 388 " Map<String, Foo<? extends Bar>> mapExtends();", 389 " Map<String, Foo<Bar>> map();", 390 "}", 391 "@Module", 392 "interface MyModule {", 393 " @Multibinds Map<String, Foo<? extends Bar>> mapExtends();", 394 " @Multibinds Map<String, Foo<Bar>> map();", 395 "}"), 396 /* kotlinComponentClass = */ 397 NEW_LINES.join( 398 "@Component(modules = [MyModule::class])", 399 "interface MyComponent {", 400 " fun mapExtends(): Map<String, Foo<out Bar>>", 401 " fun map(): Map<String, Foo<Bar>>", 402 "}", 403 "@Module", 404 "interface MyModule {", 405 " @Multibinds fun mapExtends():Map<String, Foo<out Bar>>", 406 " @Multibinds fun map(): Map<String, Foo<Bar>>", 407 "}"), 408 subject -> { 409 if (isIgnoreProvisionKeyWildcardsEnabled) { 410 subject.hasErrorCount(1); 411 subject.hasErrorContaining( 412 NEW_LINES_FOR_ERROR_MSG.join( 413 "Map<String,Foo<? extends Bar>> has incompatible bindings or declarations:", 414 " Map bindings and declarations:", 415 " @Multibinds Map<String,Foo<Bar>> MyModule.map()", 416 " @Multibinds Map<String,Foo<? extends Bar>> MyModule.mapExtends()", 417 " in component: [MyComponent]")); 418 } else { 419 subject.hasErrorCount(0); 420 } 421 }); 422 } 423 424 @Test testProvidesMultibindsMapDeclarationKeysWithDifferentTypeVariances()425 public void testProvidesMultibindsMapDeclarationKeysWithDifferentTypeVariances() { 426 compile( 427 /* javaComponentClass = */ 428 NEW_LINES.join( 429 "@Component(modules = MyModule.class)", 430 "interface MyComponent {", 431 " Map<Foo<? extends Bar>, String> mapExtends();", 432 " Map<Foo<Bar>, String> map();", 433 "}", 434 "@Module", 435 "interface MyModule {", 436 " @Multibinds Map<Foo<? extends Bar>, String> mapExtends();", 437 " @Multibinds Map<Foo<Bar>, String> map();", 438 "}"), 439 /* kotlinComponentClass = */ 440 NEW_LINES.join( 441 "@Component(modules = [MyModule::class])", 442 "interface MyComponent {", 443 " fun mapExtends(): Map<Foo<out Bar>, String>", 444 " fun map(): Map<Foo<Bar>, String>", 445 "}", 446 "@Module", 447 "interface MyModule {", 448 " @Multibinds fun mapExtends():Map<Foo<out Bar>, String>", 449 " @Multibinds fun map(): Map<Foo<Bar>, String>", 450 "}"), 451 subject -> { 452 if (isIgnoreProvisionKeyWildcardsEnabled) { 453 subject.hasErrorCount(1); 454 subject.hasErrorContaining( 455 NEW_LINES_FOR_ERROR_MSG.join( 456 "Map<Foo<? extends Bar>,String> has incompatible bindings or declarations:", 457 " Map bindings and declarations:", 458 " @Multibinds Map<Foo<Bar>,String> MyModule.map()", 459 " @Multibinds Map<Foo<? extends Bar>,String> MyModule.mapExtends()", 460 " in component: [MyComponent]")); 461 } else { 462 subject.hasErrorCount(0); 463 } 464 }); 465 } 466 467 @Test testProvidesMultibindsMapContributionsWithDifferentTypeVariances()468 public void testProvidesMultibindsMapContributionsWithDifferentTypeVariances() { 469 compile( 470 /* javaComponentClass = */ 471 NEW_LINES.join( 472 "@Component(modules = MyModule.class)", 473 "interface MyComponent {", 474 " Map<String, Foo<? extends Bar>> mapExtends();", 475 " Map<String, Foo<Bar>> map();", 476 "}", 477 "@Module", 478 "interface MyModule {", 479 " @Provides", 480 " @IntoMap", 481 " @StringKey(\"fooExtends\")", 482 " static Foo<? extends Bar> fooExtends() { return null; }", 483 "", 484 " @Provides", 485 " @IntoMap", 486 " @StringKey(\"foo\")", 487 " static Foo<Bar> foo() { return null; }", 488 "}"), 489 /* kotlinComponentClass = */ 490 NEW_LINES.join( 491 "@Component(modules = [MyModule::class])", 492 "interface MyComponent {", 493 " fun mapExtends(): Map<String, Foo<out Bar>>", 494 " fun map(): Map<String, Foo<Bar>>", 495 "}", 496 "@Module", 497 "object MyModule {", 498 " @Provides", 499 " @IntoMap", 500 " @StringKey(\"fooExtends\")", 501 " fun fooExtends(): Foo<out Bar> = TODO()", 502 "", 503 " @Provides", 504 " @IntoMap", 505 " @StringKey(\"foo\")", 506 " fun foo(): Foo<Bar> = TODO()", 507 "}"), 508 subject -> { 509 if (isIgnoreProvisionKeyWildcardsEnabled) { 510 subject.hasErrorContaining( 511 String.format( 512 NEW_LINES_FOR_ERROR_MSG.join( 513 "Map<String,Foo<? extends Bar>> has incompatible bindings or declarations:", 514 " Map bindings and declarations:", 515 " %s Foo<Bar> MyModule.foo()", 516 " %s Foo<? extends Bar> MyModule.fooExtends()", 517 " in component: [MyComponent]"), 518 "@Provides @IntoMap @StringKey(\"foo\")", 519 "@Provides @IntoMap @StringKey(\"fooExtends\")")); 520 } else { 521 subject.hasErrorCount(0); 522 } 523 }); 524 } 525 526 @Test testProvidesOptionalDeclarationWithDifferentTypeVariances()527 public void testProvidesOptionalDeclarationWithDifferentTypeVariances() { 528 compile( 529 /* javaComponentClass = */ 530 NEW_LINES.join( 531 "@Component(modules = MyModule.class)", 532 "interface MyComponent {", 533 " Optional<Foo<? extends Bar>> fooExtends();", 534 " Optional<Foo<Bar>> foo();", 535 "}", 536 "@Module", 537 "interface MyModule {", 538 " @BindsOptionalOf Foo<? extends Bar> fooExtends();", 539 " @BindsOptionalOf Foo<Bar> foo();", 540 "}"), 541 /* kotlinComponentClass = */ 542 NEW_LINES.join( 543 "@Component(modules = [MyModule::class])", 544 "interface MyComponent {", 545 " fun fooExtends(): Optional<Foo<out Bar>>", 546 " fun foo(): Optional<Foo<Bar>>", 547 "}", 548 "@Module", 549 "interface MyModule {", 550 " @BindsOptionalOf fun fooExtends(): Foo<out Bar>", 551 " @BindsOptionalOf fun foo(): Foo<Bar>", 552 "}"), 553 subject -> { 554 if (isIgnoreProvisionKeyWildcardsEnabled) { 555 subject.hasErrorCount(1); 556 subject.hasErrorContaining( 557 NEW_LINES_FOR_ERROR_MSG.join( 558 "Optional<Foo<? extends Bar>> is bound multiple times:", 559 " @BindsOptionalOf Foo<Bar> MyModule.foo()", 560 " @BindsOptionalOf Foo<? extends Bar> MyModule.fooExtends()", 561 "in component: [MyComponent]")); 562 } else { 563 subject.hasErrorCount(0); 564 } 565 }); 566 } 567 compile( String javaComponentClass, String kotlinComponentClass, Consumer<CompilationResultSubject> onCompilationResult)568 private void compile( 569 String javaComponentClass, 570 String kotlinComponentClass, 571 Consumer<CompilationResultSubject> onCompilationResult) { 572 compileInternal( 573 javaComponentClass, 574 kotlinComponentClass, 575 subject -> { 576 if (!isIgnoreProvisionKeyWildcardsEnabled) { 577 if (CompilerTests.backend(subject) == 578 androidx.room.compiler.processing.XProcessingEnv.Backend.KSP) { 579 subject.hasErrorCount(1); 580 subject.hasErrorContaining( 581 "When using KSP, you must also enable the 'dagger.ignoreProvisionKeyWildcards'"); 582 return; 583 } 584 } 585 onCompilationResult.accept(subject); 586 }); 587 } 588 compileInternal( String javaComponentClass, String kotlinComponentClass, Consumer<CompilationResultSubject> onCompilationResult)589 private void compileInternal( 590 String javaComponentClass, 591 String kotlinComponentClass, 592 Consumer<CompilationResultSubject> onCompilationResult) { 593 if (sourceKind == SourceKind.JAVA) { 594 // Compile with Java sources 595 CompilerTests.daggerCompiler( 596 CompilerTests.javaSource( 597 "test.MyComponent", 598 "package test;", 599 "", 600 "import dagger.BindsOptionalOf;", 601 "import dagger.Component;", 602 "import dagger.Module;", 603 "import dagger.Provides;", 604 "import dagger.multibindings.ElementsIntoSet;", 605 "import dagger.multibindings.IntoSet;", 606 "import dagger.multibindings.IntoMap;", 607 "import dagger.multibindings.Multibinds;", 608 "import dagger.multibindings.StringKey;", 609 "import java.util.Map;", 610 "import java.util.Optional;", 611 "import java.util.Set;", 612 "import javax.inject.Inject;", 613 "import javax.inject.Provider;", 614 "", 615 javaComponentClass, 616 "", 617 "interface Foo<T> {}", 618 "", 619 "class Bar {}")) 620 .withProcessingOptions(processingOptions) 621 .compile(onCompilationResult); 622 } 623 624 if (sourceKind == SourceKind.KOTLIN) { 625 // Compile with Kotlin sources 626 CompilerTests.daggerCompiler( 627 CompilerTests.kotlinSource( 628 "test.MyComponent.kt", 629 // TODO(bcorso): See if there's a better way to fix the following error. 630 // 631 // Error: Cannot inline bytecode built with JVM target 11 into bytecode that is 632 // being built with JVM target 1.8 633 "@file:Suppress(\"INLINE_FROM_HIGHER_PLATFORM\")", 634 "package test", 635 "", 636 "import dagger.BindsOptionalOf", 637 "import dagger.Component", 638 "import dagger.Module", 639 "import dagger.Provides", 640 "import dagger.multibindings.ElementsIntoSet", 641 "import dagger.multibindings.IntoSet", 642 "import dagger.multibindings.IntoMap", 643 "import dagger.multibindings.Multibinds", 644 "import dagger.multibindings.StringKey", 645 "import java.util.Optional;", 646 "import javax.inject.Inject", 647 "import javax.inject.Provider", 648 "", 649 kotlinComponentClass, 650 "", 651 "interface Foo<T>", 652 "", 653 "class Bar")) 654 .withProcessingOptions(processingOptions) 655 .compile(onCompilationResult); 656 } 657 } 658 } 659