More testcases for multibindings, including some fairly specific tests for toString() on the Binder API

git-svn-id: https://google-guice.googlecode.com/svn/trunk@483 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java b/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java
index e8af001..885260b 100644
--- a/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java
+++ b/extensions/multibindings/src/com/google/inject/multibindings/MapBinder.java
@@ -21,6 +21,7 @@
 import com.google.inject.internal.Objects;
 import com.google.inject.internal.TypeWithArgument;
 import com.google.inject.multibindings.Multibinder.RealMultibinder;
+import com.google.inject.spi.SourceProviders;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
@@ -88,6 +89,9 @@
  */
 public abstract class MapBinder<K, V> {
   private MapBinder() {}
+  static {
+    SourceProviders.skip(RealMapBinder.class);
+  }
 
   /**
    * Returns a new mapbinder that collects entries of {@code keyType}/{@code 
diff --git a/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java b/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java
index 8a414a3..347ce91 100644
--- a/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java
+++ b/extensions/multibindings/src/com/google/inject/multibindings/Multibinder.java
@@ -20,6 +20,7 @@
 import com.google.inject.binder.LinkedBindingBuilder;
 import static com.google.inject.internal.Objects.nonNull;
 import com.google.inject.internal.TypeWithArgument;
+import com.google.inject.spi.SourceProviders;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Type;
@@ -71,6 +72,9 @@
  */
 public abstract class Multibinder<T> {
   private Multibinder() {}
+  static {
+    SourceProviders.skip(RealMultibinder.class);
+  }
 
   /**
    * Returns a new multibinder that collects instances of {@code type} in a
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java b/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java
index 526f192..ec5ff16 100644
--- a/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java
+++ b/extensions/multibindings/test/com/google/inject/multibindings/MapBinderTest.java
@@ -266,6 +266,21 @@
     assertEquals(1, (int) injector.getInstance(Key.get(mapOfInteger)).get("one"));
   }
 
+  public void testSourceLinesInMapBindings() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          MapBinder.newMapBinder(binder(), String.class, Integer.class)
+              .addBinding("one");
+        }
+      });
+      fail();
+    } catch (CreationException e) {
+      assertTrue(e.getMessage().contains("Error at " + getClass().getName()));
+      assertTrue(e.getMessage().contains("No implementation was specified."));
+    }
+  }
+
   @Retention(RUNTIME) @BindingAnnotation
   @interface Abc {}
 
diff --git a/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java b/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
index bd5d77a..180f83f 100644
--- a/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
+++ b/extensions/multibindings/test/com/google/inject/multibindings/MultibinderTest.java
@@ -232,6 +232,20 @@
     }
   }
 
+  public void testSourceLinesInMultibindings() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override protected void configure() {
+          Multibinder.newSetBinder(binder(), Integer.class).addBinding();
+        }
+      });
+      fail();
+    } catch (CreationException e) {
+      assertTrue(e.getMessage().contains("Error at " + getClass().getName()));
+      assertTrue(e.getMessage().contains("No implementation was specified."));
+    }
+  }
+
   @Retention(RUNTIME) @BindingAnnotation
   @interface Abc {}
 
diff --git a/src/com/google/inject/BindCommandProcessor.java b/src/com/google/inject/BindCommandProcessor.java
index 59db4b9..008f6c8 100644
--- a/src/com/google/inject/BindCommandProcessor.java
+++ b/src/com/google/inject/BindCommandProcessor.java
@@ -209,11 +209,13 @@
   }
 
   @Override public Boolean visitBindConstant(BindConstantCommand command) {
-    Object value = command.getTarget().get();
-    if (value == null) {
+    BindTarget<?> target = command.getTarget();
+    if (target == null) {
       addError(command.getSource(), ErrorMessages.MISSING_CONSTANT_VALUE);
+      return true;
     }
 
+    Object value = target.get();
     validateKey(command.getSource(), command.getKey());
     ConstantFactory<Object> factory = new ConstantFactory<Object>(value);
     putBinding(new ConstantBindingImpl<Object>(
diff --git a/src/com/google/inject/commands/BindCommand.java b/src/com/google/inject/commands/BindCommand.java
index 0b21ed6..83ae5c6 100644
--- a/src/com/google/inject/commands/BindCommand.java
+++ b/src/com/google/inject/commands/BindCommand.java
@@ -17,13 +17,13 @@
 package com.google.inject.commands;
 
 import com.google.inject.*;
-import com.google.inject.spi.SourceProviders;
 import com.google.inject.binder.AnnotatedBindingBuilder;
 import com.google.inject.binder.ConstantBindingBuilder;
 import com.google.inject.binder.LinkedBindingBuilder;
 import com.google.inject.binder.ScopedBindingBuilder;
-import static com.google.inject.internal.Objects.nonNull;
 import com.google.inject.internal.ErrorMessages;
+import static com.google.inject.internal.Objects.nonNull;
+import com.google.inject.spi.SourceProviders;
 
 import java.lang.annotation.Annotation;
 
@@ -337,5 +337,12 @@
         binder.addError(SCOPE_ALREADY_SET);
       }
     }
+
+    @Override public String toString() {
+      String type = key.getAnnotationType() == null
+          ? "AnnotatedBindingBuilder<"
+          : "LinkedBindingBuilder<";
+      return type + key.getTypeLiteral() + ">";
+    }
   }
 }
diff --git a/src/com/google/inject/commands/BindConstantCommand.java b/src/com/google/inject/commands/BindConstantCommand.java
index af131ec..50d155a 100644
--- a/src/com/google/inject/commands/BindConstantCommand.java
+++ b/src/com/google/inject/commands/BindConstantCommand.java
@@ -16,16 +16,16 @@
 
 package com.google.inject.commands;
 
+import com.google.inject.Binder;
 import com.google.inject.Key;
 import com.google.inject.Provider;
-import com.google.inject.Binder;
-import com.google.inject.spi.SourceProviders;
 import com.google.inject.binder.AnnotatedConstantBindingBuilder;
 import com.google.inject.binder.ConstantBindingBuilder;
 import com.google.inject.binder.LinkedBindingBuilder;
 import com.google.inject.binder.ScopedBindingBuilder;
 import com.google.inject.internal.Objects;
 import static com.google.inject.internal.Objects.nonNull;
+import com.google.inject.spi.SourceProviders;
 
 import java.lang.annotation.Annotation;
 
@@ -358,5 +358,11 @@
         binder.addError(CONSTANT_VALUE_ALREADY_SET);
       }
     }
+
+    @Override public String toString() {
+      return bindingAnnotation == null
+          ? "AnnotatedConstantBindingBuilder"
+          : "ConstantBindingBuilder";
+    }
   }
 }
diff --git a/src/com/google/inject/commands/CommandRecorder.java b/src/com/google/inject/commands/CommandRecorder.java
index e6ce8f2..a4b3307 100644
--- a/src/com/google/inject/commands/CommandRecorder.java
+++ b/src/com/google/inject/commands/CommandRecorder.java
@@ -20,9 +20,9 @@
 import com.google.inject.binder.AnnotatedBindingBuilder;
 import com.google.inject.binder.AnnotatedConstantBindingBuilder;
 import com.google.inject.matcher.Matcher;
+import com.google.inject.spi.SourceProviders;
 import static com.google.inject.spi.SourceProviders.defaultSource;
 import com.google.inject.spi.TypeConverter;
-import com.google.inject.spi.SourceProviders;
 import org.aopalliance.intercept.MethodInterceptor;
 
 import java.lang.annotation.Annotation;
@@ -141,6 +141,10 @@
         public T get() {
           return earlyRequestsProvider.get(key);
         }
+
+        @Override public String toString() {
+          return "Provider<" + key.getTypeLiteral() + ">";
+        }
       };
     }
 
@@ -152,5 +156,9 @@
         TypeConverter converter) {
       commands.add(new ConvertToTypesCommand(defaultSource(), typeMatcher, converter));
     }
+
+    @Override public String toString() {
+      return "Binder";
+    }
   }
 }
diff --git a/test/com/google/inject/BinderTest.java b/test/com/google/inject/BinderTest.java
index b471114..8d59509 100644
--- a/test/com/google/inject/BinderTest.java
+++ b/test/com/google/inject/BinderTest.java
@@ -16,8 +16,11 @@
 
 package com.google.inject;
 
+import com.google.inject.name.Names;
 import junit.framework.TestCase;
 
+import java.util.List;
+
 /**
  * @author crazybob@google.com (Bob Lee)
  */
@@ -54,6 +57,42 @@
     }
   }
 
+  public void testDanglingConstantBinding() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override public void configure() {
+          bindConstant();
+        }
+      });
+      fail();
+    } catch (CreationException e) {
+      assertTrue(e.getMessage().contains("Missing constant value."));
+    }
+  }
+
+  public void testToStringOnBinderApi() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        @Override public void configure() {
+          assertEquals("Binder", binder().toString());
+          assertEquals("Provider<java.lang.Integer>", getProvider(Integer.class).toString());
+          assertEquals("Provider<java.util.List<java.lang.String>>",
+              getProvider(Key.get(new TypeLiteral<List<String>>() {})).toString());
+
+          assertEquals("AnnotatedBindingBuilder<java.lang.Integer>",
+              bind(Integer.class).toString());
+          assertEquals("LinkedBindingBuilder<java.lang.Integer>",
+              bind(Integer.class).annotatedWith(Names.named("a")).toString());
+          assertEquals("AnnotatedConstantBindingBuilder", bindConstant().toString());
+          assertEquals("ConstantBindingBuilder",
+              bindConstant().annotatedWith(Names.named("b")).toString());
+        }
+      });
+      fail();
+    } catch (CreationException ignored) {
+    }
+  }
+
 //  public void testBindInterfaceWithoutImplementation() {
 //    Guice.createInjector(new AbstractModule() {
 //      protected void configure() {