From a3a98af264b15a8c4b08b8562c9e6234961a2c11 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Feb 2026 17:27:31 +0000 Subject: [PATCH 1/4] Initial plan From 0338f4819591e18cd877968af7c4f93e371014c6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Feb 2026 17:43:32 +0000 Subject: [PATCH 2/4] Add AssertInRange, AssertNotNullOrWhiteSpace, CheckNotNullOrEmpty to ArgumentDefinition Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com> --- .../src/Generated/Internal/Argument.cs | 39 +++++++++++ .../src/Providers/ArgumentDefinition.cs | 60 +++++++++++++++++ .../test/Providers/ArgumentTests.cs | 65 +++++++++++++++++++ .../src/Generated/Internal/Argument.cs | 39 +++++++++++ 4 files changed, 203 insertions(+) diff --git a/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Internal/Argument.cs b/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Internal/Argument.cs index ceebb5e87f2..48144a285ae 100644 --- a/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Internal/Argument.cs +++ b/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Internal/Argument.cs @@ -67,5 +67,44 @@ public static void AssertNotNullOrEmpty(string value, string name) throw new ArgumentException("Value cannot be an empty string.", name); } } + + /// The value. + /// The name. + public static void AssertNotNullOrWhiteSpace(string value, string name) + { + if (value is null) + { + throw new ArgumentNullException(name); + } + if (string.IsNullOrWhiteSpace(value)) + { + throw new ArgumentException("Value cannot be empty or contain only white-space characters.", name); + } + } + + /// The value. + /// The minimum value. + /// The maximum value. + /// The name. + public static void AssertInRange(T value, T minimum, T maximum, string name) + where T : notnull, IComparable + { + if (minimum.CompareTo(value) > 0) + { + throw new ArgumentOutOfRangeException(name, "Value is less than the minimum allowed."); + } + if (maximum.CompareTo(value) < 0) + { + throw new ArgumentOutOfRangeException(name, "Value is greater than the maximum allowed."); + } + } + + /// The value. + /// The name. + public static string CheckNotNullOrEmpty(string value, string name) + { + AssertNotNullOrEmpty(value, name); + return value; + } } } diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ArgumentDefinition.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ArgumentDefinition.cs index 7dda538078d..64d35867088 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ArgumentDefinition.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ArgumentDefinition.cs @@ -11,6 +11,7 @@ using Microsoft.TypeSpec.Generator.Statements; using static Microsoft.TypeSpec.Generator.Snippets.ArgumentSnippets; using static Microsoft.TypeSpec.Generator.Snippets.Snippet; +using static Microsoft.TypeSpec.Generator.Snippets.StringSnippets; namespace Microsoft.TypeSpec.Generator.Providers { @@ -20,6 +21,9 @@ private class Template { } private const string AssertNotNullMethodName = "AssertNotNull"; private const string AssertNotNullOrEmptyMethodName = "AssertNotNullOrEmpty"; + private const string AssertNotNullOrWhiteSpaceMethodName = "AssertNotNullOrWhiteSpace"; + private const string AssertInRangeMethodName = "AssertInRange"; + private const string CheckNotNullOrEmptyMethodName = "CheckNotNullOrEmpty"; private readonly CSharpType _t = typeof(Template<>).GetGenericArguments()[0]; private readonly ParameterProvider _nameParam = new ParameterProvider("name", $"The name.", typeof(string)); @@ -65,9 +69,65 @@ protected internal override MethodProvider[] BuildMethods() BuildAssertNotNullStruct(), BuildAssertNotNullOrEmptyCollection(), BuildAssertNotNullOrEmptyString(), + BuildAssertNotNullOrWhiteSpace(), + BuildAssertInRange(), + BuildCheckNotNullOrEmpty(), ]; } + private MethodProvider BuildAssertNotNullOrWhiteSpace() + { + var valueParam = new ParameterProvider("value", $"The value.", typeof(string)); + var signature = GetSignature(AssertNotNullOrWhiteSpaceMethodName, [valueParam, _nameParam]); + return new MethodProvider(signature, new MethodBodyStatement[] + { + AssertNotNullSnippet(valueParam), + new IfStatement(IsNullOrWhiteSpace(valueParam.As())) + { + ThrowArgumentException("Value cannot be empty or contain only white-space characters.") + } + }, + this); + } + + private MethodProvider BuildAssertInRange() + { + var valueParam = new ParameterProvider("value", $"The value.", _t); + var minimumParam = new ParameterProvider("minimum", $"The minimum value.", _t); + var maximumParam = new ParameterProvider("maximum", $"The maximum value.", _t); + var whereExpression = Where.NotNull(_t).And(new CSharpType(typeof(IComparable<>), _t)); + var signature = GetSignature(AssertInRangeMethodName, [valueParam, minimumParam, maximumParam, _nameParam], [_t], [whereExpression]); + return new MethodProvider(signature, new MethodBodyStatement[] + { + new IfStatement(minimumParam.Invoke("CompareTo", valueParam).GreaterThan(Literal(0))) + { + ThrowArgumentOutOfRangeException("Value is less than the minimum allowed.") + }, + new IfStatement(maximumParam.Invoke("CompareTo", valueParam).LessThan(Literal(0))) + { + ThrowArgumentOutOfRangeException("Value is greater than the maximum allowed.") + } + }, + this); + } + + private MethodProvider BuildCheckNotNullOrEmpty() + { + var valueParam = new ParameterProvider("value", $"The value.", typeof(string)); + var signature = GetSignature(CheckNotNullOrEmptyMethodName, [valueParam, _nameParam], returnType: typeof(string)); + return new MethodProvider(signature, new MethodBodyStatement[] + { + Static().Invoke(AssertNotNullOrEmptyMethodName, [valueParam, _nameParam]).Terminate(), + Return(valueParam) + }, + this); + } + + private MethodBodyStatement ThrowArgumentOutOfRangeException(string message) + { + return Throw(New.ArgumentOutOfRangeException(_nameParam, message, false)); + } + private MethodProvider BuildAssertNotNullOrEmptyString() { var valueParam = new ParameterProvider("value", $"The value.", typeof(string)); diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ArgumentTests.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ArgumentTests.cs index 05055d25ba1..222522530a6 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ArgumentTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/test/Providers/ArgumentTests.cs @@ -59,6 +59,71 @@ public void NotNullOrEmptyStringThrowsOnEmpty() Assert.Throws(() => Argument.AssertNotNullOrEmpty(string.Empty, "value")); } + [Test] + public void NotNullOrWhiteSpace() + { + string value = "test"; + Argument.AssertNotNullOrWhiteSpace(value, "value"); + } + + [Test] + public void NotNullOrWhiteSpaceThrowsOnNull() + { + string? value = null; + Assert.Throws(() => Argument.AssertNotNullOrWhiteSpace(value, "value")); + } + + [Test] + public void NotNullOrWhiteSpaceThrowsOnWhiteSpace() + { + Assert.Throws(() => Argument.AssertNotNullOrWhiteSpace(" ", "value")); + } + + [Test] + public void NotNullOrWhiteSpaceThrowsOnEmpty() + { + Assert.Throws(() => Argument.AssertNotNullOrWhiteSpace(string.Empty, "value")); + } + + [Test] + public void AssertInRange() + { + Argument.AssertInRange(5, 1, 10, "value"); + } + + [Test] + public void AssertInRangeThrowsWhenBelowMinimum() + { + Assert.Throws(() => Argument.AssertInRange(0, 1, 10, "value")); + } + + [Test] + public void AssertInRangeThrowsWhenAboveMaximum() + { + Assert.Throws(() => Argument.AssertInRange(11, 1, 10, "value")); + } + + [Test] + public void CheckNotNullOrEmpty() + { + string value = "test"; + string result = Argument.CheckNotNullOrEmpty(value, "value"); + Assert.AreEqual("test", result); + } + + [Test] + public void CheckNotNullOrEmptyThrowsOnNull() + { + string? value = null; + Assert.Throws(() => Argument.CheckNotNullOrEmpty(value, "value")); + } + + [Test] + public void CheckNotNullOrEmptyThrowsOnEmpty() + { + Assert.Throws(() => Argument.CheckNotNullOrEmpty(string.Empty, "value")); + } + private readonly struct TestStructure : IEquatable { internal readonly string A; diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Internal/Argument.cs b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Internal/Argument.cs index ec840fc17ad..e9d84f503cd 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Internal/Argument.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Sample-TypeSpec/src/Generated/Internal/Argument.cs @@ -70,5 +70,44 @@ public static void AssertNotNullOrEmpty(string value, string name) throw new ArgumentException("Value cannot be an empty string.", name); } } + + /// The value. + /// The name. + public static void AssertNotNullOrWhiteSpace(string value, string name) + { + if (value is null) + { + throw new ArgumentNullException(name); + } + if (string.IsNullOrWhiteSpace(value)) + { + throw new ArgumentException("Value cannot be empty or contain only white-space characters.", name); + } + } + + /// The value. + /// The minimum value. + /// The maximum value. + /// The name. + public static void AssertInRange(T value, T minimum, T maximum, string name) + where T : notnull, IComparable + { + if (minimum.CompareTo(value) > 0) + { + throw new ArgumentOutOfRangeException(name, "Value is less than the minimum allowed."); + } + if (maximum.CompareTo(value) < 0) + { + throw new ArgumentOutOfRangeException(name, "Value is greater than the maximum allowed."); + } + } + + /// The value. + /// The name. + public static string CheckNotNullOrEmpty(string value, string name) + { + AssertNotNullOrEmpty(value, name); + return value; + } } } From fe338cd9ed140e6d4fbd712c44bb484b970ac973 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 24 Feb 2026 17:53:51 +0000 Subject: [PATCH 3/4] Remove ThrowArgumentOutOfRangeException helper, inline Throw statement in BuildAssertInRange Co-authored-by: jorgerangel-msft <102122018+jorgerangel-msft@users.noreply.github.com> --- .../src/Providers/ArgumentDefinition.cs | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) diff --git a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ArgumentDefinition.cs b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ArgumentDefinition.cs index 64d35867088..6c7e62bd102 100644 --- a/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ArgumentDefinition.cs +++ b/packages/http-client-csharp/generator/Microsoft.TypeSpec.Generator/src/Providers/ArgumentDefinition.cs @@ -101,11 +101,11 @@ private MethodProvider BuildAssertInRange() { new IfStatement(minimumParam.Invoke("CompareTo", valueParam).GreaterThan(Literal(0))) { - ThrowArgumentOutOfRangeException("Value is less than the minimum allowed.") + Throw(New.ArgumentOutOfRangeException(_nameParam, "Value is less than the minimum allowed.", false)) }, new IfStatement(maximumParam.Invoke("CompareTo", valueParam).LessThan(Literal(0))) { - ThrowArgumentOutOfRangeException("Value is greater than the maximum allowed.") + Throw(New.ArgumentOutOfRangeException(_nameParam, "Value is greater than the maximum allowed.", false)) } }, this); @@ -123,11 +123,6 @@ private MethodProvider BuildCheckNotNullOrEmpty() this); } - private MethodBodyStatement ThrowArgumentOutOfRangeException(string message) - { - return Throw(New.ArgumentOutOfRangeException(_nameParam, message, false)); - } - private MethodProvider BuildAssertNotNullOrEmptyString() { var valueParam = new ParameterProvider("value", $"The value.", typeof(string)); From b854d0939ac5685d52cb0bb34c05977152c11a97 Mon Sep 17 00:00:00 2001 From: Jorge Rangel Date: Tue, 24 Feb 2026 12:39:13 -0600 Subject: [PATCH 4/4] regen --- .../src/Generated/Internal/Argument.cs | 39 ------------------- 1 file changed, 39 deletions(-) diff --git a/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Internal/Argument.cs b/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Internal/Argument.cs index 48144a285ae..ceebb5e87f2 100644 --- a/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Internal/Argument.cs +++ b/docs/samples/client/csharp/SampleService/SampleClient/src/Generated/Internal/Argument.cs @@ -67,44 +67,5 @@ public static void AssertNotNullOrEmpty(string value, string name) throw new ArgumentException("Value cannot be an empty string.", name); } } - - /// The value. - /// The name. - public static void AssertNotNullOrWhiteSpace(string value, string name) - { - if (value is null) - { - throw new ArgumentNullException(name); - } - if (string.IsNullOrWhiteSpace(value)) - { - throw new ArgumentException("Value cannot be empty or contain only white-space characters.", name); - } - } - - /// The value. - /// The minimum value. - /// The maximum value. - /// The name. - public static void AssertInRange(T value, T minimum, T maximum, string name) - where T : notnull, IComparable - { - if (minimum.CompareTo(value) > 0) - { - throw new ArgumentOutOfRangeException(name, "Value is less than the minimum allowed."); - } - if (maximum.CompareTo(value) < 0) - { - throw new ArgumentOutOfRangeException(name, "Value is greater than the maximum allowed."); - } - } - - /// The value. - /// The name. - public static string CheckNotNullOrEmpty(string value, string name) - { - AssertNotNullOrEmpty(value, name); - return value; - } } }