/**
   * Finds the constant definition that contains aAST.
   *
   * @param ast the AST
   * @return the constant def or null if ast is not contained in a constant definition
   */
  private DetailAST findContainingConstantDef(DetailAST ast) {
    DetailAST varDefAST = ast;
    while (varDefAST != null
        && varDefAST.getType() != TokenTypes.VARIABLE_DEF
        && varDefAST.getType() != TokenTypes.ENUM_CONSTANT_DEF) {
      varDefAST = varDefAST.getParent();
    }

    // no containing variable definition?
    if (varDefAST == null) {
      return null;
    }

    // implicit constant?
    if (ScopeUtils.inInterfaceOrAnnotationBlock(varDefAST)
        || varDefAST.getType() == TokenTypes.ENUM_CONSTANT_DEF) {
      return varDefAST;
    }

    // explicit constant
    final DetailAST modifiersAST = varDefAST.findFirstToken(TokenTypes.MODIFIERS);
    if (modifiersAST.branchContains(TokenTypes.FINAL)) {
      return varDefAST;
    }

    return null;
  }
  @Override
  public void visitToken(DetailAST ast) {
    // do not check local variables and
    // fields declared in interface/annotations
    if (ScopeUtils.isLocalVariableDef(ast) || ScopeUtils.inInterfaceOrAnnotationBlock(ast)) {
      return;
    }

    final DetailAST assign = ast.findFirstToken(TokenTypes.ASSIGN);
    if (assign == null) {
      // no assign - no check
      return;
    }

    final DetailAST modifiers = ast.findFirstToken(TokenTypes.MODIFIERS);
    if (modifiers != null && modifiers.branchContains(TokenTypes.FINAL)) {
      // do not check final variables
      return;
    }

    final DetailAST type = ast.findFirstToken(TokenTypes.TYPE);
    final DetailAST ident = ast.findFirstToken(TokenTypes.IDENT);
    final DetailAST exprStart = assign.getFirstChild().getFirstChild();
    if (isObjectType(type) && exprStart.getType() == TokenTypes.LITERAL_NULL) {
      log(ident, MSG_KEY, ident.getText(), "null");
    }

    final int primitiveType = type.getFirstChild().getType();
    if (primitiveType == TokenTypes.LITERAL_BOOLEAN
        && exprStart.getType() == TokenTypes.LITERAL_FALSE) {
      log(ident, MSG_KEY, ident.getText(), "false");
    }
    if (isNumericType(primitiveType) && isZero(exprStart)) {
      log(ident, MSG_KEY, ident.getText(), "0");
    }
    if (primitiveType == TokenTypes.LITERAL_CHAR
        && (isZero(exprStart)
            || exprStart.getType() == TokenTypes.CHAR_LITERAL
                && "'\\0'".equals(exprStart.getText()))) {
      log(ident, MSG_KEY, ident.getText(), "\\0");
    }
  }