Skip to content
Merged
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
1 change: 1 addition & 0 deletions eng/Packages.props
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@
<PackageReference Update="Microsoft.VisualStudio.Setup.Configuration.Interop" Version="1.16.30" />
<PackageReference Update="Microsoft.Win32.Registry" Version="4.3.0" />
<PackageReference Update="NuGet.Build.Tasks" Version="$(NuGetBuildTasksVersion)" />
<PackageReference Update="NuGet.Frameworks" Version="$(NuGetBuildTasksVersion)" />
Comment thread
sfoslund marked this conversation as resolved.
Outdated
Comment thread
sfoslund marked this conversation as resolved.
Outdated
Comment thread
sfoslund marked this conversation as resolved.
Outdated
<PackageReference Update="PdbGit" Version="3.0.41" />
<PackageReference Update="Shouldly" Version="3.0.0" />
<PackageReference Update="SourceLink.Create.CommandLine" Version="2.1.2" />
Expand Down
101 changes: 66 additions & 35 deletions src/Build.UnitTests/Evaluation/Expander_Tests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -2800,34 +2800,23 @@ public void PropertyFunctionVersionComparisonsFailsWithInvalidArguments(string b
var expander = new Expander<ProjectPropertyInstance, ProjectItemInstance>(pg, FileSystems.Default);
string expectedMessage = ResourceUtilities.GetResourceString("InvalidVersionFormat");

AssertThrows($"$([MSBuild]::VersionGreaterThan('{badVersion}', '1.0.0'))");
AssertThrows($"$([MSBuild]::VersionGreaterThan('1.0.0', '{badVersion}'))");
AssertThrows(expander, $"$([MSBuild]::VersionGreaterThan('{badVersion}', '1.0.0'))", expectedMessage);
Comment thread
sfoslund marked this conversation as resolved.
Outdated
AssertThrows(expander, $"$([MSBuild]::VersionGreaterThan('1.0.0', '{badVersion}'))", expectedMessage);

AssertThrows($"$([MSBuild]::VersionGreaterThanOrEquals('{badVersion}', '1.0.0'))");
AssertThrows($"$([MSBuild]::VersionGreaterThanOrEquals('1.0.0', '{badVersion}'))");
AssertThrows(expander, $"$([MSBuild]::VersionGreaterThanOrEquals('{badVersion}', '1.0.0'))", expectedMessage);
AssertThrows(expander, $"$([MSBuild]::VersionGreaterThanOrEquals('1.0.0', '{badVersion}'))", expectedMessage);

AssertThrows($"$([MSBuild]::VersionLessThan('{badVersion}', '1.0.0'))");
AssertThrows($"$([MSBuild]::VersionLessThan('1.0.0', '{badVersion}'))");
AssertThrows(expander, $"$([MSBuild]::VersionLessThan('{badVersion}', '1.0.0'))", expectedMessage);
AssertThrows(expander, $"$([MSBuild]::VersionLessThan('1.0.0', '{badVersion}'))", expectedMessage);

AssertThrows($"$([MSBuild]::VersionLessThanOrEquals('{badVersion}', '1.0.0'))");
AssertThrows($"$([MSBuild]::VersionLessThanOrEquals('1.0.0', '{badVersion}'))");
AssertThrows(expander, $"$([MSBuild]::VersionLessThanOrEquals('{badVersion}', '1.0.0'))", expectedMessage);
AssertThrows(expander, $"$([MSBuild]::VersionLessThanOrEquals('1.0.0', '{badVersion}'))", expectedMessage);

AssertThrows($"$([MSBuild]::VersionEquals('{badVersion}', '1.0.0'))");
AssertThrows($"$([MSBuild]::VersionEquals('1.0.0', '{badVersion}'))");
AssertThrows(expander, $"$([MSBuild]::VersionEquals('{badVersion}', '1.0.0'))", expectedMessage);
AssertThrows(expander, $"$([MSBuild]::VersionEquals('1.0.0', '{badVersion}'))", expectedMessage);

AssertThrows($"$([MSBuild]::VersionNotEquals('{badVersion}', '1.0.0'))");
AssertThrows($"$([MSBuild]::VersionNotEquals('1.0.0', '{badVersion}'))");

void AssertThrows(string expression)
{
var ex = Assert.Throws<InvalidProjectFileException>(
() => expander.ExpandPropertiesLeaveTypedAndEscaped(
expression,
ExpanderOptions.ExpandProperties,
MockElementLocation.Instance));

Assert.Contains(expectedMessage, ex.Message);
}
AssertThrows(expander, $"$([MSBuild]::VersionNotEquals('{badVersion}', '1.0.0'))", expectedMessage);
AssertThrows(expander, $"$([MSBuild]::VersionNotEquals('1.0.0', '{badVersion}'))", expectedMessage);
}

[Theory]
Expand All @@ -2843,22 +2832,64 @@ public void PropertyFunctionVersionComparisons(string a, string b, int expectedS
var pg = new PropertyDictionary<ProjectPropertyInstance>();
var expander = new Expander<ProjectPropertyInstance, ProjectItemInstance>(pg, FileSystems.Default);

AssertSuccess(expectedSign > 0, $"$([MSBuild]::VersionGreaterThan('{a}', '{b}'))");
AssertSuccess(expectedSign >= 0, $"$([MSBuild]::VersionGreaterThanOrEquals('{a}', '{b}'))");
AssertSuccess(expectedSign < 0, $"$([MSBuild]::VersionLessThan('{a}', '{b}'))");
AssertSuccess(expectedSign <= 0, $"$([MSBuild]::VersionLessThanOrEquals('{a}', '{b}'))");
AssertSuccess(expectedSign == 0, $"$([MSBuild]::VersionEquals('{a}', '{b}'))");
AssertSuccess(expectedSign != 0, $"$([MSBuild]::VersionNotEquals('{a}', '{b}'))");
AssertSuccess(expander, expectedSign > 0, $"$([MSBuild]::VersionGreaterThan('{a}', '{b}'))");
AssertSuccess(expander, expectedSign >= 0, $"$([MSBuild]::VersionGreaterThanOrEquals('{a}', '{b}'))");
AssertSuccess(expander, expectedSign < 0, $"$([MSBuild]::VersionLessThan('{a}', '{b}'))");
AssertSuccess(expander, expectedSign <= 0, $"$([MSBuild]::VersionLessThanOrEquals('{a}', '{b}'))");
AssertSuccess(expander, expectedSign == 0, $"$([MSBuild]::VersionEquals('{a}', '{b}'))");
AssertSuccess(expander, expectedSign != 0, $"$([MSBuild]::VersionNotEquals('{a}', '{b}'))");
}

void AssertSuccess(bool expected, string expression)
{
bool actual = (bool)expander.ExpandPropertiesLeaveTypedAndEscaped(
[Theory]
[InlineData("net45", ".NETFramework", "4.5")]
[InlineData("netcoreapp3.1", ".NETCoreApp", "3.1")]
[InlineData("netstandard2.1", ".NETStandard", "2.1")]
[InlineData("foo", "Unsupported", "0.0")]
public void PropertyFunctionTargetFrameworkParsing(string tfm, string expectedIdentifier, string expectedVersion)
{
var pg = new PropertyDictionary<ProjectPropertyInstance>();
var expander = new Expander<ProjectPropertyInstance, ProjectItemInstance>(pg, FileSystems.Default);

AssertSuccess(expander, expectedIdentifier, $"$([MSBuild]::GetTargetFrameworkIdentifier('{tfm}'))");
AssertSuccess(expander, expectedVersion, $"$([MSBuild]::GetTargetFrameworkVersion('{tfm}'))");
}

[Theory]
[InlineData("net5.0", "net5.0", true)]
[InlineData("net45", "net46", false)]
[InlineData("net46", "net45", true)]
[InlineData("netcoreapp3.1", "netcoreapp1.0", true)]
[InlineData("netstandard1.6", "netstandard2.1", false)]
[InlineData("netcoreapp3.0", "netstandard2.1", true)]
[InlineData("net461", "netstandard1.0", true)]
[InlineData("foo", "netstandard1.0", false)]
public void PropertyFunctionTargetFrameworkComparisons(string tfm1, string tfm2, bool expectedFrameworkCompatible)
{
var pg = new PropertyDictionary<ProjectPropertyInstance>();
var expander = new Expander<ProjectPropertyInstance, ProjectItemInstance>(pg, FileSystems.Default);

AssertSuccess(expander, expectedFrameworkCompatible, $"$([MSBuild]::IsTargetFrameworkCompatible('{tfm1}', '{tfm2}'))");
}

private void AssertThrows(Expander<ProjectPropertyInstance, ProjectItemInstance> expander, string expression, string expectedMessage)
{
var ex = Assert.Throws<InvalidProjectFileException>(
() => expander.ExpandPropertiesLeaveTypedAndEscaped(
expression,
ExpanderOptions.ExpandProperties,
MockElementLocation.Instance);
MockElementLocation.Instance));

Assert.Equal(expected, actual);
}
Assert.Contains(expectedMessage, ex.Message);
}

private void AssertSuccess(Expander<ProjectPropertyInstance, ProjectItemInstance> expander, object expected, string expression)
{
var actual = expander.ExpandPropertiesLeaveTypedAndEscaped(
expression,
ExpanderOptions.ExpandProperties,
MockElementLocation.Instance);

Assert.Equal(expected, actual);
}

/// <summary>
Expand Down
5 changes: 5 additions & 0 deletions src/Build.UnitTests/Microsoft.Build.Engine.UnitTests.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -11,12 +11,17 @@

<!-- Define a constant so we can skip tests that require MSBuildTaskHost -->
<DefineConstants Condition="'$(MSBuildRuntimeType)' == 'Core' or '$(MonoBuild)' == 'true'">$(DefineConstants);NO_MSBUILDTASKHOST</DefineConstants>

<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
</PropertyGroup>

<ItemGroup>
<PackageReference Include="System.Collections.Concurrent" />
<PackageReference Include="Shouldly" />
<PackageReference Include="Microsoft.CodeAnalysis.Build.Tasks" />
<PackageReference Include="NuGet.Frameworks" >
<PrivateAssets>all</PrivateAssets>
</PackageReference>

<ProjectReference Include="..\Build\Microsoft.Build.csproj" />
<ProjectReference Include="..\Framework\Microsoft.Build.Framework.csproj" />
Expand Down
24 changes: 24 additions & 0 deletions src/Build/Evaluation/Expander.cs
Original file line number Diff line number Diff line change
Expand Up @@ -3916,6 +3916,30 @@ private bool TryExecuteWellKnownFunction(out object returnVal, object objectInst
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.GetTargetFrameworkIdentifier), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArg(args, out string arg0))
{
returnVal = IntrinsicFunctions.GetTargetFrameworkIdentifier(arg0);
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.GetTargetFrameworkVersion), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArg(args, out string arg0))
{
returnVal = IntrinsicFunctions.GetTargetFrameworkVersion(arg0);
return true;
}
}
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.IsTargetFrameworkCompatible), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArgs(args, out string arg0, out string arg1))
{
returnVal = IntrinsicFunctions.IsTargetFrameworkCompatible(arg0, arg1);
return true;
}
}
}
else if (_receiverType == typeof(Path))
{
Expand Down
19 changes: 17 additions & 2 deletions src/Build/Evaluation/IntrinsicFunctions.cs
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,6 @@
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Runtime.InteropServices;
using System.Text.RegularExpressions;

Expand All @@ -32,6 +30,8 @@ internal static class IntrinsicFunctions
private static readonly Lazy<Regex> RegistrySdkRegex = new Lazy<Regex>(() => new Regex(@"^HKEY_LOCAL_MACHINE\\Software\\Microsoft\\Microsoft SDKs\\Windows\\v(\d+\.\d+)$", RegexOptions.IgnoreCase));
#endif // FEATURE_WIN32_REGISTRY

private static readonly Lazy<NuGetFrameworkWrapper> NuGetFramework = new Lazy<NuGetFrameworkWrapper>(() => new NuGetFrameworkWrapper());

/// <summary>
/// Add two doubles
/// </summary>
Expand Down Expand Up @@ -480,6 +480,21 @@ internal static bool VersionLessThanOrEquals(string a, string b)
return SimpleVersion.Parse(a) <= SimpleVersion.Parse(b);
}

internal static string GetTargetFrameworkIdentifier(string tfm)
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should have a follow up issue for getting the platform (.NET 5 era intrinsics)

{
return NuGetFramework.Value.GetTargetFrameworkIdentifier(tfm);
}

internal static string GetTargetFrameworkVersion(string tfm)
{
return NuGetFramework.Value.GetTargetFrameworkVersion(tfm);
}

internal static bool IsTargetFrameworkCompatible(string target, string candidate)
{
return NuGetFramework.Value.IsCompatible(target, candidate);
}

public static string GetCurrentToolsDirectory()
{
return BuildEnvironmentHelper.Instance.CurrentMSBuildToolsDirectory;
Expand Down
1 change: 1 addition & 0 deletions src/Build/Microsoft.Build.csproj
Original file line number Diff line number Diff line change
Expand Up @@ -154,6 +154,7 @@
<Compile Include="BackEnd\BuildManager\CacheAggregator.cs" />
<Compile Include="BackEnd\Components\Caching\ConfigCacheWithOverride.cs" />
<Compile Include="BackEnd\Components\Caching\ResultsCacheWithOverride.cs" />
<Compile Include="Utilities\NuGetFrameworkWrapper.cs" />
<Compile Include="ObjectModelRemoting\ConstructionObjectLinks\ProjectUsingTaskParameterElementLink.cs" />
<Compile Include="ObjectModelRemoting\ExternalProjectsProvider.cs" />
<Compile Include="ObjectModelRemoting\LinkedObjectFactory.cs" />
Expand Down
3 changes: 3 additions & 0 deletions src/Build/Resources/Strings.resx
Original file line number Diff line number Diff line change
Expand Up @@ -1825,4 +1825,7 @@ Utilization: {0} Average Utilization: {1:###.0}</value>
<data name="PropertyAssignment" xml:space="preserve">
<value>Property initial value: $({0})="{1}" Source: {2}</value>
</data>
<data name="NuGetAssemblyNotFound" xml:space="preserve">
<value>A required NuGet assembly was not found. Expected Path: {0}</value>
</data>
</root>
5 changes: 5 additions & 0 deletions src/Build/Resources/xlf/Strings.cs.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Build/Resources/xlf/Strings.de.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Build/Resources/xlf/Strings.en.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Build/Resources/xlf/Strings.es.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Build/Resources/xlf/Strings.fr.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Build/Resources/xlf/Strings.it.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Build/Resources/xlf/Strings.ja.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions src/Build/Resources/xlf/Strings.ko.xlf

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Loading