/** This should create an AST without imports or method-body statements */
  public static CompilationUnit createAST(
      IJavaProject javaProject, final ICompilationUnit compilationUnit) {
    if (compilationUnit == null) return null;

    class CompilationUnitRequestor extends ASTRequestor {
      CompilationUnit domUnit = EMPTY_AST_UNIT;

      public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
        if (source == compilationUnit) domUnit = ast;
      }
    }

    CompilationUnitRequestor requestor = new CompilationUnitRequestor();
    ASTParser p = ASTParser.newParser(AST.JLS3);
    p.setResolveBindings(true);
    p.setBindingsRecovery(true);
    p.setProject(javaProject);
    p.setKind(ASTParser.K_COMPILATION_UNIT);
    p.setIgnoreMethodBodies(true);
    p.createASTs(new ICompilationUnit[] {compilationUnit}, NO_KEYS, requestor, null);
    if (AptPlugin.DEBUG) {
      AptPlugin.trace("created DOM AST for " + compilationUnit.getElementName()); // $NON-NLS-1$
    }
    return requestor.domUnit;
  }
  /**
   * Parse and fully resolve all files.
   *
   * @param javaProject
   * @param parseUnits the files to be parsed and resolved.
   */
  static void createASTs(
      final IJavaProject javaProject, final ICompilationUnit[] parseUnits, ASTRequestor requestor) {
    // Construct exactly 1 binding key. When acceptBinding is called we know that
    // All ASTs have been returned. This also means that a pipeline is opened when
    // there are no asts. This is needed by the batch processors.
    String bogusKey = BindingKey.createTypeBindingKey("java.lang.Object"); // $NON-NLS-1$
    String[] keys = new String[] {bogusKey};

    ASTParser p = ASTParser.newParser(AST.JLS3);
    p.setResolveBindings(true);
    p.setBindingsRecovery(true);
    p.setProject(javaProject);
    p.setKind(ASTParser.K_COMPILATION_UNIT);
    p.setIgnoreMethodBodies(true);
    p.createASTs(parseUnits, keys, requestor, null);
  }
  /**
   * @param key
   * @param unit the unit that contains the definition of type whose type key is <code>key</code> if
   *     <code>key</code> is a wild card, primitive, array type or parameterized type, this should
   *     be null.
   * @return return the type binding for the given key or null if none is found.
   */
  protected IBinding getBindingFromKey(final String key, final ICompilationUnit unit) {

    class BindingRequestor extends ASTRequestor {
      private IBinding _result = null;
      private int _kind;

      public void acceptAST(ICompilationUnit source, CompilationUnit ast) {
        if (source == unit) {
          _modelCompUnit2astCompUnit.put(source, ast);
        }
      }

      public void acceptBinding(String bindingKey, IBinding binding) {
        if (binding != null) {
          _result = binding;
          _kind = binding.getKind();
        }
      }
    }

    final BindingRequestor requestor = new BindingRequestor();
    final ASTParser parser = ASTParser.newParser(AST.JLS3);
    parser.setResolveBindings(true);
    parser.setBindingsRecovery(true);
    parser.setProject(_javaProject);
    parser.setIgnoreMethodBodies(true);
    ICompilationUnit[] units = unit == null ? NO_UNIT : new ICompilationUnit[] {unit};
    parser.createASTs(units, new String[] {key}, requestor, null);
    final IBinding result = requestor._result;
    if (result != null && unit != null) {
      final CompilationUnit astUnit = _modelCompUnit2astCompUnit.get(unit);
      // make sure everything is lining up properly.  Only cache real types, not package-infos.
      if (requestor._kind == IBinding.TYPE && astUnit.findDeclaringNode(result) != null) {
        ITypeBinding declaringClass = getDeclaringClass(result);
        _typeBinding2ModelCompUnit.put(declaringClass, unit);
      }
    }
    return result;
  }