/**
   * @param locateNode
   * @return true if the given path indicates a trait
   */
  private static boolean isTraitName(ASTNode locateNode) {
    assert locateNode != null;

    ASTNode parent = null;
    if (locateNode.getType() == ASTNode.CLASS_DECLARATION) {
      parent = locateNode;
    } else if (locateNode.getType() == ASTNode.IDENTIFIER) {
      parent = locateNode.getParent();
    } else {
      return false;
    }

    if (parent.getType() == ASTNode.NAMESPACE_NAME) {
      locateNode = parent;
      parent = parent.getParent();
    }

    final int parentType = parent.getType();
    if (parentType == ASTNode.CLASS_DECLARATION
        || parentType == ASTNode.TRAIT_USE_STATEMENT
        || parentType == ASTNode.FULLY_QUALIFIED_TRAIT_METHOD_REFERENCE) {
      if (parentType == ASTNode.FULLY_QUALIFIED_TRAIT_METHOD_REFERENCE) {
        FullyQualifiedTraitMethodReference reference = (FullyQualifiedTraitMethodReference) parent;
        if (reference.getFunctionName() == locateNode) {
          return false;
        }
      }
      return true;
    }

    return false;
  }
  /**
   * Identifies a dispatch usage
   *
   * @param locateNode
   */
  private static boolean isDispatch(ASTNode locateNode) {
    assert locateNode != null;

    ASTNode parent = null;
    // check if it is an identifier
    final int type = locateNode.getType();
    if (locateNode instanceof Identifier
        && ((Identifier) locateNode).getParent() instanceof Variable) {
      parent = (Variable) ((Identifier) locateNode).getParent();
      parent = parent.getParent();
    } else if (type == ASTNode.SINGLE_FIELD_DECLARATION
        || type == ASTNode.FIELD_DECLARATION
        || type == ASTNode.METHOD_DECLARATION) {
      parent = locateNode;
    } else {
      parent = locateNode.getParent();
    }

    if (parent instanceof TraitAlias) {
      // TraitAlias ta = (TraitAlias) parent;
      // return locateNode == ta.getTraitMethod();
      return true;
    }
    // check if it is a method declaration
    if (parent.getType() == ASTNode.FUNCTION_DECLARATION) {
      // check if it is a method declaration
      if (parent.getParent() != null) {
        parent = parent.getParent();
        if (parent.getType() == ASTNode.METHOD_DECLARATION) {
          return true;
        }
      }
      return false;
    }

    if (parent.getType() == ASTNode.FULLY_QUALIFIED_TRAIT_METHOD_REFERENCE) {
      FullyQualifiedTraitMethodReference reference = (FullyQualifiedTraitMethodReference) parent;
      if (reference.getFunctionName() == locateNode) {
        return true;
      }
      return false;
    }

    if (parent.getType() == ASTNode.SINGLE_FIELD_DECLARATION) {
      // check for $this variable
      if (parent.getParent().getType() == ASTNode.FIELD_DECLARATION
          || parent.getParent().getType() == ASTNode.SINGLE_FIELD_DECLARATION) {
        return true;
      }
    }

    if (parent.getType() == ASTNode.FIELD_DECLARATION
        || parent.getType() == ASTNode.METHOD_DECLARATION) {
      return true;
    }

    if (parent.getType() == ASTNode.VARIABLE) {
      if (parent.getParent().getType() == ASTNode.FIELD_DECLARATION
          || parent.getParent().getType() == ASTNode.SINGLE_FIELD_DECLARATION) {
        return true;
      }
    }

    if (parent.getType() == ASTNode.CONSTANT_DECLARATION) return true;

    // check if it is a dispatch
    while (parent != null) {
      if (parent instanceof Dispatch || parent instanceof StaticDispatch) {
        return true;
      }
      parent = parent.getParent();
    }
    return false;
  }