public boolean preVisit2(ASTNode node) {
    ASTNode previous = null;

    List properties = node.structuralPropertiesForType();
    for (int i = 0; i < properties.size(); i++) {
      StructuralPropertyDescriptor property = (StructuralPropertyDescriptor) properties.get(i);
      if (property.isChildProperty()) {
        ASTNode child = (ASTNode) node.getStructuralProperty(property);
        if (child != null) {
          boolean ok = checkChild(node, previous, child);
          if (ok) {
            previous = child;
          } else {
            return false;
          }
        }
      } else if (property.isChildListProperty()) {
        List children = (List) node.getStructuralProperty(property);
        for (int j = 0; j < children.size(); j++) {
          ASTNode child = (ASTNode) children.get(j);
          boolean ok = checkChild(node, previous, child);
          if (ok) {
            previous = child;
          } else {
            return false;
          }
        }
      }
    }
    return true;
  }
  /**
   * @param node the ast node in question
   * @param decls the list to be populated. adding the declaration(s) corresponding to the ast node
   *     to this list.
   */
  @SuppressWarnings("unchecked")
  protected void getDeclarations(ASTNode node, List<Declaration> decls) {
    if (node == null) return;
    IBinding binding = null;
    switch (node.getNodeType()) {
      case ASTNode.FIELD_DECLARATION:
        final List<VariableDeclarationFragment> fragments =
            ((org.aspectj.org.eclipse.jdt.core.dom.FieldDeclaration) node).fragments();
        for (VariableDeclarationFragment frag : fragments) {
          final IBinding fieldBinding = frag.resolveBinding();
          final EclipseDeclarationImpl decl;
          if (fieldBinding != null) decl = Factory.createDeclaration(fieldBinding, this);
          else {
            decl = Factory.createDeclaration(frag, getFileForNode(frag), this);
          }
          if (decl != null) decls.add(decl);
        }
        return;

      case ASTNode.ENUM_CONSTANT_DECLARATION:
        binding =
            ((org.aspectj.org.eclipse.jdt.core.dom.EnumConstantDeclaration) node).resolveVariable();
        break;
      case ASTNode.METHOD_DECLARATION:
        binding = ((org.aspectj.org.eclipse.jdt.core.dom.MethodDeclaration) node).resolveBinding();
        break;
      case ASTNode.ANNOTATION_TYPE_MEMBER_DECLARATION:
        binding = ((AnnotationTypeMemberDeclaration) node).resolveBinding();
        break;
      case ASTNode.TYPE_DECLARATION:
      case ASTNode.ANNOTATION_TYPE_DECLARATION:
      case ASTNode.ENUM_DECLARATION:
        binding = ((AbstractTypeDeclaration) node).resolveBinding();
        break;
      case ASTNode.SINGLE_VARIABLE_DECLARATION:
        // Need to create the declaration with the ast node, not the binding
        break;
      case ASTNode.PACKAGE_DECLARATION:
        binding = ((org.aspectj.org.eclipse.jdt.core.dom.PackageDeclaration) node).resolveBinding();
        break;
      default:
        throw new UnsupportedOperationException(
            "unknown node type: " + node.getNodeType()); // $NON-NLS-1$
    }

    final EclipseDeclarationImpl decl;
    if (binding != null) decl = Factory.createDeclaration(binding, this);
    else {
      decl = Factory.createDeclaration(node, getFileForNode(node), this);
    }
    if (decl != null) decls.add(decl);

    return;
  }
 /**
  * Verifies proper node nesting as specified in {@link ASTParser#setKind(int)}:
  *
  * <p>Source ranges nest properly: the source range for a child is always within the source range
  * of its parent, and the source ranges of sibling nodes never overlap.
  *
  * @param node
  * @return <code>null</code> if everything is OK; a list of errors otherwise
  */
 public String process(ASTNode node) {
   StringBuffer buffer = new StringBuffer();
   this.bugs = buffer;
   node.accept(this);
   this.bugs = null;
   if (buffer.length() == 0) return null;
   return buffer.toString();
 }
  private boolean checkChild(ASTNode parent, ASTNode previous, ASTNode child) {
    if ((parent.getFlags() & (ASTNode.RECOVERED | ASTNode.MALFORMED)) != 0
        || (child.getFlags() & (ASTNode.RECOVERED | ASTNode.MALFORMED)) != 0) return false;

    int parentStart = parent.getStartPosition();
    int parentEnd = parentStart + parent.getLength();

    int childStart = child.getStartPosition();
    int childEnd = childStart + child.getLength();

    if (previous != null) {
      // Turn a blind eye on a known problem ... see https://bugs.eclipse.org/391894#c4
      if (child.getLocationInParent() == ArrayCreation.DIMENSIONS_PROPERTY) return false;

      int previousStart = previous.getStartPosition();
      int previousEnd = previousStart + previous.getLength();
      if (childStart < previousEnd) {
        String bug =
            "- parent ["
                + parentStart
                + ", "
                + parentEnd
                + "] "
                + parent.getClass().getName()
                + '\n' //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                + "   previous ["
                + previousStart
                + ", "
                + previousEnd
                + "] "
                + previous.getClass().getName()
                + '\n' //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
                + "   "
                + child.getLocationInParent().getId()
                + " ["
                + childStart
                + ", "
                + childEnd
                + "] "
                + child.getClass().getName()
                + '\n'; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
        this.bugs.append(bug);
      }
    }
    if (!(parentStart <= childStart && childEnd <= parentEnd)) {
      String bug =
          "- parent ["
              + parentStart
              + ", "
              + parentEnd
              + "] "
              + parent.getClass().getName()
              + '\n' //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
              + "   "
              + child.getLocationInParent().getId()
              + " ["
              + childStart
              + ", "
              + childEnd
              + "] "
              + child.getClass().getName()
              + '\n'; //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ //$NON-NLS-4$
      this.bugs.append(bug);
    }
    return true;
  }
  protected IFile getFileForNode(final ASTNode node) {
    if (node.getRoot() == _astRoot) return _file;

    throw new IllegalStateException(); // should never get here.
  }