<commit_before>package tools.debugger;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.oracle.truffle.api.debug.Debugger;
import com.oracle.truffle.api.debug.DebuggerSession.SteppingLocation;
import com.oracle.truffle.api.debug.SuspendedCallback;
import com.oracle.truffle.api.debug.SuspendedEvent;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.instrumentation.Instrumenter;
import com.oracle.truffle.api.instrumentation.TruffleInstrument;
import com.oracle.truffle.api.instrumentation.TruffleInstrument.Registration;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;

import som.interpreter.actors.Actor.ActorProcessingThread;
import som.primitives.threading.ThreadPrimitives.SomThread;
import tools.debugger.frontend.Suspension;
import tools.debugger.message.InitialBreakpointsMessage;
import tools.debugger.message.Message.IncommingMessage;
import tools.debugger.message.Message.OutgoingMessage;
import tools.debugger.message.ScopesRequest;
import tools.debugger.message.ScopesResponse;
import tools.debugger.message.SourceMessage;
import tools.debugger.message.StackTraceRequest;
import tools.debugger.message.StackTraceResponse;
import tools.debugger.message.StepMessage.Resume;
import tools.debugger.message.StepMessage.Return;
import tools.debugger.message.StepMessage.StepInto;
import tools.debugger.message.StepMessage.StepOver;
import tools.debugger.message.StepMessage.Stop;
import tools.debugger.message.StoppedMessage;
import tools.debugger.message.SuspendedEventMessage;
import tools.debugger.message.SymbolMessage;
import tools.debugger.message.UpdateBreakpoint;
import tools.debugger.message.VariablesRequest;
import tools.debugger.message.VariablesResponse;
import tools.debugger.session.AsyncMessageReceiverBreakpoint;
import tools.debugger.session.BreakpointInfo;
import tools.debugger.session.Breakpoints;
import tools.debugger.session.LineBreakpoint;
import tools.debugger.session.MessageReceiverBreakpoint;
import tools.debugger.session.MessageSenderBreakpoint;
import tools.debugger.session.PromiseResolutionBreakpoint;
import tools.debugger.session.PromiseResolverBreakpoint;


/**
 * The WebDebugger connects the Truffle debugging facilities with a HTML5
 * application using WebSockets and JSON.
 */
@Registration(id = WebDebugger.ID)
public class WebDebugger extends TruffleInstrument implements SuspendedCallback {

  public static final String ID = "web-debugger";

  private FrontendConnector connector;
  private Instrumenter      instrumenter;
  private Breakpoints       breakpoints;
  private boolean debuggerProtocol;

  private final Map<Source, Map<SourceSection, Set<Class<? extends Tags>>>> loadedSourcesTags = new HashMap<>();
  private final Map<Source, Set<RootNode>> rootNodes = new HashMap<>();

  private int nextActivityId = 0;
  private final Map<Object, Suspension> activityToSuspension = new HashMap<>();
  private final Map<Integer, Suspension> idToSuspension = new HashMap<>();

  public void useDebuggerProtocol(final boolean debuggerProtocol) {
    this.debuggerProtocol = debuggerProtocol;
  }

  public void reportSyntaxElement(final Class<? extends Tags> type,
      final SourceSection source) {
    Map<SourceSection, Set<Class<? extends Tags>>> sections = loadedSourcesTags.computeIfAbsent(
        source.getSource(), s -> new HashMap<>());
    Set<Class<? extends Tags>> tags = sections.computeIfAbsent(source, s -> new HashSet<>(2));
    tags.add(type);
  }

  public void reportLoadedSource(final Source source) {
    connector.sendLoadedSource(source, loadedSourcesTags, rootNodes);
  }

  public void reportRootNodeAfterParsing(final RootNode rootNode) {
    assert rootNode.getSourceSection() != null : "RootNode without source section";
    Set<RootNode> roots = rootNodes.computeIfAbsent(
        rootNode.getSourceSection().getSource(), s -> new HashSet<>());
    assert !roots.contains(rootNode) : "This method was parsed twice? should not happen";
    roots.add(rootNode);
  }

  public void prepareSteppingUntilNextRootNode() {
    breakpoints.prepareSteppingUntilNextRootNode();
  }

  public void prepareSteppingAfterNextRootNode() {
    breakpoints.prepareSteppingAfterNextRootNode();
  }

  synchronized SuspendedEvent getSuspendedEvent(final int activityId) {
    Suspension suspension = idToSuspension.get(activityId);
    assert suspension != null;
    assert suspension.getEvent() != null;
    return suspension.getEvent();
  }

  Suspension getSuspension(final int activityId) {
    return idToSuspension.get(activityId);
  }

  private synchronized Suspension getSuspension(final Object activity) {
    Suspension suspension = activityToSuspension.get(activity);
    if (suspension == null) {
      int id = nextActivityId;
      nextActivityId += 1;
      suspension = new Suspension(activity, id);

      activityToSuspension.put(activity, suspension);
      idToSuspension.put(id, suspension);
    }
    return suspension;
  }

  private Suspension getSuspension() {
    Thread thread = Thread.currentThread();
    Object current;
    if (thread instanceof ActorProcessingThread) {
      current = ((ActorProcessingThread) thread).currentMessage.getTarget();
    } else if (thread instanceof SomThread) {
      current = thread;
    } else {
      assert thread.getClass() == Thread.class : "Should support other thread subclasses explicitly";
      current = thread;<commit_msg>Handle ProcessThread in debugger<commit_after>package tools.debugger;

import java.util.HashMap;
import java.util.HashSet;
import java.util.Map;
import java.util.Set;

import com.google.gson.Gson;
import com.google.gson.GsonBuilder;
import com.oracle.truffle.api.debug.Debugger;
import com.oracle.truffle.api.debug.DebuggerSession.SteppingLocation;
import com.oracle.truffle.api.debug.SuspendedCallback;
import com.oracle.truffle.api.debug.SuspendedEvent;
import com.oracle.truffle.api.frame.MaterializedFrame;
import com.oracle.truffle.api.instrumentation.Instrumenter;
import com.oracle.truffle.api.instrumentation.TruffleInstrument;
import com.oracle.truffle.api.instrumentation.TruffleInstrument.Registration;
import com.oracle.truffle.api.nodes.RootNode;
import com.oracle.truffle.api.source.Source;
import com.oracle.truffle.api.source.SourceSection;

import som.interpreter.actors.Actor.ActorProcessingThread;
import som.primitives.processes.ChannelPrimitives.ProcessThread;
import som.primitives.threading.ThreadPrimitives.SomThread;
import tools.debugger.frontend.Suspension;
import tools.debugger.message.InitialBreakpointsMessage;
import tools.debugger.message.Message.IncommingMessage;
import tools.debugger.message.Message.OutgoingMessage;
import tools.debugger.message.ScopesRequest;
import tools.debugger.message.ScopesResponse;
import tools.debugger.message.SourceMessage;
import tools.debugger.message.StackTraceRequest;
import tools.debugger.message.StackTraceResponse;
import tools.debugger.message.StepMessage.Resume;
import tools.debugger.message.StepMessage.Return;
import tools.debugger.message.StepMessage.StepInto;
import tools.debugger.message.StepMessage.StepOver;
import tools.debugger.message.StepMessage.Stop;
import tools.debugger.message.StoppedMessage;
import tools.debugger.message.SuspendedEventMessage;
import tools.debugger.message.SymbolMessage;
import tools.debugger.message.UpdateBreakpoint;
import tools.debugger.message.VariablesRequest;
import tools.debugger.message.VariablesResponse;
import tools.debugger.session.AsyncMessageReceiverBreakpoint;
import tools.debugger.session.BreakpointInfo;
import tools.debugger.session.Breakpoints;
import tools.debugger.session.LineBreakpoint;
import tools.debugger.session.MessageReceiverBreakpoint;
import tools.debugger.session.MessageSenderBreakpoint;
import tools.debugger.session.PromiseResolutionBreakpoint;
import tools.debugger.session.PromiseResolverBreakpoint;


/**
 * The WebDebugger connects the Truffle debugging facilities with a HTML5
 * application using WebSockets and JSON.
 */
@Registration(id = WebDebugger.ID)
public class WebDebugger extends TruffleInstrument implements SuspendedCallback {

  public static final String ID = "web-debugger";

  private FrontendConnector connector;
  private Instrumenter      instrumenter;
  private Breakpoints       breakpoints;
  private boolean debuggerProtocol;

  private final Map<Source, Map<SourceSection, Set<Class<? extends Tags>>>> loadedSourcesTags = new HashMap<>();
  private final Map<Source, Set<RootNode>> rootNodes = new HashMap<>();

  private int nextActivityId = 0;
  private final Map<Object, Suspension> activityToSuspension = new HashMap<>();
  private final Map<Integer, Suspension> idToSuspension = new HashMap<>();

  public void useDebuggerProtocol(final boolean debuggerProtocol) {
    this.debuggerProtocol = debuggerProtocol;
  }

  public void reportSyntaxElement(final Class<? extends Tags> type,
      final SourceSection source) {
    Map<SourceSection, Set<Class<? extends Tags>>> sections = loadedSourcesTags.computeIfAbsent(
        source.getSource(), s -> new HashMap<>());
    Set<Class<? extends Tags>> tags = sections.computeIfAbsent(source, s -> new HashSet<>(2));
    tags.add(type);
  }

  public void reportLoadedSource(final Source source) {
    connector.sendLoadedSource(source, loadedSourcesTags, rootNodes);
  }

  public void reportRootNodeAfterParsing(final RootNode rootNode) {
    assert rootNode.getSourceSection() != null : "RootNode without source section";
    Set<RootNode> roots = rootNodes.computeIfAbsent(
        rootNode.getSourceSection().getSource(), s -> new HashSet<>());
    assert !roots.contains(rootNode) : "This method was parsed twice? should not happen";
    roots.add(rootNode);
  }

  public void prepareSteppingUntilNextRootNode() {
    breakpoints.prepareSteppingUntilNextRootNode();
  }

  public void prepareSteppingAfterNextRootNode() {
    breakpoints.prepareSteppingAfterNextRootNode();
  }

  synchronized SuspendedEvent getSuspendedEvent(final int activityId) {
    Suspension suspension = idToSuspension.get(activityId);
    assert suspension != null;
    assert suspension.getEvent() != null;
    return suspension.getEvent();
  }

  Suspension getSuspension(final int activityId) {
    return idToSuspension.get(activityId);
  }

  private synchronized Suspension getSuspension(final Object activity) {
    Suspension suspension = activityToSuspension.get(activity);
    if (suspension == null) {
      int id = nextActivityId;
      nextActivityId += 1;
      suspension = new Suspension(activity, id);

      activityToSuspension.put(activity, suspension);
      idToSuspension.put(id, suspension);
    }
    return suspension;
  }

  private Suspension getSuspension() {
    Thread thread = Thread.currentThread();
    Object current;
    if (thread instanceof ActorProcessingThread) {
      current = ((ActorProcessingThread) thread).currentMessage.getTarget();
    } else if (thread instanceof SomThread) {
      current = thread;
    } else if (thread instanceof ProcessThread) {
      current = thread;
    } else {
      assert thread.getClass() == Thread.class : "Should support other thread subclasses explicitly";
      current = thread;
{'fraction_non_alphanumeric': 0.0942817049640414, 'fraction_numerical': 0.0007016312927556569, 'mean_word_length': 5.427846674182638, 'pattern_counts': {'":': 0, '<': 47, '<?xml version=': 0, '>': 53, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '230719', 'n_tokens_mistral': 3239, 'n_tokens_neox': 3171, 'n_words': 687}