Skip to content

Commit

Permalink
Add Function Breakpoint support. Fix breakpoint bound status
Browse files Browse the repository at this point in the history
same
  • Loading branch information
JaneySprings committed Feb 17, 2024
1 parent 1903cbe commit 53faad6
Show file tree
Hide file tree
Showing 3 changed files with 46 additions and 14 deletions.
1 change: 1 addition & 0 deletions src/DotNet.Meteor.Debug/Agents/BaseLaunchAgent.cs
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public abstract class BaseLaunchAgent {
private readonly Logger sessionLogger = LogManager.GetCurrentClassLogger();

public const string CommandPrefix = "/";
public const string LanguageSeparator = "!";
public List<Action> Disposables { get; init; }
protected LaunchConfiguration Configuration { get; init; }

Expand Down
46 changes: 39 additions & 7 deletions src/DotNet.Meteor.Debug/DebugSession.cs
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ public class DebugSession : Session {
SupportsExceptionInfoRequest = true,
SupportsConditionalBreakpoints = true,
SupportsHitConditionalBreakpoints = true,
SupportsFunctionBreakpoints = true,
SupportsLogPoints = true,
SupportsExceptionOptions = true,
SupportsExceptionFilterOptions = true,
Expand Down Expand Up @@ -82,7 +83,7 @@ public class DebugSession : Session {
#region request: Terminate
protected override TerminateResponse HandleTerminateRequest(TerminateArguments arguments) {
if (!session.HasExited)
session.Exit(MonoExtensions.TerminationTimeout);
session.Exit();

launchAgent?.Dispose();
if (launchAgent is not DebugLaunchAgent)
Expand Down Expand Up @@ -182,29 +183,60 @@ public class DebugSession : Session {
foreach(var breakpointInfo in breakpointsInfos) {
MonoClient.Breakpoint breakpoint = session.Breakpoints.Add(sourcePath, breakpointInfo.Line, breakpointInfo.Column ?? 1);
// Conditional breakpoint
if (breakpoint != null && breakpointInfo.Condition != null)
if (!string.IsNullOrEmpty(breakpointInfo.Condition))
breakpoint.ConditionExpression = breakpointInfo.Condition;
// Hit count breakpoint
if (breakpoint != null && !string.IsNullOrEmpty(breakpointInfo.HitCondition)) {
if (!string.IsNullOrEmpty(breakpointInfo.HitCondition)) {
breakpoint.HitCountMode = MonoClient.HitCountMode.EqualTo;
breakpoint.HitCount = int.TryParse(breakpointInfo.HitCondition, out int hitCount) ? hitCount : 1;
}
// Logpoint
if (breakpoint != null && breakpointInfo.LogMessage != null) {
if (!string.IsNullOrEmpty(breakpointInfo.LogMessage)) {
breakpoint.HitAction = MonoClient.HitAction.PrintExpression;
breakpoint.TraceExpression = $"[LogPoint]: {breakpointInfo.LogMessage}";
}

var verified = breakpoint.WaitForBound(session);
breakpoints.Add(new DebugProtocol.Breakpoint() {
Verified = breakpoint != null,
Line = breakpoint?.Line ?? breakpointInfo.Line,
Column = breakpoint?.Column ?? breakpointInfo.Column
Verified = verified,
Line = breakpoint.Line,
Column = breakpoint.Column
});
}

return new SetBreakpointsResponse(breakpoints);
}
#endregion request: SetBreakpoints
#region request: SetFunctionBreakpoints
protected override SetFunctionBreakpointsResponse HandleSetFunctionBreakpointsRequest(SetFunctionBreakpointsArguments arguments) {
// clear existing function breakpoints
var functionBreakpoints = session.Breakpoints.OfType<MonoClient.FunctionBreakpoint>();
foreach (var functionBreakpoint in functionBreakpoints)
session.Breakpoints.Remove(functionBreakpoint);

foreach (var breakpointInfo in arguments.Breakpoints) {
var languageName = "C#";
var functionName = breakpointInfo.Name;
var functionParts = breakpointInfo.Name.Split(BaseLaunchAgent.LanguageSeparator);
if (functionParts.Length == 2) {
languageName = functionParts[0];
functionName = functionParts[1];
}

var functionBreakpoint = new MonoClient.FunctionBreakpoint(functionName, languageName);
// Conditional breakpoint
if (!string.IsNullOrEmpty(breakpointInfo.Condition))
functionBreakpoint.ConditionExpression = breakpointInfo.Condition;
// Hit count breakpoint
if (!string.IsNullOrEmpty(breakpointInfo.HitCondition)) {
functionBreakpoint.HitCountMode = MonoClient.HitCountMode.EqualTo;
functionBreakpoint.HitCount = int.TryParse(breakpointInfo.HitCondition, out int hitCount) ? hitCount : 1;
}
session.Breakpoints.Add(functionBreakpoint);
}
return new SetFunctionBreakpointsResponse();
}
#endregion request: SetFunctionBreakpoints
#region request: StackTrace
protected override StackTraceResponse HandleStackTraceRequest(StackTraceArguments arguments) {
return DoSafe<StackTraceResponse>(() => {
Expand Down
13 changes: 6 additions & 7 deletions src/DotNet.Meteor.Debug/Extensions/MonoExtensions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -7,8 +7,6 @@
namespace DotNet.Meteor.Debug.Extensions;

public static class MonoExtensions {
public const int TerminationTimeout = 3000;

public static string ToThreadName(this string threadName, int threadId) {
if (!string.IsNullOrEmpty(threadName))
return threadName;
Expand Down Expand Up @@ -55,10 +53,11 @@ public static class MonoExtensions {
options.UseExternalTypeResolver = useExternalTypeResolver;
return frame.GetExpressionValue(expression, options);
}
public static bool Exit(this SoftDebuggerSession session, int millisecondsTimeout) {
if (session == null)
return true;

return Task.Run(() => session.Exit()).Wait(millisecondsTimeout);
public static bool WaitForBound(this BreakEvent breakEvent, SoftDebuggerSession session, int millisecondsTimeout = 150) {
return Task.Run(async() => {
while (breakEvent.GetStatus(session) == BreakEventStatus.NotBound)
await Task.Delay(millisecondsTimeout/3);
return breakEvent.GetStatus(session) == BreakEventStatus.Bound;
}).Wait(millisecondsTimeout);
}
}

0 comments on commit 53faad6

Please sign in to comment.