From 1128cc6129b7881326bac714a2bc4ea5f8d4e204 Mon Sep 17 00:00:00 2001 From: Stephen Toub Date: Mon, 15 Jul 2024 21:37:13 -0400 Subject: [PATCH] Use OverloadResolutionPriority with Debug/Trace.Assert(string) --- .../ref/System.Diagnostics.TraceSource.cs | 3 ++- .../src/System/Diagnostics/Trace.cs | 4 +++- .../TraceClassTests.cs | 18 +++++++++++++---- .../src/System/Diagnostics/Debug.cs | 3 ++- .../System.Runtime/ref/System.Runtime.cs | 3 ++- .../DebugTestsNoListeners.cs | 20 ++++++++++--------- 6 files changed, 34 insertions(+), 17 deletions(-) diff --git a/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs b/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs index 45e6a34afc0a31..213d6312bbbb3a 100644 --- a/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs +++ b/src/libraries/System.Diagnostics.TraceSource/ref/System.Diagnostics.TraceSource.cs @@ -119,9 +119,10 @@ internal Trace() { } public static System.Diagnostics.TraceListenerCollection Listeners { get { throw null; } } public static bool UseGlobalLock { get { throw null; } set { } } [System.Diagnostics.ConditionalAttribute("TRACE")] + [System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute(-1)] public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition) { } [System.Diagnostics.ConditionalAttribute("TRACE")] - public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition, string? message) { } + public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute("condition")] string? message = null) { } [System.Diagnostics.ConditionalAttribute("TRACE")] public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition, string? message, string? detailMessage) { } [System.Diagnostics.ConditionalAttribute("TRACE")] diff --git a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Trace.cs b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Trace.cs index e00b5b8c69afcb..52c35b964b8845 100644 --- a/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Trace.cs +++ b/src/libraries/System.Diagnostics.TraceSource/src/System/Diagnostics/Trace.cs @@ -3,6 +3,7 @@ #define TRACE using System.Diagnostics.CodeAnalysis; +using System.Runtime.CompilerServices; using System.Threading; namespace System.Diagnostics @@ -114,6 +115,7 @@ public static void Close() /// is . /// [Conditional("TRACE")] + [OverloadResolutionPriority(-1)] // lower priority than (bool, string) overload so that the compiler prefers using CallerArgumentExpression public static void Assert([DoesNotReturnIf(false)] bool condition) { TraceInternal.Assert(condition); @@ -124,7 +126,7 @@ public static void Assert([DoesNotReturnIf(false)] bool condition) /// . /// [Conditional("TRACE")] - public static void Assert([DoesNotReturnIf(false)] bool condition, string? message) + public static void Assert([DoesNotReturnIf(false)] bool condition, [CallerArgumentExpression(nameof(condition))] string? message = null) { TraceInternal.Assert(condition, message); } diff --git a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceClassTests.cs b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceClassTests.cs index b74f30dbb3e1b7..5a270508c62e7e 100644 --- a/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceClassTests.cs +++ b/src/libraries/System.Diagnostics.TraceSource/tests/System.Diagnostics.TraceSource.Tests/TraceClassTests.cs @@ -122,15 +122,19 @@ public void Assert2Test() Trace.Listeners.Clear(); Trace.Listeners.Add(listener); Trace.Listeners.Add(text); - Trace.Assert(true, "Message"); + bool someSuccessfulCondition = true; + Trace.Assert(someSuccessfulCondition, "Message"); Assert.Equal(0, listener.GetCallCount(Method.WriteLine)); Assert.Equal(0, listener.GetCallCount(Method.Fail)); text.Flush(); Assert.DoesNotContain("Message", text.Output); - Trace.Assert(false, "Message"); + bool someFailureCondition = false; + Trace.Assert(someFailureCondition); + Trace.Assert(someFailureCondition, "Message"); Assert.Equal(0, listener.GetCallCount(Method.WriteLine)); - Assert.Equal(1, listener.GetCallCount(Method.Fail)); + Assert.Equal(2, listener.GetCallCount(Method.Fail)); text.Flush(); + Assert.Contains("someFailureCondition", text.Output); Assert.Contains("Message", text.Output); } @@ -384,7 +388,13 @@ public void TraceTest02() Trace.WriteLine("Message end."); textTL.Flush(); newLine = Environment.NewLine; - var expected = "Message start." + newLine + " This message should be indented.This should not be indented." + newLine + " " + fail + "This failure is reported with a detailed message" + newLine + " " + fail + newLine + " " + fail + "This assert is reported" + newLine + "Message end." + newLine; + var expected = + "Message start." + newLine + + " This message should be indented.This should not be indented." + newLine + + " " + fail + "This failure is reported with a detailed message" + newLine + + " " + fail + "false" + newLine + + " " + fail + "This assert is reported" + newLine + + "Message end." + newLine; Assert.Equal(expected, textTL.Output); } } diff --git a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Debug.cs b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Debug.cs index c8cf7ade70f092..2ec074ebbf6a4a 100644 --- a/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Debug.cs +++ b/src/libraries/System.Private.CoreLib/src/System/Diagnostics/Debug.cs @@ -78,11 +78,12 @@ public static void Print([StringSyntax(StringSyntaxAttribute.CompositeFormat)] s WriteLine(string.Format(null, format, args)); [Conditional("DEBUG")] + [OverloadResolutionPriority(-1)] // lower priority than (bool, string) overload so that the compiler prefers using CallerArgumentExpression public static void Assert([DoesNotReturnIf(false)] bool condition) => Assert(condition, string.Empty, string.Empty); [Conditional("DEBUG")] - public static void Assert([DoesNotReturnIf(false)] bool condition, string? message) => + public static void Assert([DoesNotReturnIf(false)] bool condition, [CallerArgumentExpression(nameof(condition))] string? message = null) => Assert(condition, message, string.Empty); [Conditional("DEBUG")] diff --git a/src/libraries/System.Runtime/ref/System.Runtime.cs b/src/libraries/System.Runtime/ref/System.Runtime.cs index e7e61105315e09..60dbd438528895 100644 --- a/src/libraries/System.Runtime/ref/System.Runtime.cs +++ b/src/libraries/System.Runtime/ref/System.Runtime.cs @@ -8535,13 +8535,14 @@ public static partial class Debug public static int IndentLevel { get { throw null; } set { } } public static int IndentSize { get { throw null; } set { } } [System.Diagnostics.ConditionalAttribute("DEBUG")] + [System.Runtime.CompilerServices.OverloadResolutionPriorityAttribute(-1)] public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition) { } [System.Diagnostics.ConditionalAttribute("DEBUG")] public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] ref System.Diagnostics.Debug.AssertInterpolatedStringHandler message) { } [System.Diagnostics.ConditionalAttribute("DEBUG")] public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] ref System.Diagnostics.Debug.AssertInterpolatedStringHandler message, [System.Runtime.CompilerServices.InterpolatedStringHandlerArgumentAttribute("condition")] ref System.Diagnostics.Debug.AssertInterpolatedStringHandler detailMessage) { } [System.Diagnostics.ConditionalAttribute("DEBUG")] - public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition, string? message) { } + public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition, [System.Runtime.CompilerServices.CallerArgumentExpressionAttribute("condition")] string? message = null) { } [System.Diagnostics.ConditionalAttribute("DEBUG")] public static void Assert([System.Diagnostics.CodeAnalysis.DoesNotReturnIfAttribute(false)] bool condition, string? message, string? detailMessage) { } [System.Diagnostics.ConditionalAttribute("DEBUG")] diff --git a/src/libraries/System.Runtime/tests/System.Diagnostics.Debug.Tests/DebugTestsNoListeners.cs b/src/libraries/System.Runtime/tests/System.Diagnostics.Debug.Tests/DebugTestsNoListeners.cs index 359df1c062da3d..09bdb4d3516e84 100644 --- a/src/libraries/System.Runtime/tests/System.Diagnostics.Debug.Tests/DebugTestsNoListeners.cs +++ b/src/libraries/System.Runtime/tests/System.Diagnostics.Debug.Tests/DebugTestsNoListeners.cs @@ -81,15 +81,17 @@ public void Debug_WriteLineNull_IndentsEmptyStringProperly() [Fact] public void Asserts() { - VerifyLogged(() => Debug.Assert(true), ""); - VerifyLogged(() => Debug.Assert(true, "assert passed"), ""); - VerifyLogged(() => Debug.Assert(true, "assert passed", "nothing is wrong"), ""); - VerifyLogged(() => Debug.Assert(true, "assert passed", "nothing is wrong {0} {1}", 'a', 'b'), ""); - - VerifyAssert(() => Debug.Assert(false), ""); - VerifyAssert(() => Debug.Assert(false, "assert passed"), "assert passed"); - VerifyAssert(() => Debug.Assert(false, "assert passed", "nothing is wrong"), "assert passed", "nothing is wrong"); - VerifyAssert(() => Debug.Assert(false, "assert passed", "nothing is wrong {0} {1}", 'a', 'b'), "assert passed", "nothing is wrong a b"); + bool someSuccessfulCondition = true; + VerifyLogged(() => Debug.Assert(someSuccessfulCondition), ""); + VerifyLogged(() => Debug.Assert(someSuccessfulCondition, "assert passed"), ""); + VerifyLogged(() => Debug.Assert(someSuccessfulCondition, "assert passed", "nothing is wrong"), ""); + VerifyLogged(() => Debug.Assert(someSuccessfulCondition, "assert passed", "nothing is wrong {0} {1}", 'a', 'b'), ""); + + bool someFailedCondition = false; + VerifyAssert(() => Debug.Assert(someFailedCondition), "someFailedCondition"); + VerifyAssert(() => Debug.Assert(someFailedCondition, "assert passed"), "assert passed"); + VerifyAssert(() => Debug.Assert(someFailedCondition, "assert passed", "nothing is wrong"), "assert passed", "nothing is wrong"); + VerifyAssert(() => Debug.Assert(someFailedCondition, "assert passed", "nothing is wrong {0} {1}", 'a', 'b'), "assert passed", "nothing is wrong a b"); } [Fact]