/**
   * @param binding must be correspond to a type, method or field declaration.
   * @return the compilation unit that contains the declaration of the given binding.
   */
  public CompilationUnit getCompilationUnitForBinding(final IBinding binding) {
    assert binding.getKind() == IBinding.TYPE
        || binding.getKind() == IBinding.METHOD
        || binding.getKind() == IBinding.VARIABLE;
    CompilationUnit domUnit = searchLocallyForBinding(binding);
    if (domUnit != null) return domUnit;
    else {
      final IMember member = (IMember) binding.getJavaElement();
      final ICompilationUnit unit;
      if (member != null) {
        unit = member.getCompilationUnit();
      } else {
        final ITypeBinding typeBinding = getDeclaringClass(binding);
        // binary type don't have compilation unit.
        if (!typeBinding.isFromSource()) return null;
        if (_typeBinding2ModelCompUnit.get(typeBinding) != null)
          unit = _typeBinding2ModelCompUnit.get(typeBinding);
        else {
          final String qname = typeBinding.getQualifiedName();
          unit = getICompilationUnitForTopLevelType(qname);
        }
      }
      if (unit == null) return null;

      final CompilationUnit astUnit = _modelCompUnit2astCompUnit.get(unit);
      if (astUnit != null) return astUnit;
      else {
        // Note: very expensive operation. we are re-compiling a file with binding information.
        final ASTParser parser = ASTParser.newParser(AST.JLS3);
        parser.setResolveBindings(true);
        parser.setBindingsRecovery(true);
        parser.setSource(unit);
        parser.setFocalPosition(0);
        parser.setIgnoreMethodBodies(true);
        CompilationUnit resultUnit = (CompilationUnit) parser.createAST(null);
        _modelCompUnit2astCompUnit.put(unit, resultUnit);
        return resultUnit;
      }
    }
  }
  /**
   * @param binding must be correspond to a type, method or field declaration
   * @return the file that contains the declaration of given binding.
   */
  public IFile getDeclaringFileForBinding(final IBinding binding) {
    assert binding.getKind() == IBinding.TYPE
        || binding.getKind() == IBinding.METHOD
        || binding.getKind() == IBinding.VARIABLE;
    // check to see whether it is in the current file.
    IFile file = searchLocallyForIFile(binding);
    if (file != null) return file;

    final IMember member = (IMember) binding.getJavaElement();
    if (member != null) {
      final ICompilationUnit unit = member.getCompilationUnit();
      return (IFile) unit.getResource();
    } else {
      final ITypeBinding type = getDeclaringClass(binding);
      assert type.isTopLevel() : "type must be top-level type"; // $NON-NLS-1$
      ICompilationUnit unit = _typeBinding2ModelCompUnit.get(type);
      if (unit != null) return (IFile) unit.getResource();
      final String qname = type.getQualifiedName();
      unit = getICompilationUnitForTopLevelType(qname);
      if (unit == null) return null;
      return (IFile) unit.getResource();
    }
  }
 /**
  * @param binding a type, method or field binding.
  * @return the top-level type binding that declares <code>binding</code> or itself if it is
  *     already one.
  */
 protected static ITypeBinding getDeclaringClass(final IBinding binding) {
   assert binding != null : "binding cannot be null"; // $NON-NLS-1$
   ITypeBinding aTypeBinding = null;
   switch (binding.getKind()) {
     case IBinding.TYPE:
       aTypeBinding = (ITypeBinding) binding;
       break;
     case IBinding.METHOD:
       aTypeBinding = ((IMethodBinding) binding).getDeclaringClass();
       break;
     case IBinding.VARIABLE:
       aTypeBinding = ((IVariableBinding) binding).getDeclaringClass();
       break;
     default:
       throw new IllegalStateException(
           "unrecognized binding type " + binding.getKind()); // $NON-NLS-1$
   }
   if (aTypeBinding == null) return null;
   while (!aTypeBinding.isTopLevel()) {
     aTypeBinding = aTypeBinding.getDeclaringClass();
   }
   return aTypeBinding;
 }
 public void acceptBinding(String bindingKey, IBinding binding) {
   if (binding != null) {
     _result = binding;
     _kind = binding.getKind();
   }
 }
 /**
  * @param binding must be correspond to a type, method or field declaration.
  * @return the ast node the corresponds to the declaration of the given binding. Return null if
  *     none is found.
  */
 public ASTNode getASTNodeForBinding(final IBinding binding) {
   final CompilationUnit astUnit = getCompilationUnitForBinding(binding);
   if (astUnit == null) return null;
   return astUnit.findDeclaringNode(binding.getKey());
 }