Skip to content
This repository was archived by the owner on Oct 4, 2021. It is now read-only.

Commit b497d87

Browse files
authored
Merge pull request #9259 from mono/vsts-1000552-debug-test
[Unit Test] Show source code while debugging
2 parents 6fd3949 + 4cd87f9 commit b497d87

File tree

2 files changed

+119
-96
lines changed

2 files changed

+119
-96
lines changed

main/src/addins/MonoDevelop.Debugger.VSCodeDebugProtocol/MonoDevelop.Debugger.VsCodeDebugProtocol/VSCodeDebuggerSession.cs

Lines changed: 23 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -156,18 +156,21 @@ protected override BreakEventInfo OnInsertBreakEvent (BreakEvent breakEvent)
156156
}
157157

158158
bool currentExceptionState = false;
159+
bool unhandleExceptionRegistered = false;
159160
void UpdateExceptions ()
160161
{
161162
//Disposed
162163
if (protocolClient == null)
163164
return;
164165

165166
var hasCustomExceptions = breakpoints.Select (b => b.Key).OfType<Catchpoint> ().Any (e => e.Enabled);
166-
if (currentExceptionState != hasCustomExceptions) {
167+
if (currentExceptionState != hasCustomExceptions || !unhandleExceptionRegistered) {
167168
currentExceptionState = hasCustomExceptions;
168-
protocolClient.SendRequest (new SetExceptionBreakpointsRequest (
169-
Capabilities.ExceptionBreakpointFilters.Where (f => hasCustomExceptions || (f.Default ?? false)).Select (f => f.Filter).ToList ()
170-
), null);
169+
var exceptionRequest = new SetExceptionBreakpointsRequest (
170+
Capabilities.ExceptionBreakpointFilters.Where (f => hasCustomExceptions || (f.Default ?? false)).Select (f => f.Filter).ToList ());
171+
exceptionRequest.ExceptionOptions = new List<ExceptionOptions> () {new ExceptionOptions(ExceptionBreakMode.UserUnhandled)};
172+
protocolClient.SendRequest (exceptionRequest, null);
173+
unhandleExceptionRegistered = true;
171174
}
172175
}
173176

@@ -268,6 +271,7 @@ protected void Launch (DebuggerStartInfo startInfo)
268271
LaunchRequest launchRequest = CreateLaunchRequest (startInfo);
269272
protocolClient.SendRequestSync (launchRequest);
270273
protocolClient.SendRequestSync (new ConfigurationDoneRequest ());
274+
UpdateExceptions ();
271275
}
272276

273277
protected void Attach (long processId)
@@ -277,6 +281,7 @@ protected void Attach (long processId)
277281
protocolClient.SendRequestSync (attachRequest);
278282
OnStarted ();
279283
protocolClient.SendRequestSync (new ConfigurationDoneRequest ());
284+
UpdateExceptions ();
280285
}
281286

282287
protected internal DebugProtocolHost protocolClient;
@@ -347,6 +352,7 @@ bool ShouldStopOnExceptionCatchpoint (Catchpoint catchpoint, int frameId)
347352
return string.IsNullOrWhiteSpace (catchpoint.ConditionExpression) || EvaluateCondition (frameId, catchpoint.ConditionExpression) != false;
348353
}
349354

355+
350356
protected void HandleEvent (object sender, EventReceivedEventArgs obj)
351357
{
352358
Task.Run (() => {
@@ -403,12 +409,16 @@ protected void HandleEvent (object sender, EventReceivedEventArgs obj)
403409
// It's OK to evaluate expressions in external code
404410
stackFrame = (VsCodeStackFrame)backtrace.GetFrame (0);
405411
}
406-
407-
if (!breakpoints.Select (b => b.Key).OfType<Catchpoint> ().Any (c => ShouldStopOnExceptionCatchpoint (c, stackFrame.frameId))) {
408-
OnContinue ();
409-
return;
412+
var response = protocolClient.SendRequestSync (new ExceptionInfoRequest (body.ThreadId ?? -1));
413+
if (response.BreakMode.Equals (ExceptionBreakMode.UserUnhandled)) {
414+
args = new TargetEventArgs (TargetEventType.UnhandledException);
415+
} else {
416+
if (!breakpoints.Select (b => b.Key).OfType<Catchpoint> ().Any (c => ShouldStopOnExceptionCatchpoint (c, stackFrame.frameId))) {
417+
OnContinue ();
418+
return;
419+
}
420+
args = new TargetEventArgs (TargetEventType.ExceptionThrown);
410421
}
411-
args = new TargetEventArgs (TargetEventType.ExceptionThrown);
412422
break;
413423
default:
414424
throw new NotImplementedException (body.Reason.ToString ());
@@ -502,13 +512,13 @@ void UpdateBreakpoints ()
502512
return;
503513

504514
protocolClient.SendRequest (
505-
new SetBreakpointsRequest (source) {
515+
new SetBreakpointsRequest (source) {
506516
Breakpoints = sourceFile.Select (b => new SourceBreakpoint {
507517
Line = b.OriginalLine,
508518
Column = b.OriginalColumn,
509-
Condition = b.ConditionExpression,
510-
HitCondition = GetHitCondition(b)
511-
}).ToList ()
519+
Condition = b.ConditionExpression,
520+
HitCondition = GetHitCondition(b)
521+
}).ToList ()
512522
}, (obj) => {
513523
Task.Run (() => {
514524
for (int i = 0; i < obj.Breakpoints.Count; i++) {

main/src/addins/MonoDevelop.Debugger/MonoDevelop.Debugger/Initializer.cs

Lines changed: 96 additions & 83 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,7 @@ public class Initializer: CommandHandler
4646
Document noSourceDoc;
4747
NoSourceView noSourceView;
4848
string symbolCachePath;
49+
bool changingFrame;
4950

5051
protected override void Run ()
5152
{
@@ -67,108 +68,120 @@ void OnStackChanged (object s, EventArgs a)
6768

6869
async void OnFrameChanged (object s, EventArgs a)
6970
{
70-
if (disassemblyDoc != null && DebuggingService.IsFeatureSupported (DebuggerFeatures.Disassembly))
71-
disassemblyView.Update ();
72-
73-
var frame = DebuggingService.CurrentFrame;
74-
if (frame == null)
71+
if (changingFrame) {
7572
return;
76-
77-
FilePath file = frame.SourceLocation.FileName;
73+
}
74+
try {
75+
changingFrame = true;
76+
if (disassemblyDoc != null && DebuggingService.IsFeatureSupported (DebuggerFeatures.Disassembly))
77+
disassemblyView.Update ();
7878

79-
int line = frame.SourceLocation.Line;
80-
if (line != -1) {
81-
if (!file.IsNullOrEmpty && File.Exists (file)) {
82-
var doc = await IdeApp.Workbench.OpenDocument (file, null, line, 1, OpenDocumentOptions.Debugger);
83-
if (doc != null)
84-
return;
79+
var frame = DebuggingService.CurrentFrame;
80+
if (frame == null) {
81+
return;
8582
}
86-
bool alternateLocationExists = false;
87-
if (frame.SourceLocation.FileHash != null) {
88-
var newFilePath = SourceCodeLookup.FindSourceFile (file, frame.SourceLocation.FileHash);
89-
if (newFilePath != null && File.Exists (newFilePath)) {
90-
frame.UpdateSourceFile (newFilePath);
91-
var doc = await IdeApp.Workbench.OpenDocument (newFilePath, null, line, 1, OpenDocumentOptions.Debugger);
92-
if (doc != null)
83+
84+
FilePath file = frame.SourceLocation.FileName;
85+
86+
int line = frame.SourceLocation.Line;
87+
if (line != -1) {
88+
if (!file.IsNullOrEmpty && File.Exists (file)) {
89+
var doc = await IdeApp.Workbench.OpenDocument (file, null, line, 1, OpenDocumentOptions.Debugger);
90+
if (doc != null) {
9391
return;
92+
}
9493
}
95-
}
96-
var debuggerOptions = DebuggingService.GetUserOptions ();
97-
var automaticSourceDownload = debuggerOptions.AutomaticSourceLinkDownload;
94+
bool alternateLocationExists = false;
95+
if (frame.SourceLocation.FileHash != null) {
96+
var newFilePath = SourceCodeLookup.FindSourceFile (file, frame.SourceLocation.FileHash);
97+
if (newFilePath != null && File.Exists (newFilePath)) {
98+
frame.UpdateSourceFile (newFilePath);
99+
var doc = await IdeApp.Workbench.OpenDocument (newFilePath, null, line, 1, OpenDocumentOptions.Debugger);
100+
if (doc != null) {
101+
return;
102+
}
103+
}
104+
}
105+
var debuggerOptions = DebuggingService.GetUserOptions ();
106+
var automaticSourceDownload = debuggerOptions.AutomaticSourceLinkDownload;
98107

99-
var sourceLink = frame.SourceLocation.SourceLink;
100-
if (sourceLink != null && automaticSourceDownload != AutomaticSourceDownload.Never) {
101-
var downloadLocation = sourceLink.GetDownloadLocation (symbolCachePath);
102-
Document doc = null;
103-
// ~/Library/Caches/VisualStudio/8.0/Symbols/org/projectname/git-sha/path/to/file.cs
104-
if (!File.Exists (downloadLocation)) {
105-
if (automaticSourceDownload == AutomaticSourceDownload.Always) {
106-
doc = await DownloadAndOpenFileAsync (frame, line, sourceLink);
107-
} else {
108-
var hyperlink = $"<a href='{ sourceLink.Uri }'>{ Path.GetFileName (sourceLink.RelativeFilePath) }</a>";
109-
var stackframeText = $"<b>{frame.FullStackframeText}</b>";
108+
var sourceLink = frame.SourceLocation.SourceLink;
109+
if (sourceLink != null && automaticSourceDownload != AutomaticSourceDownload.Never) {
110+
var downloadLocation = sourceLink.GetDownloadLocation (symbolCachePath);
111+
Document doc = null;
112+
// ~/Library/Caches/VisualStudio/8.0/Symbols/org/projectname/git-sha/path/to/file.cs
113+
if (!File.Exists (downloadLocation)) {
114+
if (automaticSourceDownload == AutomaticSourceDownload.Always) {
115+
doc = await DownloadAndOpenFileAsync (frame, line, sourceLink);
116+
} else {
117+
var hyperlink = $"<a href='{ sourceLink.Uri }'>{ Path.GetFileName (sourceLink.RelativeFilePath) }</a>";
118+
var stackframeText = $"<b>{frame.FullStackframeText}</b>";
110119

111-
var text = GettextCatalog.GetString
112-
("{0} is a call to external source code. Would you like to get '{1}' and view it?", stackframeText, hyperlink);
113-
var message = new Ide.GenericMessage {
114-
Text = GettextCatalog.GetString ("External source code available"),
115-
SecondaryText = text
116-
};
117-
message.AddOption (nameof (automaticSourceDownload), GettextCatalog.GetString ("Always get source code automatically"), false);
118-
message.Buttons.Add (AlertButton.Cancel);
119-
message.Buttons.Add (new AlertButton (GettextCatalog.GetString ("Get and Open")));
120-
message.DefaultButton = 1;
120+
var text = GettextCatalog.GetString
121+
("{0} is a call to external source code. Would you like to get '{1}' and view it?", stackframeText, hyperlink);
122+
var message = new Ide.GenericMessage {
123+
Text = GettextCatalog.GetString ("External source code available"),
124+
SecondaryText = text
125+
};
126+
message.AddOption (nameof (automaticSourceDownload), GettextCatalog.GetString ("Always get source code automatically"), false);
127+
message.Buttons.Add (AlertButton.Cancel);
128+
message.Buttons.Add (new AlertButton (GettextCatalog.GetString ("Get and Open")));
129+
message.DefaultButton = 1;
121130

122-
var didNotCancel = MessageService.GenericAlert (message) != AlertButton.Cancel;
123-
if (didNotCancel) {
124-
if (message.GetOptionValue (nameof (automaticSourceDownload))) {
125-
debuggerOptions.AutomaticSourceLinkDownload = AutomaticSourceDownload.Always;
126-
DebuggingService.SetUserOptions (debuggerOptions);
131+
var didNotCancel = MessageService.GenericAlert (message) != AlertButton.Cancel;
132+
if (didNotCancel) {
133+
if (message.GetOptionValue (nameof (automaticSourceDownload))) {
134+
debuggerOptions.AutomaticSourceLinkDownload = AutomaticSourceDownload.Always;
135+
DebuggingService.SetUserOptions (debuggerOptions);
136+
}
137+
doc = await DownloadAndOpenFileAsync (frame, line, sourceLink);
127138
}
128-
doc = await DownloadAndOpenFileAsync (frame, line, sourceLink);
129139
}
140+
} else {
141+
// The file has previously been downloaded for a different solution.
142+
// We need to map the cached location
143+
frame.UpdateSourceFile (downloadLocation);
144+
doc = await IdeApp.Workbench.OpenDocument (downloadLocation, null, line, 1, OpenDocumentOptions.Debugger);
145+
}
146+
if (doc != null) {
147+
return;
130148
}
131-
} else {
132-
// The file has previously been downloaded for a different solution.
133-
// We need to map the cached location
134-
frame.UpdateSourceFile (downloadLocation);
135-
doc = await IdeApp.Workbench.OpenDocument (downloadLocation, null, line, 1, OpenDocumentOptions.Debugger);
136149
}
137-
if (doc != null)
138-
return;
139150
}
140-
}
141151

142-
bool disassemblyNotSupported = false;
143-
// If we don't have an address space, we can't disassemble
144-
if (string.IsNullOrEmpty (frame.AddressSpace))
145-
disassemblyNotSupported = true;
152+
bool disassemblyNotSupported = false;
153+
// If we don't have an address space, we can't disassemble
154+
if (string.IsNullOrEmpty (frame.AddressSpace))
155+
disassemblyNotSupported = true;
146156

147-
if (!DebuggingService.CurrentSessionSupportsFeature (DebuggerFeatures.Disassembly))
148-
disassemblyNotSupported = true;
157+
if (!DebuggingService.CurrentSessionSupportsFeature (DebuggerFeatures.Disassembly))
158+
disassemblyNotSupported = true;
149159

150-
if (disassemblyNotSupported && disassemblyDoc != null) {
151-
disassemblyDoc.Close ().Ignore ();
152-
disassemblyDoc = null;
153-
disassemblyView = null;
154-
}
160+
if (disassemblyNotSupported && disassemblyDoc != null) {
161+
disassemblyDoc.Close ().Ignore ();
162+
disassemblyDoc = null;
163+
disassemblyView = null;
164+
}
155165

156-
// If disassembly is open don't show NoSourceView
157-
if (disassemblyDoc == null) {
158-
if (noSourceDoc == null) {
159-
noSourceView = new NoSourceView ();
160-
noSourceView.Update (disassemblyNotSupported);
161-
noSourceDoc = await IdeApp.Workbench.OpenDocument (noSourceView, true);
162-
noSourceDoc.Closed += delegate {
163-
noSourceDoc = null;
164-
noSourceView = null;
165-
};
166+
// If disassembly is open don't show NoSourceView
167+
if (disassemblyDoc == null) {
168+
if (noSourceDoc == null) {
169+
noSourceView = new NoSourceView ();
170+
noSourceView.Update (disassemblyNotSupported);
171+
noSourceDoc = await IdeApp.Workbench.OpenDocument (noSourceView, true);
172+
noSourceDoc.Closed += delegate {
173+
noSourceDoc = null;
174+
noSourceView = null;
175+
};
176+
} else {
177+
noSourceView.Update (disassemblyNotSupported);
178+
noSourceDoc.Select ();
179+
}
166180
} else {
167-
noSourceView.Update (disassemblyNotSupported);
168-
noSourceDoc.Select ();
181+
disassemblyDoc.Select ();
169182
}
170-
} else {
171-
disassemblyDoc.Select ();
183+
} finally {
184+
changingFrame = false;
172185
}
173186
}
174187

0 commit comments

Comments
 (0)