From f8ba8f1f75ab7f5ac4d24e2ff82878197572a6f4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Sat, 3 Aug 2019 01:44:49 +0100 Subject: [PATCH 1/3] Add assertions for missing binding when linker is null --- .../test/java/com/example/IntegrationTest.java | 18 +++++++++++++++--- .../src/main/java/dagger/reflect/Scope.java | 2 +- 2 files changed, 16 insertions(+), 4 deletions(-) diff --git a/integration-tests/src/test/java/com/example/IntegrationTest.java b/integration-tests/src/test/java/com/example/IntegrationTest.java index bce171fb..f603dd12 100644 --- a/integration-tests/src/test/java/com/example/IntegrationTest.java +++ b/integration-tests/src/test/java/com/example/IntegrationTest.java @@ -245,7 +245,11 @@ public void justInTimeWrongScope() { component.thing(); fail(); } catch (IllegalStateException e) { - // TODO assert some message + assertThat(e) + .hasMessageThat() + .isEqualTo( + "Unable to find binding for key=com.example.JustInTimeWrongScope$Thing" + + " with linker=null"); } } @@ -257,7 +261,11 @@ public void justInTimeScopedIntoUnscoped() { component.thing(); fail(); } catch (IllegalStateException e) { - // TODO assert some message + assertThat(e) + .hasMessageThat() + .isEqualTo( + "Unable to find binding for key=com.example.JustInTimeScopedIntoUnscoped$Thing" + + " with linker=null"); } } @@ -270,7 +278,11 @@ public void justInTimeNotScopedInAncestry() { child.thing(); fail(); } catch (IllegalStateException e) { - // TODO assert some message + assertThat(e) + .hasMessageThat() + .isEqualTo( + "Unable to find binding for key=com.example.JustInTimeNotScopedInAncestry$Thing" + + " with linker=null"); } } diff --git a/reflect/src/main/java/dagger/reflect/Scope.java b/reflect/src/main/java/dagger/reflect/Scope.java index a18a529d..d8aec785 100644 --- a/reflect/src/main/java/dagger/reflect/Scope.java +++ b/reflect/src/main/java/dagger/reflect/Scope.java @@ -78,7 +78,7 @@ LinkedBinding findBinding(Key key, @Nullable Linker linker) { throw new IllegalStateException( "Unable to find binding for key=" + key - + " and linker=" + + " with linker=" + linker); // TODO nice error message with scope chain } return jitBinding; From 674233ad41a8c547b688b55485bdcc841c3ceee1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Sat, 3 Aug 2019 01:46:19 +0100 Subject: [PATCH 2/3] Add toString for Linker and Scope classes --- reflect/src/main/java/dagger/reflect/Linker.java | 16 ++++++++++++++-- reflect/src/main/java/dagger/reflect/Scope.java | 10 ++++++---- 2 files changed, 20 insertions(+), 6 deletions(-) diff --git a/reflect/src/main/java/dagger/reflect/Linker.java b/reflect/src/main/java/dagger/reflect/Linker.java index bfb445d8..b4179587 100644 --- a/reflect/src/main/java/dagger/reflect/Linker.java +++ b/reflect/src/main/java/dagger/reflect/Linker.java @@ -40,6 +40,20 @@ LinkedBinding link(Key key, UnlinkedBinding unlinkedBinding) { private RuntimeException failure(Key key, String reason, String cause) { StringBuilder builder = new StringBuilder(reason).append(" for ").append(key).append('\n'); + appendChain(builder); + builder.append(" * Requested: ").append(key).append("\n which ").append(cause).append('.'); + throw new IllegalStateException(builder.toString()); + } + + @Override + public String toString() { + StringBuilder builder = new StringBuilder(); + builder.append("Linker with ").append(scope).append("\n"); + appendChain(builder); + return builder.toString(); + } + + private void appendChain(StringBuilder builder) { for (Map.Entry entry : chain.entrySet()) { builder .append(" * Requested: ") @@ -48,7 +62,5 @@ private RuntimeException failure(Key key, String reason, String cause) { .append(entry.getValue()) .append('\n'); } - builder.append(" * Requested: ").append(key).append("\n which ").append(cause).append('.'); - throw new IllegalStateException(builder.toString()); } } diff --git a/reflect/src/main/java/dagger/reflect/Scope.java b/reflect/src/main/java/dagger/reflect/Scope.java index d8aec785..7d1d26ee 100644 --- a/reflect/src/main/java/dagger/reflect/Scope.java +++ b/reflect/src/main/java/dagger/reflect/Scope.java @@ -35,6 +35,11 @@ private Scope( this.parent = parent; } + @Override + public String toString() { + return "Scope" + annotations; + } + LinkedBinding getBinding(Key key) { LinkedBinding binding = findBinding(key, null); if (binding != null) { @@ -76,10 +81,7 @@ LinkedBinding findBinding(Key key, @Nullable Linker linker) { LinkedBinding jitBinding = putJitBinding(key, linker, jitLookup); if (jitBinding == null) { throw new IllegalStateException( - "Unable to find binding for key=" - + key - + " with linker=" - + linker); // TODO nice error message with scope chain + "Unable to find binding for key=" + key + " with linker=" + linker); } return jitBinding; } From c12dab664fc53d3dec2cb17d5ab10867b7b2d524 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?R=C3=B3bert=20Papp=20=28TWiStErRob=29?= Date: Sat, 3 Aug 2019 01:48:04 +0100 Subject: [PATCH 3/3] Try to reproduce a failure with linker != null --- .../example/OptionalBindingWrongScope.java | 42 +++++++++++++++++++ .../java/com/example/IntegrationTest.java | 18 ++++++++ 2 files changed, 60 insertions(+) create mode 100644 integration-tests/src/main/java/com/example/OptionalBindingWrongScope.java diff --git a/integration-tests/src/main/java/com/example/OptionalBindingWrongScope.java b/integration-tests/src/main/java/com/example/OptionalBindingWrongScope.java new file mode 100644 index 00000000..99c3a9d5 --- /dev/null +++ b/integration-tests/src/main/java/com/example/OptionalBindingWrongScope.java @@ -0,0 +1,42 @@ +package com.example; + +import static java.lang.annotation.RetentionPolicy.RUNTIME; + +import dagger.BindsOptionalOf; +import dagger.Component; +import dagger.Module; +import java.lang.annotation.Retention; +import java.util.Optional; +import javax.inject.Inject; +import javax.inject.Qualifier; +import javax.inject.Scope; +import javax.inject.Singleton; + +@Singleton +@Component(modules = OptionalBindingWrongScope.Module1.class) +public interface OptionalBindingWrongScope { + @Qualified + Optional thing(); + + @Module + abstract class Module1 { + @BindsOptionalOf + @Qualified + abstract Thing optionalThing(); + } + + @Qualified // @BindsOptionalOf cannot work with unqualified JIT, so a @Qualifier is needed + @Unrelated // mismatched scope (to Singleton) makes putJitBinding return null + final class Thing { + @Inject + Thing() {} + } + + @Scope + @Retention(RUNTIME) + @interface Unrelated {} + + @Qualifier + // @Retention(RUNTIME) missing, so that binding is not found + @interface Qualified {} +} diff --git a/integration-tests/src/test/java/com/example/IntegrationTest.java b/integration-tests/src/test/java/com/example/IntegrationTest.java index f603dd12..fd74d44f 100644 --- a/integration-tests/src/test/java/com/example/IntegrationTest.java +++ b/integration-tests/src/test/java/com/example/IntegrationTest.java @@ -158,6 +158,24 @@ public void optionalBindingNullable() { } } + @Test + @IgnoreCodegen + public void optionalBindingWrongScope() { + OptionalBindingWrongScope component = backend.create(OptionalBindingWrongScope.class); + try { + component.thing(); + fail(); + } catch (IllegalStateException e) { + assertThat(e) + .hasMessageThat() + .isEqualTo( + "Unable to find binding for key=com.example.OptionalBindingWrongScope$Thing" + + " with linker=Linker with Scope[@javax.inject.Singleton()]\n" + + " * Requested: java.util.Optional\n" + + " from @Optional[com.example.OptionalBindingWrongScope$Module1.optionalThing(…)]\n"); + } + } + @Test public void optionalBindingAbsent() { OptionalBindingAbsent component = backend.create(OptionalBindingAbsent.class);