</ItemGroup>
<ItemGroup Condition="'$(TargetsWindows)' == 'true'">
<Compile Include="$(BclSourcesRoot)\Interop\Windows\Kernel32\Interop.GetSystemDirectoryW.cs" />
- <Compile Include="$(BclSourcesRoot)\System\Diagnostics\Debug.Windows.cs" />
+ <Compile Include="$(BclSourcesRoot)\System\Diagnostics\DebugProvider.Windows.cs" />
<Compile Include="$(BclSourcesRoot)\System\Globalization\CultureInfo.Windows.cs" />
<Compile Include="$(BclSourcesRoot)\System\Globalization\GlobalizationMode.Windows.cs" />
<Compile Include="$(BclSourcesRoot)\System\Threading\ClrThreadPoolBoundHandle.Windows.cs" />
namespace System.Diagnostics
{
- public static partial class Debug
+ public partial class DebugProvider
{
- private static void ShowDialog(string stackTrace, string message, string detailMessage, string errorSource)
+ public virtual void ShowDialog(string stackTrace, string message, string detailMessage, string errorSource)
{
if (Debugger.IsAttached)
{
}
]
}
+ },
+ {
+ "name": "System.Diagnostics.Tests",
+ "enabled": true,
+ "exclusions": {
+ "namespaces": null,
+ "classes": [
+ {
+ "name" : "System.Diagnostics.Tests.DebugTests",
+ "reason" : "refactoring Debug"
+ }
+ ]
+ }
}
]
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebuggerStepperBoundaryAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebuggerTypeProxyAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebuggerVisualizerAttribute.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebugProvider.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\StackFrame.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\StackTraceHiddenAttribute.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\DivideByZeroException.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Internal\IO\File.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeDirectoryHandle.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)Microsoft\Win32\SafeHandles\SafeFileHandle.Unix.cs" />
- <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\Debug.Unix.cs" />
+ <Compile Include="$(MSBuildThisFileDirectory)System\Diagnostics\DebugProvider.Unix.cs" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CalendarData.Unix.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CompareInfo.Unix.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
<Compile Include="$(MSBuildThisFileDirectory)System\Globalization\CultureData.Unix.cs" Condition="'$(EnableDummyGlobalizationImplementation)' != 'true'" />
// Do not remove this, it is needed to retain calls to these conditional methods in release builds
#define DEBUG
-using System.Diagnostics.Contracts;
-using System.Runtime.CompilerServices;
+using System.Threading;
namespace System.Diagnostics
{
/// </summary>
public static partial class Debug
{
- private static readonly object s_lock = new object();
+ private static DebugProvider s_provider = new DebugProvider();
+
+ public static DebugProvider SetProvider(DebugProvider provider)
+ {
+ if (provider == null)
+ throw new ArgumentNullException(nameof(provider));
+
+ return Interlocked.Exchange(ref s_provider, provider);
+ }
public static bool AutoFlush { get { return true; } set { } }
- [ThreadStatic]
- private static int s_indentLevel;
public static int IndentLevel
{
get
{
- return s_indentLevel;
+ return DebugProvider.IndentLevel;
}
set
{
- s_indentLevel = value < 0 ? 0 : value;
+ DebugProvider.IndentLevel = value;
}
}
- private static int s_indentSize = 4;
public static int IndentSize
{
get
{
- return s_indentSize;
+ return DebugProvider.IndentSize;
}
set
{
- s_indentSize = value < 0 ? 0 : value;
+ DebugProvider.IndentSize = value;
}
}
stackTrace = "";
}
WriteLine(FormatAssert(stackTrace, message, detailMessage));
- s_ShowDialog(stackTrace, message, detailMessage, "Assertion Failed");
+ s_provider.ShowDialog(stackTrace, message, detailMessage, "Assertion Failed");
}
}
stackTrace = "";
}
WriteLine(FormatAssert(stackTrace, message, detailMessage));
- s_ShowDialog(stackTrace, message, detailMessage, SR.GetResourceString(failureKindMessage));
+ s_provider.ShowDialog(stackTrace, message, detailMessage, SR.GetResourceString(failureKindMessage));
}
}
private static string FormatAssert(string stackTrace, string message, string detailMessage)
{
- string newLine = GetIndentString() + Environment.NewLine;
+ string newLine = DebugProvider.GetIndentString() + Environment.NewLine;
return SR.DebugAssertBanner + newLine
+ SR.DebugAssertShortMessage + newLine
+ message + newLine
[System.Diagnostics.Conditional("DEBUG")]
public static void Write(string message)
{
- lock (s_lock)
- {
- if (message == null)
- {
- s_WriteCore(string.Empty);
- return;
- }
- if (s_needIndent)
- {
- message = GetIndentString() + message;
- s_needIndent = false;
- }
- s_WriteCore(message);
- if (message.EndsWith(Environment.NewLine))
- {
- s_needIndent = true;
- }
- }
+ s_provider.Write(message);
}
[System.Diagnostics.Conditional("DEBUG")]
WriteLine(message, category);
}
}
-
- private static bool s_needIndent;
-
- private static string s_indentString;
-
- private static string GetIndentString()
- {
- int indentCount = IndentSize * IndentLevel;
- if (s_indentString?.Length == indentCount)
- {
- return s_indentString;
- }
- return s_indentString = new string(' ', indentCount);
- }
-
- private sealed class DebugAssertException : Exception
- {
- internal DebugAssertException(string stackTrace) :
- base(Environment.NewLine + stackTrace)
- {
- }
-
- internal DebugAssertException(string message, string stackTrace) :
- base(message + Environment.NewLine + Environment.NewLine + stackTrace)
- {
- }
-
- internal DebugAssertException(string message, string detailMessage, string stackTrace) :
- base(message + Environment.NewLine + detailMessage + Environment.NewLine + Environment.NewLine + stackTrace)
- {
- }
- }
-
- // internal and not readonly so that the tests can swap this out.
- internal static Action<string, string, string, string> s_ShowDialog = ShowDialog;
-
- internal static Action<string> s_WriteCore = WriteCore;
}
}
namespace System.Diagnostics
{
- public static partial class Debug
+ public partial class DebugProvider
{
private static readonly bool s_shouldWriteToStdErr = Environment.GetEnvironmentVariable("COMPlus_DebugWriteToStdErr") == "1";
- private static void ShowDialog(string stackTrace, string message, string detailMessage, string errorSource)
+ public virtual void ShowDialog(string stackTrace, string message, string detailMessage, string errorSource)
{
if (Debugger.IsAttached)
{
--- /dev/null
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+// Do not remove this, it is needed to retain calls to these conditional methods in release builds
+#define DEBUG
+
+namespace System.Diagnostics
+{
+ /// <summary>
+ /// Provides default implementation for Write and ShowDialog methods in Debug class.
+ /// </summary>
+ public partial class DebugProvider
+ {
+ public virtual void Write(string message)
+ {
+ lock (s_lock)
+ {
+ if (message == null)
+ {
+ s_WriteCore(string.Empty);
+ return;
+ }
+ if (s_needIndent)
+ {
+ message = GetIndentString() + message;
+ s_needIndent = false;
+ }
+ s_WriteCore(message);
+ if (message.EndsWith(Environment.NewLine))
+ {
+ s_needIndent = true;
+ }
+ }
+ }
+
+ private static readonly object s_lock = new object();
+
+ private sealed class DebugAssertException : Exception
+ {
+ internal DebugAssertException(string stackTrace) :
+ base(Environment.NewLine + stackTrace)
+ {
+ }
+
+ internal DebugAssertException(string message, string stackTrace) :
+ base(message + Environment.NewLine + Environment.NewLine + stackTrace)
+ {
+ }
+
+ internal DebugAssertException(string message, string detailMessage, string stackTrace) :
+ base(message + Environment.NewLine + detailMessage + Environment.NewLine + Environment.NewLine + stackTrace)
+ {
+ }
+ }
+
+ [ThreadStatic]
+ private static int s_indentLevel;
+ internal static int IndentLevel
+ {
+ get
+ {
+ return s_indentLevel;
+ }
+ set
+ {
+ s_indentLevel = value < 0 ? 0 : value;
+ }
+ }
+
+ private static int s_indentSize = 4;
+ internal static int IndentSize
+ {
+ get
+ {
+ return s_indentSize;
+ }
+ set
+ {
+ s_indentSize = value < 0 ? 0 : value;
+ }
+ }
+
+ private static bool s_needIndent;
+
+ private static string s_indentString;
+
+ internal static string GetIndentString()
+ {
+ int indentCount = IndentSize * IndentLevel;
+ if (s_indentString?.Length == indentCount)
+ {
+ return s_indentString;
+ }
+ return s_indentString = new string(' ', indentCount);
+ }
+
+ // internal and not readonly so that the tests can swap this out.
+ internal static Action<string> s_WriteCore = WriteCore;
+ }
+}