/**
   * @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();
    }
  }