Skip to content

Commit 3051621

Browse files
author
David Karlaš
committed
Added StackFrameFormat which allows DebuggerSession to format stack trace text instead of stack trace pad
Mostly useful for VsCode Debug protocol
1 parent ea9d7f7 commit 3051621

File tree

3 files changed

+118
-24
lines changed

3 files changed

+118
-24
lines changed

Mono.Debugging/Mono.Debugging.Client/Backtrace.cs

Lines changed: 10 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ public Backtrace (IBacktrace serverBacktrace)
2121

2222
count = serverBacktrace.FrameCount;
2323

24-
// Get some initial frames
24+
// Get first frame, which is most used(for thread location)
2525
if (count > 0)
26-
GetFrame (0);
26+
GetFrame (0, 1);
2727
}
2828

2929
internal void Attach (DebuggerSession session)
@@ -44,12 +44,17 @@ public int FrameCount
4444
}
4545

4646
public StackFrame GetFrame (int n)
47+
{
48+
return GetFrame (n, 20);
49+
}
50+
51+
private StackFrame GetFrame(int index, int fetchMultipleCount)
4752
{
4853
if (frames == null)
4954
frames = new List<StackFrame>();
5055

51-
if (n >= frames.Count) {
52-
StackFrame[] newSet = serverBacktrace.GetStackFrames(frames.Count, n + 20);
56+
if (index >= frames.Count) {
57+
StackFrame[] newSet = serverBacktrace.GetStackFrames(frames.Count, index + fetchMultipleCount);
5358
foreach (StackFrame sf in newSet) {
5459
sf.SourceBacktrace = serverBacktrace;
5560
sf.Index = frames.Count;
@@ -59,7 +64,7 @@ public StackFrame GetFrame (int n)
5964
}
6065

6166
if (frames.Count > 0)
62-
return frames[System.Math.Min (System.Math.Max (0, n), frames.Count - 1)];
67+
return frames[System.Math.Min (System.Math.Max (0, index), frames.Count - 1)];
6368

6469
return null;
6570
}

Mono.Debugging/Mono.Debugging.Client/EvaluationOptions.cs

Lines changed: 56 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -33,9 +33,9 @@ public class EvaluationOptions
3333
{
3434
bool allowMethodEvaluation;
3535
bool allowToStringCalls;
36-
37-
public static readonly char Ellipsis = '…';
38-
36+
37+
public const char Ellipsis = '…';
38+
3939
public static EvaluationOptions DefaultOptions {
4040
get {
4141
EvaluationOptions ops = new EvaluationOptions ();
@@ -53,57 +53,94 @@ public static EvaluationOptions DefaultOptions {
5353
ops.EllipsizeStrings = true;
5454
ops.EllipsizedLength = 100;
5555
ops.ChunkRawStrings = false;
56+
ops.StackFrameFormat = new StackFrameFormat ();
5657
return ops;
5758
}
5859
}
59-
60+
6061
public EvaluationOptions Clone ()
6162
{
62-
return (EvaluationOptions) MemberwiseClone ();
63+
var clone = (EvaluationOptions)MemberwiseClone ();
64+
clone.StackFrameFormat = new StackFrameFormat (StackFrameFormat);
65+
return clone;
6366
}
64-
67+
6568
public bool ChunkRawStrings { get; set; }
66-
69+
6770
public bool EllipsizeStrings { get; set; }
6871
public int EllipsizedLength { get; set; }
69-
72+
7073
public int EvaluationTimeout { get; set; }
7174
public int MemberEvaluationTimeout { get; set; }
7275
public bool AllowTargetInvoke { get; set; }
73-
76+
7477
public bool AllowMethodEvaluation {
7578
get { return allowMethodEvaluation && AllowTargetInvoke; }
7679
set { allowMethodEvaluation = value; }
7780
}
78-
81+
7982
public bool AllowToStringCalls {
8083
get { return allowToStringCalls && AllowTargetInvoke; }
8184
set { allowToStringCalls = value; }
8285
}
83-
86+
8487
public bool AllowDisplayStringEvaluation {
8588
get { return AllowTargetInvoke; }
8689
}
87-
90+
8891
public bool AllowDebuggerProxy {
8992
get { return AllowTargetInvoke; }
9093
}
91-
94+
9295
public bool FlattenHierarchy { get; set; }
93-
96+
9497
public bool GroupPrivateMembers { get; set; }
95-
98+
9699
public bool GroupStaticMembers { get; set; }
97-
100+
98101
public bool UseExternalTypeResolver { get; set; }
99-
102+
100103
public IntegerDisplayFormat IntegerDisplayFormat { get; set; }
101-
104+
102105
public string CurrentExceptionTag { get; set; }
103106

104107
public bool IEnumerable { get; set; }
108+
109+
public StackFrameFormat StackFrameFormat { get; set; }
110+
}
111+
112+
public class StackFrameFormat
113+
{
114+
public bool Line { get; set; } = true;
115+
116+
public bool Module { get; set; } = false;
117+
118+
public bool ParameterNames { get; set; } = true;
119+
120+
public bool ParameterTypes { get; set; } = true;
121+
122+
public bool ParameterValues { get; set; } = false;
123+
124+
/// <summary>
125+
/// Default is null. Which means do same as "ProjectAssembliesOnly" setting.
126+
/// </summary>
127+
public bool? ExternalCode { get; set; } = null;
128+
129+
public StackFrameFormat ()
130+
{
131+
}
132+
133+
public StackFrameFormat (StackFrameFormat copy)
134+
{
135+
Line = copy.Line;
136+
Module = copy.Module;
137+
ParameterNames = copy.ParameterNames;
138+
ParameterTypes = copy.ParameterTypes;
139+
ParameterValues = copy.ParameterValues;
140+
ExternalCode = copy.ExternalCode;
141+
}
105142
}
106-
143+
107144
public enum IntegerDisplayFormat
108145
{
109146
Decimal,

Mono.Debugging/Mono.Debugging.Client/StackFrame.cs

Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
using System;
2+
using System.Text;
23
using Mono.Debugging.Backend;
34

45
namespace Mono.Debugging.Client
@@ -115,6 +116,57 @@ public string FullModuleName {
115116
public string FullTypeName {
116117
get { return fullTypeName; }
117118
}
119+
120+
/// <summary>
121+
/// Gets the full name of the stackframe. Which respects Session.EvaluationOptions.StackFrameFormat
122+
/// </summary>
123+
public virtual string FullStackframeText {
124+
get {
125+
var methodNameBuilder = new StringBuilder (this.SourceLocation.MethodName);
126+
var options = session.EvaluationOptions.Clone ();
127+
if (options.StackFrameFormat.ParameterValues) {
128+
options.AllowMethodEvaluation = true;
129+
options.AllowToStringCalls = true;
130+
options.AllowTargetInvoke = true;
131+
} else {
132+
options.AllowMethodEvaluation = false;
133+
options.AllowToStringCalls = false;
134+
options.AllowTargetInvoke = false;
135+
}
136+
137+
var args = this.GetParameters (options);
138+
139+
//MethodName starting with "["... it's something like [ExternalCode]
140+
if (!this.SourceLocation.MethodName.StartsWith ("[", StringComparison.Ordinal)) {
141+
if (options.StackFrameFormat.Module && !string.IsNullOrEmpty (this.FullModuleName)) {
142+
methodNameBuilder.Insert (0, System.IO.Path.GetFileName (this.FullModuleName) + "!");
143+
}
144+
if (options.StackFrameFormat.ParameterTypes || options.StackFrameFormat.ParameterNames || options.StackFrameFormat.ParameterValues) {
145+
methodNameBuilder.Append ("(");
146+
for (int n = 0; n < args.Length; n++) {
147+
if (n > 0)
148+
methodNameBuilder.Append (", ");
149+
if (options.StackFrameFormat.ParameterTypes) {
150+
methodNameBuilder.Append (args [n].TypeName);
151+
if (options.StackFrameFormat.ParameterNames)
152+
methodNameBuilder.Append (" ");
153+
}
154+
if (options.StackFrameFormat.ParameterNames)
155+
methodNameBuilder.Append (args [n].Name);
156+
if (options.StackFrameFormat.ParameterValues) {
157+
if (options.StackFrameFormat.ParameterTypes || options.StackFrameFormat.ParameterNames)
158+
methodNameBuilder.Append (" = ");
159+
var val = args [n].Value ?? "";
160+
methodNameBuilder.Append (val.Replace ("\r\n", " ").Replace ("\n", " "));
161+
}
162+
}
163+
methodNameBuilder.Append (")");
164+
}
165+
}
166+
167+
return methodNameBuilder.ToString ();
168+
}
169+
}
118170

119171
public ObjectValue[] GetLocalVariables ()
120172
{

0 commit comments

Comments
 (0)