Revision: 8557c775d526
Author:   Sam Berlin <[email protected]>
Date:     Thu Mar  1 11:21:26 2012
Log: Add a new method to ThrowingProviderBinder: providing(Class) or providing(TypeLiteral). This instructs ThrowingProviderBinder to create a proxy implementation of the CheckedProvider interface and delegate it to the constructor of the class in question. As a bonus, the class it constructs fully participates in Guice AOP.

This is a binary-safe change, but a compile-unsafe change if classes directly kept a reference to SecondaryBinder. SecondaryBinder now has two generic types (as opposed to one).

Revision created by MOE tool push_codebase.
MOE_MIGRATION=4307

http://code.google.com/p/google-guice/source/detail?r=8557c775d526

Added:
/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvideUtils.java /extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderWithDependencies.java
Modified:
/extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethod.java /extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethodsModule.java /extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProviderBinder.java /extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderTest.java

=======================================
--- /dev/null
+++ /extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProvideUtils.java Thu Mar 1 11:21:26 2012
@@ -0,0 +1,48 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+package com.google.inject.throwingproviders;
+
+import com.google.inject.Binder;
+import com.google.inject.TypeLiteral;
+
+/**
+ * Utilities for the throwing provider module.
+ *
+ * @author [email protected] (Sam Berlin)
+ */
+class CheckedProvideUtils {
+
+  private CheckedProvideUtils() {}
+
+  /** Adds errors to the binder if the exceptions aren't valid. */
+  static void validateExceptions(Binder binder,
+      Iterable<TypeLiteral<?>> actualExceptionTypes,
+      Iterable<Class<? extends Throwable>> expectedExceptionTypes,
+      Class<? extends CheckedProvider> checkedProvider) {
+    // Validate the exceptions in the method match the exceptions
+    // in the CheckedProvider.
+    for (TypeLiteral<?> exType : actualExceptionTypes) {
+      Class<?> exActual = exType.getRawType();
+      // Ignore runtime exceptions & errors.
+      if (RuntimeException.class.isAssignableFrom(exActual)
+          || Error.class.isAssignableFrom(exActual)) {
+        continue;
+      }
+
+      boolean notAssignable = true;
+ for (Class<? extends Throwable> exExpected : expectedExceptionTypes) {
+        if (exExpected.isAssignableFrom(exActual)) {
+          notAssignable = false;
+          break;
+        }
+      }
+      if (notAssignable) {
+        binder.addError(
+            "%s is not compatible with the exceptions (%s) declared in "
+            + "the CheckedProvider interface (%s)",
+            exActual, expectedExceptionTypes, checkedProvider);
+      }
+    }
+  }
+
+}
=======================================
--- /dev/null
+++ /extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderWithDependencies.java Thu Mar 1 11:21:26 2012
@@ -0,0 +1,16 @@
+// Copyright 2012 Google Inc. All Rights Reserved.
+
+package com.google.inject.throwingproviders;
+
+import com.google.inject.spi.HasDependencies;
+import com.google.inject.throwingproviders.ThrowingProviderBinder.SecondaryBinder;
+
+/**
+ * A checked provider with dependencies, so {@link HasDependencies} can be implemented
+ * when using the {@link SecondaryBinder#using} methods.
+ *
+ * @author [email protected] (Sam Berlin)
+ */
+interface CheckedProviderWithDependencies<T> extends CheckedProvider<T>, HasDependencies {
+
+}
=======================================
--- /extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethod.java Thu Jul 7 17:34:16 2011 +++ /extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethod.java Thu Mar 1 11:21:26 2012
@@ -76,9 +76,9 @@
   void configure(Binder binder) {
     binder = binder.withSource(method);

-    SecondaryBinder<?> sbinder =
+    SecondaryBinder<?, ?> sbinder =
       ThrowingProviderBinder.create(binder)
-        .bind(checkedProvider, key.getTypeLiteral().getType());
+        .bind(checkedProvider, key.getTypeLiteral());
     if(key.getAnnotation() != null) {
       sbinder = sbinder.annotatedWith(key.getAnnotation());
     } else if(key.getAnnotationType() != null) {
@@ -94,29 +94,9 @@
// misplaced @Exposed, calling this will add an error to the binder's error queue
       ((PrivateBinder) binder).expose(sbinder.getKey());
     }
-
-    // Validate the exceptions in the method match the exceptions
-    // in the CheckedProvider.
-    for(TypeLiteral<?> exType : exceptionTypes) {
-      Class<?> exActual = exType.getRawType();
-      // Ignore runtime exceptions & errors.
- if(RuntimeException.class.isAssignableFrom(exActual) || Error.class.isAssignableFrom(exActual)) {
-        continue;
-      }
-
-      boolean notAssignable = true;
- for(Class<? extends Throwable> exExpected : sbinder.getExceptionTypes()) {
-        if (exExpected.isAssignableFrom(exActual)) {
-          notAssignable = false;
-          break;
-        }
-      }
-      if(notAssignable) {
-        binder.addError(
- "%s is not compatible with the exceptions (%s) declared in the CheckedProvider interface (%s)",
-            exActual, sbinder.getExceptionTypes(), checkedProvider);
-      }
-    }
+
+    CheckedProvideUtils.validateExceptions(
+ binder, exceptionTypes, sbinder.getExceptionTypes(), checkedProvider);
   }

   public T get() throws Exception {
=======================================
--- /extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethodsModule.java Thu Jul 7 17:34:16 2011 +++ /extensions/throwingproviders/src/com/google/inject/throwingproviders/CheckedProviderMethodsModule.java Thu Mar 1 11:21:26 2012
@@ -75,8 +75,7 @@
     List<CheckedProviderMethod<?>> result = Lists.newArrayList();
for (Class<?> c = delegate.getClass(); c != Object.class; c = c.getSuperclass()) {
       for (Method method : c.getDeclaredMethods()) {
-        CheckedProvides checkedProvides =
-          (CheckedProvides)method.getAnnotation(CheckedProvides.class);
+ CheckedProvides checkedProvides = method.getAnnotation(CheckedProvides.class);
         if(checkedProvides != null) {
result.add(createProviderMethod(binder, method, checkedProvides.value()));
         }
=======================================
--- /extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProviderBinder.java Thu Jul 7 17:34:16 2011 +++ /extensions/throwingproviders/src/com/google/inject/throwingproviders/ThrowingProviderBinder.java Thu Mar 1 11:21:26 2012
@@ -22,18 +22,24 @@
 import com.google.common.collect.ImmutableSet;
 import com.google.common.collect.Lists;
 import com.google.inject.Binder;
+import com.google.inject.ConfigurationException;
 import com.google.inject.Key;
 import com.google.inject.Module;
 import com.google.inject.Provider;
+import com.google.inject.ProvisionException;
+import com.google.inject.Scopes;
 import com.google.inject.TypeLiteral;
 import com.google.inject.binder.ScopedBindingBuilder;
 import com.google.inject.internal.UniqueAnnotations;
 import com.google.inject.spi.Dependency;
+import com.google.inject.spi.InjectionPoint;
+import com.google.inject.spi.Message;
 import com.google.inject.spi.ProviderWithDependencies;
 import com.google.inject.util.Types;

 import java.io.Serializable;
 import java.lang.annotation.Annotation;
+import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationHandler;
 import java.lang.reflect.Method;
 import java.lang.reflect.ParameterizedType;
@@ -65,10 +71,18 @@
  *     return creator.getCustomerOrThrow();
  *   }
  * }
+ * </code></pre>
+ * You also can declare that a CheckedProvider construct
+ * a particular class whose constructor throws an exception:
+ * <pre><code>ThrowingProviderBinder.create(binder())
+ *    .bind(RemoteProvider.class, Customer.class)
+ *    .providing(CustomerImpl.class)
+ *    .in(RequestScope.class);
  * </code></pre>
  *
  * @author [email protected] (Jerome Mourits)
  * @author [email protected] (Jesse Wilson)
+ * @author [email protected] (Sam Berlin)
  */
 public class ThrowingProviderBinder {

@@ -92,13 +106,27 @@
   public static Module forModule(Module module) {
     return CheckedProviderMethodsModule.forModule(module);
   }
-
-  public <P extends CheckedProvider> SecondaryBinder<P>
-      bind(final Class<P> interfaceType, final Type valueType) {
-    return new SecondaryBinder<P>(interfaceType, valueType);
+
+  /**
+ * @deprecated Use {@link #bind(Class, Class)} or {@link #bind(Class, TypeLiteral)} instead.
+   */
+  @Deprecated
+  public <P extends CheckedProvider> SecondaryBinder<P, ?>
+      bind(Class<P> interfaceType, Type clazz) {
+    return new SecondaryBinder<P, Object>(interfaceType, clazz);
+  }
+
+  public <P extends CheckedProvider, T> SecondaryBinder<P, T>
+      bind(Class<P> interfaceType, Class<T> clazz) {
+    return new SecondaryBinder<P, T>(interfaceType, clazz);
+  }
+
+  public <P extends CheckedProvider, T> SecondaryBinder<P, T>
+      bind(Class<P> interfaceType, TypeLiteral<T> typeLiteral) {
+    return new SecondaryBinder<P, T>(interfaceType, typeLiteral.getType());
   }

-  public class SecondaryBinder<P extends CheckedProvider> {
+  public class SecondaryBinder<P extends CheckedProvider, T> {
     private final Class<P> interfaceType;
     private final Type valueType;
     private final List<Class<? extends Throwable>> exceptionTypes;
@@ -128,17 +156,17 @@
       return interfaceKey;
     }

- public SecondaryBinder<P> annotatedWith(Class<? extends Annotation> annotationType) { + public SecondaryBinder<P, T> annotatedWith(Class<? extends Annotation> annotationType) {
       if (!(this.annotationType == null && this.annotation == null)) {
-        throw new IllegalStateException();
+        throw new IllegalStateException("Cannot set annotation twice");
       }
       this.annotationType = annotationType;
       return this;
     }

-    public SecondaryBinder<P> annotatedWith(Annotation annotation) {
+    public SecondaryBinder<P, T> annotatedWith(Annotation annotation) {
       if (!(this.annotationType == null && this.annotation == null)) {
-        throw new IllegalStateException();
+        throw new IllegalStateException("Cannot set annotation twice");
       }
       this.annotation = annotation;
       return this;
@@ -149,16 +177,79 @@
       binder.bind(targetKey).toInstance(target);
       return to(targetKey);
     }
-
+
     public ScopedBindingBuilder to(Class<? extends P> targetType) {
       return to(Key.get(targetType));
     }
+
+    public ScopedBindingBuilder providing(Class<? extends T> cxtorClass) {
+      return providing(TypeLiteral.get(cxtorClass));
+    }
+
+ @SuppressWarnings("unchecked") // safe because this is the cxtor of the literal + public ScopedBindingBuilder providing(TypeLiteral<? extends T> cxtorLiteral) { + // Find the injection point of the class we want to create & get its constructor.
+      InjectionPoint ip = null;
+      try {
+        ip = InjectionPoint.forConstructorOf(cxtorLiteral);
+      } catch (ConfigurationException ce) {
+        for (Message message : ce.getErrorMessages()) {
+          binder.addError(message);
+        }
+      }
+
+      final Provider<T> typeProvider;
+      final Key<? extends T> typeKey;
+ // If we found an injection point, then bind the cxtor to a unique key
+      if (ip != null) {
+ Constructor<? extends T> cxtor = (Constructor<? extends T>) ip.getMember(); + // Validate the exceptions are consistent with the CheckedProvider interface.
+        CheckedProvideUtils.validateExceptions(
+ binder, cxtorLiteral.getExceptionTypes(cxtor), exceptionTypes, interfaceType);
+
+        typeKey = Key.get(cxtorLiteral, UniqueAnnotations.create());
+ binder.bind(typeKey).toConstructor((Constructor) cxtor).in(Scopes.NO_SCOPE);
+        typeProvider = binder.getProvider((Key<T>) typeKey);
+      } else {
+        // never used, but need it assigned.
+        typeProvider = null;
+        typeKey = null;
+      }
+
+      // Create a CheckedProvider that calls our cxtor
+ CheckedProvider<T> checkedProvider = new CheckedProviderWithDependencies<T>() {
+        @Override
+        public T get() throws Exception {
+          try {
+            return typeProvider.get();
+          } catch (ProvisionException pe) {
+            // Rethrow the provision cause as the actual exception
+            if (pe.getCause() instanceof Exception) {
+              throw (Exception) pe.getCause();
+            } else if (pe.getCause() instanceof Error) {
+              throw (Error) pe.getCause();
+            } else {
+              throw new AssertionError(pe.getCause()); // Impossible!
+            }
+          }
+        }
+
+        @Override
+        public Set<Dependency<?>> getDependencies() {
+          return ImmutableSet.<Dependency<?>>of(Dependency.get(typeKey));
+        }
+      };
+
+ Key<CheckedProvider> targetKey = Key.get(CheckedProvider.class, UniqueAnnotations.create());
+      binder.bind(targetKey).toInstance(checkedProvider);
+      return toInternal(targetKey);
+    }

ScopedBindingBuilder toProviderMethod(CheckedProviderMethod<?> target) {
       Key<CheckedProviderMethod> targetKey =
-        Key.get(CheckedProviderMethod.class, UniqueAnnotations.create());
+          Key.get(CheckedProviderMethod.class, UniqueAnnotations.create());
       binder.bind(targetKey).toInstance(target);
-
+
       return toInternal(targetKey);
     }

=======================================
--- /extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderTest.java Thu Jul 7 17:34:16 2011 +++ /extensions/throwingproviders/test/com/google/inject/throwingproviders/CheckedProviderTest.java Thu Mar 1 11:21:26 2012
@@ -42,6 +42,7 @@
 import java.net.BindException;
 import java.rmi.AccessException;
 import java.rmi.RemoteException;
+import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
 import java.util.Set;
@@ -50,34 +51,68 @@
 /**
  * @author [email protected] (Jerome Mourits)
  * @author [email protected] (Jesse Wilson)
+ * @author [email protected] (Sam Berlin)
  */
 public class CheckedProviderTest extends TestCase {
-
-  private final TypeLiteral<RemoteProvider<String>> remoteProviderOfString
-      = new TypeLiteral<RemoteProvider<String>>() { };
- private final MockRemoteProvider<String> mockRemoteProvider = new MockRemoteProvider<String>();
+
+  private static final Function<Dependency<?>, Key<?>> DEPENDENCY_TO_KEY =
+      new Function<Dependency<?>, Key<?>>() {
+        public Key<?> apply(Dependency<?> from) {
+          return from.getKey();
+        }
+      };
+
+  private final TypeLiteral<RemoteProvider<Foo>> remoteProviderOfFoo
+      = new TypeLiteral<RemoteProvider<Foo>>() { };
+ private final MockRemoteProvider<Foo> mockRemoteProvider = new MockRemoteProvider<Foo>();
   private final TestScope testScope = new TestScope();
- private Injector bindInjector = Guice.createInjector(new AbstractModule() {
-    protected void configure() {
-      ThrowingProviderBinder.create(binder())
-          .bind(RemoteProvider.class, String.class)
-          .to(mockRemoteProvider)
-          .in(testScope);
-    }
-  });
- private Injector providesInjector = Guice.createInjector(new AbstractModule() {
-    protected void configure() {
-     install(ThrowingProviderBinder.forModule(this));
-     bindScope(TestScope.Scoped.class, testScope);
-    }
-
-    @SuppressWarnings("unused")
-    @CheckedProvides(RemoteProvider.class)
-    @TestScope.Scoped
-    String throwOrGet() throws RemoteException, BindException {
-      return mockRemoteProvider.get();
-    }
-  });
+
+  private Injector bindInjector;
+  private Injector providesInjector;
+  private Injector cxtorInjector;
+
+  @Override
+  protected void setUp() throws Exception {
+    MockFoo.nextToThrow = null;
+    MockFoo.nextToReturn = null;
+    AnotherMockFoo.nextToThrow = null;
+    AnotherMockFoo.nextToReturn = null;
+
+    bindInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, Foo.class)
+            .to(mockRemoteProvider)
+            .in(testScope);
+      }
+    });
+
+    providesInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+       install(ThrowingProviderBinder.forModule(this));
+       bindScope(TestScope.Scoped.class, testScope);
+      }
+
+      @SuppressWarnings("unused")
+      @CheckedProvides(RemoteProvider.class)
+      @TestScope.Scoped
+      Foo throwOrGet() throws RemoteException, BindException {
+        return mockRemoteProvider.get();
+      }
+    });
+
+    cxtorInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+          .bind(RemoteProvider.class, Foo.class)
+          .providing(MockFoo.class)
+          .in(testScope);
+      }
+    });
+  }

   public void testExceptionsThrown_Bind() throws Exception {
     tExceptionsThrown(bindInjector);
@@ -86,12 +121,17 @@
   public void testExceptionsThrown_Provides() throws Exception {
     tExceptionsThrown(providesInjector);
   }
+
+  public void testExceptionsThrown_Cxtor() throws Exception {
+    tExceptionsThrown(cxtorInjector);
+  }

   private void tExceptionsThrown(Injector injector) throws Exception {
-    RemoteProvider<String> remoteProvider =
-      injector.getInstance(Key.get(remoteProviderOfString));
+    RemoteProvider<Foo> remoteProvider =
+      injector.getInstance(Key.get(remoteProviderOfFoo));

     mockRemoteProvider.throwOnNextGet(new BindException("kaboom!"));
+    MockFoo.nextToThrow = new BindException("kaboom!");
     try {
       remoteProvider.get();
       fail();
@@ -109,17 +149,28 @@
   }

   private void tValuesScoped(Injector injector) throws Exception {
-    RemoteProvider<String> remoteProvider =
-      injector.getInstance(Key.get(remoteProviderOfString));
-
-    mockRemoteProvider.setNextToReturn("A");
-    assertEquals("A", remoteProvider.get());
-
-    mockRemoteProvider.setNextToReturn("B");
-    assertEquals("A", remoteProvider.get());
+    RemoteProvider<Foo> remoteProvider =
+      injector.getInstance(Key.get(remoteProviderOfFoo));
+
+    mockRemoteProvider.setNextToReturn(new SimpleFoo("A"));
+    assertEquals("A", remoteProvider.get().s());
+
+    mockRemoteProvider.setNextToReturn(new SimpleFoo("B"));
+    assertEquals("A", remoteProvider.get().s());

     testScope.beginNewScope();
-    assertEquals("B", remoteProvider.get());
+    assertEquals("B", remoteProvider.get().s());
+  }
+
+  public void testValuesScoped_Cxtor() throws Exception {
+    RemoteProvider<Foo> remoteProvider =
+        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));
+
+    Foo retrieved = remoteProvider.get();
+    assertSame(retrieved, remoteProvider.get()); // same, not in new scope.
+
+    testScope.beginNewScope();
+ assertNotSame(retrieved, remoteProvider.get()); // different, new scope.
   }

   public void testExceptionsScoped_Bind() throws Exception {
@@ -129,12 +180,17 @@
   public void testExceptionsScoped_Provides() throws Exception {
     tExceptionsScoped(providesInjector);
   }
+
+  public void testExceptionScopes_Cxtor() throws Exception {
+    tExceptionsScoped(cxtorInjector);
+  }

   private void tExceptionsScoped(Injector injector) throws Exception {
-    RemoteProvider<String> remoteProvider =
-        injector.getInstance(Key.get(remoteProviderOfString));
+    RemoteProvider<Foo> remoteProvider =
+        injector.getInstance(Key.get(remoteProviderOfFoo));

     mockRemoteProvider.throwOnNextGet(new RemoteException("A"));
+    MockFoo.nextToThrow = new RemoteException("A");
     try {
       remoteProvider.get();
       fail();
@@ -143,6 +199,7 @@
     }

     mockRemoteProvider.throwOnNextGet(new RemoteException("B"));
+    MockFoo.nextToThrow = new RemoteException("B");
     try {
       remoteProvider.get();
       fail();
@@ -152,17 +209,18 @@
   }

   public void testAnnotations_Bind() throws Exception {
- final MockRemoteProvider<String> mockRemoteProviderA = new MockRemoteProvider<String>(); - final MockRemoteProvider<String> mockRemoteProviderB = new MockRemoteProvider<String>(); + final MockRemoteProvider<Foo> mockRemoteProviderA = new MockRemoteProvider<Foo>(); + final MockRemoteProvider<Foo> mockRemoteProviderB = new MockRemoteProvider<Foo>();
     bindInjector = Guice.createInjector(new AbstractModule() {
+      @Override
       protected void configure() {
         ThrowingProviderBinder.create(binder())
-            .bind(RemoteProvider.class, String.class)
+            .bind(RemoteProvider.class, Foo.class)
             .annotatedWith(Names.named("a"))
             .to(mockRemoteProviderA);

         ThrowingProviderBinder.create(binder())
-            .bind(RemoteProvider.class, String.class)
+            .bind(RemoteProvider.class, Foo.class)
             .to(mockRemoteProviderB);
       }
     });
@@ -170,9 +228,10 @@
   }

   public void testAnnotations_Provides() throws Exception {
- final MockRemoteProvider<String> mockRemoteProviderA = new MockRemoteProvider<String>(); - final MockRemoteProvider<String> mockRemoteProviderB = new MockRemoteProvider<String>(); + final MockRemoteProvider<Foo> mockRemoteProviderA = new MockRemoteProvider<Foo>(); + final MockRemoteProvider<Foo> mockRemoteProviderB = new MockRemoteProvider<Foo>();
     providesInjector = Guice.createInjector(new AbstractModule() {
+      @Override
       protected void configure() {
         install(ThrowingProviderBinder.forModule(this));
        }
@@ -180,28 +239,51 @@
        @SuppressWarnings("unused")
        @CheckedProvides(RemoteProvider.class)
        @Named("a")
-       String throwOrGet() throws RemoteException, BindException {
+       Foo throwOrGet() throws RemoteException, BindException {
          return mockRemoteProviderA.get();
        }

        @SuppressWarnings("unused")
        @CheckedProvides(RemoteProvider.class)
-       String throwOrGet2() throws RemoteException, BindException {
+       Foo throwOrGet2() throws RemoteException, BindException {
          return mockRemoteProviderB.get();
        }
     });
tAnnotations(providesInjector, mockRemoteProviderA, mockRemoteProviderB);
   }

- private void tAnnotations(Injector injector, MockRemoteProvider<String> mockA,
-      MockRemoteProvider<String> mockB) throws Exception {
-    mockA.setNextToReturn("A");
-    mockB.setNextToReturn("B");
+ private void tAnnotations(Injector injector, MockRemoteProvider<Foo> mockA,
+      MockRemoteProvider<Foo> mockB) throws Exception {
+    mockA.setNextToReturn(new SimpleFoo("A"));
+    mockB.setNextToReturn(new SimpleFoo("B"));
     assertEquals("A",
- injector.getInstance(Key.get(remoteProviderOfString, Names.named("a"))).get()); + injector.getInstance(Key.get(remoteProviderOfFoo, Names.named("a"))).get().s());

     assertEquals("B",
-        injector.getInstance(Key.get(remoteProviderOfString)).get());
+        injector.getInstance(Key.get(remoteProviderOfFoo)).get().s());
+  }
+
+  public void testAnnotations_Cxtor() throws Exception {
+    cxtorInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, Foo.class)
+            .annotatedWith(Names.named("a"))
+            .providing(MockFoo.class);
+
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, Foo.class)
+            .providing(AnotherMockFoo.class);
+      }
+    });
+    MockFoo.nextToReturn = "A";
+    AnotherMockFoo.nextToReturn = "B";
+    assertEquals("A",
+ cxtorInjector.getInstance(Key.get(remoteProviderOfFoo, Names.named("a"))).get().s());
+
+    assertEquals("B",
+        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo)).get().s());
   }

   public void testUndeclaredExceptions_Bind() throws Exception {
@@ -211,11 +293,16 @@
   public void testUndeclaredExceptions_Provides() throws Exception {
     tUndeclaredExceptions(providesInjector);
   }
+
+  public void testUndeclaredExceptions_Cxtor() throws Exception {
+    tUndeclaredExceptions(cxtorInjector);
+  }

   private void tUndeclaredExceptions(Injector injector) throws Exception {
-    RemoteProvider<String> remoteProvider =
-        injector.getInstance(Key.get(remoteProviderOfString));
+    RemoteProvider<Foo> remoteProvider =
+        injector.getInstance(Key.get(remoteProviderOfFoo));
     mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("A"));
+    MockFoo.nextToThrow = new IndexOutOfBoundsException("A");
     try {
       remoteProvider.get();
       fail();
@@ -225,6 +312,7 @@

     // undeclared exceptions shouldn't be scoped
     mockRemoteProvider.throwOnNextGet(new IndexOutOfBoundsException("B"));
+    MockFoo.nextToThrow = new IndexOutOfBoundsException("B");
     try {
       remoteProvider.get();
       fail();
@@ -235,28 +323,30 @@

   public void testThrowingProviderSubclassing() throws Exception {
     final SubMockRemoteProvider aProvider = new SubMockRemoteProvider();
-    aProvider.setNextToReturn("A");
+    aProvider.setNextToReturn(new SimpleFoo("A"));

     bindInjector = Guice.createInjector(new AbstractModule() {
+      @Override
       protected void configure() {
         ThrowingProviderBinder.create(binder())
-            .bind(RemoteProvider.class, String.class)
+            .bind(RemoteProvider.class, Foo.class)
             .to(aProvider);
       }
     });

     assertEquals("A",
-        bindInjector.getInstance(Key.get(remoteProviderOfString)).get());
+        bindInjector.getInstance(Key.get(remoteProviderOfFoo)).get().s());
   }

-  static class SubMockRemoteProvider extends MockRemoteProvider<String> { }
+  static class SubMockRemoteProvider extends MockRemoteProvider<Foo> { }

   public void testBindingToNonInterfaceType_Bind() throws Exception {
     try {
       Guice.createInjector(new AbstractModule() {
+        @Override
         protected void configure() {
           ThrowingProviderBinder.create(binder())
-              .bind(MockRemoteProvider.class, String.class)
+              .bind(MockRemoteProvider.class, Foo.class)
               .to(mockRemoteProvider);
         }
       });
@@ -270,13 +360,14 @@
   public void testBindingToNonInterfaceType_Provides() throws Exception {
     try {
       Guice.createInjector(new AbstractModule() {
+        @Override
         protected void configure() {
           install(ThrowingProviderBinder.forModule(this));
         }

         @SuppressWarnings("unused")
         @CheckedProvides(MockRemoteProvider.class)
-        String foo() {
+        Foo foo() {
           return null;
         }
       });
@@ -290,9 +381,10 @@
   public void testBindingToSubSubInterface_Bind() throws Exception {
     try {
       bindInjector = Guice.createInjector(new AbstractModule() {
+        @Override
         protected void configure() {
           ThrowingProviderBinder.create(binder())
-              .bind(SubRemoteProvider.class, String.class);
+              .bind(SubRemoteProvider.class, Foo.class);
         }
       });
       fail();
@@ -305,13 +397,14 @@
   public void testBindingToSubSubInterface_Provides() throws Exception {
     try {
       Guice.createInjector(new AbstractModule() {
+        @Override
         protected void configure() {
           install(ThrowingProviderBinder.forModule(this));
         }

         @SuppressWarnings("unused")
         @CheckedProvides(SubRemoteProvider.class)
-        String foo() {
+        Foo foo() {
           return null;
         }
       });
@@ -327,9 +420,10 @@
public void testBindingToInterfaceWithExtraMethod_Bind() throws Exception {
     try {
       bindInjector = Guice.createInjector(new AbstractModule() {
+        @Override
         protected void configure() {
           ThrowingProviderBinder.create(binder())
-              .bind(RemoteProviderWithExtraMethod.class, String.class);
+              .bind(RemoteProviderWithExtraMethod.class, Foo.class);
         }
       });
       fail();
@@ -343,13 +437,14 @@
public void testBindingToInterfaceWithExtraMethod_Provides() throws Exception {
     try {
       Guice.createInjector(new AbstractModule() {
+        @Override
         protected void configure() {
           install(ThrowingProviderBinder.forModule(this));
         }

         @SuppressWarnings("unused")
         @CheckedProvides(RemoteProviderWithExtraMethod.class)
-        String foo() {
+        Foo foo() {
           return null;
         }
       });
@@ -363,19 +458,20 @@

   public void testDependencies_Bind() {
     bindInjector = Guice.createInjector(new AbstractModule() {
+      @Override
       protected void configure() {
         bind(String.class).toInstance("Foo");
         bind(Integer.class).toInstance(5);
         bind(Double.class).toInstance(5d);
         bind(Long.class).toInstance(5L);
         ThrowingProviderBinder.create(binder())
-            .bind(RemoteProvider.class, String.class)
+            .bind(RemoteProvider.class, Foo.class)
             .to(DependentRemoteProvider.class);
       }
     });

     HasDependencies hasDependencies =
- (HasDependencies)bindInjector.getBinding(Key.get(remoteProviderOfString)); + (HasDependencies)bindInjector.getBinding(Key.get(remoteProviderOfFoo));
     hasDependencies =
         (HasDependencies)bindInjector.getBinding(
Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
@@ -385,18 +481,14 @@
     // And make sure DependentRemoteProvider has the proper dependencies.
hasDependencies = (HasDependencies)bindInjector.getBinding(DependentRemoteProvider.class);
     Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
-        Iterables.transform(hasDependencies.getDependencies(),
-          new Function<Dependency<?>, Key<?>>() {
-            public Key<?> apply(Dependency<?> from) {
-              return from.getKey();
-            }
-          }));
+ Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY)); assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
         Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
   }

   public void testDependencies_Provides() {
     providesInjector = Guice.createInjector(new AbstractModule() {
+      @Override
       protected void configure() {
         bind(String.class).toInstance("Foo");
         bind(Integer.class).toInstance(5);
@@ -407,30 +499,63 @@

       @SuppressWarnings("unused")
       @CheckedProvides(RemoteProvider.class)
-      String foo(String s, Integer i, Double d, Long l) {
+      Foo foo(String s, Integer i, Double d, Long l) {
         return null;
       }
     });

     HasDependencies hasDependencies =
- (HasDependencies)providesInjector.getBinding(Key.get(remoteProviderOfString)); + (HasDependencies) providesInjector.getBinding(Key.get(remoteProviderOfFoo));
     // RemoteProvider<String> is dependent on the provider method..
-    hasDependencies =
-        (HasDependencies)providesInjector.getBinding(
- Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
+    hasDependencies = (HasDependencies) providesInjector.getBinding(
+ Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
     // And the provider method has our real dependencies..
     hasDependencies = (HasDependencies)providesInjector.getBinding(
Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey());
     Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
-        Iterables.transform(hasDependencies.getDependencies(),
-          new Function<Dependency<?>, Key<?>>() {
-            public Key<?> apply(Dependency<?> from) {
-              return from.getKey();
-            }
-          }));
+ Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY)); assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
         Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
   }
+
+  public void testDependencies_Cxtor() {
+    cxtorInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        bind(String.class).toInstance("Foo");
+        bind(Integer.class).toInstance(5);
+        bind(Double.class).toInstance(5d);
+        bind(Long.class).toInstance(5L);
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, Foo.class)
+            .providing(DependentMockFoo.class);
+      }
+    });
+
+    Key<?> key = Key.get(remoteProviderOfFoo);
+
+    // RemoteProvider<String> is dependent on Result.
+ HasDependencies hasDependencies = (HasDependencies) cxtorInjector.getBinding(key); + key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey();
+    assertEquals(Result.class, key.getTypeLiteral().getRawType());
+
+    // Result is dependent on the fake CheckedProvider impl
+    hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
+ key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey(); + assertTrue(CheckedProvider.class.isAssignableFrom(key.getTypeLiteral().getRawType()));
+
+    // And the CheckedProvider is dependent on DependentMockFoo...
+    hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
+ key = Iterables.getOnlyElement(hasDependencies.getDependencies()).getKey(); + assertEquals(DependentMockFoo.class, key.getTypeLiteral().getRawType());
+
+    // And DependentMockFoo is dependent on the goods.
+    hasDependencies = (HasDependencies) cxtorInjector.getBinding(key);
+    Set<Key<?>> dependencyKeys = ImmutableSet.copyOf(
+ Iterables.transform(hasDependencies.getDependencies(), DEPENDENCY_TO_KEY)); + assertEquals(ImmutableSet.<Key<?>>of(Key.get(String.class), Key.get(Integer.class),
+        Key.get(Long.class), Key.get(Double.class)), dependencyKeys);
+  }

   interface RemoteProviderWithExtraMethod<T> extends CheckedProvider<T> {
     T get(T defaultValue) throws RemoteException, BindException;
@@ -439,6 +564,20 @@
   interface RemoteProvider<T> extends CheckedProvider<T> {
     public T get() throws RemoteException, BindException;
   }
+
+  static class DependentMockFoo implements Foo {
+    @Inject double foo;
+
+    @Inject public DependentMockFoo(String foo, int bar) {
+    }
+
+    @Inject void initialize(long foo) {}
+
+    @Override
+    public String s() {
+      return null;
+    }
+  }

   static class DependentRemoteProvider<T> implements RemoteProvider<T> {
     @Inject double foo;
@@ -448,10 +587,90 @@

     @Inject void initialize(long foo) {}

-    public T get() throws RemoteException {
+    public T get() {
       return null;
     }
   }
+
+  interface Foo {
+    String s();
+  }
+
+  static class SimpleFoo implements Foo {
+    private String s;
+
+    SimpleFoo(String s) {
+      this.s = s;
+    }
+
+    @Override
+    public String s() {
+      return s;
+    }
+
+    @Override
+    public String toString() {
+      return s;
+    }
+  }
+
+  static class MockFoo implements Foo {
+    static Exception nextToThrow;
+    static String nextToReturn;
+
+    MockFoo() throws RemoteException, BindException {
+      if (nextToThrow instanceof RemoteException) {
+        throw (RemoteException) nextToThrow;
+      } else if (nextToThrow instanceof BindException) {
+        throw (BindException) nextToThrow;
+      } else if (nextToThrow instanceof RuntimeException) {
+        throw (RuntimeException) nextToThrow;
+      } else if (nextToThrow == null) {
+        // Do nothing, return this.
+      } else {
+ throw new AssertionError("nextToThrow must be a runtime or remote exception");
+      }
+    }
+
+    @Override
+    public String s() {
+      return nextToReturn;
+    }
+
+    @Override
+    public String toString() {
+      return nextToReturn;
+    }
+  }
+
+  static class AnotherMockFoo implements Foo {
+    static Exception nextToThrow;
+    static String nextToReturn;
+
+    AnotherMockFoo() throws RemoteException, BindException {
+      if (nextToThrow instanceof RemoteException) {
+        throw (RemoteException) nextToThrow;
+      } else if (nextToThrow instanceof BindException) {
+        throw (BindException) nextToThrow;
+      } else if (nextToThrow instanceof RuntimeException) {
+        throw (RuntimeException) nextToThrow;
+      } else if (nextToThrow == null) {
+        // Do nothing, return this.
+      } else {
+ throw new AssertionError("nextToThrow must be a runtime or remote exception");
+      }
+    }
+
+    @Override
+    public String s() {
+      return nextToReturn;
+    }
+
+    @Override
+    public String toString() {
+      return nextToReturn;
+    }
+  }

   static class MockRemoteProvider<T> implements RemoteProvider<T> {
     Exception nextToThrow;
@@ -482,11 +701,12 @@

public void testBindingToInterfaceWithBoundValueType_Bind() throws RemoteException {
     bindInjector = Guice.createInjector(new AbstractModule() {
+      @Override
       protected void configure() {
         ThrowingProviderBinder.create(binder())
             .bind(StringRemoteProvider.class, String.class)
             .to(new StringRemoteProvider() {
-              public String get() throws RemoteException {
+              public String get() {
                 return "A";
               }
             });
@@ -498,6 +718,7 @@

public void testBindingToInterfaceWithBoundValueType_Provides() throws RemoteException {
     providesInjector = Guice.createInjector(new AbstractModule() {
+      @Override
       protected void configure() {
         install(ThrowingProviderBinder.forModule(this));
       }
@@ -516,19 +737,40 @@
     String get() throws RemoteException;
   }

+  @SuppressWarnings("deprecation")
   public void testBindingToInterfaceWithGeneric_Bind() throws Exception {
     bindInjector = Guice.createInjector(new AbstractModule() {
+      @Override
       protected void configure() {
         ThrowingProviderBinder.create(binder())
.bind(RemoteProvider.class, new TypeLiteral<List<String>>() { }.getType())
             .to(new RemoteProvider<List<String>>() {
-              public List<String> get() throws RemoteException {
+              public List<String> get() {
                 return Arrays.asList("A", "B");
               }
             });
       }
     });

+    Key<RemoteProvider<List<String>>> key
+        = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
+ assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get());
+  }
+
+ public void testBindingToInterfaceWithGeneric_BindUsingTypeLiteral() throws Exception {
+    bindInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, new TypeLiteral<List<String>>() {})
+            .to(new RemoteProvider<List<String>>() {
+              public List<String> get() {
+                return Arrays.asList("A", "B");
+              }
+            });
+      }
+    });
+
     Key<RemoteProvider<List<String>>> key
         = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
assertEquals(Arrays.asList("A", "B"), bindInjector.getInstance(key).get());
@@ -536,6 +778,7 @@

public void testBindingToInterfaceWithGeneric_Provides() throws Exception {
     providesInjector = Guice.createInjector(new AbstractModule() {
+      @Override
       protected void configure() {
         install(ThrowingProviderBinder.forModule(this));
       }
@@ -551,10 +794,26 @@
         = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
assertEquals(Arrays.asList("A", "B"), providesInjector.getInstance(key).get());
   }
+
+  public void testBindingToInterfaceWithGeneric_Cxtor() throws Exception {
+    cxtorInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+        .bind(RemoteProvider.class, new TypeLiteral<List<String>>() {})
+        .providing(new TypeLiteral<ArrayList<String>>() {});
+      }
+    });
+
+    Key<RemoteProvider<List<String>>> key
+        = Key.get(new TypeLiteral<RemoteProvider<List<String>>>() { });
+    assertEquals(Arrays.asList(), cxtorInjector.getInstance(key).get());
+  }

   public void testProviderMethodWithWrongException() {
     try {
       Guice.createInjector(new AbstractModule() {
+        @Override
         protected void configure() {
           install(ThrowingProviderBinder.forModule(this));
         }
@@ -576,22 +835,54 @@
           Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
     }
   }
+
+  public void testCxtorWithWrongException() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(RemoteProvider.class, Foo.class)
+              .providing(WrongExceptionFoo.class);
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(InterruptedException.class.getName()
+          + " is not compatible with the exceptions (["
+          + RemoteException.class + ", " + BindException.class
+          + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName()
+          + ")",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+
+  static class WrongExceptionFoo implements Foo {
+    @SuppressWarnings("unused")
+    public WrongExceptionFoo() throws InterruptedException {
+    }
+
+    @Override
+    public String s() { return null; }
+  }

public void testProviderMethodWithSubclassOfExceptionIsOk() throws Exception {
     providesInjector = Guice.createInjector(new AbstractModule() {
+      @Override
       protected void configure() {
         install(ThrowingProviderBinder.forModule(this));
       }

       @SuppressWarnings("unused")
       @CheckedProvides(RemoteProvider.class)
-      String foo() throws AccessException {
+      Foo foo() throws AccessException {
         throw new AccessException("boo!");
       }
     });

-    RemoteProvider<String> remoteProvider =
-      providesInjector.getInstance(Key.get(remoteProviderOfString));
+    RemoteProvider<Foo> remoteProvider =
+      providesInjector.getInstance(Key.get(remoteProviderOfFoo));

     try {
       remoteProvider.get();
@@ -602,16 +893,48 @@
     }
   }

-  public void testProviderMethodWithSuperclassFails() {
+  public void testCxtorWithSubclassOfExceptionIsOk() throws Exception {
+    cxtorInjector = Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(RemoteProvider.class, Foo.class)
+              .providing(SubclassExceptionFoo.class);
+        }
+      });
+
+    RemoteProvider<Foo> remoteProvider =
+        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));
+
+      try {
+        remoteProvider.get();
+        fail();
+      } catch (RemoteException expected) {
+        assertTrue(expected instanceof AccessException);
+        assertEquals("boo!", expected.getMessage());
+      }
+  }
+
+  static class SubclassExceptionFoo implements Foo {
+    public SubclassExceptionFoo() throws AccessException {
+      throw new AccessException("boo!");
+    }
+
+    @Override
+    public String s() { return null; }
+  }
+
+  public void testProviderMethodWithSuperclassExceptionFails() {
     try {
       Guice.createInjector(new AbstractModule() {
+        @Override
         protected void configure() {
           install(ThrowingProviderBinder.forModule(this));
         }

         @SuppressWarnings("unused")
         @CheckedProvides(RemoteProvider.class)
-        String foo() throws IOException {
+        Foo foo() throws IOException {
             return null;
         }
       });
@@ -626,22 +949,54 @@
           Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
     }
   }
+
+  public void testCxtorWithSuperclassExceptionFails() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(RemoteProvider.class, Foo.class)
+              .providing(SuperclassExceptionFoo.class);
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+      assertEquals(IOException.class.getName()
+          + " is not compatible with the exceptions (["
+          + RemoteException.class + ", " + BindException.class
+          + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName()
+          + ")",
+          Iterables.getOnlyElement(ce.getErrorMessages()).getMessage());
+    }
+  }
+
+  static class SuperclassExceptionFoo implements Foo {
+    @SuppressWarnings("unused")
+    public SuperclassExceptionFoo() throws IOException {
+    }
+
+    @Override
+    public String s() { return null; }
+  }

public void testProviderMethodWithRuntimeExceptionsIsOk() throws Exception {
     providesInjector = Guice.createInjector(new AbstractModule() {
+      @Override
       protected void configure() {
         install(ThrowingProviderBinder.forModule(this));
       }

       @SuppressWarnings("unused")
       @CheckedProvides(RemoteProvider.class)
-      String foo() throws RuntimeException {
+      Foo foo() throws RuntimeException {
         throw new RuntimeException("boo!");
       }
     });

-    RemoteProvider<String> remoteProvider =
-      providesInjector.getInstance(Key.get(remoteProviderOfString));
+    RemoteProvider<Foo> remoteProvider =
+      providesInjector.getInstance(Key.get(remoteProviderOfFoo));

     try {
       remoteProvider.get();
@@ -650,12 +1005,43 @@
       assertEquals("boo!", expected.getCause().getMessage());
     }
   }
+
+  public void testCxtorWithRuntimeExceptionsIsOk() throws Exception {
+    cxtorInjector = Guice.createInjector(new AbstractModule() {
+      @Override
+      protected void configure() {
+        ThrowingProviderBinder.create(binder())
+            .bind(RemoteProvider.class, Foo.class)
+            .providing(RuntimeExceptionFoo.class);
+      }
+    });
+
+    RemoteProvider<Foo> remoteProvider =
+        cxtorInjector.getInstance(Key.get(remoteProviderOfFoo));
+
+    try {
+      remoteProvider.get();
+      fail();
+    } catch (RuntimeException expected) {
+      assertEquals("boo!", expected.getCause().getMessage());
+    }
+  }
+
+  static class RuntimeExceptionFoo implements Foo {
+    public RuntimeExceptionFoo() throws RuntimeException {
+      throw new RuntimeException("boo!");
+    }
+
+    @Override
+    public String s() { return null; }
+  }

   private static class SubBindException extends BindException {}

   public void testProviderMethodWithManyExceptions() {
     try {
       Guice.createInjector(new AbstractModule() {
+        @Override
         protected void configure() {
           install(ThrowingProviderBinder.forModule(this));
         }
@@ -689,10 +1075,59 @@
       assertEquals(2, errors.size());
     }
   }
+
+  public void testCxtorWithManyExceptions() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override
+        protected void configure() {
+          ThrowingProviderBinder.create(binder())
+              .bind(RemoteProvider.class, Foo.class)
+              .providing(ManyExceptionFoo.class);
+        }
+      });
+      fail();
+    } catch (CreationException ce) {
+ // The only two that should fail are Interrupted & TooManyListeners.. the rest are OK.
+      List<Message> errors = ImmutableList.copyOf(ce.getErrorMessages());
+      assertEquals(InterruptedException.class.getName()
+          + " is not compatible with the exceptions (["
+          + RemoteException.class + ", " + BindException.class
+          + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName()
+          + ")",
+          errors.get(0).getMessage());
+      assertEquals(TooManyListenersException.class.getName()
+          + " is not compatible with the exceptions (["
+          + RemoteException.class + ", " + BindException.class
+          + "]) declared in the CheckedProvider interface ("
+          + RemoteProvider.class.getName()
+          + ")",
+          errors.get(1).getMessage());
+      assertEquals(2, errors.size());
+    }
+  }
+
+  static class ManyExceptionFoo implements Foo {
***The diff for this file has been truncated for email.***

--
You received this message because you are subscribed to the Google Groups 
"google-guice-dev" group.
To post to this group, send email to [email protected].
To unsubscribe from this group, send email to 
[email protected].
For more options, visit this group at 
http://groups.google.com/group/google-guice-dev?hl=en.

Reply via email to