issue 574 - don't freak out on generated classes when trying to get line numbers.

git-svn-id: https://google-guice.googlecode.com/svn/trunk@1492 d779f126-a31b-0410-b53b-1d3aecad763e
diff --git a/core/src/com/google/inject/internal/util/LineNumbers.java b/core/src/com/google/inject/internal/util/LineNumbers.java
index ad5dbad..91bf389 100644
--- a/core/src/com/google/inject/internal/util/LineNumbers.java
+++ b/core/src/com/google/inject/internal/util/LineNumbers.java
@@ -58,8 +58,9 @@
 
     if (!type.isArray()) {
       InputStream in = type.getResourceAsStream("/" + type.getName().replace('.', '/') + ".class");
-      Preconditions.checkArgument(in != null, "Cannot find bytecode for %s", type);
-      new ClassReader(in).accept(new LineNumberReader(), ClassReader.SKIP_FRAMES);
+      if (in != null) {
+        new ClassReader(in).accept(new LineNumberReader(), ClassReader.SKIP_FRAMES);
+      }
     }
   }
 
diff --git a/core/test/com/google/inject/internal/util/LineNumbersTest.java b/core/test/com/google/inject/internal/util/LineNumbersTest.java
index 8566978..9ca5c38 100644
--- a/core/test/com/google/inject/internal/util/LineNumbersTest.java
+++ b/core/test/com/google/inject/internal/util/LineNumbersTest.java
@@ -21,8 +21,14 @@
 import com.google.inject.CreationException;
 import com.google.inject.Guice;
 import com.google.inject.Inject;
+import com.google.inject.Injector;
 import com.google.inject.matcher.Matchers;
+import java.lang.reflect.Modifier;
 import junit.framework.TestCase;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.MethodVisitor;
+import org.objectweb.asm.Opcodes;
+import org.objectweb.asm.Type;
 
 /**
  * @author jessewilson@google.com (Jesse Wilson)
@@ -73,6 +79,63 @@
   static class A {
     @Inject A(B b) {}
   }
-  interface B {}
+  public interface B {}
 
+  static class GeneratingClassLoader extends ClassLoader {
+    static String name = "__generated";
+
+    GeneratingClassLoader() {
+      super(B.class.getClassLoader());
+    }
+
+    Class<?> generate() {
+      ClassWriter cw = new ClassWriter(ClassWriter.COMPUTE_MAXS);
+      cw.visit(Opcodes.V1_5, Modifier.PUBLIC, name, null, Type.getInternalName(Object.class), null);
+
+      String sig = "("+Type.getDescriptor(B.class)+")V";
+
+      MethodVisitor mv = cw.visitMethod(Modifier.PUBLIC, "<init>", sig, null, null);
+
+      mv.visitAnnotation(Type.getDescriptor(Inject.class), true);
+      mv.visitCode();
+      mv.visitVarInsn(Opcodes.ALOAD, 0);
+      mv.visitMethodInsn( Opcodes.INVOKESPECIAL, Type.getInternalName(Object.class), "<init>", "()V" );
+      mv.visitInsn(Opcodes.RETURN);
+      mv.visitMaxs(0, 0);
+      mv.visitEnd();
+      cw.visitEnd();
+
+      byte[] buf = cw.toByteArray();
+
+      return defineClass(name.replace('/', '.'), buf, 0, buf.length);
+    }
+  }
+
+  public void testUnavailableByteCodeShowsUnknownSource() {
+    try {
+      Guice.createInjector(new AbstractModule() {
+        protected void configure() {
+          bind(new GeneratingClassLoader().generate());
+        }
+      });
+      fail();
+    } catch (CreationException expected) {
+      assertContains(expected.getMessage(),
+          "1) No implementation for " + B.class.getName() + " was bound.",
+          "for parameter 0 at " + GeneratingClassLoader.name + ".<init>(Unknown Source)",
+          "at " + LineNumbersTest.class.getName(), ".configure(LineNumbersTest.java:");
+    }
+  }
+  
+  public void testGeneratedClassesCanSucceed() {
+    final Class<?> generated = new GeneratingClassLoader().generate();
+    Injector injector = Guice.createInjector(new AbstractModule() {
+      protected void configure() {
+        bind(generated);
+        bind(B.class).toInstance(new B() {});
+      }
+    });
+    Object instance = injector.getInstance(generated);
+    assertEquals(instance.getClass(), generated);
+  }
 }