Skip to content
Draft
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
53 changes: 53 additions & 0 deletions src/Build.UnitTests/Evaluation/Expander_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -5207,5 +5207,58 @@ public void PropertyFunctionRegisterBuildCheck()
logger.AllBuildEvents.Count.ShouldBe(1);
}
}

/// <summary>
/// Test ToolLocationHelper.GetPlatformSDKLocation fast path
/// </summary>
[Fact]
public void PropertyFunctionToolLocationHelperGetPlatformSDKLocation()
{
PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

Expander<ProjectPropertyInstance, ProjectItemInstance> expander = new Expander<ProjectPropertyInstance, ProjectItemInstance>(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();
}

/// <summary>
/// Test ToolLocationHelper.GetPlatformSDKDisplayName fast path
/// </summary>
[Fact]
public void PropertyFunctionToolLocationHelperGetPlatformSDKDisplayName()
{
PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

Expander<ProjectPropertyInstance, ProjectItemInstance> expander = new Expander<ProjectPropertyInstance, ProjectItemInstance>(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();
}

/// <summary>
/// Test that both ToolLocationHelper methods work together in the same property expansion
/// </summary>
[Fact]
public void PropertyFunctionToolLocationHelperBothMethodsTogether()
{
PropertyDictionary<ProjectPropertyInstance> pg = new PropertyDictionary<ProjectPropertyInstance>();

Expander<ProjectPropertyInstance, ProjectItemInstance> expander = new Expander<ProjectPropertyInstance, ProjectItemInstance>(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();
}
}
}
29 changes: 29 additions & 0 deletions src/Build/Evaluation/Expander/WellKnownFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -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)
Expand Down
Loading