Skip to content

Commit 16e8f49

Browse files
authored
Merge pull request #258 from AArnott/fastVerifyOp
Add `Verify.Operation` overloads that only load the string resource on failures
2 parents 33485cc + 7e7d178 commit 16e8f49

File tree

3 files changed

+85
-1
lines changed

3 files changed

+85
-1
lines changed

src/Microsoft.VisualStudio.Validation/Verify.cs

Lines changed: 66 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33

44
using System.Diagnostics;
55
using System.Diagnostics.CodeAnalysis;
6+
using System.Globalization;
7+
using System.Resources;
68
using System.Runtime.CompilerServices;
79
using System.Runtime.InteropServices;
810

@@ -73,6 +75,70 @@ public static void Operation([DoesNotReturnIf(false)] bool condition, [Interpola
7375
}
7476
}
7577

78+
/// <inheritdoc cref="Operation(bool, ResourceManager, string, object?)"/>
79+
/// <param name="condition"><inheritdoc cref="Operation(bool, ResourceManager, string, object?[])" path="/param[@name='condition']"/></param>
80+
/// <param name="resourceManager"><inheritdoc cref="Operation(bool, ResourceManager, string, object?[])" path="/param[@name='resourceManager']"/></param>
81+
/// <param name="resourceName"><inheritdoc cref="Operation(bool, ResourceManager, string, object?[])" path="/param[@name='unformattedMessageResourceName']"/></param>
82+
[DebuggerStepThrough]
83+
public static void Operation([DoesNotReturnIf(false)] bool condition, ResourceManager resourceManager, string resourceName)
84+
{
85+
Requires.NotNull(resourceManager, nameof(resourceManager));
86+
if (!condition)
87+
{
88+
throw new InvalidOperationException(resourceManager.GetString(resourceName, CultureInfo.CurrentCulture));
89+
}
90+
}
91+
92+
/// <inheritdoc cref="Operation(bool, ResourceManager, string, object?, object?)"/>
93+
[DebuggerStepThrough]
94+
public static void Operation([DoesNotReturnIf(false)] bool condition, ResourceManager resourceManager, string unformattedMessageResourceName, object? arg1)
95+
{
96+
Requires.NotNull(resourceManager, nameof(resourceManager));
97+
if (!condition)
98+
{
99+
throw new InvalidOperationException(PrivateErrorHelpers.Format(resourceManager.GetString(unformattedMessageResourceName, CultureInfo.CurrentCulture)!, arg1));
100+
}
101+
}
102+
103+
/// <inheritdoc cref="Operation(bool, ResourceManager, string, object?[])"/>
104+
/// <param name="condition"><inheritdoc cref="Operation(bool, ResourceManager, string, object?[])" path="/param[@name='condition']"/></param>
105+
/// <param name="resourceManager"><inheritdoc cref="Operation(bool, ResourceManager, string, object?[])" path="/param[@name='resourceManager']"/></param>
106+
/// <param name="unformattedMessageResourceName"><inheritdoc cref="Operation(bool, ResourceManager, string, object?[])" path="/param[@name='unformattedMessageResourceName']"/></param>
107+
/// <param name="arg1">The first formatting argument.</param>
108+
/// <param name="arg2">The second formatting argument.</param>
109+
[DebuggerStepThrough]
110+
public static void Operation([DoesNotReturnIf(false)] bool condition, ResourceManager resourceManager, string unformattedMessageResourceName, object? arg1, object? arg2)
111+
{
112+
Requires.NotNull(resourceManager, nameof(resourceManager));
113+
if (!condition)
114+
{
115+
throw new InvalidOperationException(PrivateErrorHelpers.Format(resourceManager.GetString(unformattedMessageResourceName, CultureInfo.CurrentCulture)!, arg1, arg2));
116+
}
117+
}
118+
119+
/// <summary>
120+
/// Throws an <see cref="InvalidOperationException"/> if a condition is false.
121+
/// </summary>
122+
/// <param name="condition">The condition to check.</param>
123+
/// <param name="resourceManager">The resource manager from which to retrieve the exception message. For example: <c>Strings.ResourceManager</c>.</param>
124+
/// <param name="unformattedMessageResourceName">The name of the string resource to obtain for the exception message. For example: <c>nameof(Strings.SomeError)</c>.</param>
125+
/// <param name="args">The formatting arguments.</param>
126+
/// <remarks>
127+
/// This overload allows only loading a localized string in the error condition as an optimization in perf critical sections over the simpler
128+
/// to use <see cref="Operation(bool, string?)"/> overload.
129+
/// </remarks>
130+
/// <exception cref="ArgumentNullException">Thrown if <paramref name="resourceManager"/> is <see langword="null"/>.</exception>
131+
/// <exception cref="InvalidOperationException">Thrown if <paramref name="condition"/> is <see langword="false"/>.</exception>
132+
[DebuggerStepThrough]
133+
public static void Operation([DoesNotReturnIf(false)] bool condition, ResourceManager resourceManager, string unformattedMessageResourceName, params object?[] args)
134+
{
135+
Requires.NotNull(resourceManager, nameof(resourceManager));
136+
if (!condition)
137+
{
138+
throw new InvalidOperationException(PrivateErrorHelpers.Format(resourceManager.GetString(unformattedMessageResourceName, CultureInfo.CurrentCulture)!, args));
139+
}
140+
}
141+
76142
/// <summary>
77143
/// Throws an <see cref="InvalidOperationException"/> if a condition is false.
78144
/// </summary>

test/Microsoft.VisualStudio.Validation.Tests/VerifyTests.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,7 @@
33

44
using System.Runtime.InteropServices;
55
using Microsoft;
6+
using Microsoft.VisualStudio.Validation.Tests;
67
using Xunit;
78

89
public class VerifyTests
@@ -39,6 +40,23 @@ string FormattingMethod()
3940
Assert.StartsWith("Some generated string method.", ex.Message);
4041
}
4142

43+
[Fact]
44+
public void Operation_ResourceManager()
45+
{
46+
AssertThrows(TestStrings.GetResourceString(TestStrings.SomeError), c => Verify.Operation(c, TestStrings.ResourceManager, TestStrings.SomeError));
47+
AssertThrows(TestStrings.FormatSomeError1Arg("A"), c => Verify.Operation(c, TestStrings.ResourceManager, TestStrings.SomeError1Arg, "A"));
48+
AssertThrows(TestStrings.FormatSomeError2Args("A", "B"), c => Verify.Operation(c, TestStrings.ResourceManager, TestStrings.SomeError2Args, "A", "B"));
49+
AssertThrows(TestStrings.FormatSomeError3Args("A", "B", "C"), c => Verify.Operation(c, TestStrings.ResourceManager, TestStrings.SomeError3Args, "A", "B", "C"));
50+
51+
static void AssertThrows(string? expectedMessage, Action<bool> action)
52+
{
53+
action(true);
54+
55+
InvalidOperationException actual = Assert.Throws<InvalidOperationException>(() => action(false));
56+
Assert.Equal(expectedMessage, actual.Message);
57+
}
58+
}
59+
4260
[Fact]
4361
public void OperationWithHelp()
4462
{

version.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"$schema": "https://raw.githubusercontent.com/dotnet/Nerdbank.GitVersioning/master/src/NerdBank.GitVersioning/version.schema.json",
3-
"version": "17.8",
3+
"version": "17.12-beta",
44
"publicReleaseRefSpec": [
55
"^refs/heads/main$",
66
"^refs/heads/v\\d+(?:\\.\\d+)?$"

0 commit comments

Comments
 (0)