private void visitBreak(IASTStatement statement)
      throws ScopeTraceException, BadLocationException {
    if (_scopeStack.isEmpty())
      throw new ScopeTraceException("break without scope: " + statement); // $NON-NLS-1$

    ScopeInfo scope = _scopeStack.peek();

    String hintType;
    if (scope._statement instanceof IASTForStatement) hintType = "break-for"; // $NON-NLS-1$
    else if (scope._statement instanceof IASTWhileStatement)
      hintType = "break-while"; // $NON-NLS-1$
    else if (scope._statement instanceof IASTDoStatement) hintType = "break-do"; // $NON-NLS-1$
    else if (scope._statement instanceof IASTCaseStatement
        || scope._statement instanceof IASTDefaultStatement) hintType = "break-case"; // $NON-NLS-1$
    else
      throw new ScopeTraceException(
          "Unexpect scope ("
              + scope._statement
              + ") on break/continue:"
              + statement); //$NON-NLS-1$ //$NON-NLS-2$

    int endLoc =
        statement.getFileLocation().getNodeOffset()
            + statement.getFileLocation().getNodeLength()
            - 1;
    _container.add(new Hint(hintType, scope._offset, endLoc, scope._str));
  }
  private void visitIf(IASTIfStatement statement) throws BadLocationException {
    /* TODO: specific params: don't show the if hint if there's an "else if" after it (by checking if the elseClause is an instance of ifstatment) */

    String hint = ""; // $NON-NLS-1$
    if (statement.getConditionExpression() != null) {
      hint = statement.getConditionExpression().getRawSignature();
    } else {
      if ((statement instanceof ICPPASTIfStatement)
          && ((ICPPASTIfStatement) statement).getConditionDeclaration() != null) {
        hint = ((ICPPASTIfStatement) statement).getConditionDeclaration().getRawSignature();
      }
    }

    IASTStatement thenClause = statement.getThenClause();
    IASTStatement elseClause = statement.getElseClause();

    boolean showIfHint = (elseClause == null);
    int endLoc = -1;
    if (!showIfHint) {
      if (elseClause.getFileLocation().getStartingLineNumber()
          != thenClause.getFileLocation().getEndingLineNumber()) {
        showIfHint = true;
      }

      // if the else looks like this "} else {", then show the hint on the "{"
      if (!showIfHint && !(elseClause instanceof IASTIfStatement)) {
        endLoc = elseClause.getFileLocation().getNodeOffset();
        showIfHint = true;
      }
    }

    if (showIfHint && !(thenClause instanceof IASTCompoundStatement)) showIfHint = false;

    if (showIfHint) {
      IASTFileLocation location = thenClause.getFileLocation();
      if (endLoc == -1) endLoc = location.getNodeOffset() + location.getNodeLength() - 1;
      int startLoc = statement.getFileLocation().getNodeOffset();
      _container.add(
          new Hint(
              "if",
              startLoc,
              endLoc,
              "if( " + hint + " )")); // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    }

    if (elseClause != null
        && !(elseClause instanceof IASTIfStatement)
        && (elseClause instanceof IASTCompoundStatement)) {
      IASTFileLocation location = elseClause.getFileLocation();
      endLoc = location.getNodeOffset() + location.getNodeLength() - 1;
      int startLoc = location.getNodeOffset();
      _container.add(
          new Hint(
              "if",
              startLoc,
              endLoc,
              "else_of_if( " + hint + " )")); // $NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$
    }
  }
  private void visitFunc(IASTFunctionDefinition declaration) throws BadLocationException {
    IASTStatement body = declaration.getBody();
    if (!(body instanceof IASTCompoundStatement)) return;

    // starting a function empties the stack... (which should already be empty on good flow)
    _scopeStack.clear();

    IASTFileLocation location = body.getFileLocation();
    int endLoc = location.getNodeOffset() + location.getNodeLength() - 1;

    IASTFunctionDeclarator declerator = declaration.getDeclarator();
    int startLoc = declerator.getFileLocation().getNodeOffset();

    StringBuffer hint = new StringBuffer();
    hint.append(declerator.getName().getRawSignature());
    /* TODO: specific params: exclude function parameters (show only the name) */
    hint.append("( "); // $NON-NLS-1$
    IASTNode[] decChildren = declerator.getChildren();
    boolean firstParam = true;
    for (int i = 0; i < decChildren.length; i++) {
      IASTNode node = decChildren[i];
      if (node instanceof IASTParameterDeclaration) {
        IASTParameterDeclaration param = (IASTParameterDeclaration) node;
        if (firstParam) firstParam = false;
        else hint.append(", "); // $NON-NLS-1$
        hint.append(param.getDeclarator().getName());
      }
    }
    hint.append(" )"); // $NON-NLS-1$

    _container.add(new Hint("function", startLoc, endLoc, hint.toString())); // $NON-NLS-1$
  }
  private void visitCase(IASTStatement statement) throws ScopeTraceException {
    /* TODO: specific params: don't show the switch part (only the case argument) */

    ScopeInfo scope = _scopeStack.peek();
    if (!(scope._statement instanceof IASTSwitchStatement)) {
      if (!((scope._statement instanceof IASTCaseStatement)
          || (scope._statement instanceof IASTDefaultStatement))) {
        throw new ScopeTraceException(
            "Lost track of stack (in case), found:" + scope._statement); // $NON-NLS-1$
      }

      _scopeStack.pop();
      scope = _scopeStack.peek();
    }

    if (!(scope._statement instanceof IASTSwitchStatement)) {
      throw new ScopeTraceException(
          "Lost track of stack (in case2), found:" + scope._statement); // $NON-NLS-1$
    }

    String hint = ""; // $NON-NLS-1$
    if (statement instanceof IASTCaseStatement) {
      IASTExpression cond = ((IASTCaseStatement) statement).getExpression();
      if (cond != null) hint = cond.getRawSignature();
      hint = "case: " + hint; // $NON-NLS-1$
    } else // default
    {
      hint = "default"; // $NON-NLS-1$
    }

    int startLoc = statement.getFileLocation().getNodeOffset();
    _scopeStack.push(new ScopeInfo(scope._str + " - " + hint, startLoc, statement)); // $NON-NLS-1$
  }
  protected int writeMixedStatement(IASTStatement statement) {
    IFile file = FileHelper.getFileFromNode(statement);
    int offset = statement.getFileLocation().getNodeOffset();
    int length = statement.getFileLocation().getNodeLength();
    String code = FileContentHelper.getContent(file, offset, length);

    scribe.println(code);
    return ASTVisitor.PROCESS_SKIP;
  }
  private void visitWhile(IASTWhileStatement statement) throws BadLocationException {
    IASTExpression cond = statement.getCondition();
    String hint = ""; // $NON-NLS-1$
    if (cond != null) hint = cond.getRawSignature();
    hint = "while( " + hint + " )"; // $NON-NLS-1$ //$NON-NLS-2$
    int startLoc = statement.getFileLocation().getNodeOffset();
    _scopeStack.push(new ScopeInfo(hint, startLoc, statement));

    IASTStatement body = statement.getBody();
    if (body instanceof IASTCompoundStatement) {
      IASTFileLocation location = body.getFileLocation();

      int endLoc = location.getNodeOffset() + location.getNodeLength() - 1;
      _container.add(new Hint("while", startLoc, endLoc, hint)); // $NON-NLS-1$
    }
  }
  private void visitFor(IASTForStatement statement) throws BadLocationException {
    /* TODO: specific params: show also initializer && increment expressions */

    IASTExpression cond = statement.getConditionExpression();
    String hint = ""; // $NON-NLS-1$
    if (cond != null) hint = cond.getRawSignature();
    hint = "for( " + hint + " )"; // $NON-NLS-1$ //$NON-NLS-2$
    int startLoc = statement.getFileLocation().getNodeOffset();
    _scopeStack.push(new ScopeInfo(hint, startLoc, statement));

    IASTStatement body = statement.getBody();
    if (body instanceof IASTCompoundStatement) {
      IASTFileLocation location = body.getFileLocation();
      int endLoc = location.getNodeOffset() + location.getNodeLength() - 1;
      _container.add(new Hint("for", startLoc, endLoc, hint)); // $NON-NLS-1$
    }
  }