From d9ad3577ad4b351778de25a370630258d8fc4cbc Mon Sep 17 00:00:00 2001
From: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com>
Date: Wed, 24 Apr 2024 07:50:09 +0000
Subject: [PATCH 1/4] Fix "Unable to translate Unicode character"
---
src/Tasks/Microsoft.Common.CurrentVersion.targets | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Tasks/Microsoft.Common.CurrentVersion.targets b/src/Tasks/Microsoft.Common.CurrentVersion.targets
index 1c931d712d0..60bc769d75f 100644
--- a/src/Tasks/Microsoft.Common.CurrentVersion.targets
+++ b/src/Tasks/Microsoft.Common.CurrentVersion.targets
@@ -5579,6 +5579,7 @@ Copyright (C) Microsoft Corporation. All rights reserved.
File="$(IntermediateOutputPath)$(CleanFile)"
Lines="@(_CleanUniqueRemainingFileWritesAfterIncrementalClean)"
Condition="'@(_CleanUnfilteredPriorFileWrites)'!='@(_CleanUniqueRemainingFileWritesAfterIncrementalClean)'"
+ Encoding="Unicode"
Overwrite="true"/>
From e0fea3a8c5a3da6d6105dc9d7de7f2f79c114fce Mon Sep 17 00:00:00 2001
From: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com>
Date: Wed, 24 Apr 2024 13:35:41 +0000
Subject: [PATCH 2/4] Half-fix
---
.../Microsoft.Common.CurrentVersion.targets | 5 +--
src/Tasks/ShortenAndHashProjectName.cs | 35 +++++++++++++++++++
2 files changed, 38 insertions(+), 2 deletions(-)
create mode 100644 src/Tasks/ShortenAndHashProjectName.cs
diff --git a/src/Tasks/Microsoft.Common.CurrentVersion.targets b/src/Tasks/Microsoft.Common.CurrentVersion.targets
index 60bc769d75f..2c6592add66 100644
--- a/src/Tasks/Microsoft.Common.CurrentVersion.targets
+++ b/src/Tasks/Microsoft.Common.CurrentVersion.targets
@@ -389,7 +389,9 @@ Copyright (C) Microsoft Corporation. All rights reserved.
$(MSBuildProjectFile)
- $(MSBuildProjectFile.Substring(0,8)).$([MSBuild]::StableStringHash($(MSBuildProjectFile)).ToString("X8"))
+
+
+
$(MSBuildCopyMarkerName).Up2Date
@@ -5579,7 +5581,6 @@ Copyright (C) Microsoft Corporation. All rights reserved.
File="$(IntermediateOutputPath)$(CleanFile)"
Lines="@(_CleanUniqueRemainingFileWritesAfterIncrementalClean)"
Condition="'@(_CleanUnfilteredPriorFileWrites)'!='@(_CleanUniqueRemainingFileWritesAfterIncrementalClean)'"
- Encoding="Unicode"
Overwrite="true"/>
diff --git a/src/Tasks/ShortenAndHashProjectName.cs b/src/Tasks/ShortenAndHashProjectName.cs
new file mode 100644
index 00000000000..e28573a9e70
--- /dev/null
+++ b/src/Tasks/ShortenAndHashProjectName.cs
@@ -0,0 +1,35 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+
+using System;
+using Microsoft.Build.Utilities;
+
+#nullable disable
+
+namespace Microsoft.Build.Tasks
+{
+ // For a long MSBuildProjectFile let's shorten this to 17 chars - using the first 8 chars of the filename and a filename hash.
+ public sealed class ShortenAndHashProjectName : Task
+ {
+ [Required]
+ public string ProjectName { get; set; }
+
+ [Output]
+ public string ShortProjectName { get; set; }
+
+ public override bool Execute()
+ {
+ if (ProjectName.Length <= 17)
+ {
+ ShortProjectName = ProjectName;
+ return true;
+ }
+
+ // if the last char of string is a surrogate, cutting it in half would confuse encoder
+ int length = char.IsHighSurrogate(ProjectName[7]) ? 9 : 8;
+ string truncatedProjectName = ProjectName.Substring(0, length);
+ string originalProjectNameHash = StableStringHash(ProjectName);
+ ShortProjectName = $"{truncatedProjectName}.{originalProjectNameHash}".ToString("X8");
+ return true;
+ }
+}
\ No newline at end of file
From 8fc3eede0ee5579bbe3f59317e99e0602783b6aa Mon Sep 17 00:00:00 2001
From: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com>
Date: Wed, 24 Apr 2024 15:19:20 +0000
Subject: [PATCH 3/4] Expose SubstringByTextElements in IntrinsicFunctions +
test.
---
.../Evaluation/Expander_Tests.cs | 12 +++++++
src/Build/Evaluation/IntrinsicFunctions.cs | 7 ++++
.../Microsoft.Common.CurrentVersion.targets | 6 ++--
src/Tasks/ShortenAndHashProjectName.cs | 35 -------------------
4 files changed, 21 insertions(+), 39 deletions(-)
delete mode 100644 src/Tasks/ShortenAndHashProjectName.cs
diff --git a/src/Build.UnitTests/Evaluation/Expander_Tests.cs b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
index 4af483bd8e8..ccc15f1a584 100644
--- a/src/Build.UnitTests/Evaluation/Expander_Tests.cs
+++ b/src/Build.UnitTests/Evaluation/Expander_Tests.cs
@@ -4380,6 +4380,18 @@ public void PropertyFunctionCheckFeatureAvailability(string featureName, string
Assert.Equal(availability, result);
}
+ [Theory]
+ [InlineData("\u3407\ud840\udc60\ud86a\ude30\ud86e\udc0a\ud86e\udda0\ud879\udeae\u2fd5\u0023", 0, 3, "\u3407\ud840\udc60\ud86a\ude30")]
+ [InlineData("\u3407\ud840\udc60\ud86a\ude30\ud86e\udc0a\ud86e\udda0\ud879\udeae\u2fd5\u0023", 2, 5, "\ud86a\ude30\ud86e\udc0a\ud86e\udda0\ud879\udeae\u2fd5")]
+ public void SubstringByTextElements(string featureName, int start, int length, string expected)
+ {
+ var expander = new Expander(new PropertyDictionary(), FileSystems.Default);
+
+ var result = expander.ExpandIntoStringLeaveEscaped($"$([MSBuild]::SubstringByTextElements({featureName}, {start}, {length}))", ExpanderOptions.ExpandProperties, MockElementLocation.Instance);
+
+ Assert.Equal(expected, result);
+ }
+
[Fact]
public void PropertyFunctionIntrinsicFunctionGetCurrentToolsDirectory()
{
diff --git a/src/Build/Evaluation/IntrinsicFunctions.cs b/src/Build/Evaluation/IntrinsicFunctions.cs
index 92c09ec6c01..64245d70a8b 100644
--- a/src/Build/Evaluation/IntrinsicFunctions.cs
+++ b/src/Build/Evaluation/IntrinsicFunctions.cs
@@ -9,6 +9,7 @@
using System.Runtime.Versioning;
using System.Text;
using System.Text.RegularExpressions;
+using System.Globalization;
using Microsoft.Build.Framework;
using Microsoft.Build.Internal;
@@ -627,6 +628,12 @@ internal static bool AreFeaturesEnabled(Version wave)
return ChangeWaves.AreFeaturesEnabled(wave);
}
+ internal static string SubstringByTextElements(string input, int start, int length)
+ {
+ StringInfo stringInfo = new StringInfo(input);
+ return stringInfo.SubstringByTextElements(start, length);
+ }
+
internal static string CheckFeatureAvailability(string featureName)
{
return Features.CheckFeatureAvailability(featureName).ToString();
diff --git a/src/Tasks/Microsoft.Common.CurrentVersion.targets b/src/Tasks/Microsoft.Common.CurrentVersion.targets
index 2c6592add66..3fc9a9c4d00 100644
--- a/src/Tasks/Microsoft.Common.CurrentVersion.targets
+++ b/src/Tasks/Microsoft.Common.CurrentVersion.targets
@@ -388,10 +388,8 @@ Copyright (C) Microsoft Corporation. All rights reserved.
$(MSBuildProjectFile)
-
-
-
-
+
+ $([MSBuild]::SubstringByTextElements($(MSBuildProjectFile), 0, 8)).$([MSBuild]::StableStringHash($(MSBuildProjectFile)).ToString("X8"))
$(MSBuildCopyMarkerName).Up2Date
diff --git a/src/Tasks/ShortenAndHashProjectName.cs b/src/Tasks/ShortenAndHashProjectName.cs
deleted file mode 100644
index e28573a9e70..00000000000
--- a/src/Tasks/ShortenAndHashProjectName.cs
+++ /dev/null
@@ -1,35 +0,0 @@
-// Licensed to the .NET Foundation under one or more agreements.
-// The .NET Foundation licenses this file to you under the MIT license.
-
-using System;
-using Microsoft.Build.Utilities;
-
-#nullable disable
-
-namespace Microsoft.Build.Tasks
-{
- // For a long MSBuildProjectFile let's shorten this to 17 chars - using the first 8 chars of the filename and a filename hash.
- public sealed class ShortenAndHashProjectName : Task
- {
- [Required]
- public string ProjectName { get; set; }
-
- [Output]
- public string ShortProjectName { get; set; }
-
- public override bool Execute()
- {
- if (ProjectName.Length <= 17)
- {
- ShortProjectName = ProjectName;
- return true;
- }
-
- // if the last char of string is a surrogate, cutting it in half would confuse encoder
- int length = char.IsHighSurrogate(ProjectName[7]) ? 9 : 8;
- string truncatedProjectName = ProjectName.Substring(0, length);
- string originalProjectNameHash = StableStringHash(ProjectName);
- ShortProjectName = $"{truncatedProjectName}.{originalProjectNameHash}".ToString("X8");
- return true;
- }
-}
\ No newline at end of file
From 259728cf6522ec844498802d948feaa40c16b19a Mon Sep 17 00:00:00 2001
From: Ilona Tomkowicz <32700855+ilonatommy@users.noreply.github.com>
Date: Thu, 25 Apr 2024 08:05:27 +0000
Subject: [PATCH 4/4] Feedback.
---
src/Build/Evaluation/Expander.cs | 34 ++++++++++++++++++++++++++++++++
1 file changed, 34 insertions(+)
diff --git a/src/Build/Evaluation/Expander.cs b/src/Build/Evaluation/Expander.cs
index c8c3d32f072..53aa7ba7b8a 100644
--- a/src/Build/Evaluation/Expander.cs
+++ b/src/Build/Evaluation/Expander.cs
@@ -4187,6 +4187,14 @@ private bool TryExecuteWellKnownFunction(out object returnVal, object objectInst
return true;
}
}
+ else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.SubstringByTextElements), StringComparison.OrdinalIgnoreCase))
+ {
+ if (TryGetArgs(args, out string arg0, out int arg1, out int arg2))
+ {
+ returnVal = IntrinsicFunctions.SubstringByTextElements(arg0, arg1, arg2);
+ return true;
+ }
+ }
else if (string.Equals(_methodMethodName, nameof(IntrinsicFunctions.CheckFeatureAvailability), StringComparison.OrdinalIgnoreCase))
{
if (TryGetArg(args, out string arg0))
@@ -4518,6 +4526,32 @@ private bool TryGetArgs(object[] args, out string arg0, out string arg1)
return false;
}
+ private static bool TryGetArgs(object[] args, out string arg0, out int arg1, out int arg2)
+ {
+ arg0 = null;
+ arg1 = 0;
+ arg2 = 0;
+
+ if (args.Length != 3)
+ {
+ return false;
+ }
+
+ var value1 = args[1] as string;
+ var value2 = args[2] as string;
+ arg0 = args[0] as string;
+ if (value1 != null &&
+ value2 != null &&
+ arg0 != null &&
+ int.TryParse(value1, out arg1) &&
+ int.TryParse(value2, out arg2))
+ {
+ return true;
+ }
+
+ return false;
+ }
+
private static bool TryGetArg(object[] args, out int arg0)
{
if (args.Length != 1)