fix issue 508 -- consider method return type when deciding whether to bridge.  patch contributed by stuart.

git-svn-id: https://google-guice.googlecode.com/svn/trunk@1374 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/core/src/com/google/inject/internal/BytecodeGen.java b/core/src/com/google/inject/internal/BytecodeGen.java
index 6f24ea8..1bdfb75 100644
--- a/core/src/com/google/inject/internal/BytecodeGen.java
+++ b/core/src/com/google/inject/internal/BytecodeGen.java
@@ -258,9 +258,17 @@
         return SAME_PACKAGE;
       }
 
-      Class[] parameterTypes = member instanceof Constructor
-          ? ((Constructor) member).getParameterTypes()
-          : ((Method) member).getParameterTypes();
+      Class[] parameterTypes;
+      if (member instanceof Constructor) {
+        parameterTypes = ((Constructor) member).getParameterTypes();
+      } else {
+        Method method = (Method) member;
+        if (forType(method.getReturnType()) == SAME_PACKAGE) {
+          return SAME_PACKAGE;
+        }
+        parameterTypes = method.getParameterTypes();
+      }
+
       for (Class<?> type : parameterTypes) {
         if (forType(type) == SAME_PACKAGE) {
           return SAME_PACKAGE;
diff --git a/core/test/com/googlecode/guice/BytecodeGenTest.java b/core/test/com/googlecode/guice/BytecodeGenTest.java
index ddba099..054bd38 100644
--- a/core/test/com/googlecode/guice/BytecodeGenTest.java
+++ b/core/test/com/googlecode/guice/BytecodeGenTest.java
@@ -26,6 +26,7 @@
 import java.io.File;
 import java.lang.ref.Reference;
 import java.lang.ref.WeakReference;
+import java.lang.reflect.Constructor;
 import java.lang.reflect.Method;
 import java.net.MalformedURLException;
 import java.net.URL;
@@ -55,6 +56,17 @@
     }
   };
 
+  private final Module noopInterceptorModule = new AbstractModule() {
+      protected void configure() {
+        bindInterceptor(any(), any(), new MethodInterceptor() {
+          public Object invoke(MethodInvocation chain)
+              throws Throwable {
+            return chain.proceed();
+          }
+        });
+      }
+    };
+
   public void testPackageVisibility() {
     Injector injector = Guice.createInjector(new PackageVisibilityTestModule());
     injector.getInstance(PublicUserOfPackagePrivate.class); // This must pass.
@@ -80,9 +92,13 @@
   static class TestVisibilityClassLoader
       extends URLClassLoader {
 
-    public TestVisibilityClassLoader() {
+    boolean hideInternals;
+
+    public TestVisibilityClassLoader(boolean hideInternals) {
       super(new URL[0]);
 
+      this.hideInternals = hideInternals;
+
       final String[] classpath = System.getProperty("java.class.path").split(File.pathSeparator);
       for (final String element : classpath) {
         try {
@@ -137,7 +153,10 @@
       }
 
       // hide internal non-test classes
-      throw new ClassNotFoundException();
+      if (hideInternals) {
+        throw new ClassNotFoundException();
+      }
+      return super.loadClass(name, resolve);
     }
   }
 
@@ -150,7 +169,7 @@
   protected void setUp() throws Exception {
     super.setUp();
 
-    ClassLoader testClassLoader = new TestVisibilityClassLoader();
+    ClassLoader testClassLoader = new TestVisibilityClassLoader(true);
     proxyTestClass = (Class<ProxyTest>) testClassLoader.loadClass(ProxyTest.class.getName());
     realClass = (Class<ProxyTestImpl>) testClassLoader.loadClass(ProxyTestImpl.class.getName());
 
@@ -268,4 +287,40 @@
       return "HI";
     }
   }
+
+  static class Hidden {
+  }
+
+  public static class HiddenMethodReturn {
+    public Hidden method() {
+      return new Hidden();
+    }
+  }
+
+  public static class HiddenMethodParameter {
+    public void method(Hidden h) {
+    }
+  }
+
+  public void testClassLoaderBridging() throws Exception {
+    ClassLoader testClassLoader = new TestVisibilityClassLoader(false);
+
+    Class hiddenMethodReturnClass = testClassLoader.loadClass(HiddenMethodReturn.class.getName());
+    Class hiddenMethodParameterClass = testClassLoader.loadClass(HiddenMethodParameter.class.getName());
+
+    Injector injector = Guice.createInjector(noopInterceptorModule);
+
+    Class hiddenClass = testClassLoader.loadClass(Hidden.class.getName());
+    Constructor ctor = hiddenClass.getDeclaredConstructor();
+
+    ctor.setAccessible(true);
+
+    // don't use bridging for proxies with private parameters
+    Object o1 = injector.getInstance(hiddenMethodParameterClass);
+    o1.getClass().getDeclaredMethod("method", hiddenClass).invoke(o1, ctor.newInstance());
+
+    // don't use bridging for proxies with private return types
+    Object o2 = injector.getInstance(hiddenMethodReturnClass);
+    o2.getClass().getDeclaredMethod("method").invoke(o2);
+  }
 }