/**
   * Wrap the given expression with a logging method call. Some kinds of expressions don't like
   * being wrapped in a simple fashion and so we have to handle them specially. The
   * ExpressionTransformer doesn't have methods for each type so we check for each one here.
   *
   * <p>TODO: There are potentially other expressions which need special handling (like indexing and
   * variables). This code may be working because those types have their parent being wrapped and we
   * don't transform their children.
   *
   * @param lineNumber line number to report for this value
   * @param expression the expression whose value we want to report
   * @return an expression that computes the value and also reports it somewheres
   */
  private Expression loggingExpression(Integer lineNumber, Expression expression) {
    if (expression instanceof DeclarationExpression) {
      DeclarationExpression declarationExpression = (DeclarationExpression) expression;

      return new DeclarationExpression(
          declarationExpression.getLeftExpression(),
          declarationExpression.getOperation(),
          loggingExpression(lineNumber, declarationExpression.getRightExpression()));
    }

    if (expression instanceof BooleanExpression) {
      BooleanExpression booleanExpression = (BooleanExpression) expression;
      return new BooleanExpression(
          new MethodCallExpression(
              new VariableExpression("this"),
              "_log",
              new ArgumentListExpression(
                  new ConstantExpression(lineNumber), booleanExpression.getExpression())));
    }

    return new MethodCallExpression(
        new VariableExpression("this"),
        "_log",
        new ArgumentListExpression(new ConstantExpression(lineNumber), expression));
  }
  protected void addError(String msg, ASTNode expr) {
    int line = expr.getLineNumber();
    int col = expr.getColumnNumber();
    // GRECLIPSE
    int start = expr.getStart();
    int end = expr.getEnd() - 1;
    if (expr instanceof ClassNode) {
      // assume we have a class declaration
      ClassNode cn = (ClassNode) expr;
      if (cn.getNameEnd() > 0) {
        start = cn.getNameStart();
        end = cn.getNameEnd();
      } else if (cn.getComponentType() != null) {
        // avoid extra whitespace after closing ]
        end--;
      }

    } else if (expr instanceof DeclarationExpression) {
      // assume that we just want to underline the variable declaration
      DeclarationExpression decl = (DeclarationExpression) expr;
      Expression lhs = decl.getLeftExpression();
      start = lhs.getStart();
      // avoid extra space before = if a variable
      end =
          lhs instanceof VariableExpression ? start + lhs.getText().length() - 1 : lhs.getEnd() - 1;
    }
    // end

    SourceUnit source = getSourceUnit();
    source
        .getErrorCollector()
        .addErrorAndContinue(
            // GRECLIPSE: start
            new SyntaxErrorMessage(
                new PreciseSyntaxException(msg + '\n', line, col, start, end), source)
            // end
            );
  }