From f6b122d3d95542a53622bd1c8858c20ddd68c628 Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 22 Oct 2025 10:00:59 +0000
Subject: [PATCH 1/3] Initial plan
From 79257ce9d494c66829b3cbf7238a05203238bbbc Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 22 Oct 2025 10:16:39 +0000
Subject: [PATCH 2/3] Add fast-paths for ToolLocationHelper property functions
Co-authored-by: JanProvaznik <25267098+JanProvaznik@users.noreply.github.com>
---
.../Evaluation/Expander_Tests.cs | 34 +++++++++++++++++++
.../Evaluation/Expander/WellKnownFunctions.cs | 29 ++++++++++++++++
2 files changed, 63 insertions(+)
diff --git a/src/Build.UnitTests/Evaluation/Expander_Tests.cs b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
index c39c1c358aa..a5c0849b55f 100644
--- a/src/Build.UnitTests/Evaluation/Expander_Tests.cs
+++ b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
@@ -5207,5 +5207,39 @@ public void PropertyFunctionRegisterBuildCheck()
logger.AllBuildEvents.Count.ShouldBe(1);
}
}
+
+ ///
+ /// Test ToolLocationHelper.GetPlatformSDKLocation fast path
+ ///
+ [Fact]
+ public void PropertyFunctionToolLocationHelperGetPlatformSDKLocation()
+ {
+ PropertyDictionary pg = new PropertyDictionary();
+
+ Expander expander = new Expander(pg, FileSystems.Default);
+
+ // This should use the fast path and not throw even if the SDK doesn't exist
+ string result = expander.ExpandIntoStringLeaveEscaped("$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformSDKLocation('Windows', '10.0'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+
+ // The result could be empty if SDK is not installed, but it should not throw
+ result.ShouldNotBeNull();
+ }
+
+ ///
+ /// Test ToolLocationHelper.GetPlatformSDKDisplayName fast path
+ ///
+ [Fact]
+ public void PropertyFunctionToolLocationHelperGetPlatformSDKDisplayName()
+ {
+ PropertyDictionary pg = new PropertyDictionary();
+
+ Expander expander = new Expander(pg, FileSystems.Default);
+
+ // This should use the fast path and not throw even if the SDK doesn't exist
+ string result = expander.ExpandIntoStringLeaveEscaped("$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformSDKDisplayName('Windows', '10.0'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+
+ // The result could be a generated default name if SDK is not installed, but it should not throw
+ result.ShouldNotBeNull();
+ }
}
}
diff --git a/src/Build/Evaluation/Expander/WellKnownFunctions.cs b/src/Build/Evaluation/Expander/WellKnownFunctions.cs
index e35c847123f..d0eecaf0a64 100644
--- a/src/Build/Evaluation/Expander/WellKnownFunctions.cs
+++ b/src/Build/Evaluation/Expander/WellKnownFunctions.cs
@@ -898,6 +898,35 @@ internal static bool TryExecuteWellKnownFunction(string methodName, Type receive
}
}
}
+ else if (receiverType.FullName == "Microsoft.Build.Utilities.ToolLocationHelper")
+ {
+ if (string.Equals(methodName, "GetPlatformSDKLocation", StringComparison.OrdinalIgnoreCase))
+ {
+ if (ParseArgs.TryGetArgs(args, out string? arg0, out string? arg1))
+ {
+ // Use reflection to invoke the method, but avoid the expensive binding process
+ var method = receiverType.GetMethod("GetPlatformSDKLocation", new[] { typeof(string), typeof(string) });
+ if (method != null)
+ {
+ returnVal = method.Invoke(null, new object?[] { arg0, arg1 });
+ return true;
+ }
+ }
+ }
+ else if (string.Equals(methodName, "GetPlatformSDKDisplayName", StringComparison.OrdinalIgnoreCase))
+ {
+ if (ParseArgs.TryGetArgs(args, out string? arg0, out string? arg1))
+ {
+ // Use reflection to invoke the method, but avoid the expensive binding process
+ var method = receiverType.GetMethod("GetPlatformSDKDisplayName", new[] { typeof(string), typeof(string) });
+ if (method != null)
+ {
+ returnVal = method.Invoke(null, new object?[] { arg0, arg1 });
+ 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 29026074b7e3116e940a85d1d934bcca6788a03a Mon Sep 17 00:00:00 2001
From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com>
Date: Wed, 22 Oct 2025 10:23:11 +0000
Subject: [PATCH 3/3] Add comprehensive test for ToolLocationHelper fast paths
Co-authored-by: JanProvaznik <25267098+JanProvaznik@users.noreply.github.com>
---
.../Evaluation/Expander_Tests.cs | 19 +++++++++++++++++++
1 file changed, 19 insertions(+)
diff --git a/src/Build.UnitTests/Evaluation/Expander_Tests.cs b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
index a5c0849b55f..095d7515200 100644
--- a/src/Build.UnitTests/Evaluation/Expander_Tests.cs
+++ b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
@@ -5241,5 +5241,24 @@ public void PropertyFunctionToolLocationHelperGetPlatformSDKDisplayName()
// The result could be a generated default name if SDK is not installed, but it should not throw
result.ShouldNotBeNull();
}
+
+ ///
+ /// Test that both ToolLocationHelper methods work together in the same property expansion
+ ///
+ [Fact]
+ public void PropertyFunctionToolLocationHelperBothMethodsTogether()
+ {
+ PropertyDictionary pg = new PropertyDictionary();
+
+ Expander expander = new Expander(pg, FileSystems.Default);
+
+ // Test both methods in sequence
+ string result1 = expander.ExpandIntoStringLeaveEscaped("$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformSDKLocation('Windows', '10.0'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+ string result2 = expander.ExpandIntoStringLeaveEscaped("$([Microsoft.Build.Utilities.ToolLocationHelper]::GetPlatformSDKDisplayName('Windows', '10.0'))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+
+ // Both should complete without throwing
+ result1.ShouldNotBeNull();
+ result2.ShouldNotBeNull();
+ }
}
}