From 7863e84bc46de70683a08e6f5f5c09788bd3b400 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Jun 2025 13:55:14 +0000
Subject: [PATCH 1/7] Initial plan for issue
From 806731d3b0fc9af8281add6463ff4e9e4ec9080d Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Jun 2025 14:05:51 +0000
Subject: [PATCH 2/7] Add fast-path optimizations for Char.IsDigit in
performance-critical paths
Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com>
---
src/Build.UnitTests/Scanner_Tests.cs | 21 +++++++++++++++++++
.../Conditionals/CharacterUtilities.cs | 11 +++++++---
src/Build/Evaluation/Conditionals/Scanner.cs | 2 +-
3 files changed, 30 insertions(+), 4 deletions(-)
diff --git a/src/Build.UnitTests/Scanner_Tests.cs b/src/Build.UnitTests/Scanner_Tests.cs
index da75fd75436..5d98f7cdf10 100644
--- a/src/Build.UnitTests/Scanner_Tests.cs
+++ b/src/Build.UnitTests/Scanner_Tests.cs
@@ -562,5 +562,26 @@ public void NegativeTests()
Scanner lexer = new Scanner("'$(DEBUG) == true", ParserOptions.AllowAll);
Assert.False(lexer.Advance());
}
+
+ ///
+ /// Tests the fast-path IsDigit method in CharacterUtilities.
+ ///
+ [Fact]
+ public void CharacterUtilities_IsDigit_WorksCorrectly()
+ {
+ // Test ASCII digits
+ for (char c = '0'; c <= '9'; c++)
+ {
+ Assert.True(CharacterUtilities.IsDigit(c), $"Character '{c}' should be identified as a digit");
+ }
+
+ // Test non-digit characters
+ Assert.False(CharacterUtilities.IsDigit('/'), "Character '/' should not be identified as a digit");
+ Assert.False(CharacterUtilities.IsDigit(':'), "Character ':' should not be identified as a digit");
+ Assert.False(CharacterUtilities.IsDigit('a'), "Character 'a' should not be identified as a digit");
+ Assert.False(CharacterUtilities.IsDigit('A'), "Character 'A' should not be identified as a digit");
+ Assert.False(CharacterUtilities.IsDigit(' '), "Character ' ' should not be identified as a digit");
+ Assert.False(CharacterUtilities.IsDigit('\0'), "Character '\\0' should not be identified as a digit");
+ }
}
}
diff --git a/src/Build/Evaluation/Conditionals/CharacterUtilities.cs b/src/Build/Evaluation/Conditionals/CharacterUtilities.cs
index ed5502e91ca..5601d0491ab 100644
--- a/src/Build/Evaluation/Conditionals/CharacterUtilities.cs
+++ b/src/Build/Evaluation/Conditionals/CharacterUtilities.cs
@@ -9,7 +9,7 @@ internal static class CharacterUtilities
{
internal static bool IsNumberStart(char candidate)
{
- return candidate == '+' || candidate == '-' || candidate == '.' || char.IsDigit(candidate);
+ return candidate == '+' || candidate == '-' || candidate == '.' || IsDigit(candidate);
}
internal static bool IsSimpleStringStart(char candidate)
@@ -19,12 +19,17 @@ internal static bool IsSimpleStringStart(char candidate)
internal static bool IsSimpleStringChar(char candidate)
{
- return IsSimpleStringStart(candidate) || char.IsDigit(candidate);
+ return IsSimpleStringStart(candidate) || IsDigit(candidate);
+ }
+
+ internal static bool IsDigit(char candidate)
+ {
+ return candidate >= '0' && candidate <= '9';
}
internal static bool IsHexDigit(char candidate)
{
- return char.IsDigit(candidate) || ((uint)((candidate | 0x20) - 'a') <= 'f' - 'a');
+ return IsDigit(candidate) || ((uint)((candidate | 0x20) - 'a') <= 'f' - 'a');
}
}
}
diff --git a/src/Build/Evaluation/Conditionals/Scanner.cs b/src/Build/Evaluation/Conditionals/Scanner.cs
index 718ae73d23d..500ef93df91 100644
--- a/src/Build/Evaluation/Conditionals/Scanner.cs
+++ b/src/Build/Evaluation/Conditionals/Scanner.cs
@@ -772,7 +772,7 @@ private void SkipWhiteSpace()
}
private void SkipDigits()
{
- while (_parsePoint < _expression.Length && char.IsDigit(_expression[_parsePoint]))
+ while (_parsePoint < _expression.Length && CharacterUtilities.IsDigit(_expression[_parsePoint]))
{
_parsePoint++;
}
From 721ed1aa8ca5d4cd25944bb8c00c1197beb0b537 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Jun 2025 14:55:47 +0000
Subject: [PATCH 3/7] Add fast-path for Char.IsDigit in WellKnownFunctions
Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com>
---
.../Evaluation/Expander_Tests.cs | 34 +++++++++++++++++++
src/Build.UnitTests/Scanner_Tests.cs | 21 ------------
.../Conditionals/CharacterUtilities.cs | 11 ++----
src/Build/Evaluation/Conditionals/Scanner.cs | 2 +-
.../Evaluation/Expander/WellKnownFunctions.cs | 12 +++++++
5 files changed, 50 insertions(+), 30 deletions(-)
diff --git a/src/Build.UnitTests/Evaluation/Expander_Tests.cs b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
index 1da44037bef..b4f2c5d5a99 100644
--- a/src/Build.UnitTests/Evaluation/Expander_Tests.cs
+++ b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
@@ -4741,6 +4741,40 @@ public void PropertyFunctionStringArrayGetValue()
TestPropertyFunction("$(X.Split($([System.Convert]::ToString(`.`).ToCharArray())).GetValue($([System.Convert]::ToInt32(0))))", "X", "ab.cd", "ab");
}
+ ///
+ /// Test that Char.IsDigit fast-path works correctly
+ ///
+ [Fact]
+ public void PropertyFunctionCharIsDigit()
+ {
+ PropertyDictionary pg = new PropertyDictionary();
+
+ Expander expander = new Expander(pg, FileSystems.Default);
+
+ // Test with digit characters
+ string result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('5'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+ Assert.Equal("True", result);
+
+ result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('0'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+ Assert.Equal("True", result);
+
+ result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('9'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+ Assert.Equal("True", result);
+
+ // Test with non-digit characters
+ result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('a'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+ Assert.Equal("False", result);
+
+ result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit(' '))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+ Assert.Equal("False", result);
+
+ result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('/'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+ Assert.Equal("False", result);
+
+ result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit(':'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+ Assert.Equal("False", result);
+ }
+
private void TestPropertyFunction(string expression, string propertyName, string propertyValue, string expected)
{
var properties = new PropertyDictionary();
diff --git a/src/Build.UnitTests/Scanner_Tests.cs b/src/Build.UnitTests/Scanner_Tests.cs
index 5d98f7cdf10..da75fd75436 100644
--- a/src/Build.UnitTests/Scanner_Tests.cs
+++ b/src/Build.UnitTests/Scanner_Tests.cs
@@ -562,26 +562,5 @@ public void NegativeTests()
Scanner lexer = new Scanner("'$(DEBUG) == true", ParserOptions.AllowAll);
Assert.False(lexer.Advance());
}
-
- ///
- /// Tests the fast-path IsDigit method in CharacterUtilities.
- ///
- [Fact]
- public void CharacterUtilities_IsDigit_WorksCorrectly()
- {
- // Test ASCII digits
- for (char c = '0'; c <= '9'; c++)
- {
- Assert.True(CharacterUtilities.IsDigit(c), $"Character '{c}' should be identified as a digit");
- }
-
- // Test non-digit characters
- Assert.False(CharacterUtilities.IsDigit('/'), "Character '/' should not be identified as a digit");
- Assert.False(CharacterUtilities.IsDigit(':'), "Character ':' should not be identified as a digit");
- Assert.False(CharacterUtilities.IsDigit('a'), "Character 'a' should not be identified as a digit");
- Assert.False(CharacterUtilities.IsDigit('A'), "Character 'A' should not be identified as a digit");
- Assert.False(CharacterUtilities.IsDigit(' '), "Character ' ' should not be identified as a digit");
- Assert.False(CharacterUtilities.IsDigit('\0'), "Character '\\0' should not be identified as a digit");
- }
}
}
diff --git a/src/Build/Evaluation/Conditionals/CharacterUtilities.cs b/src/Build/Evaluation/Conditionals/CharacterUtilities.cs
index 5601d0491ab..ed5502e91ca 100644
--- a/src/Build/Evaluation/Conditionals/CharacterUtilities.cs
+++ b/src/Build/Evaluation/Conditionals/CharacterUtilities.cs
@@ -9,7 +9,7 @@ internal static class CharacterUtilities
{
internal static bool IsNumberStart(char candidate)
{
- return candidate == '+' || candidate == '-' || candidate == '.' || IsDigit(candidate);
+ return candidate == '+' || candidate == '-' || candidate == '.' || char.IsDigit(candidate);
}
internal static bool IsSimpleStringStart(char candidate)
@@ -19,17 +19,12 @@ internal static bool IsSimpleStringStart(char candidate)
internal static bool IsSimpleStringChar(char candidate)
{
- return IsSimpleStringStart(candidate) || IsDigit(candidate);
- }
-
- internal static bool IsDigit(char candidate)
- {
- return candidate >= '0' && candidate <= '9';
+ return IsSimpleStringStart(candidate) || char.IsDigit(candidate);
}
internal static bool IsHexDigit(char candidate)
{
- return IsDigit(candidate) || ((uint)((candidate | 0x20) - 'a') <= 'f' - 'a');
+ return char.IsDigit(candidate) || ((uint)((candidate | 0x20) - 'a') <= 'f' - 'a');
}
}
}
diff --git a/src/Build/Evaluation/Conditionals/Scanner.cs b/src/Build/Evaluation/Conditionals/Scanner.cs
index 500ef93df91..718ae73d23d 100644
--- a/src/Build/Evaluation/Conditionals/Scanner.cs
+++ b/src/Build/Evaluation/Conditionals/Scanner.cs
@@ -772,7 +772,7 @@ private void SkipWhiteSpace()
}
private void SkipDigits()
{
- while (_parsePoint < _expression.Length && CharacterUtilities.IsDigit(_expression[_parsePoint]))
+ while (_parsePoint < _expression.Length && char.IsDigit(_expression[_parsePoint]))
{
_parsePoint++;
}
diff --git a/src/Build/Evaluation/Expander/WellKnownFunctions.cs b/src/Build/Evaluation/Expander/WellKnownFunctions.cs
index 5f75b6cb636..5d31b60fcae 100644
--- a/src/Build/Evaluation/Expander/WellKnownFunctions.cs
+++ b/src/Build/Evaluation/Expander/WellKnownFunctions.cs
@@ -875,6 +875,18 @@ internal static bool TryExecuteWellKnownFunction(string methodName, Type receive
}
}
}
+ else if (receiverType == typeof(char))
+ {
+ if (string.Equals(methodName, nameof(char.IsDigit), StringComparison.OrdinalIgnoreCase))
+ {
+ if (ParseArgs.TryGetArg(args, out string? arg0) && arg0?.Length == 1)
+ {
+ char c = arg0[0];
+ returnVal = c >= '0' && c <= '9';
+ return true;
+ }
+ }
+ }
else if (string.Equals(methodName, nameof(Regex.Replace), StringComparison.OrdinalIgnoreCase) && args.Length == 3)
{
if (ParseArgs.TryGetArgs(args, out string? arg1, out string? arg2, out string? arg3) && arg1 != null && arg2 != null && arg3 != null)
From 116a6cb6ac807f5f2a4f02e4ccb61984aa5715a4 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Jun 2025 15:16:12 +0000
Subject: [PATCH 4/7] Use char.IsDigit instead of manual ASCII range check
Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com>
---
src/Build/Evaluation/Expander/WellKnownFunctions.cs | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/Build/Evaluation/Expander/WellKnownFunctions.cs b/src/Build/Evaluation/Expander/WellKnownFunctions.cs
index 5d31b60fcae..442f6180a2a 100644
--- a/src/Build/Evaluation/Expander/WellKnownFunctions.cs
+++ b/src/Build/Evaluation/Expander/WellKnownFunctions.cs
@@ -882,7 +882,7 @@ internal static bool TryExecuteWellKnownFunction(string methodName, Type receive
if (ParseArgs.TryGetArg(args, out string? arg0) && arg0?.Length == 1)
{
char c = arg0[0];
- returnVal = c >= '0' && c <= '9';
+ returnVal = char.IsDigit(c);
return true;
}
}
From fda73b3c7cca8c521111be97b3bcf91166ebf90c Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Tue, 17 Jun 2025 15:33:58 +0000
Subject: [PATCH 5/7] Add support for Char.IsDigit(String, Int32) overload with
comprehensive tests
Co-authored-by: baronfel <573979+baronfel@users.noreply.github.com>
---
.../Evaluation/Expander_Tests.cs | 23 +++++++++++++++++--
.../Evaluation/Expander/WellKnownFunctions.cs | 5 ++++
2 files changed, 26 insertions(+), 2 deletions(-)
diff --git a/src/Build.UnitTests/Evaluation/Expander_Tests.cs b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
index b4f2c5d5a99..4feb0f2336f 100644
--- a/src/Build.UnitTests/Evaluation/Expander_Tests.cs
+++ b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
@@ -4751,7 +4751,7 @@ public void PropertyFunctionCharIsDigit()
Expander expander = new Expander(pg, FileSystems.Default);
- // Test with digit characters
+ // Test with digit characters - single char version
string result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('5'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
Assert.Equal("True", result);
@@ -4761,7 +4761,7 @@ public void PropertyFunctionCharIsDigit()
result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('9'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
Assert.Equal("True", result);
- // Test with non-digit characters
+ // Test with non-digit characters - single char version
result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('a'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
Assert.Equal("False", result);
@@ -4773,6 +4773,25 @@ public void PropertyFunctionCharIsDigit()
result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit(':'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
Assert.Equal("False", result);
+
+ // Test with string and index version
+ result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('abc123def', 3))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+ Assert.Equal("True", result);
+
+ result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('abc123def', 4))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+ Assert.Equal("True", result);
+
+ result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('abc123def', 5))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+ Assert.Equal("True", result);
+
+ result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('abc123def', 0))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+ Assert.Equal("False", result);
+
+ result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('abc123def', 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+ Assert.Equal("False", result);
+
+ result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('hello789', 5))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+ Assert.Equal("True", result);
}
private void TestPropertyFunction(string expression, string propertyName, string propertyValue, string expected)
diff --git a/src/Build/Evaluation/Expander/WellKnownFunctions.cs b/src/Build/Evaluation/Expander/WellKnownFunctions.cs
index 442f6180a2a..a0b577585f3 100644
--- a/src/Build/Evaluation/Expander/WellKnownFunctions.cs
+++ b/src/Build/Evaluation/Expander/WellKnownFunctions.cs
@@ -885,6 +885,11 @@ internal static bool TryExecuteWellKnownFunction(string methodName, Type receive
returnVal = char.IsDigit(c);
return true;
}
+ else if (ParseArgs.TryGetArgs(args, out string? str, out int index) && str != null)
+ {
+ returnVal = char.IsDigit(str, index);
+ return true;
+ }
}
}
else if (string.Equals(methodName, nameof(Regex.Replace), StringComparison.OrdinalIgnoreCase) && args.Length == 3)
From 949d5cd543fe83d07de78244afaeb658c883c827 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 18 Jun 2025 07:09:43 +0000
Subject: [PATCH 6/7] Deduplicate returnVal assignment and return logic for
Char.IsDigit overloads
Co-authored-by: YuliiaKovalova <95473390+YuliiaKovalova@users.noreply.github.com>
---
src/Build/Evaluation/Expander/WellKnownFunctions.cs | 12 +++++++++---
1 file changed, 9 insertions(+), 3 deletions(-)
diff --git a/src/Build/Evaluation/Expander/WellKnownFunctions.cs b/src/Build/Evaluation/Expander/WellKnownFunctions.cs
index a0b577585f3..e35c847123f 100644
--- a/src/Build/Evaluation/Expander/WellKnownFunctions.cs
+++ b/src/Build/Evaluation/Expander/WellKnownFunctions.cs
@@ -879,15 +879,21 @@ internal static bool TryExecuteWellKnownFunction(string methodName, Type receive
{
if (string.Equals(methodName, nameof(char.IsDigit), StringComparison.OrdinalIgnoreCase))
{
+ bool? result = null;
+
if (ParseArgs.TryGetArg(args, out string? arg0) && arg0?.Length == 1)
{
char c = arg0[0];
- returnVal = char.IsDigit(c);
- return true;
+ result = char.IsDigit(c);
}
else if (ParseArgs.TryGetArgs(args, out string? str, out int index) && str != null)
{
- returnVal = char.IsDigit(str, index);
+ result = char.IsDigit(str, index);
+ }
+
+ if (result.HasValue)
+ {
+ returnVal = result.Value;
return true;
}
}
From c2dbba7a2654d834acf3bbf298eddb03c93d2e58 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 18 Jun 2025 09:09:40 +0000
Subject: [PATCH 7/7] Rewrite PropertyFunctionCharIsDigit test as data-driven
Theory using TestPropertyFunction helper
Co-authored-by: rainersigwald <3347530+rainersigwald@users.noreply.github.com>
---
.../Evaluation/Expander_Tests.cs | 68 ++++++-------------
1 file changed, 20 insertions(+), 48 deletions(-)
diff --git a/src/Build.UnitTests/Evaluation/Expander_Tests.cs b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
index 4feb0f2336f..c39c1c358aa 100644
--- a/src/Build.UnitTests/Evaluation/Expander_Tests.cs
+++ b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
@@ -4744,54 +4744,26 @@ public void PropertyFunctionStringArrayGetValue()
///
/// Test that Char.IsDigit fast-path works correctly
///
- [Fact]
- public void PropertyFunctionCharIsDigit()
- {
- PropertyDictionary pg = new PropertyDictionary();
-
- Expander expander = new Expander(pg, FileSystems.Default);
-
- // Test with digit characters - single char version
- string result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('5'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
- Assert.Equal("True", result);
-
- result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('0'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
- Assert.Equal("True", result);
-
- result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('9'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
- Assert.Equal("True", result);
-
- // Test with non-digit characters - single char version
- result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('a'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
- Assert.Equal("False", result);
-
- result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit(' '))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
- Assert.Equal("False", result);
-
- result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('/'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
- Assert.Equal("False", result);
-
- result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit(':'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
- Assert.Equal("False", result);
-
- // Test with string and index version
- result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('abc123def', 3))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
- Assert.Equal("True", result);
-
- result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('abc123def', 4))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
- Assert.Equal("True", result);
-
- result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('abc123def', 5))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
- Assert.Equal("True", result);
-
- result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('abc123def', 0))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
- Assert.Equal("False", result);
-
- result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('abc123def', 2))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
- Assert.Equal("False", result);
-
- result = expander.ExpandIntoStringLeaveEscaped("$([System.Char]::IsDigit('hello789', 5))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
- Assert.Equal("True", result);
+ [Theory]
+ // Test with digit characters - single char version
+ [InlineData("$([System.Char]::IsDigit('0'))", "True")]
+ [InlineData("$([System.Char]::IsDigit('5'))", "True")]
+ [InlineData("$([System.Char]::IsDigit('9'))", "True")]
+ // Test with non-digit characters - single char version
+ [InlineData("$([System.Char]::IsDigit('a'))", "False")]
+ [InlineData("$([System.Char]::IsDigit(' '))", "False")]
+ [InlineData("$([System.Char]::IsDigit('/'))", "False")]
+ [InlineData("$([System.Char]::IsDigit(':'))", "False")]
+ // Test with string and index version
+ [InlineData("$([System.Char]::IsDigit('abc123def', 3))", "True")]
+ [InlineData("$([System.Char]::IsDigit('abc123def', 4))", "True")]
+ [InlineData("$([System.Char]::IsDigit('abc123def', 5))", "True")]
+ [InlineData("$([System.Char]::IsDigit('abc123def', 0))", "False")]
+ [InlineData("$([System.Char]::IsDigit('abc123def', 2))", "False")]
+ [InlineData("$([System.Char]::IsDigit('hello789', 5))", "True")]
+ public void PropertyFunctionCharIsDigit(string expression, string expected)
+ {
+ TestPropertyFunction(expression, "dummy", "", expected);
}
private void TestPropertyFunction(string expression, string propertyName, string propertyValue, string expected)