Exposes ElementSource at getSource() methods.
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=50645247
diff --git a/core/src/com/google/inject/internal/BindingImpl.java b/core/src/com/google/inject/internal/BindingImpl.java
index a891e9d..7319dd6 100644
--- a/core/src/com/google/inject/internal/BindingImpl.java
+++ b/core/src/com/google/inject/internal/BindingImpl.java
@@ -21,7 +21,6 @@
 import com.google.inject.Key;
 import com.google.inject.Provider;
 import com.google.inject.spi.BindingScopingVisitor;
-import com.google.inject.spi.ElementSource;
 import com.google.inject.spi.ElementVisitor;
 import com.google.inject.spi.InstanceBinding;
 
@@ -58,9 +57,6 @@
   }
 
   public Object getSource() {
-    if (source instanceof ElementSource) {
-      return ((ElementSource) source).getDeclaringSource();
-    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/internal/PrivateElementsImpl.java b/core/src/com/google/inject/internal/PrivateElementsImpl.java
index bb7eeab..6a3d915 100644
--- a/core/src/com/google/inject/internal/PrivateElementsImpl.java
+++ b/core/src/com/google/inject/internal/PrivateElementsImpl.java
@@ -30,7 +30,6 @@
 import com.google.inject.Key;
 import com.google.inject.PrivateBinder;
 import com.google.inject.spi.Element;
-import com.google.inject.spi.ElementSource;
 import com.google.inject.spi.ElementVisitor;
 import com.google.inject.spi.PrivateElements;
 
@@ -66,9 +65,6 @@
   }
 
   public Object getSource() {
-    if (source instanceof ElementSource) {
-      return ((ElementSource) source).getDeclaringSource();
-    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/DisableCircularProxiesOption.java b/core/src/com/google/inject/spi/DisableCircularProxiesOption.java
index 633d204..4193e0a 100644
--- a/core/src/com/google/inject/spi/DisableCircularProxiesOption.java
+++ b/core/src/com/google/inject/spi/DisableCircularProxiesOption.java
@@ -34,9 +34,6 @@
   }
 
   public Object getSource() {
-    if (source instanceof ElementSource) {
-      return ((ElementSource) source).getDeclaringSource();
-    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/ElementSource.java b/core/src/com/google/inject/spi/ElementSource.java
index fff4400..cfe7bb9 100644
--- a/core/src/com/google/inject/spi/ElementSource.java
+++ b/core/src/com/google/inject/spi/ElementSource.java
@@ -14,14 +14,18 @@
  * defines the Guice {@link Element element}. For example, if the element is created from a method
  * annotated by {@literal @Provides}, the declaring source of element would be the method itself. 
  * <p>
- * The creation call stack is the sequence of calls ends at one of {@link Binder} {@code bindXXX()} 
- * methods and eventually defines the element. Note that {@link #getStackTrace()} lists {@link 
- * StackTraceElement StackTraceElements} in reverse chronological order. The first element (index 
- * zero) is the last method call and the last element is the first method invocation.
+ * The {@link #getStackTrace()} refers to the sequence of calls ends at one of {@link Binder} 
+ * {@code bindXXX()} methods and eventually defines the element. Note that {@link #getStackTrace()} 
+ * lists {@link StackTraceElement StackTraceElements} in reverse chronological order. The first 
+ * element (index zero) is the last method call and the last element is the first method invocation.
+ * By default, the stack trace is not collected. The default behavior can be changed by setting the 
+ * {@code guice_include_stack_traces} flag value. The value can be either {@code DEFAULT} or 
+ * {@code COMPLETE}. Note that collecting stack traces for every binding can cause a performance hit
+ * when the injector is created.
  * <p>
  * The sequence of class names of {@link Module modules} involved in the element creation can be 
- * retrieved by {@link #getModuleClassNames()}. Similar to the call stack, the order is reverse 
- * chronological. The first module (index 0) is the module that installs the {@link Element 
+ * retrieved by {@link #getModuleClassNames()}. Similar to {@link #getStackTrace()}, the order is 
+ * reverse chronological. The first module (index 0) is the module that installs the {@link Element 
  * element}. The last module is the root module.
  * <p>
  * In order to support the cases where a Guice {@link Element element} is created from another
@@ -125,18 +129,24 @@
    *  4 - theRest(). 
    * }
    * <p>
-   * 1 and 3 are returned.   
+   * 1 and 3 are returned.
+   * <p>
+   * In the cases where stack trace is not available (i.e.,the stack trace was not collected), 
+   * it returns an empty array.
    */
   public List<Integer> getModuleConfigurePositionsInStackTrace() {
+    if (!isStackTraceRetained()) {
+      return ImmutableList.<Integer>of();
+    }
     int size = moduleSource.size();
     Integer[] positions = new Integer[size];
     int position = partialCallStack.length;
-    positions[0] = position;
+    positions[0] = position - 1;
     ModuleSource current = moduleSource;
     int cursor = 1;
     while (cursor < size) {
       position += current.getPartialCallStack().length;
-      positions[cursor] = position;
+      positions[cursor] = position - 1;
       current = current.getParent();
       cursor++;
     }
@@ -147,7 +157,9 @@
    * Returns the sequence of method calls that ends at one of {@link Binder} {@code bindXXX()} 
    * methods and eventually defines the element. Note that {@link #getStackTrace()} lists {@link 
    * StackTraceElement StackTraceElements} in reverse chronological order. The first element (index 
-   * zero) is the last method call and the last element is the first method invocation.
+   * zero) is the last method call and the last element is the first method invocation. In the cases
+   * where stack trace is not available (i.e.,the stack trace was not collected), it returns an 
+   * empty array.
    */
   public StackTraceElement[] getStackTrace() {
     int modulesCallStackSize = moduleSource.getStackTraceSize();
@@ -162,6 +174,13 @@
   }
   
   /**
+   * Returns true if stack trace was collected.
+   */ 
+  public boolean isStackTraceRetained() {
+    return (partialCallStack.length > 0);
+  }
+
+  /**
    * Returns {@code getDeclaringSource().toString()} value.
    */
   @Override
diff --git a/core/src/com/google/inject/spi/Elements.java b/core/src/com/google/inject/spi/Elements.java
index 65cfc28..03887d9 100644
--- a/core/src/com/google/inject/spi/Elements.java
+++ b/core/src/com/google/inject/spi/Elements.java
@@ -72,10 +72,6 @@
     COMPLETE
   }
 
-  // Use "-Dguice_include_stack_traces={DEFAULT,COMPLETE}" to specify
-  // how guice should collect stack trace data.
-  private static final String guice_include_stack_traces_property =
-       System.getProperty("guice_include_stack_traces", "DEFAULT");
 
   private static final BindingTargetVisitor<Object, Object> GET_INSTANCE_VISITOR
       = new DefaultBindingTargetVisitor<Object, Object>() {
@@ -143,10 +139,9 @@
     return (BindingTargetVisitor<T, T>) GET_INSTANCE_VISITOR;
   }
 
-
   private static boolean collectCompleteStackTrace() {
     return IncludeStackTraceFlagValues.COMPLETE.name().equals(
-        guice_include_stack_traces_property);
+        System.getProperty("guice_include_stack_traces"));
   }
 
   private static class RecordingBinder implements Binder, PrivateBinder, RehashableKeys {
diff --git a/core/src/com/google/inject/spi/InjectionRequest.java b/core/src/com/google/inject/spi/InjectionRequest.java
index 21bd575..f80e37a 100644
--- a/core/src/com/google/inject/spi/InjectionRequest.java
+++ b/core/src/com/google/inject/spi/InjectionRequest.java
@@ -47,9 +47,6 @@
   }
 
   public Object getSource() {
-    if (source instanceof ElementSource) {
-      return ((ElementSource) source).getDeclaringSource();
-    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/InterceptorBinding.java b/core/src/com/google/inject/spi/InterceptorBinding.java
index 410eeb1..a16e701 100644
--- a/core/src/com/google/inject/spi/InterceptorBinding.java
+++ b/core/src/com/google/inject/spi/InterceptorBinding.java
@@ -60,9 +60,6 @@
   }
 
   public Object getSource() {
-    if (source instanceof ElementSource) {
-      return ((ElementSource) source).getDeclaringSource();
-    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/MembersInjectorLookup.java b/core/src/com/google/inject/spi/MembersInjectorLookup.java
index 5a152fb..d4da8bd 100644
--- a/core/src/com/google/inject/spi/MembersInjectorLookup.java
+++ b/core/src/com/google/inject/spi/MembersInjectorLookup.java
@@ -45,9 +45,6 @@
   }
 
   public Object getSource() {
-    if (source instanceof ElementSource) {
-      return ((ElementSource) source).getDeclaringSource();
-    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/ModuleSource.java b/core/src/com/google/inject/spi/ModuleSource.java
index f5074ba..627ff4d 100644
--- a/core/src/com/google/inject/spi/ModuleSource.java
+++ b/core/src/com/google/inject/spi/ModuleSource.java
@@ -74,10 +74,14 @@
    * Module#configure(Binder) configure(Binder)} method invocation
    */
   StackTraceElement[] getPartialCallStack() {
-    int chunkSize = partialCallStack.length;
-    StackTraceElement[] callStack = new StackTraceElement[chunkSize];
-    System.arraycopy(partialCallStack, 0, callStack, 0, chunkSize);
-    return callStack;
+    return StackTraceElements.convertToStackTraceElement(partialCallStack);
+  }
+  
+  /**
+   * Returns the size of partial call stack.
+   */
+  int getPartialCallStackSize() {
+    return partialCallStack.length;
   }
   
   /** 
diff --git a/core/src/com/google/inject/spi/ProviderLookup.java b/core/src/com/google/inject/spi/ProviderLookup.java
index 050b59c..ee4337d 100644
--- a/core/src/com/google/inject/spi/ProviderLookup.java
+++ b/core/src/com/google/inject/spi/ProviderLookup.java
@@ -47,9 +47,6 @@
   }
 
   public Object getSource() {
-    if (source instanceof ElementSource) {
-      return ((ElementSource) source).getDeclaringSource();
-    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/ProvisionListenerBinding.java b/core/src/com/google/inject/spi/ProvisionListenerBinding.java
index 33229d8..4f349d4 100644
--- a/core/src/com/google/inject/spi/ProvisionListenerBinding.java
+++ b/core/src/com/google/inject/spi/ProvisionListenerBinding.java
@@ -57,9 +57,6 @@
   }
 
   public Object getSource() {
-    if (source instanceof ElementSource) {
-      return ((ElementSource) source).getDeclaringSource();
-    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/RequireAtInjectOnConstructorsOption.java b/core/src/com/google/inject/spi/RequireAtInjectOnConstructorsOption.java
index 4992a5c..03d8c34 100644
--- a/core/src/com/google/inject/spi/RequireAtInjectOnConstructorsOption.java
+++ b/core/src/com/google/inject/spi/RequireAtInjectOnConstructorsOption.java
@@ -35,9 +35,6 @@
   }
 
   public Object getSource() {
-    if (source instanceof ElementSource) {
-      return ((ElementSource) source).getDeclaringSource();
-    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/RequireExactBindingAnnotationsOption.java b/core/src/com/google/inject/spi/RequireExactBindingAnnotationsOption.java
index afab64b..ee52cfc 100644
--- a/core/src/com/google/inject/spi/RequireExactBindingAnnotationsOption.java
+++ b/core/src/com/google/inject/spi/RequireExactBindingAnnotationsOption.java
@@ -34,9 +34,6 @@
   }
 
   public Object getSource() {
-    if (source instanceof ElementSource) {
-      return ((ElementSource) source).getDeclaringSource();
-    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java b/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java
index 812ee43..5962eb7 100644
--- a/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java
+++ b/core/src/com/google/inject/spi/RequireExplicitBindingsOption.java
@@ -34,9 +34,6 @@
   }
 
   public Object getSource() {
-    if (source instanceof ElementSource) {
-      return ((ElementSource) source).getDeclaringSource();
-    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/ScopeBinding.java b/core/src/com/google/inject/spi/ScopeBinding.java
index ad062f1..86ed685 100644
--- a/core/src/com/google/inject/spi/ScopeBinding.java
+++ b/core/src/com/google/inject/spi/ScopeBinding.java
@@ -46,9 +46,6 @@
   }
 
   public Object getSource() {
-    if (source instanceof ElementSource) {
-      return ((ElementSource) source).getDeclaringSource();
-    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/StaticInjectionRequest.java b/core/src/com/google/inject/spi/StaticInjectionRequest.java
index 97c4e42..87e5376 100644
--- a/core/src/com/google/inject/spi/StaticInjectionRequest.java
+++ b/core/src/com/google/inject/spi/StaticInjectionRequest.java
@@ -43,9 +43,6 @@
   }
 
   public Object getSource() {
-    if (source instanceof ElementSource) {
-      return ((ElementSource) source).getDeclaringSource();
-    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/TypeConverterBinding.java b/core/src/com/google/inject/spi/TypeConverterBinding.java
index e8c8b17..f4925a5 100644
--- a/core/src/com/google/inject/spi/TypeConverterBinding.java
+++ b/core/src/com/google/inject/spi/TypeConverterBinding.java
@@ -46,9 +46,6 @@
   }
 
   public Object getSource() {
-    if (source instanceof ElementSource) {
-      return ((ElementSource) source).getDeclaringSource();
-    }
     return source;
   }
 
diff --git a/core/src/com/google/inject/spi/TypeListenerBinding.java b/core/src/com/google/inject/spi/TypeListenerBinding.java
index 752d495..8ad4672 100644
--- a/core/src/com/google/inject/spi/TypeListenerBinding.java
+++ b/core/src/com/google/inject/spi/TypeListenerBinding.java
@@ -54,9 +54,6 @@
   }
 
   public Object getSource() {
-    if (source instanceof ElementSource) {
-      return ((ElementSource) source).getDeclaringSource();
-    }
     return source;
   }
 
diff --git a/core/test/com/google/inject/ModulesTest.java b/core/test/com/google/inject/ModulesTest.java
index 76a28e0..7eaa494 100644
--- a/core/test/com/google/inject/ModulesTest.java
+++ b/core/test/com/google/inject/ModulesTest.java
@@ -16,6 +16,8 @@
 
 package com.google.inject;
 
+import com.google.common.collect.ImmutableList;
+import com.google.inject.spi.ElementSource;
 import com.google.inject.util.Modules;
 
 import junit.framework.TestCase;
@@ -53,8 +55,14 @@
       }
     };
     Injector injector = Guice.createInjector(Modules.combine(skipSourcesModule));
-    StackTraceElement source = (StackTraceElement) injector.getBinding(Integer.class).getSource();
-    assertEquals(skipSourcesModule.getClass().getName(), source.getClassName());
+    ElementSource source = (ElementSource) injector.getBinding(Integer.class).getSource();
+    // Check modules stack
+    assertEquals(source.getModuleClassNames().size(), 4);
+    assertEquals(ImmutableList.of("com.google.inject.ModulesTest$2",
+        "com.google.inject.util.Modules$2", "com.google.inject.ModulesTest$1",
+        "com.google.inject.util.Modules$2"), source.getModuleClassNames());
+    StackTraceElement stackTraceElement = (StackTraceElement) source.getDeclaringSource();
+    assertEquals(skipSourcesModule.getClass().getName(), stackTraceElement.getClassName());
   }
 
   private <T> Module newModule(final T toBind) {
diff --git a/core/test/com/google/inject/ReflectionTest.java b/core/test/com/google/inject/ReflectionTest.java
index 15695e4..610f099 100644
--- a/core/test/com/google/inject/ReflectionTest.java
+++ b/core/test/com/google/inject/ReflectionTest.java
@@ -18,6 +18,8 @@
 
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
+import com.google.inject.spi.ElementSource;
+
 import junit.framework.TestCase;
 
 import java.lang.annotation.Retention;
@@ -41,7 +43,8 @@
 
     Binding<Foo> fooBinding = injector.getBinding(Key.get(Foo.class));
     assertSame(foo, fooBinding.getProvider().get());
-    assertNotNull(fooBinding.getSource());
+    ElementSource source = (ElementSource) fooBinding.getSource();
+    assertNotNull(source.getDeclaringSource());
     assertEquals(Key.get(Foo.class), fooBinding.getKey());
   }
 
@@ -54,7 +57,8 @@
 
     Binding<?> i = injector.getBinding(Key.get(int.class, I.class));
     assertEquals(5, i.getProvider().get());
-    assertNotNull(i.getSource());
+    ElementSource source = (ElementSource) i.getSource();
+    assertNotNull(source.getDeclaringSource());
     assertEquals(Key.get(int.class, I.class), i.getKey());
   }
 
@@ -70,7 +74,8 @@
 
     Binding<Foo> fooBinding = injector.getBinding(Key.get(Foo.class));
     assertSame(bar, fooBinding.getProvider().get());
-    assertNotNull(fooBinding.getSource());
+    ElementSource source = (ElementSource) fooBinding.getSource();
+    assertNotNull(source.getDeclaringSource());
     assertEquals(Key.get(Foo.class), fooBinding.getKey());
   }
 
diff --git a/core/test/com/google/inject/spi/ElementSourceTest.java b/core/test/com/google/inject/spi/ElementSourceTest.java
index 6406b2a..5c63f4a 100644
--- a/core/test/com/google/inject/spi/ElementSourceTest.java
+++ b/core/test/com/google/inject/spi/ElementSourceTest.java
@@ -21,10 +21,15 @@
  */
 public class ElementSourceTest extends TestCase {
 
-  private static final StackTraceElement BINDER_INSTALL = 
-      new StackTraceElement("com.google.inject.spi.Elements$RecordingBinder", "install", 
+  private static final StackTraceElement BINDER_INSTALL =
+      new StackTraceElement("com.google.inject.spi.Elements$RecordingBinder", "install",
           "Unknown Source", 234 /* line number*/);
-  
+
+  @Override
+  protected void tearDown() throws Exception {
+    System.clearProperty("guice_include_stack_traces");
+  }
+
   public void testCallStackSize() {
     ModuleSource moduleSource = createModuleSource();
     StackTraceElement[] bindingCallStack = new StackTraceElement[3];
@@ -37,90 +42,116 @@
     ElementSource elementSource = new ElementSource(
         null /* No original element source */, "" /* Don't care */, moduleSource, bindingCallStack);
     assertEquals(10 /* call stack size */, elementSource.getStackTrace().length);
-  }  
+  }
 
-  public void testSourceIsNotElementSource() {
+  public void testGetCallStack_IntegrationTest_Default() throws Exception {
+    System.setProperty("guice_include_stack_traces", "DEFAULT");
     List<Element> elements = Elements.getElements(new A());
     for (Element element : elements) {
       if (element instanceof Binding) {
         Binding<?> binding = (Binding<?>) element;
         Class<? extends Annotation> annotationType = binding.getKey().getAnnotationType();
         if (annotationType != null && annotationType.equals(SampleAnnotation.class)) {
-          assertFalse("Source can not be an ElementSource.", 
-              binding.getSource() instanceof ElementSource);
+          ElementSource elementSource = (ElementSource) binding.getSource();
+          // Check module stack
+          List<String> moduleClassNames = elementSource.getModuleClassNames();
+          // Module C
+          assertEquals("com.google.inject.spi.ElementSourceTest$C", moduleClassNames.get(0));
+          // Module B
+          assertEquals("com.google.inject.spi.ElementSourceTest$B", moduleClassNames.get(1));
+          // Module A
+          assertEquals("com.google.inject.spi.ElementSourceTest$A", moduleClassNames.get(2));
+          // Check call stack
+          StackTraceElement[] callStack = elementSource.getStackTrace();
+          assertEquals(0, elementSource.getStackTrace().length);
+          return;
         }
       }
     }
-  }  
-  
-  // TODO(salmanmir): uncomment this test when the above test is removed.
-//  public void testGetCallStack_integrationTest() {
-//    List<Element> elements = Elements.getElements(new A());
-//    for (Element element : elements) {
-//      if (element instanceof Binding) {
-//        Binding<?> binding = (Binding<?>) element;
-//        Class<? extends Annotation> annotationType = binding.getKey().getAnnotationType();
-//        if (annotationType != null && annotationType.equals(SampleAnnotation.class)) {
-//          ElementSource elementSource = (ElementSource) binding.getSource();
-//          StackTraceElement[] callStack = elementSource.getStackTrace();
-//          // check call stack size
-//          int skippedCallStackSize = new Throwable().getStackTrace().length - 1;
-//          assertEquals(skippedCallStackSize + 15, elementSource.getStackTrace().length);
-//          assertEquals("com.google.inject.spi.Elements$RecordingBinder",
-//              callStack[0].getClassName());
-//          assertEquals("com.google.inject.spi.Elements$RecordingBinder",
-//              callStack[1].getClassName());
-//          assertEquals("com.google.inject.AbstractModule",
-//              callStack[2].getClassName());
-//          // Module C
-//          assertEquals("com.google.inject.spi.ElementSourceTest$C",
-//              callStack[3].getClassName());
-//          assertEquals("configure",
-//              callStack[3].getMethodName());
-//          assertEquals("Unknown Source",
-//              callStack[3].getFileName());
-//          assertEquals("com.google.inject.AbstractModule",
-//              callStack[4].getClassName());
-//          assertEquals("com.google.inject.spi.Elements$RecordingBinder",
-//              callStack[5].getClassName());
-//          // Module B
-//          assertEquals("com.google.inject.spi.ElementSourceTest$B",
-//              callStack[6].getClassName());
-//          assertEquals("com.google.inject.spi.Elements$RecordingBinder",
-//              callStack[7].getClassName());
-//          // Module A
-//          assertEquals("com.google.inject.AbstractModule",
-//              callStack[8].getClassName());
-//          assertEquals("com.google.inject.spi.ElementSourceTest$A",
-//              callStack[9].getClassName());
-//          assertEquals("com.google.inject.AbstractModule",
-//              callStack[10].getClassName());
-//          assertEquals("com.google.inject.spi.Elements$RecordingBinder",
-//              callStack[11].getClassName());
-//          assertEquals("com.google.inject.spi.Elements",
-//              callStack[12].getClassName());
-//          assertEquals("com.google.inject.spi.Elements",
-//              callStack[13].getClassName());
-//          assertEquals("com.google.inject.spi.ElementSourceTest",
-//              callStack[14].getClassName());
-//          return;
-//        }
-//      }
-//    }
-//  fail("The test should not reach this line.");
-//  }  
+    fail("The test should not reach this line.");
+  }
+
+  public void testGetCallStack_IntegrationTest_Complete() throws Exception {
+    System.setProperty("guice_include_stack_traces", "COMPLETE");
+    List<Element> elements = Elements.getElements(new A());
+    for (Element element : elements) {
+      if (element instanceof Binding) {
+        Binding<?> binding = (Binding<?>) element;
+        Class<? extends Annotation> annotationType = binding.getKey().getAnnotationType();
+        if (annotationType != null && annotationType.equals(SampleAnnotation.class)) {
+          ElementSource elementSource = (ElementSource) binding.getSource();
+          // Check module stack
+          List<String> moduleClassNames = elementSource.getModuleClassNames();
+          // Module C
+          assertEquals("com.google.inject.spi.ElementSourceTest$C", moduleClassNames.get(0));
+          // Module B
+          assertEquals("com.google.inject.spi.ElementSourceTest$B", moduleClassNames.get(1));
+          // Module A
+          assertEquals("com.google.inject.spi.ElementSourceTest$A", moduleClassNames.get(2));
+          // Check call stack
+          StackTraceElement[] callStack = elementSource.getStackTrace();
+          int skippedCallStackSize = new Throwable().getStackTrace().length - 1;
+          assertEquals(skippedCallStackSize + 15, elementSource.getStackTrace().length);
+          assertEquals("com.google.inject.spi.Elements$RecordingBinder",
+              callStack[0].getClassName());
+          assertEquals("com.google.inject.spi.Elements$RecordingBinder",
+              callStack[1].getClassName());
+          assertEquals("com.google.inject.AbstractModule",
+              callStack[2].getClassName());
+          // Module C
+          assertEquals("com.google.inject.spi.ElementSourceTest$C",
+              callStack[3].getClassName());
+          assertEquals("configure",
+              callStack[3].getMethodName());
+          assertEquals("Unknown Source",
+              callStack[3].getFileName());
+          assertEquals("com.google.inject.AbstractModule",
+              callStack[4].getClassName());
+          assertEquals("com.google.inject.spi.Elements$RecordingBinder",
+              callStack[5].getClassName());
+          // Module B
+          assertEquals("com.google.inject.spi.ElementSourceTest$B",
+              callStack[6].getClassName());
+          assertEquals("com.google.inject.spi.Elements$RecordingBinder",
+              callStack[7].getClassName());
+          // Module A
+          assertEquals("com.google.inject.AbstractModule",
+              callStack[8].getClassName());
+          assertEquals("com.google.inject.spi.ElementSourceTest$A",
+              callStack[9].getClassName());
+          assertEquals("com.google.inject.AbstractModule",
+              callStack[10].getClassName());
+          assertEquals("com.google.inject.spi.Elements$RecordingBinder",
+              callStack[11].getClassName());
+          assertEquals("com.google.inject.spi.Elements",
+              callStack[12].getClassName());
+          assertEquals("com.google.inject.spi.Elements",
+              callStack[13].getClassName());
+          assertEquals("com.google.inject.spi.ElementSourceTest",
+              callStack[14].getClassName());
+          // Check modules index
+          List<Integer> indexes = elementSource.getModuleConfigurePositionsInStackTrace();
+          assertEquals((int) indexes.get(0), 4);
+          assertEquals((int) indexes.get(1), 6);
+          assertEquals((int) indexes.get(2), 10);
+          return;
+        }
+      }
+    }
+    fail("The test should not reach this line.");
+  }
 
   private ModuleSource createModuleSource() {
     // First module
     StackTraceElement[] partialCallStack = new StackTraceElement[1];
-    partialCallStack[0] = BINDER_INSTALL;    
+    partialCallStack[0] = BINDER_INSTALL;
     ModuleSource moduleSource = new ModuleSource(new A(), partialCallStack);
-    // Second module 
+    // Second module
     partialCallStack = new StackTraceElement[2];
     partialCallStack[0] = BINDER_INSTALL;
     partialCallStack[1] = new StackTraceElement(
         "com.google.inject.spi.moduleSourceTest$A", "configure", "Unknown Source", 100);
-    moduleSource = moduleSource.createChild(new B(), partialCallStack);    
+    moduleSource = moduleSource.createChild(new B(), partialCallStack);
     // Third module
     partialCallStack = new StackTraceElement[4];
     partialCallStack[0] = BINDER_INSTALL;
@@ -137,14 +168,14 @@
       install(new B());
     }
   }
-  
+
   private static class B implements Module {
     @Override
     public void configure(Binder binder) {
       binder.install(new C());
     }
   }
-  
+
   @Retention(RUNTIME)
   @Target({ ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD })
   @BindingAnnotation
@@ -155,5 +186,5 @@
     public void configure() {
       bind(String.class).annotatedWith(SampleAnnotation.class).toInstance("the value");
     }
-  }  
+  }
 }
diff --git a/core/test/com/google/inject/spi/ElementsTest.java b/core/test/com/google/inject/spi/ElementsTest.java
index 53eeb82..5054f76 100644
--- a/core/test/com/google/inject/spi/ElementsTest.java
+++ b/core/test/com/google/inject/spi/ElementsTest.java
@@ -20,6 +20,7 @@
 import static com.google.inject.Asserts.assertContains;
 import static java.lang.annotation.RetentionPolicy.RUNTIME;
 
+import com.google.common.collect.ImmutableList;
 import com.google.common.collect.ImmutableMap;
 import com.google.common.collect.ImmutableSet;
 import com.google.inject.AbstractModule;
@@ -1228,6 +1229,12 @@
     for (int i = 0; i < visitors.length; i++) {
       ElementVisitor<?> visitor = visitors[i];
       Element element = elements.get(i);
+      if (!(element instanceof Message)) {
+          ElementSource source = (ElementSource) element.getSource();
+          assertTrue(source.getModuleClassNames().size() > 0);
+          assertFalse(source.isStackTraceRetained()) ;
+          assertEquals(0, source.getStackTrace().length);
+      }
       if (!(visitor instanceof ExternalFailureVisitor)) {
         assertContains(element.getSource().toString(), "ElementsTest.java");
       }
diff --git a/core/test/com/google/inject/spi/SpiBindingsTest.java b/core/test/com/google/inject/spi/SpiBindingsTest.java
index a5fb45a..ccf50a9 100644
--- a/core/test/com/google/inject/spi/SpiBindingsTest.java
+++ b/core/test/com/google/inject/spi/SpiBindingsTest.java
@@ -79,7 +79,7 @@
         new FailingElementVisitor() {
           @Override public <T> Void visit(Binding<T> binding) {
             assertTrue(binding instanceof InstanceBinding);
-            assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
+            checkBindingSource(binding);
             assertEquals(Key.get(String.class), binding.getKey());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
               @Override public Void visit(InstanceBinding<? extends T> binding) {
@@ -111,7 +111,7 @@
         new FailingElementVisitor() {
           @Override public <T> Void visit(Binding<T> binding) {
             assertTrue(binding instanceof ProviderInstanceBinding);
-            assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
+            checkBindingSource(binding);
             assertEquals(Key.get(String.class), binding.getKey());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
               @Override public Void visit(
@@ -137,7 +137,7 @@
         new FailingElementVisitor() {
           @Override public <T> Void visit(Binding<T> binding) {
             assertTrue(binding instanceof ProviderKeyBinding);
-            assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
+            checkBindingSource(binding);
             assertEquals(Key.get(String.class), binding.getKey());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
               @Override public Void visit(ProviderKeyBinding<? extends T> binding) {
@@ -166,7 +166,7 @@
         new FailingElementVisitor() {
           @Override public <T> Void visit(Binding<T> binding) {
             assertTrue(binding instanceof LinkedKeyBinding);
-            assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
+            checkBindingSource(binding);
             assertEquals(aKey, binding.getKey());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
               @Override public Void visit(LinkedKeyBinding<? extends T> binding) {
@@ -198,7 +198,7 @@
         new FailingElementVisitor() {
           @Override public <T> Void visit(Binding<T> binding) {
             assertTrue(binding instanceof ConstructorBinding);
-            assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
+            checkBindingSource(binding);
             assertEquals(Key.get(D.class), binding.getKey());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
               @Override public Void visit(ConstructorBinding<? extends T> binding) {
@@ -225,7 +225,7 @@
         new FailingElementVisitor() {
           @Override public <T> Void visit(Binding<T> binding) {
             assertTrue(binding instanceof InstanceBinding);
-            assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
+            checkBindingSource(binding);
             assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey());
             binding.acceptTargetVisitor(new FailingTargetVisitor<T>() {
               @Override public Void visit(InstanceBinding<? extends T> binding) {
@@ -248,7 +248,7 @@
 
     Binding<Integer> binding = injector.getBinding(Key.get(Integer.class, Names.named("one")));
     assertEquals(Key.get(Integer.class, Names.named("one")), binding.getKey());
-    assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
+    checkBindingSource(binding);
     assertTrue(binding instanceof ConvertedConstantBinding);
     binding.acceptTargetVisitor(new FailingTargetVisitor<Integer>() {
       @Override public Void visit(
@@ -270,7 +270,7 @@
     Key<Provider<String>> providerOfStringKey = new Key<Provider<String>>() {};
     Binding<Provider<String>> binding = injector.getBinding(providerOfStringKey);
     assertEquals(providerOfStringKey, binding.getKey());
-    assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
+    checkBindingSource(binding);
     assertTrue(binding instanceof ProviderBinding);
     binding.acceptTargetVisitor(new FailingTargetVisitor<Provider<String>>() {
       @Override public Void visit(
@@ -382,7 +382,7 @@
     Key<Provider<String>> providerOfStringKey = new Key<Provider<String>>() {};
     Binding<Provider<String>> providerBinding = injector.getBinding(providerOfStringKey);
     assertEquals(providerOfStringKey, providerBinding.getKey());
-    assertContains(providerBinding.getSource().toString(), "SpiBindingsTest.java");
+    checkBindingSource(providerBinding);
     assertTrue("binding: " + providerBinding, providerBinding instanceof ProviderBinding);
     providerBinding.acceptTargetVisitor(new FailingTargetVisitor<Provider<String>>() {
       @Override public Void visit(ProviderBinding<? extends Provider<String>> binding) {
@@ -394,7 +394,7 @@
     // Check for String binding -- that one is ProviderInstanceBinding, and gets hooked
     Binding<String> binding = injector.getBinding(String.class);
     assertEquals(Key.get(String.class), binding.getKey());
-    assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
+    checkBindingSource(binding);
     assertTrue(binding instanceof ProviderInstanceBinding);
     assertEquals("visited", binding.acceptTargetVisitor(new FailingSpiTargetVisitor<String>()));
   }
@@ -406,6 +406,14 @@
     }
   }
 
+  public void checkBindingSource(Binding binding) {
+    assertContains(binding.getSource().toString(), "SpiBindingsTest.java");
+    ElementSource source = (ElementSource) binding.getSource();
+    assertTrue(source.getModuleClassNames().size() > 0);
+    assertFalse(source.isStackTraceRetained()) ;
+    assertEquals(0, source.getStackTrace().length);
+  }
+  
   public void checkInjector(Module module, ElementVisitor<?>... visitors) {
     Injector injector = Guice.createInjector(module);
 
diff --git a/extensions/grapher/src/com/google/inject/grapher/ShortNameFactory.java b/extensions/grapher/src/com/google/inject/grapher/ShortNameFactory.java
index 1bf6b3e..e8c6d57 100644
--- a/extensions/grapher/src/com/google/inject/grapher/ShortNameFactory.java
+++ b/extensions/grapher/src/com/google/inject/grapher/ShortNameFactory.java
@@ -22,6 +22,7 @@
 import com.google.inject.TypeLiteral;
 import com.google.inject.internal.ProviderMethod;
 import com.google.inject.internal.util.StackTraceElements;
+import com.google.inject.spi.ElementSource;
 
 import java.lang.annotation.Annotation;
 import java.lang.reflect.Constructor;
@@ -98,6 +99,9 @@
    * or a {@link Method} when a provider method is used.
    */
   public String getSourceName(Object source) {
+    if (source instanceof ElementSource) {
+      source = ((ElementSource) source).getDeclaringSource();
+    }
     if (source instanceof Method) {
       source = StackTraceElements.forMember((Method) source);
     }