SafeASTVisitor unilaterally avoids visiting error/unreachable local types

This prevents a class of compiler crashes that can occur when unreferenced error types end up in the source path.

http://gwt-code-reviews.appspot.com/682801/show
Review by: spoon


git-svn-id: https://google-web-toolkit.googlecode.com/svn/trunk@8376 8db76d5a-ed1c-0410-87a9-c151d255dfc7
diff --git a/dev/core/src/com/google/gwt/dev/javac/ArtificialRescueChecker.java b/dev/core/src/com/google/gwt/dev/javac/ArtificialRescueChecker.java
index 5e921ba..eee5bbd 100644
--- a/dev/core/src/com/google/gwt/dev/javac/ArtificialRescueChecker.java
+++ b/dev/core/src/com/google/gwt/dev/javac/ArtificialRescueChecker.java
@@ -16,13 +16,13 @@
 package com.google.gwt.dev.javac;
 
 import com.google.gwt.core.client.impl.ArtificialRescue;
+import com.google.gwt.dev.jdt.SafeASTVisitor;
 import com.google.gwt.dev.jjs.InternalCompilerException;
 import com.google.gwt.dev.util.Empty;
 import com.google.gwt.dev.util.JsniRef;
 import com.google.gwt.dev.util.collect.Lists;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.ast.Annotation;
 import org.eclipse.jdt.internal.compiler.ast.ArrayInitializer;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
@@ -54,18 +54,13 @@
  * </ul>
  */
 public class ArtificialRescueChecker {
-  private class Visitor extends ASTVisitor {
+  private class Visitor extends SafeASTVisitor {
 
     {
       assert collectTypes || reportErrors : "No work to be done";
     }
 
     @Override
-    public void endVisit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
-      processType(localTypeDeclaration);
-    }
-
-    @Override
     public void endVisit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
       processType(memberTypeDeclaration);
     }
@@ -76,6 +71,11 @@
       processType(typeDeclaration);
     }
 
+    @Override
+    public void endVisitValid(TypeDeclaration localTypeDeclaration, BlockScope scope) {
+      processType(localTypeDeclaration);
+    }
+
     private void processArtificialRescue(Annotation rescue) {
       if (!allowArtificialRescue) {
         // Goal (1)
@@ -349,12 +349,12 @@
 
   private boolean collectTypes;
 
-  private boolean reportErrors;
-
   private final CompilationUnitDeclaration cud;
 
   private List<String> referencedTypes;
 
+  private boolean reportErrors;
+
   private ArtificialRescueChecker(CompilationUnitDeclaration cud) {
     allowArtificialRescue = true;
     this.cud = cud;
diff --git a/dev/core/src/com/google/gwt/dev/javac/JSORestrictionsChecker.java b/dev/core/src/com/google/gwt/dev/javac/JSORestrictionsChecker.java
index 20cb178..9833fbb 100644
--- a/dev/core/src/com/google/gwt/dev/javac/JSORestrictionsChecker.java
+++ b/dev/core/src/com/google/gwt/dev/javac/JSORestrictionsChecker.java
@@ -15,10 +15,10 @@
  */
 package com.google.gwt.dev.javac;
 
+import com.google.gwt.dev.jdt.SafeASTVisitor;
 import com.google.gwt.dev.util.InstalledHelpInfo;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
@@ -78,7 +78,7 @@
     }
   }
 
-  private class JSORestrictionsVisitor extends ASTVisitor implements
+  private class JSORestrictionsVisitor extends SafeASTVisitor implements
       ClassFileConstants {
 
     private final Stack<Boolean> isJsoStack = new Stack<Boolean>();
@@ -150,11 +150,6 @@
     }
 
     @Override
-    public void endVisit(TypeDeclaration type, BlockScope scope) {
-      popIsJso();
-    }
-
-    @Override
     public void endVisit(TypeDeclaration type, ClassScope scope) {
       popIsJso();
     }
@@ -165,9 +160,8 @@
     }
 
     @Override
-    public boolean visit(TypeDeclaration type, BlockScope scope) {
-      pushIsJso(checkType(type));
-      return true;
+    public void endVisitValid(TypeDeclaration type, BlockScope scope) {
+      popIsJso();
     }
 
     @Override
@@ -182,6 +176,12 @@
       return true;
     }
 
+    @Override
+    public boolean visitValid(TypeDeclaration type, BlockScope scope) {
+      pushIsJso(checkType(type));
+      return true;
+    }
+
     private boolean checkType(TypeDeclaration type) {
       if (!isJsoSubclass(type.binding)) {
         return false;
diff --git a/dev/core/src/com/google/gwt/dev/javac/JdtCompiler.java b/dev/core/src/com/google/gwt/dev/javac/JdtCompiler.java
index 3cf13ec..3701f4f 100644
--- a/dev/core/src/com/google/gwt/dev/javac/JdtCompiler.java
+++ b/dev/core/src/com/google/gwt/dev/javac/JdtCompiler.java
@@ -15,6 +15,7 @@
  */
 package com.google.gwt.dev.javac;
 
+import com.google.gwt.dev.jdt.SafeASTVisitor;
 import com.google.gwt.dev.jdt.TypeRefVisitor;
 import com.google.gwt.dev.util.PerfLogger;
 import com.google.gwt.dev.util.collect.IdentityHashMap;
@@ -23,7 +24,6 @@
 import com.google.gwt.util.tools.Utility;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.Compiler;
 import org.eclipse.jdt.internal.compiler.DefaultErrorHandlingPolicies;
@@ -192,7 +192,7 @@
     }
   }
 
-  private class FindTypesInCud extends ASTVisitor {
+  private class FindTypesInCud extends SafeASTVisitor {
     Map<SourceTypeBinding, CompiledClass> map = new IdentityHashMap<SourceTypeBinding, CompiledClass>();
 
     public List<CompiledClass> getClasses() {
@@ -200,21 +200,6 @@
     }
 
     @Override
-    public boolean visit(TypeDeclaration typeDecl, BlockScope scope) {
-      /*
-       * Weird case: if JDT determines that this local class is totally
-       * uninstantiable, it won't bother allocating a local name.
-       */
-      if (typeDecl.binding.constantPoolName() != null) {
-        CompiledClass enclosingClass = map.get(typeDecl.binding.enclosingType());
-        assert (enclosingClass != null);
-        CompiledClass newClass = new CompiledClass(typeDecl, enclosingClass);
-        map.put(typeDecl.binding, newClass);
-      }
-      return true;
-    }
-
-    @Override
     public boolean visit(TypeDeclaration typeDecl, ClassScope scope) {
       CompiledClass enclosingClass = map.get(typeDecl.binding.enclosingType());
       assert (enclosingClass != null);
@@ -230,6 +215,15 @@
       map.put(typeDecl.binding, newClass);
       return true;
     }
+
+    @Override
+    public boolean visitValid(TypeDeclaration typeDecl, BlockScope scope) {
+      CompiledClass enclosingClass = map.get(typeDecl.binding.enclosingType());
+      assert (enclosingClass != null);
+      CompiledClass newClass = new CompiledClass(typeDecl, enclosingClass);
+      map.put(typeDecl.binding, newClass);
+      return true;
+    }
   }
 
   /**
diff --git a/dev/core/src/com/google/gwt/dev/javac/JsniChecker.java b/dev/core/src/com/google/gwt/dev/javac/JsniChecker.java
index 7064bc5..bab3cfc 100644
--- a/dev/core/src/com/google/gwt/dev/javac/JsniChecker.java
+++ b/dev/core/src/com/google/gwt/dev/javac/JsniChecker.java
@@ -16,6 +16,7 @@
 package com.google.gwt.dev.javac;
 
 import com.google.gwt.core.client.UnsafeNativeLong;
+import com.google.gwt.dev.jdt.SafeASTVisitor;
 import com.google.gwt.dev.jjs.InternalCompilerException;
 import com.google.gwt.dev.jjs.SourceInfo;
 import com.google.gwt.dev.js.ast.JsContext;
@@ -28,7 +29,6 @@
 import com.google.gwt.dev.util.collect.Sets;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.ast.ASTNode;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Annotation;
@@ -83,7 +83,7 @@
     ReferenceBinding resolveType(String typeName);
   }
 
-  private class JsniDeclChecker extends ASTVisitor implements
+  private class JsniDeclChecker extends SafeASTVisitor implements
       ClassFileConstants {
     @Override
     public void endVisit(MethodDeclaration meth, ClassScope scope) {
@@ -100,10 +100,6 @@
       suppressWarningsStack.pop();
     }
 
-    public void endVisit(TypeDeclaration typeDeclaration, BlockScope scope) {
-      suppressWarningsStack.pop();
-    }
-
     public void endVisit(TypeDeclaration typeDeclaration, ClassScope scope) {
       suppressWarningsStack.pop();
     }
@@ -113,17 +109,16 @@
       suppressWarningsStack.pop();
     }
 
+    public void endVisitValid(TypeDeclaration typeDeclaration, BlockScope scope) {
+      suppressWarningsStack.pop();
+    }
+
     @Override
     public boolean visit(MethodDeclaration meth, ClassScope scope) {
       suppressWarningsStack.push(getSuppressedWarnings(meth.annotations));
       return true;
     }
 
-    public boolean visit(TypeDeclaration typeDeclaration, BlockScope scope) {
-      suppressWarningsStack.push(getSuppressedWarnings(typeDeclaration.annotations));
-      return true;
-    }
-
     @Override
     public boolean visit(TypeDeclaration typeDeclaration, ClassScope scope) {
       suppressWarningsStack.push(getSuppressedWarnings(typeDeclaration.annotations));
@@ -136,6 +131,11 @@
       return true;
     }
 
+    public boolean visitValid(TypeDeclaration typeDeclaration, BlockScope scope) {
+      suppressWarningsStack.push(getSuppressedWarnings(typeDeclaration.annotations));
+      return true;
+    }
+
     private void checkDecl(MethodDeclaration meth, ClassScope scope) {
       TypeReference returnType = meth.returnType;
       if (containsLong(returnType, scope)) {
@@ -495,8 +495,8 @@
   }
 
   /**
-   * Check whether the argument type is the <code>long</code> primitive type.
-   * If the argument is <code>null</code>, returns <code>false</code>.
+   * Check whether the argument type is the <code>long</code> primitive type. If
+   * the argument is <code>null</code>, returns <code>false</code>.
    */
   private boolean containsLong(TypeBinding type) {
     if (type instanceof BaseTypeBinding) {
diff --git a/dev/core/src/com/google/gwt/dev/javac/MethodVisitor.java b/dev/core/src/com/google/gwt/dev/javac/MethodVisitor.java
index eab9613..a726da6 100644
--- a/dev/core/src/com/google/gwt/dev/javac/MethodVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/javac/MethodVisitor.java
@@ -15,9 +15,9 @@
  */
 package com.google.gwt.dev.javac;
 
+import com.google.gwt.dev.jdt.SafeASTVisitor;
 import com.google.gwt.dev.util.Name.InternalName;
 
-import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Argument;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
@@ -27,8 +27,8 @@
 import org.eclipse.jdt.internal.compiler.lookup.CompilationUnitScope;
 
 /**
- * Base class of things that walk methods in a CUD and collect things
- * about interesting methods.
+ * Base class of things that walk methods in a CUD and collect things about
+ * interesting methods.
  */
 public abstract class MethodVisitor {
 
@@ -55,12 +55,7 @@
    * @param cud
    */
   public final void collect(final CompilationUnitDeclaration cud) {
-    cud.traverse(new ASTVisitor() {
-      @Override
-      public void endVisit(TypeDeclaration type, BlockScope scope) {
-        collectMethods(cud, type);
-      }
-
+    cud.traverse(new SafeASTVisitor() {
       @Override
       public void endVisit(TypeDeclaration type, ClassScope scope) {
         collectMethods(cud, type);
@@ -70,6 +65,11 @@
       public void endVisit(TypeDeclaration type, CompilationUnitScope scope) {
         collectMethods(cud, type);
       }
+
+      @Override
+      public void endVisitValid(TypeDeclaration type, BlockScope scope) {
+        collectMethods(cud, type);
+      }
     }, cud.scope);
   }
 
@@ -81,11 +81,10 @@
    * @param method
    * @return true if processMethod should be called on this method
    */
-  protected abstract boolean interestingMethod(
-      AbstractMethodDeclaration method);
+  protected abstract boolean interestingMethod(AbstractMethodDeclaration method);
 
   /**
-   * Provided by a subclass to process a method definition.  Methods which have
+   * Provided by a subclass to process a method definition. Methods which have
    * no name are not passed to this method, even if {@link #interestingMethod}
    * returns true.
    * 
@@ -100,7 +99,7 @@
   /**
    * Collect data about interesting methods on a particular type in a
    * compilation unit.
-   *  
+   * 
    * @param cud
    * @param typeDecl
    */
@@ -122,13 +121,7 @@
       }
 
       if (!lazyInitialized) {
-        char[] constantPoolName = typeDecl.binding.constantPoolName();
-        if (constantPoolName == null) {
-          // Unreachable local type
-          return;
-        }
-        enclosingType = InternalName.toBinaryName(String.valueOf(
-            constantPoolName));
+        enclosingType = InternalName.toBinaryName(String.valueOf(typeDecl.binding.constantPoolName()));
         loc = String.valueOf(cud.getFileName());
         lazyInitialized = true;
       }
diff --git a/dev/core/src/com/google/gwt/dev/jdt/FindDeferredBindingSitesVisitor.java b/dev/core/src/com/google/gwt/dev/jdt/FindDeferredBindingSitesVisitor.java
index 75bb4e8..1842886 100644
--- a/dev/core/src/com/google/gwt/dev/jdt/FindDeferredBindingSitesVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jdt/FindDeferredBindingSitesVisitor.java
@@ -18,7 +18,6 @@
 import com.google.gwt.dev.javac.GWTProblem;
 
 import org.eclipse.jdt.core.compiler.CharOperation;
-import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.ast.ClassLiteralAccess;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.Expression;
@@ -38,7 +37,7 @@
  * find <code>GWT.create()</code> class so that we can eagerly complain about
  * deferred binding problems.
  */
-public class FindDeferredBindingSitesVisitor extends ASTVisitor {
+public class FindDeferredBindingSitesVisitor extends SafeASTVisitor {
 
   /**
    * Information about the site at which a rebind request was found, used to
diff --git a/dev/core/src/com/google/gwt/dev/jdt/FindJsniRefVisitor.java b/dev/core/src/com/google/gwt/dev/jdt/FindJsniRefVisitor.java
index 57fcc27..47dbf41 100644
--- a/dev/core/src/com/google/gwt/dev/jdt/FindJsniRefVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jdt/FindJsniRefVisitor.java
@@ -27,7 +27,6 @@
 import com.google.gwt.dev.js.ast.JsStatement;
 import com.google.gwt.dev.js.ast.JsVisitor;
 
-import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.ast.Argument;
 import org.eclipse.jdt.internal.compiler.ast.MethodDeclaration;
 import org.eclipse.jdt.internal.compiler.lookup.ClassScope;
@@ -45,7 +44,7 @@
  * references. If {@link #beSloppy()} is called, then it will run much more
  * quickly but it will return a superset of the actual JSNI references.
  */
-public class FindJsniRefVisitor extends ASTVisitor {
+public class FindJsniRefVisitor extends SafeASTVisitor {
   private final Set<String> jsniRefs = new LinkedHashSet<String>();
 
   public Set<String> getJsniRefs() {
diff --git a/dev/core/src/com/google/gwt/dev/jdt/SafeASTVisitor.java b/dev/core/src/com/google/gwt/dev/jdt/SafeASTVisitor.java
new file mode 100644
index 0000000..9f220ee
--- /dev/null
+++ b/dev/core/src/com/google/gwt/dev/jdt/SafeASTVisitor.java
@@ -0,0 +1,58 @@
+/*
+ * Copyright 2010 Google Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License"); you may not
+ * use this file except in compliance with the License. You may obtain a copy of
+ * the License at
+ * 
+ * http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
+ * WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
+ * License for the specific language governing permissions and limitations under
+ * the License.
+ */
+package com.google.gwt.dev.jdt;
+
+import org.eclipse.jdt.internal.compiler.ASTVisitor;
+import org.eclipse.jdt.internal.compiler.ast.TypeDeclaration;
+import org.eclipse.jdt.internal.compiler.lookup.BlockScope;
+
+/**
+ * Avoids visiting invalid local types due to compile errors or unreachability.
+ */
+public class SafeASTVisitor extends ASTVisitor {
+
+  @Override
+  public final void endVisit(TypeDeclaration typeDecl, BlockScope scope) {
+    if (typeDecl.binding == null || typeDecl.binding.constantPoolName() == null) {
+      /*
+       * Weird case: if JDT determines that this local class is totally
+       * uninstantiable, it won't bother allocating a local name.
+       */
+      return;
+    }
+    endVisitValid(typeDecl, scope);
+  }
+
+  public void endVisitValid(TypeDeclaration typeDecl, BlockScope scope) {
+    super.endVisit(typeDecl, scope);
+  }
+
+  @Override
+  public final boolean visit(TypeDeclaration typeDecl, BlockScope scope) {
+    if (typeDecl.binding == null || typeDecl.binding.constantPoolName() == null) {
+      /*
+       * Weird case: if JDT determines that this local class is totally
+       * uninstantiable, it won't bother allocating a local name.
+       */
+      return false;
+    }
+    return visitValid(typeDecl, scope);
+  }
+
+  public boolean visitValid(TypeDeclaration typeDecl, BlockScope scope) {
+    return super.visit(typeDecl, scope);
+  }
+}
diff --git a/dev/core/src/com/google/gwt/dev/jdt/TypeRefVisitor.java b/dev/core/src/com/google/gwt/dev/jdt/TypeRefVisitor.java
index 8aabe9f..f5fbe76 100644
--- a/dev/core/src/com/google/gwt/dev/jdt/TypeRefVisitor.java
+++ b/dev/core/src/com/google/gwt/dev/jdt/TypeRefVisitor.java
@@ -15,7 +15,7 @@
  */
 package com.google.gwt.dev.jdt;
 
-import org.eclipse.jdt.internal.compiler.ASTVisitor;
+
 import org.eclipse.jdt.internal.compiler.ast.ArrayQualifiedTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.ArrayTypeReference;
 import org.eclipse.jdt.internal.compiler.ast.CompilationUnitDeclaration;
@@ -41,7 +41,7 @@
 /**
  * Walks the AST to determine every location from which a type is referenced.
  */
-public abstract class TypeRefVisitor extends ASTVisitor {
+public abstract class TypeRefVisitor extends SafeASTVisitor {
 
   private final CompilationUnitDeclaration cud;
 
diff --git a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
index 7182bf3..b760bc6 100644
--- a/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
+++ b/dev/core/src/com/google/gwt/dev/jjs/impl/BuildTypeMap.java
@@ -16,6 +16,7 @@
 package com.google.gwt.dev.jjs.impl;
 
 import com.google.gwt.dev.javac.JsniCollector;
+import com.google.gwt.dev.jdt.SafeASTVisitor;
 import com.google.gwt.dev.jjs.HasSourceInfo;
 import com.google.gwt.dev.jjs.InternalCompilerException;
 import com.google.gwt.dev.jjs.SourceInfo;
@@ -41,7 +42,6 @@
 import com.google.gwt.dev.js.ast.JsNameRef;
 import com.google.gwt.dev.js.ast.JsProgram;
 
-import org.eclipse.jdt.internal.compiler.ASTVisitor;
 import org.eclipse.jdt.internal.compiler.CompilationResult;
 import org.eclipse.jdt.internal.compiler.ast.AbstractMethodDeclaration;
 import org.eclipse.jdt.internal.compiler.ast.AllocationExpression;
@@ -102,7 +102,7 @@
    * Note that methods and fields are not added to their classes here, that
    * isn't done until {@link GenerateJavaAST}.
    */
-  private static class BuildDeclMapVisitor extends ASTVisitor {
+  private static class BuildDeclMapVisitor extends SafeASTVisitor {
 
     private String currentFileName;
 
@@ -281,11 +281,6 @@
     }
 
     @Override
-    public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
-      return process(localTypeDeclaration);
-    }
-
-    @Override
     public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
       return process(memberTypeDeclaration);
     }
@@ -296,6 +291,12 @@
       return process(typeDeclaration);
     }
 
+    @Override
+    public boolean visitValid(TypeDeclaration localTypeDeclaration,
+        BlockScope scope) {
+      return process(localTypeDeclaration);
+    }
+
     private void addThrownExceptions(MethodBinding methodBinding, JMethod method) {
       for (ReferenceBinding thrownBinding : methodBinding.thrownExceptions) {
         JClassType type = (JClassType) typeMap.get(thrownBinding.erasure());
@@ -457,14 +458,6 @@
       currentSeparatorPositions = compResult.lineSeparatorPositions;
       currentFileName = String.valueOf(compResult.fileName);
       SourceTypeBinding binding = typeDeclaration.binding;
-
-      if (binding.constantPoolName() == null) {
-        /*
-         * Weird case: if JDT determines that this local class is totally
-         * uninstantiable, it won't bother allocating a local name.
-         */
-        return false;
-      }
       JDeclaredType type = (JDeclaredType) typeMap.get(binding);
       try {
         // Create an override for getClass().
@@ -637,7 +630,7 @@
    * there could be forward references, it is not possible to set up super
    * types; it must be done is a subsequent pass.
    */
-  private static class BuildTypeMapVisitor extends ASTVisitor {
+  private static class BuildTypeMapVisitor extends SafeASTVisitor {
 
     private final JProgram program;
 
@@ -649,12 +642,6 @@
     }
 
     @Override
-    public boolean visit(TypeDeclaration localTypeDeclaration, BlockScope scope) {
-      assert (TypeDeclaration.kind(localTypeDeclaration.modifiers) != TypeDeclaration.INTERFACE_DECL);
-      return process(localTypeDeclaration);
-    }
-
-    @Override
     public boolean visit(TypeDeclaration memberTypeDeclaration, ClassScope scope) {
       return process(memberTypeDeclaration);
     }
@@ -665,6 +652,13 @@
       return process(typeDeclaration);
     }
 
+    @Override
+    public boolean visitValid(TypeDeclaration localTypeDeclaration,
+        BlockScope scope) {
+      assert (TypeDeclaration.kind(localTypeDeclaration.modifiers) != TypeDeclaration.INTERFACE_DECL);
+      return process(localTypeDeclaration);
+    }
+
     private SourceInfo makeSourceInfo(TypeDeclaration typeDecl) {
       CompilationResult compResult = typeDecl.compilationResult;
       int[] indexes = compResult.lineSeparatorPositions;
@@ -677,18 +671,10 @@
 
     private boolean process(TypeDeclaration typeDeclaration) {
       try {
-        String name = dotify(typeDeclaration.binding.compoundName);
         SourceTypeBinding binding = typeDeclaration.binding;
+        String name = dotify(binding.compoundName);
         if (binding instanceof LocalTypeBinding) {
           char[] localName = binding.constantPoolName();
-          if (localName == null) {
-            /*
-             * Weird case: if JDT determines that this local class is totally
-             * uninstantiable, it won't bother allocating a local name.
-             */
-            return false;
-          }
-
           name = new String(localName).replace('/', '.');
         }