Fix ModuleAnnotatedMethodScanners so that they scan modules installed in
binders created from skipSources or withSource.
-------------
Created by MOE: http://code.google.com/p/moe-java
MOE_MIGRATED_REVID=89146131
diff --git a/core/src/com/google/inject/spi/Elements.java b/core/src/com/google/inject/spi/Elements.java
index 46072e3..f5bbe89 100644
--- a/core/src/com/google/inject/spi/Elements.java
+++ b/core/src/com/google/inject/spi/Elements.java
@@ -147,10 +147,12 @@
   private static class ModuleInfo {
     private final Binder binder;
     private final ModuleSource moduleSource;
+    private final boolean skipScanning;
 
-    private ModuleInfo(Binder binder, ModuleSource moduleSource) {
+    private ModuleInfo(Binder binder, ModuleSource moduleSource, boolean skipScanning) {
       this.binder = binder;
       this.moduleSource = moduleSource;
+      this.skipScanning = skipScanning;
     }
   }
 
@@ -270,19 +272,25 @@
       }
     }
 
+    /**
+     * Applies all scanners to the modules we've installed. We skip certain
+     * PrivateModules because store them in more than one Modules map and only
+     * want to process them through one of the maps.  (They're stored in both
+     * maps to prevent a module from being installed more than once.)
+     */
     void scanForAnnotatedMethods() {
       for (ModuleAnnotatedMethodScanner scanner : scanners) {
         // Note: we must iterate over a copy of the modules because calling install(..)
         // will mutate modules, otherwise causing a ConcurrentModificationException.
         for (Map.Entry<Module, ModuleInfo> entry : Maps.newLinkedHashMap(modules).entrySet()) {
           Module module = entry.getKey();
-          // If this was from a child private binder, skip it... we'll process it later.
-          if (entry.getValue().binder != this) {
+          ModuleInfo info = entry.getValue();
+          if (info.skipScanning) {
             continue;
           }
           moduleSource = entry.getValue().moduleSource;
           try {
-            install(ProviderMethodsModule.forModule(module, scanner));
+            info.binder.install(ProviderMethodsModule.forModule(module, scanner));
           } catch(RuntimeException e) {
             Collection<Message> messages = Errors.getMessagesFromThrowable(e);
             if (!messages.isEmpty()) {
@@ -298,7 +306,7 @@
 
     public void install(Module module) {
       if (!modules.containsKey(module)) {
-        Binder binder = this;
+        RecordingBinder binder = this;
         boolean unwrapModuleSource = false;
         // Update the module source for the new module
         if (module instanceof ProviderMethodsModule) {
@@ -316,14 +324,16 @@
           moduleSource = getModuleSource(module);
           unwrapModuleSource = true;
         }
+        boolean skipScanning = false;
         if (module instanceof PrivateModule) {
-          binder = binder.newPrivateBinder();
-          // Store the module in the private binder too.
-          ((RecordingBinder) binder).modules.put(module, new ModuleInfo(binder, moduleSource));
+          binder = (RecordingBinder) binder.newPrivateBinder();
+          // Store the module in the private binder too so we scan for it.
+          binder.modules.put(module, new ModuleInfo(binder, moduleSource, false));
+          skipScanning = true; // don't scan this module in the parent's module set.
         }
         // Always store this in the parent binder (even if it was a private module)
         // so that we know not to process it again, and so that scanners inherit down.
-        modules.put(module, new ModuleInfo(binder, moduleSource));
+        modules.put(module, new ModuleInfo(binder, moduleSource, skipScanning));
         try {
           module.configure(binder);
         } catch (RuntimeException e) {
diff --git a/core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java b/core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java
index e73a9af..6c797b1 100644
--- a/core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java
+++ b/core/test/com/google/inject/spi/ModuleAnnotatedMethodScannerTest.java
@@ -75,6 +75,34 @@
         foo2Binding.getProvider().toString());
   }
 
+  public void testSkipSources() throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        binder().skipSources(getClass()).install(new AbstractModule() {
+          @Override protected void configure() {}
+
+          @TestProvides @Named("foo") String foo() { return "foo"; }
+        });
+      }
+    };
+    Injector injector = Guice.createInjector(module, NamedMunger.module());
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+  
+  public void testWithSource() throws Exception {
+    Module module = new AbstractModule() {
+      @Override protected void configure() {
+        binder().withSource("source").install(new AbstractModule() {
+          @Override protected void configure() {}
+
+          @TestProvides @Named("foo") String foo() { return "foo"; }
+        });
+      }
+    };
+    Injector injector = Guice.createInjector(module, NamedMunger.module());
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+
   public void testMoreThanOneClaimedAnnotationFails() throws Exception {
     Module module = new AbstractModule() {
       @Override protected void configure() {}
@@ -228,6 +256,34 @@
     assertMungedBinding(injector, String.class, "foo", "foo");
   }
 
+  public void testPrivateModule_skipSourcesWithinPrivateModule() {
+    Injector injector = Guice.createInjector(NamedMunger.module(), new PrivateModule() {
+      @Override protected void configure() {
+        binder().skipSources(getClass()).install(new AbstractModule() {
+          @Override protected void configure() {}
+          @Exposed @TestProvides @Named("foo") String foo() {
+            return "foo";
+          }
+        });
+      }
+    });
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+
+  public void testPrivateModule_skipSourcesForPrivateModule() {
+    Injector injector = Guice.createInjector(NamedMunger.module(), new AbstractModule() {
+      @Override protected void configure() {
+        binder().skipSources(getClass()).install(new PrivateModule() {
+          @Override protected void configure() {}
+
+          @Exposed @TestProvides @Named("foo") String foo() {
+            return "foo";
+          }
+        });
+      }});
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+
   public void testPrivateModuleInheritScanner_usingPrivateBinder() {
     Injector injector = Guice.createInjector(NamedMunger.module(), new AbstractModule() {
       @Override protected void configure() {
@@ -243,6 +299,36 @@
     assertMungedBinding(injector, String.class, "foo", "foo");
   }
 
+  public void testPrivateModuleInheritScanner_skipSourcesFromPrivateBinder() {
+    Injector injector = Guice.createInjector(NamedMunger.module(), new AbstractModule() {
+      @Override protected void configure() {
+        binder().newPrivateBinder().skipSources(getClass()).install(new AbstractModule() {
+          @Override protected void configure() {}
+
+          @Exposed @TestProvides @Named("foo") String foo() {
+            return "foo";
+          }
+        });
+      }
+    });
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+
+  public void testPrivateModuleInheritScanner_skipSourcesFromPrivateBinder2() {
+    Injector injector = Guice.createInjector(NamedMunger.module(), new AbstractModule() {
+      @Override protected void configure() {
+        binder().skipSources(getClass()).newPrivateBinder().install(new AbstractModule() {
+          @Override protected void configure() {}
+
+          @Exposed @TestProvides @Named("foo") String foo() {
+            return "foo";
+          }
+        });
+      }
+    });
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
+
   public void testPrivateModuleScannersDontImpactSiblings_usingPrivateModule() {
     Injector injector = Guice.createInjector(new PrivateModule() {
       @Override protected void configure() {
@@ -289,4 +375,20 @@
       }});
     assertMungedBinding(injector, String.class, "foo", "foo");
   }
+
+  public void testPrivateModuleWithinPrivateModule() {
+    Injector injector = Guice.createInjector(NamedMunger.module(), new PrivateModule() {
+      @Override protected void configure() {
+        expose(Key.get(String.class, named("foo-munged")));
+        install(new PrivateModule() {
+          @Override protected void configure() {}
+
+          @Exposed @TestProvides @Named("foo") String foo() {
+            return "foo";
+          }
+        });
+      }
+    });
+    assertMungedBinding(injector, String.class, "foo", "foo");
+  }
 }