Browse Source

Use custom dialog for assertion failures.

The new dialog allows viewing the full stack trace; and ignoring all occurrences of a given assertion.
pull/32/merge
Daniel Grunwald 13 years ago
parent
commit
04c5e7560b
  1. 3
      src/Main/Base/Project/Src/Gui/Dialogs/SharpDevelopAboutPanels.cs
  2. 2
      src/Main/ICSharpCode.Core.WinForms/MessageService/CustomDialog.cs
  3. 21
      src/Main/SharpDevelop/Logging/ExceptionBox.cs
  4. 82
      src/Main/SharpDevelop/Logging/SDTraceListener.cs
  5. 1
      src/Main/SharpDevelop/SharpDevelop.csproj
  6. 1
      src/Main/SharpDevelop/Startup/SharpDevelopMain.cs

3
src/Main/Base/Project/Src/Gui/Dialogs/SharpDevelopAboutPanels.cs

@ -2,6 +2,7 @@
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt) // This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System; using System;
using System.Diagnostics;
using System.Diagnostics.CodeAnalysis; using System.Diagnostics.CodeAnalysis;
using System.Globalization; using System.Globalization;
using System.Reflection; using System.Reflection;
@ -79,6 +80,8 @@ namespace ICSharpCode.SharpDevelop.Gui
#if DEBUG #if DEBUG
if (e.KeyData == (Keys.Control | Keys.Shift | Keys.E)) { if (e.KeyData == (Keys.Control | Keys.Shift | Keys.E)) {
throw new ClownFishException(); throw new ClownFishException();
} else if (e.KeyData == (Keys.Control | Keys.Shift | Keys.A)) {
Trace.Fail("Trace failure");
} else if (e.KeyData == (Keys.Control | Keys.Shift | Keys.G)) { } else if (e.KeyData == (Keys.Control | Keys.Shift | Keys.G)) {
GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced); GC.Collect(GC.MaxGeneration, GCCollectionMode.Forced);
GC.WaitForPendingFinalizers(); GC.WaitForPendingFinalizers();

2
src/Main/ICSharpCode.Core.WinForms/MessageService/CustomDialog.cs

@ -7,7 +7,7 @@ using System.Windows.Forms;
namespace ICSharpCode.Core.WinForms namespace ICSharpCode.Core.WinForms
{ {
sealed class CustomDialog : System.Windows.Forms.Form public sealed class CustomDialog : System.Windows.Forms.Form
{ {
System.Windows.Forms.Label label; System.Windows.Forms.Label label;
System.Windows.Forms.Panel panel; System.Windows.Forms.Panel panel;

21
src/Main/SharpDevelop/Logging/ExceptionBox.cs

@ -76,18 +76,17 @@ namespace ICSharpCode.SharpDevelop.Logging
[SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")] [SuppressMessage("Microsoft.Design", "CA1031:DoNotCatchGeneralExceptionTypes")]
static void ShowErrorBox(Exception exception, string message, bool mustTerminate) static void ShowErrorBox(Exception exception, string message, bool mustTerminate)
{ {
if (exception == null)
throw new ArgumentNullException("exception");
// ignore reentrant calls (e.g. when there's an exception in OnRender) // ignore reentrant calls (e.g. when there's an exception in OnRender)
if (showingBox) if (showingBox)
return; return;
showingBox = true; showingBox = true;
try { try {
try { if (exception != null) {
SD.AnalyticsMonitor.TrackException(exception); try {
} catch (Exception ex) { SD.AnalyticsMonitor.TrackException(exception);
LoggingService.Warn("Error tracking exception", ex); } catch (Exception ex) {
LoggingService.Warn("Error tracking exception", ex);
}
} }
using (ExceptionBox box = new ExceptionBox(exception, message, mustTerminate)) { using (ExceptionBox box = new ExceptionBox(exception, message, mustTerminate)) {
if (SD.MainThread.InvokeRequired) { if (SD.MainThread.InvokeRequired) {
@ -98,7 +97,7 @@ namespace ICSharpCode.SharpDevelop.Logging
} }
} catch (Exception ex) { } catch (Exception ex) {
LoggingService.Warn("Error showing ExceptionBox", ex); LoggingService.Warn("Error showing ExceptionBox", ex);
MessageBox.Show(exception.ToString(), message, MessageBoxButtons.OK, MessageBox.Show(exception != null ? exception.ToString() : "Error", message, MessageBoxButtons.OK,
MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly); MessageBoxIcon.Error, MessageBoxDefaultButton.Button1, MessageBoxOptions.DefaultDesktopOnly);
} finally { } finally {
showingBox = false; showingBox = false;
@ -155,8 +154,10 @@ namespace ICSharpCode.SharpDevelop.Logging
if (message != null) { if (message != null) {
sb.AppendLine(message); sb.AppendLine(message);
} }
sb.AppendLine("Exception thrown:"); if (exceptionThrown != null) {
sb.AppendLine(exceptionThrown.ToString()); sb.AppendLine("Exception thrown:");
sb.AppendLine(exceptionThrown.ToString());
}
sb.AppendLine(); sb.AppendLine();
sb.AppendLine("---- Recent log messages:"); sb.AppendLine("---- Recent log messages:");
try { try {

82
src/Main/SharpDevelop/Logging/SDTraceListener.cs

@ -0,0 +1,82 @@
// Copyright (c) AlphaSierraPapa for the SharpDevelop Team (for details please see \doc\copyright.txt)
// This code is distributed under the GNU LGPL (for details please see \doc\license.txt)
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Net.Mime;
using System.Threading;
using System.Windows;
using System.Windows.Threading;
using ICSharpCode.Core.WinForms;
namespace ICSharpCode.SharpDevelop.Logging
{
sealed class SDTraceListener : DefaultTraceListener
{
[Conditional("DEBUG")]
public static void Install()
{
Debug.Listeners.Clear();
Debug.Listeners.Add(new SDTraceListener());
}
public SDTraceListener()
{
base.AssertUiEnabled = false;
}
HashSet<string> ignoredStacks = new HashSet<string>();
bool dialogIsOpen;
public override void Fail(string message)
{
this.Fail(message, null);
}
public override void Fail(string message, string detailMessage)
{
base.Fail(message, detailMessage); // let base class write the assert to the debug console
if (dialogIsOpen)
return;
string stackTrace = "";
try {
stackTrace = new StackTrace(true).ToString();
} catch {}
lock (ignoredStacks) {
if (ignoredStacks.Contains(stackTrace))
return;
}
message = message + Environment.NewLine + detailMessage + Environment.NewLine + stackTrace;
dialogIsOpen = true;
CustomDialog inputBox = new CustomDialog("Assertion Failed", message.TakeStartEllipsis(750), -1, 2, new[] { "Show Stacktrace", "Debug", "Ignore", "Ignore All" });
try {
while (true) { // show the dialog repeatedly until an option other than 'Show Stacktrace' is selected
if (SD.MainThread.InvokeRequired) {
inputBox.ShowDialog();
} else {
inputBox.ShowDialog(SD.WinForms.MainWin32Window);
}
switch (inputBox.Result) {
case 0:
ExceptionBox.ShowErrorBox(null, message);
break; // show the custom dialog again
case 1:
Debugger.Break();
return;
case 2:
return;
case 3:
lock (ignoredStacks) {
ignoredStacks.Add(stackTrace);
}
return;
}
}
} finally {
dialogIsOpen = false;
inputBox.Dispose();
}
}
}
}

1
src/Main/SharpDevelop/SharpDevelop.csproj

@ -91,6 +91,7 @@
<Compile Include="Editor\Bookmarks\BookmarkMenuCommands.cs" /> <Compile Include="Editor\Bookmarks\BookmarkMenuCommands.cs" />
<Compile Include="Editor\TextContentCondition.cs" /> <Compile Include="Editor\TextContentCondition.cs" />
<Compile Include="Editor\TextSelectedCondition.cs" /> <Compile Include="Editor\TextSelectedCondition.cs" />
<Compile Include="Logging\SDTraceListener.cs" />
<Compile Include="OptionPanels\LoadSaveOptions.xaml.cs"> <Compile Include="OptionPanels\LoadSaveOptions.xaml.cs">
<DependentUpon>LoadSaveOptions.xaml</DependentUpon> <DependentUpon>LoadSaveOptions.xaml</DependentUpon>
<SubType>Code</SubType> <SubType>Code</SubType>

1
src/Main/SharpDevelop/Startup/SharpDevelopMain.cs

@ -207,6 +207,7 @@ namespace ICSharpCode.SharpDevelop.Startup
for (int i = 0; i < fileList.Length; i++) { for (int i = 0; i < fileList.Length; i++) {
workbenchSettings.InitialFileList.Add(fileList[i]); workbenchSettings.InitialFileList.Add(fileList[i]);
} }
SDTraceListener.Install();
host.RunWorkbench(workbenchSettings); host.RunWorkbench(workbenchSettings);
} finally { } finally {
LoggingService.Info("Leaving RunApplication()"); LoggingService.Info("Leaving RunApplication()");

Loading…
Cancel
Save