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
17 changes: 17 additions & 0 deletions PolyShim.Tests/NetCore30/PathTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -41,4 +41,21 @@ public void TrimEndingDirectorySeparator_Test()
Path.TrimEndingDirectorySeparator("/a/b/c").Should().Be("/a/b/c");
Path.TrimEndingDirectorySeparator(string.Empty).Should().Be(string.Empty);
}

[Fact]
public void Join_Test()
{
// Act & assert

// For some reason, dropping the array literals leads to nullability errors on .NET Framework
// ReSharper disable RedundantExplicitParamsArrayCreation
Path.Join(["C:/Program Files/", "Utilities/SystemUtilities"])
.Should()
.Be("C:/Program Files/Utilities/SystemUtilities");
Path.Join(["C:/", "/Program Files"]).Should().Be("C://Program Files");
Path.Join(["C:/Users/Public/Documents/", "C:/Users/User1/Documents/Financial/"])
.Should()
.Be("C:/Users/Public/Documents/C:/Users/User1/Documents/Financial/");
// ReSharper restore RedundantExplicitParamsArrayCreation
}
}
64 changes: 52 additions & 12 deletions PolyShim/NetCore30/Path.cs
Original file line number Diff line number Diff line change
Expand Up @@ -6,33 +6,73 @@
// ReSharper disable PartialTypeWithSinglePart

using System.IO;
using System.Linq;
using System.Text;

internal static partial class PolyfillExtensions
{
extension(Path)
{
// https://learn.microsoft.com/dotnet/api/system.io.path.endsindirectoryseparator#system-io-path-endsindirectoryseparator(system-string)
public static bool EndsInDirectorySeparator(string? path)
{
if (string.IsNullOrEmpty(path))
return false;

var lastChar = path![^1];

private static bool IsDirectorySeparator(char c) =>
#if !NETSTANDARD || NETSTANDARD1_3_OR_GREATER
return lastChar == Path.DirectorySeparatorChar
|| lastChar == Path.AltDirectorySeparatorChar;
c == Path.DirectorySeparatorChar || c == Path.AltDirectorySeparatorChar;
#else
return lastChar is '\\' or '/';
c is '\\' or '/';
#endif
}

// https://learn.microsoft.com/dotnet/api/system.io.path.endsindirectoryseparator#system-io-path-endsindirectoryseparator(system-string)
public static bool EndsInDirectorySeparator(string? path) =>
!string.IsNullOrEmpty(path) && Path.IsDirectorySeparator(path![^1]);

// https://learn.microsoft.com/dotnet/api/system.io.path.trimendingdirectoryseparator#system-io-path-trimendingdirectoryseparator(system-string)
public static string TrimEndingDirectorySeparator(string path) =>
EndsInDirectorySeparator(path)
&& !Path.GetPathRoot(path).Equals(path, System.StringComparison.Ordinal)
? path[..^1]
: path;

// https://learn.microsoft.com/dotnet/api/system.io.path.join#system-io-path-join(system-string())
public static string Join(params string?[] paths)
{
if (paths.Length <= 0)
return string.Empty;

var maxSize = paths.Sum(path => path?.Length ?? 0);
maxSize += paths.Length - 1;

var builder = new StringBuilder(maxSize);

foreach (var path in paths)
{
if (string.IsNullOrEmpty(path))
continue;

if (builder.Length == 0)
{
builder.Append(path);
}
else
{
if (
!Path.IsDirectorySeparator(builder[^1])
&& !Path.IsDirectorySeparator(path![0])
)
{
builder.Append(
#if !NETSTANDARD || NETSTANDARD1_3_OR_GREATER
Path.DirectorySeparatorChar
#else
'/'
#endif
);
}

builder.Append(path);
}
}

return builder.ToString();
}
}
}
#endif
Loading