private void ResetOnDisconnect() { // consider resetting this.events filter enabled state to defaults from constructor _options = new LaunchAttach(); _breakpoints.Clear(); _output.ValueCodes.Clear(); ContinueAllThreads(); }
private async Task <Message> DispatchAsync(Message message, CancellationToken cancellationToken) { if (message is Request request) { if (message is Request <Initialize> initialize) { var body = MakeCapabilities(); var response = Response.From(NextSeq, initialize, body); await SendAsync(response, cancellationToken).ConfigureAwait(false); return(Event.From(NextSeq, "initialized", new { })); } if (message is Request <Launch> launch) { _options = launch.Arguments; return(Response.From(NextSeq, launch, new { })); } if (message is Request <Attach> attach) { _options = attach.Arguments; return(Response.From(NextSeq, attach, new { })); } if (message is Request <SetBreakpoints> setBreakpoints) { var arguments = setBreakpoints.Arguments; var file = Path.GetFileName(arguments.Source.Path); await OutputAsync($"Set breakpoints for {file}", null, null, cancellationToken).ConfigureAwait(false); var breakpoints = _breakpoints.SetBreakpoints(arguments.Source, arguments.Breakpoints); foreach (var breakpoint in breakpoints) { if (breakpoint.Verified) { var item = _breakpoints.ItemFor(breakpoint); await OutputAsync($"Set breakpoint at {_codeModel.NameFor(item)}", item, null, cancellationToken).ConfigureAwait(false); } } return(Response.From(NextSeq, setBreakpoints, new { breakpoints })); } if (message is Request <SetFunctionBreakpoints> setFunctionBreakpoints) { var arguments = setFunctionBreakpoints.Arguments; await OutputAsync("Set function breakpoints.", null, null, cancellationToken).ConfigureAwait(false); var breakpoints = _breakpoints.SetBreakpoints(arguments.Breakpoints); foreach (var breakpoint in breakpoints) { if (breakpoint.Verified) { var item = _breakpoints.ItemFor(breakpoint); await OutputAsync($"Set breakpoint at {_codeModel.NameFor(item)}", item, null, cancellationToken).ConfigureAwait(false); } } return(Response.From(NextSeq, setFunctionBreakpoints, new { breakpoints })); } if (message is Request <SetExceptionBreakpoints> setExceptionBreakpoints) { var arguments = setExceptionBreakpoints.Arguments; _events.Reset(arguments.Filters); return(Response.From(NextSeq, setExceptionBreakpoints, new { })); } if (message is Request <Threads> threads) { var body = new { threads = _threads.Select(t => new { id = t.Key, name = t.Value.Name }).ToArray() }; return(Response.From(NextSeq, threads, body)); } if (message is Request <StackTrace> stackTrace) { var arguments = stackTrace.Arguments; var thread = _threads[arguments.ThreadId]; var frames = thread.Frames; var stackFrames = new List <StackFrame>(); foreach (var frame in frames) { var stackFrame = new StackFrame { Id = EncodeFrame(thread, frame), Name = frame.Name }; var item = _codeModel.NameFor(frame.Item); DebuggerSourceMap.Assign(stackFrame, item, frame.More); if (_sourceMap.TryGetValue(frame.Item, out var range)) { DebuggerSourceMap.Assign(stackFrame, range); } stackFrames.Add(stackFrame); } return(Response.From(NextSeq, stackTrace, new { stackFrames })); } if (message is Request <Scopes> scopes) { var arguments = scopes.Arguments; DecodeFrame(arguments.FrameId, out var thread, out var frame); const bool expensive = false; var body = new { scopes = new[] { new { expensive, name = frame.Name, variablesReference = EncodeValue(thread, frame.Data) } } }; return(Response.From(NextSeq, scopes, body)); } if (message is Request <Variables> vars) { var arguments = vars.Arguments; DecodeValue(arguments.VariablesReference, out var arena, out var context); var names = _dataModel.Names(context); var body = new { variables = (from name in names let value = _dataModel[context, name] let variablesReference = EncodeValue(arena, value) select new { name = _dataModel.ToString(name), value = _dataModel.ToString(value), variablesReference }) .ToArray() }; return(Response.From(NextSeq, vars, body)); } if (message is Request <SetVariable> setVariable) { var arguments = setVariable.Arguments; DecodeValue(arguments.VariablesReference, out var arena, out var context); var value = _dataModel[context, arguments.Name] = JToken.Parse(arguments.Value); var body = new { value = _dataModel.ToString(value), variablesReference = EncodeValue(arena, value) }; return(Response.From(NextSeq, setVariable, body)); } if (message is Request <Evaluate> evaluate) { var arguments = evaluate.Arguments; DecodeFrame(arguments.FrameId, out var thread, out var frame); var expression = arguments.Expression.Trim('"'); try { var result = frame.Evaluate(expression); var body = new { result = _dataModel.ToString(result), variablesReference = EncodeValue(thread, result), }; return(Response.From(NextSeq, evaluate, body)); } #pragma warning disable CA1031 // Do not catch general exception types (catch any exception and return it) catch (Exception ex) #pragma warning restore CA1031 // Do not catch general exception types { return(Response.Fail(NextSeq, evaluate, ex.Message)); } } Response Post <TBody>(PerThread perThread, Phase phase, TBody body) { // "constructing the response" and "posting to the thread" have side-effects // for extra determinism, construct the response before signaling the thread var response = Response.From(NextSeq, request, body); var found = _threads.TryGetValue(perThread.ThreadId, out var thread); if (found) { thread.Run.Post(phase); } return(response); } if (message is Request <Continue> cont) { return(Post(cont.Arguments, Phase.Continue, new { allThreadsContinued = false })); } if (message is Request <Pause> pause) { return(Post(pause.Arguments, Phase.Pause, new { })); } if (message is Request <Next> next) { return(Post(next.Arguments, Phase.Next, new { })); } if (message is Request <Terminate> terminate) { if (_terminate != null) { _terminate(); } return(Response.From(NextSeq, terminate, new { })); } if (message is Request <Disconnect> disconnect) { var arguments = disconnect.Arguments; if (arguments.TerminateDebuggee && _terminate != null) { _terminate(); } else { ResetOnDisconnect(); } return(Response.From(NextSeq, disconnect, new { })); } return(Response.From(NextSeq, request, new { })); } if (message is Event @event) { throw new NotImplementedException(); } throw new NotImplementedException(); }