From b26323dd6fe3c50b8d55b1b8608a2c1b36630163 Mon Sep 17 00:00:00 2001
From: "Ryland 41491307+ryalanms@users.noreply.github.com"
<41491307+ryalanms@users.noreply.github.com>
Date: Wed, 17 Jul 2019 13:51:04 -0700
Subject: [PATCH 1/7] Adding a default 'true' for unset properties owned by WPF
---
.../targets/Microsoft.NET.Sdk.WindowsDesktop.props | 2 ++
1 file changed, 2 insertions(+)
diff --git a/packaging/Microsoft.NET.Sdk.WindowsDesktop/targets/Microsoft.NET.Sdk.WindowsDesktop.props b/packaging/Microsoft.NET.Sdk.WindowsDesktop/targets/Microsoft.NET.Sdk.WindowsDesktop.props
index 985437424fe..923c2d9bdf3 100644
--- a/packaging/Microsoft.NET.Sdk.WindowsDesktop/targets/Microsoft.NET.Sdk.WindowsDesktop.props
+++ b/packaging/Microsoft.NET.Sdk.WindowsDesktop/targets/Microsoft.NET.Sdk.WindowsDesktop.props
@@ -1,6 +1,8 @@
<_MicrosoftNetSdkWindowsDesktop>true
+ true
+ true
From 8a777ad8caff39ce4fe94dadc6117b281b33ab38 Mon Sep 17 00:00:00 2001
From: "Ryland 41491307+ryalanms@users.noreply.github.com"
<41491307+ryalanms@users.noreply.github.com>
Date: Mon, 30 Sep 2019 13:17:29 -0700
Subject: [PATCH 2/7] Add CoreFX GetRelativePath implementation for .NET
Framework code generation
---
.../NETFrameworkGetRelativePath.cs | 370 ++++++++++++++++++
.../PresentationBuildTasks.csproj | 2 +
2 files changed, 372 insertions(+)
create mode 100644 src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/NETFrameworkGetRelativePath.cs
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/NETFrameworkGetRelativePath.cs b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/NETFrameworkGetRelativePath.cs
new file mode 100644
index 00000000000..23f8f9a8250
--- /dev/null
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/NETFrameworkGetRelativePath.cs
@@ -0,0 +1,370 @@
+// Licensed to the .NET Foundation under one or more agreements.
+// The .NET Foundation licenses this file to you under the MIT license.
+// See the LICENSE file in the project root for more information.
+
+//---------------------------------------------------------------------------
+//
+// Description:
+// Returns a relative path from one path to another.
+//
+// Paths are resolved by calling the GetFullPath method before calculating
+// the difference. The method uses the default file path comparison for the
+// current platform (StringComparison.OrdinalIgnoreCase for Windows.)
+//
+//---------------------------------------------------------------------------
+
+#pragma warning disable 1634, 1691
+
+using System;
+using System.Xml;
+using System.IO;
+using System.Text;
+using System.Reflection;
+using System.Globalization;
+using System.ComponentModel;
+using System.Security.Cryptography;
+
+using System.CodeDom;
+using System.CodeDom.Compiler;
+using System.Collections;
+using System.Collections.Generic;
+using System.ComponentModel.Design.Serialization;
+
+using System.Diagnostics;
+using System.Diagnostics.CodeAnalysis;
+
+using System.Threading;
+using MS.Internal.Markup;
+using MS.Internal.Tasks;
+using MS.Utility; // for SR
+using Microsoft.Build.Utilities;
+using Microsoft.Build.Tasks.Windows;
+using System.Runtime.CompilerServices;
+
+namespace MS.Internal
+{
+ internal sealed class PathInternal
+ {
+ internal static string GetRelativePath(string relativeTo, string path, StringComparison comparisonType)
+ {
+ if (relativeTo == null)
+ throw new ArgumentNullException(nameof(relativeTo));
+
+ if (PathInternal.IsEffectivelyEmpty(relativeTo.AsSpan()))
+ throw new ArgumentException(nameof(relativeTo));
+
+ if (path == null)
+ throw new ArgumentNullException(nameof(path));
+
+ if (PathInternal.IsEffectivelyEmpty(path.AsSpan()))
+ throw new ArgumentException(nameof(path));
+
+ Debug.Assert(comparisonType == StringComparison.Ordinal || comparisonType == StringComparison.OrdinalIgnoreCase);
+
+ relativeTo = Path.GetFullPath(relativeTo);
+ path = Path.GetFullPath(path);
+
+ // Need to check if the roots are different- if they are we need to return the "to" path.
+ if (!PathInternal.AreRootsEqual(relativeTo, path, comparisonType))
+ return path;
+
+ int commonLength = PathInternal.GetCommonPathLength(relativeTo, path, ignoreCase: comparisonType == StringComparison.OrdinalIgnoreCase);
+
+ // If there is nothing in common they can't share the same root, return the "to" path as is.
+ if (commonLength == 0)
+ return path;
+
+ // Trailing separators aren't significant for comparison
+ int relativeToLength = relativeTo.Length;
+ if (EndsInDirectorySeparator(relativeTo.AsSpan()))
+ relativeToLength--;
+
+ bool pathEndsInSeparator = EndsInDirectorySeparator(path.AsSpan());
+ int pathLength = path.Length;
+ if (pathEndsInSeparator)
+ pathLength--;
+
+ // If we have effectively the same path, return "."
+ if (relativeToLength == pathLength && commonLength >= relativeToLength) return ".";
+
+ // We have the same root, we need to calculate the difference now using the
+ // common Length and Segment count past the length.
+ //
+ // Some examples:
+ //
+ // C:\Foo C:\Bar L3, S1 -> ..\Bar
+ // C:\Foo C:\Foo\Bar L6, S0 -> Bar
+ // C:\Foo\Bar C:\Bar\Bar L3, S2 -> ..\..\Bar\Bar
+ // C:\Foo\Foo C:\Foo\Bar L7, S1 -> ..\Bar
+
+ StringBuilder sb = new StringBuilder();
+
+ // Add parent segments for segments past the common on the "from" path
+ if (commonLength < relativeToLength)
+ {
+ sb.Append("..");
+
+ for (int i = commonLength + 1; i < relativeToLength; i++)
+ {
+ if (PathInternal.IsDirectorySeparator(relativeTo[i]))
+ {
+ sb.Append(DirectorySeparatorChar);
+ sb.Append("..");
+ }
+ }
+ }
+ else if (PathInternal.IsDirectorySeparator(path[commonLength]))
+ {
+ // No parent segments and we need to eat the initial separator
+ // (C:\Foo C:\Foo\Bar case)
+ commonLength++;
+ }
+
+ // Now add the rest of the "to" path, adding back the trailing separator
+ int differenceLength = pathLength - commonLength;
+ if (pathEndsInSeparator)
+ differenceLength++;
+
+ if (differenceLength > 0)
+ {
+ if (sb.Length > 0)
+ {
+ sb.Append(DirectorySeparatorChar);
+ }
+
+ sb.Append(path, commonLength, differenceLength);
+ }
+
+ return sb.ToString();
+ }
+
+ ///
+ /// True if the given character is a directory separator.
+ ///
+ [MethodImpl(MethodImplOptions.AggressiveInlining)]
+ internal static bool IsDirectorySeparator(char c)
+ {
+ return c == DirectorySeparatorChar || c == AltDirectorySeparatorChar;
+ }
+
+ ///
+ /// Get the common path length from the start of the string.
+ ///
+ internal static int GetCommonPathLength(string first, string second, bool ignoreCase)
+ {
+ int commonChars = EqualStartingCharacterCount(first, second, ignoreCase: ignoreCase);
+
+ // If nothing matches
+ if (commonChars == 0)
+ return commonChars;
+
+ // Or we're a full string and equal length or match to a separator
+ if (commonChars == first.Length
+ && (commonChars == second.Length || IsDirectorySeparator(second[commonChars])))
+ return commonChars;
+
+ if (commonChars == second.Length && IsDirectorySeparator(first[commonChars]))
+ return commonChars;
+
+ // It's possible we matched somewhere in the middle of a segment e.g. C:\Foodie and C:\Foobar.
+ while (commonChars > 0 && !IsDirectorySeparator(first[commonChars - 1]))
+ commonChars--;
+
+ return commonChars;
+ }
+
+ ///
+ /// Returns true if the two paths have the same root
+ ///
+ internal static bool AreRootsEqual(string first, string second, StringComparison comparisonType)
+ {
+ int firstRootLength = GetRootLength(first.AsSpan());
+ int secondRootLength = GetRootLength(second.AsSpan());
+
+ return firstRootLength == secondRootLength
+ && string.Compare(
+ strA: first,
+ indexA: 0,
+ strB: second,
+ indexB: 0,
+ length: firstRootLength,
+ comparisonType: comparisonType) == 0;
+ }
+
+ ///
+ /// Returns true if the path is effectively empty for the current OS.
+ /// For unix, this is empty or null. For Windows, this is empty, null, or
+ /// just spaces ((char)32).
+ ///
+ internal static bool IsEffectivelyEmpty(ReadOnlySpan path)
+ {
+ if (path.IsEmpty)
+ return true;
+
+ foreach (char c in path)
+ {
+ if (c != ' ')
+ return false;
+ }
+ return true;
+ }
+
+
+ ///
+ /// Gets the length of the root of the path (drive, share, etc.).
+ ///
+ internal static int GetRootLength(ReadOnlySpan path)
+ {
+ int pathLength = path.Length;
+ int i = 0;
+
+ bool deviceSyntax = IsDevice(path);
+ bool deviceUnc = deviceSyntax && IsDeviceUNC(path);
+
+ if ((!deviceSyntax || deviceUnc) && pathLength > 0 && IsDirectorySeparator(path[0]))
+ {
+ // UNC or simple rooted path (e.g. "\foo", NOT "\\?\C:\foo")
+ if (deviceUnc || (pathLength > 1 && IsDirectorySeparator(path[1])))
+ {
+ // UNC (\\?\UNC\ or \\), scan past server\share
+
+ // Start past the prefix ("\\" or "\\?\UNC\")
+ i = deviceUnc ? UncExtendedPrefixLength : UncPrefixLength;
+
+ // Skip two separators at most
+ int n = 2;
+ while (i < pathLength && (!IsDirectorySeparator(path[i]) || --n > 0))
+ i++;
+ }
+ else
+ {
+ // Current drive rooted (e.g. "\foo")
+ i = 1;
+ }
+ }
+ else if (deviceSyntax)
+ {
+ // Device path (e.g. "\\?\.", "\\.\")
+ // Skip any characters following the prefix that aren't a separator
+ i = DevicePrefixLength;
+ while (i < pathLength && !IsDirectorySeparator(path[i]))
+ i++;
+
+ // If there is another separator take it, as long as we have had at least one
+ // non-separator after the prefix (e.g. don't take "\\?\\", but take "\\?\a\")
+ if (i < pathLength && i > DevicePrefixLength && IsDirectorySeparator(path[i]))
+ i++;
+ }
+ else if (pathLength >= 2
+ && path[1] == VolumeSeparatorChar
+ && IsValidDriveChar(path[0]))
+ {
+ // Valid drive specified path ("C:", "D:", etc.)
+ i = 2;
+
+ // If the colon is followed by a directory separator, move past it (e.g "C:\")
+ if (pathLength > 2 && IsDirectorySeparator(path[2]))
+ i++;
+ }
+
+ return i;
+ }
+
+ ///
+ /// Gets the count of common characters from the left optionally ignoring case
+ ///
+ internal static int EqualStartingCharacterCount(string first, string second, bool ignoreCase)
+ {
+ if (string.IsNullOrEmpty(first) || string.IsNullOrEmpty(second)) return 0;
+
+ // Current index
+ int index = 0;
+
+ while (index != first.Length && index != second.Length &&
+ first[index] == second[index] || (ignoreCase && char.ToUpperInvariant(first[index]) == char.ToUpperInvariant(second[index])))
+ {
+ index++;
+ }
+
+ return index;
+ }
+
+ ///
+ /// Returns true if the path uses any of the DOS device path syntaxes. ("\\.\", "\\?\", or "\??\")
+ ///
+ internal static bool IsDevice(ReadOnlySpan path)
+ {
+ // If the path begins with any two separators is will be recognized and normalized and prepped with
+ // "\??\" for internal usage correctly. "\??\" is recognized and handled, "/??/" is not.
+ return IsExtended(path)
+ ||
+ (
+ path.Length >= DevicePrefixLength
+ && IsDirectorySeparator(path[0])
+ && IsDirectorySeparator(path[1])
+ && (path[2] == '.' || path[2] == '?')
+ && IsDirectorySeparator(path[3])
+ );
+ }
+
+ ///
+ /// Returns true if the path is a device UNC (\\?\UNC\, \\.\UNC\)
+ ///
+ internal static bool IsDeviceUNC(ReadOnlySpan path)
+ {
+ return path.Length >= UncExtendedPrefixLength
+ && IsDevice(path)
+ && IsDirectorySeparator(path[7])
+ && path[4] == 'U'
+ && path[5] == 'N'
+ && path[6] == 'C';
+ }
+
+ ///
+ /// Returns true if the given character is a valid drive letter
+ ///
+ internal static bool IsValidDriveChar(char value)
+ {
+ return ((value >= 'A' && value <= 'Z') || (value >= 'a' && value <= 'z'));
+ }
+
+ ///
+ /// Returns true if the path uses the canonical form of extended syntax ("\\?\" or "\??\"). If the
+ /// path matches exactly (cannot use alternate directory separators) Windows will skip normalization
+ /// and path length checks.
+ ///
+ internal static bool IsExtended(ReadOnlySpan path)
+ {
+ // While paths like "//?/C:/" will work, they're treated the same as "\\.\" paths.
+ // Skipping of normalization will *only* occur if back slashes ('\') are used.
+ return path.Length >= DevicePrefixLength
+ && path[0] == '\\'
+ && (path[1] == '\\' || path[1] == '?')
+ && path[2] == '?'
+ && path[3] == '\\';
+ }
+
+ ///
+ /// Returns true if the path ends in a directory separator.
+ ///
+ public static bool EndsInDirectorySeparator(ReadOnlySpan path)
+ => path.Length > 0 && PathInternal.IsDirectorySeparator(path[path.Length - 1]);
+
+ ///
+ /// Returns true if the path ends in a directory separator.
+ ///
+ public static bool EndsInDirectorySeparator(string path)
+ => path != null && path.Length > 0 && PathInternal.IsDirectorySeparator(path[path.Length - 1]);
+
+ internal const char DirectorySeparatorChar = '\\';
+ internal const char AltDirectorySeparatorChar = '/';
+ internal const char VolumeSeparatorChar = ':';
+ // \\?\UNC\, \\.\UNC\
+ internal const int UncExtendedPrefixLength = 8;
+ // \\?\, \\.\, \??\
+ internal const int DevicePrefixLength = 4;
+ // \\
+ internal const int UncPrefixLength = 2;
+ }
+}
+
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj
index 61dbb1e744d..cf3cd1e6d9d 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj
@@ -277,6 +277,7 @@
+
@@ -314,6 +315,7 @@
Provide specific/old versions for PresentationBuildTasks which needs to run inside MSBuild
-->
+
From 900b82d2665fa65da8484405ddafcbe9dfa3f8bf Mon Sep 17 00:00:00 2001
From: "Ryland 41491307+ryalanms@users.noreply.github.com"
<41491307+ryalanms@users.noreply.github.com>
Date: Mon, 30 Sep 2019 14:06:37 -0700
Subject: [PATCH 3/7] Use more robust relative path calculation in markup code
generation
---
.../Internal/MarkupCompiler/MarkupCompiler.cs | 17 ++++---------
.../NETFrameworkGetRelativePath.cs | 24 +++++++++++++------
.../PresentationBuildTasks.csproj | 1 +
3 files changed, 23 insertions(+), 19 deletions(-)
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/MarkupCompiler.cs b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/MarkupCompiler.cs
index 76a0aa297a8..9a47bb3102a 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/MarkupCompiler.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/MarkupCompiler.cs
@@ -1568,19 +1568,12 @@ private string ParentFolderPrefix
{
get
{
- string parentFolderPrefix = string.Empty;
- if (TargetPath.StartsWith(SourceFileInfo.SourcePath, StringComparison.OrdinalIgnoreCase))
- {
- string relPath = TargetPath.Substring(SourceFileInfo.SourcePath.Length);
- relPath += SourceFileInfo.RelativeSourceFilePath;
- string[] dirs = relPath.Split(new Char[] { ESCAPED_BACKSLASH_CHAR });
- for (int i = 1; i < dirs.Length; i++)
- {
- parentFolderPrefix += PARENTFOLDER;
- }
- }
+#if NETFX && !NETCOREAPP
+ return PathInternal.GetRelativePath(TargetPath, SourceFileInfo.SourcePath, StringComparison.OrdinalIgnoreCase);
+#else
- return parentFolderPrefix;
+ return Path.GetRelativePath(TargetPath, SourceFileInfo.SourcePath);
+#endif
}
}
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/NETFrameworkGetRelativePath.cs b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/NETFrameworkGetRelativePath.cs
index 23f8f9a8250..245403747ce 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/NETFrameworkGetRelativePath.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/NETFrameworkGetRelativePath.cs
@@ -273,20 +273,30 @@ internal static int GetRootLength(ReadOnlySpan path)
///
/// Gets the count of common characters from the left optionally ignoring case
///
- internal static int EqualStartingCharacterCount(string first, string second, bool ignoreCase)
+ internal static unsafe int EqualStartingCharacterCount(string first, string second, bool ignoreCase)
{
if (string.IsNullOrEmpty(first) || string.IsNullOrEmpty(second)) return 0;
- // Current index
- int index = 0;
+ int commonChars = 0;
- while (index != first.Length && index != second.Length &&
- first[index] == second[index] || (ignoreCase && char.ToUpperInvariant(first[index]) == char.ToUpperInvariant(second[index])))
+ fixed (char* f = first)
+ fixed (char* s = second)
{
- index++;
+ char* l = f;
+ char* r = s;
+ char* leftEnd = l + first.Length;
+ char* rightEnd = r + second.Length;
+
+ while (l != leftEnd && r != rightEnd
+ && (*l == *r || (ignoreCase && char.ToUpperInvariant((*l)) == char.ToUpperInvariant((*r)))))
+ {
+ commonChars++;
+ l++;
+ r++;
+ }
}
- return index;
+ return commonChars;
}
///
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj
index cf3cd1e6d9d..04b5bd87873 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj
@@ -27,6 +27,7 @@
true
true
AnyCPU;x64
+ true
From 0eaf8c8a7c43909acfc8444d473c170d32173a55 Mon Sep 17 00:00:00 2001
From: Ryland Alaniz
Date: Wed, 10 Jun 2020 12:04:26 -0700
Subject: [PATCH 4/7] Revive 2019 fix
---
.../src/PresentationBuildTasks/PresentationBuildTasks.csproj | 1 +
1 file changed, 1 insertion(+)
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj
index f8a17ebab50..5d8f2349931 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj
@@ -280,6 +280,7 @@
+
From 94d96b1961650a5b62900592a697a7ab4d7899ac Mon Sep 17 00:00:00 2001
From: Ryland <41491307+ryalanms@users.noreply.github.com>
Date: Wed, 9 Sep 2020 12:09:39 -0700
Subject: [PATCH 5/7] Address PR feedback
---
.../MS/Internal/MarkupCompiler/MarkupCompiler.cs | 2 +-
.../{NETFrameworkGetRelativePath.cs => PathInternal.cs} | 0
.../src/PresentationBuildTasks/PresentationBuildTasks.csproj | 2 +-
3 files changed, 2 insertions(+), 2 deletions(-)
rename src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/{NETFrameworkGetRelativePath.cs => PathInternal.cs} (100%)
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/MarkupCompiler.cs b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/MarkupCompiler.cs
index eb241da4949..a2dce6f3559 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/MarkupCompiler.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/MarkupCompiler.cs
@@ -1575,7 +1575,7 @@ private string ParentFolderPrefix
{
get
{
-#if NETFX && !NETCOREAPP
+#if NETFX
return PathInternal.GetRelativePath(TargetPath, SourceFileInfo.SourcePath, StringComparison.OrdinalIgnoreCase);
#else
return Path.GetRelativePath(TargetPath, SourceFileInfo.SourcePath);
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/NETFrameworkGetRelativePath.cs b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/PathInternal.cs
similarity index 100%
rename from src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/NETFrameworkGetRelativePath.cs
rename to src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/PathInternal.cs
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj
index 7c36b7db9c5..38b33730d47 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/PresentationBuildTasks.csproj
@@ -279,7 +279,7 @@
-
+
From 484790e47a44c97a6e898a5b49432e619d263559 Mon Sep 17 00:00:00 2001
From: Ryland <41491307+ryalanms@users.noreply.github.com>
Date: Wed, 9 Sep 2020 12:10:28 -0700
Subject: [PATCH 6/7] Address PR feedback
---
.../MS/Internal/MarkupCompiler/PathInternal.cs | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/PathInternal.cs b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/PathInternal.cs
index 245403747ce..9b8361f347f 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/PathInternal.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/PathInternal.cs
@@ -76,10 +76,10 @@ internal static string GetRelativePath(string relativeTo, string path, StringCom
// Trailing separators aren't significant for comparison
int relativeToLength = relativeTo.Length;
- if (EndsInDirectorySeparator(relativeTo.AsSpan()))
+ if (DoesEndInDirectorySeparator(relativeTo.AsSpan()))
relativeToLength--;
- bool pathEndsInSeparator = EndsInDirectorySeparator(path.AsSpan());
+ bool pathEndsInSeparator = DoesEndInDirectorySeparator(path.AsSpan());
int pathLength = path.Length;
if (pathEndsInSeparator)
pathLength--;
@@ -97,7 +97,7 @@ internal static string GetRelativePath(string relativeTo, string path, StringCom
// C:\Foo\Bar C:\Bar\Bar L3, S2 -> ..\..\Bar\Bar
// C:\Foo\Foo C:\Foo\Bar L7, S1 -> ..\Bar
- StringBuilder sb = new StringBuilder();
+ var sb = new StringBuilder();
// Add parent segments for segments past the common on the "from" path
if (commonLength < relativeToLength)
@@ -152,7 +152,7 @@ internal static bool IsDirectorySeparator(char c)
///
internal static int GetCommonPathLength(string first, string second, bool ignoreCase)
{
- int commonChars = EqualStartingCharacterCount(first, second, ignoreCase: ignoreCase);
+ int commonChars = EqualStartingCharacterCount(first, second, ignoreCase);
// If nothing matches
if (commonChars == 0)
@@ -357,13 +357,13 @@ internal static bool IsExtended(ReadOnlySpan path)
///
/// Returns true if the path ends in a directory separator.
///
- public static bool EndsInDirectorySeparator(ReadOnlySpan path)
+ public static bool DoesEndInDirectorySeparator(ReadOnlySpan path)
=> path.Length > 0 && PathInternal.IsDirectorySeparator(path[path.Length - 1]);
///
/// Returns true if the path ends in a directory separator.
///
- public static bool EndsInDirectorySeparator(string path)
+ public static bool DoesEndInDirectorySeparator(string path)
=> path != null && path.Length > 0 && PathInternal.IsDirectorySeparator(path[path.Length - 1]);
internal const char DirectorySeparatorChar = '\\';
From e70e971e135f2fa98f29c8cc3c9c4f7526254d21 Mon Sep 17 00:00:00 2001
From: Ryland <41491307+ryalanms@users.noreply.github.com>
Date: Wed, 9 Sep 2020 12:41:21 -0700
Subject: [PATCH 7/7] PR feedback
---
.../MS/Internal/MarkupCompiler/PathInternal.cs | 18 ++++++++++--------
1 file changed, 10 insertions(+), 8 deletions(-)
diff --git a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/PathInternal.cs b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/PathInternal.cs
index 9b8361f347f..661aa18714e 100644
--- a/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/PathInternal.cs
+++ b/src/Microsoft.DotNet.Wpf/src/PresentationBuildTasks/MS/Internal/MarkupCompiler/PathInternal.cs
@@ -85,7 +85,7 @@ internal static string GetRelativePath(string relativeTo, string path, StringCom
pathLength--;
// If we have effectively the same path, return "."
- if (relativeToLength == pathLength && commonLength >= relativeToLength) return ".";
+ if (relativeToLength == pathLength && commonLength >= relativeToLength) return CurrentDir.ToString();
// We have the same root, we need to calculate the difference now using the
// common Length and Segment count past the length.
@@ -102,14 +102,14 @@ internal static string GetRelativePath(string relativeTo, string path, StringCom
// Add parent segments for segments past the common on the "from" path
if (commonLength < relativeToLength)
{
- sb.Append("..");
+ sb.Append(ParentDir);
for (int i = commonLength + 1; i < relativeToLength; i++)
{
if (PathInternal.IsDirectorySeparator(relativeTo[i]))
{
- sb.Append(DirectorySeparatorChar);
- sb.Append("..");
+ sb.Append(Path.DirectorySeparatorChar);
+ sb.Append(ParentDir);
}
}
}
@@ -129,7 +129,7 @@ internal static string GetRelativePath(string relativeTo, string path, StringCom
{
if (sb.Length > 0)
{
- sb.Append(DirectorySeparatorChar);
+ sb.Append(Path.DirectorySeparatorChar);
}
sb.Append(path, commonLength, differenceLength);
@@ -144,7 +144,7 @@ internal static string GetRelativePath(string relativeTo, string path, StringCom
[MethodImpl(MethodImplOptions.AggressiveInlining)]
internal static bool IsDirectorySeparator(char c)
{
- return c == DirectorySeparatorChar || c == AltDirectorySeparatorChar;
+ return c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar;
}
///
@@ -366,8 +366,6 @@ public static bool DoesEndInDirectorySeparator(ReadOnlySpan path)
public static bool DoesEndInDirectorySeparator(string path)
=> path != null && path.Length > 0 && PathInternal.IsDirectorySeparator(path[path.Length - 1]);
- internal const char DirectorySeparatorChar = '\\';
- internal const char AltDirectorySeparatorChar = '/';
internal const char VolumeSeparatorChar = ':';
// \\?\UNC\, \\.\UNC\
internal const int UncExtendedPrefixLength = 8;
@@ -375,6 +373,10 @@ public static bool DoesEndInDirectorySeparator(string path)
internal const int DevicePrefixLength = 4;
// \\
internal const int UncPrefixLength = 2;
+ // ".."
+ internal const string ParentDir = "..";
+ // '.'
+ internal const char CurrentDir = '.';
}
}