Fix handling of unnamed inner classes

The InnerClass attributes for anonymous classes have a null class name,
which turbine shouldn't try to read. This fixes a NPE when repackaging
supertypes loaded from implementation jars; turbine itself doesn't write
InnerClass attributes for anonymous classes.

MOE_MIGRATED_REVID=146268069
diff --git a/java/com/google/turbine/bytecode/ClassFile.java b/java/com/google/turbine/bytecode/ClassFile.java
index 6321ec1..2761fec 100644
--- a/java/com/google/turbine/bytecode/ClassFile.java
+++ b/java/com/google/turbine/bytecode/ClassFile.java
@@ -16,6 +16,8 @@
 
 package com.google.turbine.bytecode;
 
+import static java.util.Objects.requireNonNull;
+
 import com.google.common.collect.ImmutableList;
 import com.google.turbine.bytecode.ClassFile.AnnotationInfo.ElementValue;
 import com.google.turbine.model.Const;
@@ -188,9 +190,9 @@
     private final int access;
 
     public InnerClass(String innerClass, String outerClass, String innerName, int access) {
-      this.innerClass = innerClass;
-      this.outerClass = outerClass;
-      this.innerName = innerName;
+      this.innerClass = requireNonNull(innerClass);
+      this.outerClass = requireNonNull(outerClass);
+      this.innerName = requireNonNull(innerName);
       this.access = access;
     }
 
diff --git a/java/com/google/turbine/bytecode/ClassReader.java b/java/com/google/turbine/bytecode/ClassReader.java
index 45da3a4..b59448a 100644
--- a/java/com/google/turbine/bytecode/ClassReader.java
+++ b/java/com/google/turbine/bytecode/ClassReader.java
@@ -130,7 +130,7 @@
       int innerNameIndex = reader.u2();
       String innerName = innerNameIndex != 0 ? constantPool.utf8(innerNameIndex) : null;
       int innerClassAccessFlags = reader.u2();
-      if (thisClass.equals(innerClass) || thisClass.equals(outerClass)) {
+      if (innerName != null && (thisClass.equals(innerClass) || thisClass.equals(outerClass))) {
         innerclasses.add(
             new ClassFile.InnerClass(innerClass, outerClass, innerName, innerClassAccessFlags));
       }
diff --git a/javatests/com/google/turbine/deps/TransitiveTest.java b/javatests/com/google/turbine/deps/TransitiveTest.java
index c6a6eea..d460287 100644
--- a/javatests/com/google/turbine/deps/TransitiveTest.java
+++ b/javatests/com/google/turbine/deps/TransitiveTest.java
@@ -30,6 +30,7 @@
 import com.google.turbine.main.Main;
 import com.google.turbine.options.TurbineOptions;
 import java.io.IOException;
+import java.io.OutputStream;
 import java.nio.file.Files;
 import java.nio.file.Path;
 import java.nio.file.Paths;
@@ -40,11 +41,14 @@
 import java.util.Map;
 import java.util.jar.JarEntry;
 import java.util.jar.JarFile;
+import java.util.jar.JarOutputStream;
 import org.junit.Rule;
 import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
+import org.objectweb.asm.ClassWriter;
+import org.objectweb.asm.Opcodes;
 
 @RunWith(JUnit4.class)
 public class TransitiveTest {
@@ -173,4 +177,48 @@
             "META-INF/TRANSITIVE/a/A$Anno.class",
             "META-INF/TRANSITIVE/a/A$Inner.class");
   }
+
+  @Test
+  public void anonymous() throws Exception {
+    Path liba = temporaryFolder.newFolder().toPath().resolve("out.jar");
+    try (OutputStream os = Files.newOutputStream(liba);
+        JarOutputStream jos = new JarOutputStream(os)) {
+      {
+        jos.putNextEntry(new JarEntry("a/A.class"));
+        ClassWriter cw = new ClassWriter(0);
+        cw.visit(52, Opcodes.ACC_SUPER, "a/A", null, "java/lang/Object", null);
+        cw.visitInnerClass("a/A$1", "a/A", null, Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC);
+        cw.visitInnerClass("a/A$I", "a/A", "I", Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC);
+        jos.write(cw.toByteArray());
+      }
+      {
+        jos.putNextEntry(new JarEntry("a/A$1.class"));
+        ClassWriter cw = new ClassWriter(0);
+        cw.visit(52, Opcodes.ACC_SUPER, "a/A$1", null, "java/lang/Object", null);
+        cw.visitInnerClass("a/A$1", "a/A", "I", Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC);
+        jos.write(cw.toByteArray());
+      }
+      {
+        jos.putNextEntry(new JarEntry("a/A$I.class"));
+        ClassWriter cw = new ClassWriter(0);
+        cw.visit(52, Opcodes.ACC_SUPER, "a/A$I", null, "java/lang/Object", null);
+        cw.visitInnerClass("a/A$I", "a/A", "I", Opcodes.ACC_STATIC | Opcodes.ACC_SYNTHETIC);
+        jos.write(cw.toByteArray());
+      }
+    }
+    Path libb =
+        runTurbine(
+            new SourceBuilder()
+                .addSourceLines(
+                    "b/B.java", //
+                    "package b;",
+                    "public class B extends a.A {}")
+                .build(),
+            ImmutableList.of(liba));
+
+    // libb repackages A and any named member types
+    assertThat(readJar(libb).keySet())
+        .containsExactly(
+            "b/B.class", "META-INF/TRANSITIVE/a/A.class", "META-INF/TRANSITIVE/a/A$I.class");
+  }
 }