package com.mikesamuel.cil.util;

import java.util.logging.Level;
import java.util.logging.Logger;

import javax.annotation.Nullable;

import com.google.common.collect.ImmutableSet;
import com.mikesamuel.cil.parser.Positioned;
import com.mikesamuel.cil.parser.SourcePosition;

/**
 * Utilities for java.util.logging.
 */
public class LogUtils {

  private static final ImmutableSet<String> LOG_WRAPPER_METHOD_NAMES =
      ImmutableSet.of("log", "error", "warn");

  /**
   * Emits a log message.
   */
  public static void log(
      Logger logger, Level level, @Nullable Positioned pos, String message,
      Throwable th) {
    String fullMessage = fullMessage(pos, message);
    StackTraceElement[] trace = Thread.currentThread().getStackTrace();
    String sourceClass = null;
    String sourceMethod = null;
    for (int i = 1, n = trace.length; i < n; ++i) {
      StackTraceElement traceElement = trace[i];
      String methodName = traceElement.getMethodName();
      if (!LOG_WRAPPER_METHOD_NAMES.contains(methodName)) {
        sourceClass = traceElement.getClassName();
        sourceMethod = methodName;
        break;
      }
    }

    logger.logp(level, sourceClass, sourceMethod, fullMessage, th);
  }

  private static String fullMessage(
      @Nullable Positioned p, String message) {
    SourcePosition pos = p != null ? p.getSourcePosition() : null;
    return pos != null ? pos + ": " + message : message;
  }
}

@@ -128,16 +128,56 @@
 lable;%0A%0A
+import com.google.common.base.Optional;%0A
 import c
@@ -245,74 +245,499 @@
 cil.
-parser.Positioned;%0Aimport com.mikesamuel.cil.parser.SourcePosition
+ast.Trees;%0Aimport com.mikesamuel.cil.ast.j8.J8BaseNode;%0Aimport com.mikesamuel.cil.event.Event;%0Aimport com.mikesamuel.cil.parser.Positioned;%0Aimport com.mikesamuel.cil.parser.SList;%0Aimport com.mikesamuel.cil.parser.SerialErrorReceiver;%0Aimport com.mikesamuel.cil.parser.SerialState;%0Aimport com.mikesamuel.cil.parser.SourcePosition;%0Aimport com.mikesamuel.cil.parser.Unparse;%0Aimport com.mikesamuel.cil.parser.Unparse.UnparseVerificationException;%0Aimport com.mikesamuel.cil.parser.Unparse.Verified
 ;%0A%0A/
@@ -1890,11 +1890,807 @@
 age;%0A  %7D
+%0A%0A  /** Best effort to format the given AST.  Output is not length limited. */%0A  public static String serialize(J8BaseNode node) %7B%0A    SList%3CEvent%3E events = Trees.startUnparse(null, node, null);%0A    Optional%3CSerialState%3E sstate = node.getVariant().getParSer().unparse(%0A        new SerialState(SList.forwardIterable(events)),%0A        SerialErrorReceiver.DEV_NULL);%0A    if (sstate.isPresent()) %7B%0A      Verified verified;%0A      try %7B%0A        verified = Unparse.verify(%0A            SList.forwardIterable(sstate.get().output));%0A      %7D catch (@SuppressWarnings(%22unused%22)%0A               UnparseVerificationException e) %7B%0A        verified = null;%0A      %7D%0A      if (verified != null) %7B%0A        return Unparse.format(verified).code;%0A      %7D%0A    %7D%0A    return %22%3Cunprintable %22 + node.getNodeType() + %22%3E%22;%0A  %7D
 %0A%7D%0A

make it easy to render nodes for error messages