Skip to content

Commit a786e3b

Browse files
committed
feat: add Path.Join APIs
1 parent 5ee421f commit a786e3b

12 files changed

Lines changed: 99 additions & 22 deletions

System.IO.Abstractions.sln

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO.Abstractions.Test
1717
EndProject
1818
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "System.IO.Abstractions.Benchmarks", "benchmarks\System.IO.Abstractions.Benchmarks\System.IO.Abstractions.Benchmarks.csproj", "{015B3812-E01D-479C-895D-BDDF16E798CA}"
1919
EndProject
20+
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tests", "tests", "{BCEC61BD-4941-41EC-975A-ACEFC7AC1780}"
21+
EndProject
22+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "System.IO.Abstractions.Tests", "tests\System.IO.Abstractions.Tests\System.IO.Abstractions.Tests.csproj", "{7105D748-1253-409F-A624-4879412EF3C2}"
23+
EndProject
2024
Global
2125
GlobalSection(SolutionConfigurationPlatforms) = preSolution
2226
Debug|Any CPU = Debug|Any CPU
@@ -39,11 +43,18 @@ Global
3943
{015B3812-E01D-479C-895D-BDDF16E798CA}.Debug|Any CPU.Build.0 = Debug|Any CPU
4044
{015B3812-E01D-479C-895D-BDDF16E798CA}.Release|Any CPU.ActiveCfg = Release|Any CPU
4145
{015B3812-E01D-479C-895D-BDDF16E798CA}.Release|Any CPU.Build.0 = Release|Any CPU
46+
{7105D748-1253-409F-A624-4879412EF3C2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
47+
{7105D748-1253-409F-A624-4879412EF3C2}.Debug|Any CPU.Build.0 = Debug|Any CPU
48+
{7105D748-1253-409F-A624-4879412EF3C2}.Release|Any CPU.ActiveCfg = Release|Any CPU
49+
{7105D748-1253-409F-A624-4879412EF3C2}.Release|Any CPU.Build.0 = Release|Any CPU
4250
EndGlobalSection
4351
GlobalSection(SolutionProperties) = preSolution
4452
HideSolutionNode = FALSE
4553
EndGlobalSection
4654
GlobalSection(ExtensibilityGlobals) = postSolution
4755
SolutionGuid = {8885C59C-F6A0-4C2F-A3BC-B720E9BD161F}
4856
EndGlobalSection
57+
GlobalSection(NestedProjects) = preSolution
58+
{7105D748-1253-409F-A624-4879412EF3C2} = {BCEC61BD-4941-41EC-975A-ACEFC7AC1780}
59+
EndGlobalSection
4960
EndGlobal

src/System.IO.Abstractions/IPath.cs

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,8 @@ public interface IPath
1414
char PathSeparator { get; }
1515
/// <inheritdoc cref="Path.VolumeSeparatorChar"/>
1616
char VolumeSeparatorChar { get; }
17-
17+
/// <inheritdoc cref="Path.InvalidPathChars"/>
18+
char[] InvalidPathChars { get; }
1819
/// <inheritdoc cref="Path.ChangeExtension"/>
1920
string ChangeExtension(string path, string extension);
2021
/// <inheritdoc cref="Path.Combine(string[])"/>
@@ -59,5 +60,19 @@ public interface IPath
5960
/// <inheritdoc cref="Path.GetRelativePath(string,string)"/>
6061
string GetRelativePath(string relativeTo, string path);
6162
#endif
63+
64+
#if FEATURE_PATH_JOIN_WITH_SPAN
65+
/// <inheritdoc cref="Path.Join(ReadOnlySpan<char>,ReadOnlySpan<char>)"/>
66+
string Join(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2);
67+
68+
/// <inheritdoc cref="Path.Join(ReadOnlySpan<char>,ReadOnlySpan<char>)"/>
69+
string Join(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2, ReadOnlySpan<char> path3);
70+
71+
/// <inheritdoc cref="Path.Join(ReadOnlySpan<char>,ReadOnlySpan<char>,ReadOnlySpan<char>,Span<char>,int)"/>
72+
bool TryJoin(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2, ReadOnlySpan<char> path3, Span<char> destination, out int charsWritten);
73+
74+
/// <inheritdoc cref="Path.Join(ReadOnlySpan<char>,ReadOnlySpan<char>,Span<char>,int)"/>
75+
bool TryJoin(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2, Span<char> destination, out int charsWritten);
76+
#endif
6277
}
6378
}

src/System.IO.Abstractions/PathBase.cs

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -94,5 +94,19 @@ internal PathBase() { }
9494
/// <inheritdoc />
9595
public abstract string GetRelativePath(string relativeTo, string path);
9696
#endif
97+
98+
#if FEATURE_PATH_JOIN_WITH_SPAN
99+
/// <inheritdoc />
100+
public abstract string Join(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2);
101+
102+
/// <inheritdoc />
103+
public abstract string Join(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2, ReadOnlySpan<char> path3);
104+
105+
/// <inheritdoc />
106+
public abstract bool TryJoin(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2, ReadOnlySpan<char> path3, Span<char> destination, out int charsWritten);
107+
108+
/// <inheritdoc />
109+
public abstract bool TryJoin(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2, Span<char> destination, out int charsWritten);
110+
#endif
97111
}
98112
}

src/System.IO.Abstractions/PathWrapper.cs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,24 @@ public override string GetRelativePath(string relativeTo, string path)
130130
}
131131
#endif
132132

133+
#if FEATURE_PATH_JOIN_WITH_SPAN
134+
/// <inheritdoc />
135+
public override string Join(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2) =>
136+
Path.Join(path2, path2);
137+
138+
/// <inheritdoc />
139+
public override string Join(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2, ReadOnlySpan<char> path3) =>
140+
Path.Join(path2, path2, path3);
141+
142+
/// <inheritdoc />
143+
public override bool TryJoin(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2, Span<char> destination, out int charsWritten) =>
144+
Path.TryJoin(path2, path2, destination, out charsWritten);
145+
146+
/// <inheritdoc />
147+
public override bool TryJoin(ReadOnlySpan<char> path1, ReadOnlySpan<char> path2, ReadOnlySpan<char> path3, Span<char> destination, out int charsWritten) =>
148+
Path.TryJoin(path2, path2, path3, destination, out charsWritten);
149+
#endif
150+
133151
public override bool IsPathRooted(string path)
134152
{
135153
return Path.IsPathRooted(path);

src/System.IO.Abstractions/Properties/AssemblyInfo.cs

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,12 @@
44
[assembly: CLSCompliant(true)]
55

66
#if DEBUG
7-
[assembly: InternalsVisibleTo("System.IO.Abstractions.TestingHelpers.Tests")]
8-
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
7+
[assembly: InternalsVisibleTo("System.IO.Abstractions.Tests")]
8+
[assembly: InternalsVisibleTo("System.IO.Abstractions.TestingHelpers.Tests")]
9+
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2")]
910
#else
10-
[assembly: InternalsVisibleTo("System.IO.Abstractions.TestingHelpers.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001001160c7a0f907c400c5392975b66d2f3752fb82625d5674d386b83896d4d4ae8d0ef8319ef391fbb3466de0058ad2f361b8f5cb8a32ecb4e908bece5c519387552cedd2ca0250e36b59c6d6dc3dc260ca73a7e27c3add4ae22d5abaa562225d7ba34d427e8f3f52928a46a674deb0208eca7d379aa22712355b91a55a5ce521d2")]
11-
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2,PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
11+
[assembly: InternalsVisibleTo("System.IO.Abstractions.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001001160c7a0f907c400c5392975b66d2f3752fb82625d5674d386b83896d4d4ae8d0ef8319ef391fbb3466de0058ad2f361b8f5cb8a32ecb4e908bece5c519387552cedd2ca0250e36b59c6d6dc3dc260ca73a7e27c3add4ae22d5abaa562225d7ba34d427e8f3f52928a46a674deb0208eca7d379aa22712355b91a55a5ce521d2")]
12+
[assembly: InternalsVisibleTo("System.IO.Abstractions.TestingHelpers.Tests, PublicKey=00240000048000009400000006020000002400005253413100040000010001001160c7a0f907c400c5392975b66d2f3752fb82625d5674d386b83896d4d4ae8d0ef8319ef391fbb3466de0058ad2f361b8f5cb8a32ecb4e908bece5c519387552cedd2ca0250e36b59c6d6dc3dc260ca73a7e27c3add4ae22d5abaa562225d7ba34d427e8f3f52928a46a674deb0208eca7d379aa22712355b91a55a5ce521d2")]
13+
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2,PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]
1214
#endif
1315

src/System.IO.Abstractions/System.IO.Abstractions.csproj

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -3,11 +3,11 @@
33
<AssemblyName>System.IO.Abstractions</AssemblyName>
44
<RootNamespace>System.IO.Abstractions</RootNamespace>
55
<Description>A set of abstractions to help make file system interactions testable.</Description>
6-
<TargetFrameworks>netstandard2.0;netstandard2.1;net461</TargetFrameworks>
6+
<TargetFrameworks>netstandard2.1;netstandard2.0;net461</TargetFrameworks>
77
<PackageProjectUrl>https://github.com/System-IO-Abstractions/System.IO.Abstractions</PackageProjectUrl>
88
<PackageLicenseExpression>MIT</PackageLicenseExpression>
99
<PackageTags>testing</PackageTags>
10-
<DefineConstants Condition="'$(TargetFramework)' == 'netstandard2.1'">$(DefineConstants);FEATURE_ASYNC_FILE;FEATURE_ENUMERATION_OPTIONS;FEATURE_ADVANCED_PATH_OPERATIONS</DefineConstants>
10+
<DefineConstants Condition="'$(TargetFramework)' == 'netstandard2.1'">$(DefineConstants);FEATURE_ASYNC_FILE;FEATURE_ENUMERATION_OPTIONS;FEATURE_ADVANCED_PATH_OPERATIONS;FEATURE_PATH_JOIN_WITH_SPAN</DefineConstants>
1111
</PropertyGroup>
1212
<ItemGroup Condition="'$(TargetFramework)' != 'net461'">
1313
<PackageReference Include="System.IO.FileSystem.AccessControl" Version="4.7.0"/>

tests/System.IO.Abstractions.TestingHelpers.Tests/ConvertersTests.cs renamed to tests/System.IO.Abstractions.Tests/ConvertersTests.cs

Lines changed: 8 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22
using System.Collections.Generic;
33
using NUnit.Framework;
44

5-
namespace System.IO.Abstractions.TestingHelpers.Tests
5+
namespace System.IO.Abstractions.Tests
66
{
77
[TestFixture]
88
public class ConvertersTests
@@ -21,7 +21,7 @@ public void Reset() { }
2121

2222
public void Dispose() { }
2323
}
24-
24+
2525
public IEnumerator<T> GetEnumerator() => new CrashingEnumerator();
2626

2727
IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
@@ -31,23 +31,23 @@ public void Dispose() { }
3131
public void WrapFileSystemInfos_with_IEnumerable_is_lazy()
3232
{
3333
var crashingFileSystemInfos = new CrashingEnumerable<FileSystemInfo>();
34-
35-
Assert.DoesNotThrow(() => crashingFileSystemInfos.WrapFileSystemInfos(new MockFileSystem()));
34+
35+
Assert.DoesNotThrow(() => crashingFileSystemInfos.WrapFileSystemInfos(new FileSystem()));
3636
}
3737

3838
[Test]
3939
public void WrapFiles_with_IEnumerable_is_lazy()
4040
{
4141
var crashingFileInfos = new CrashingEnumerable<FileInfo>();
42-
43-
Assert.DoesNotThrow(() => crashingFileInfos.WrapFiles(new MockFileSystem()));
42+
43+
Assert.DoesNotThrow(() => crashingFileInfos.WrapFiles(new FileSystem()));
4444
}
4545
[Test]
4646
public void WrapDirectories_with_IEnumerable_is_lazy()
4747
{
4848
var crashingDirectoryInfos = new CrashingEnumerable<DirectoryInfo>();
49-
50-
Assert.DoesNotThrow(() => crashingDirectoryInfos.WrapDirectories(new MockFileSystem()));
49+
50+
Assert.DoesNotThrow(() => crashingDirectoryInfos.WrapDirectories(new FileSystem()));
5151
}
5252

5353
}

tests/System.IO.Abstractions.TestingHelpers.Tests/DirectoryInfoTests.cs renamed to tests/System.IO.Abstractions.Tests/DirectoryInfoTests.cs

Lines changed: 1 addition & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,6 @@
11
using NUnit.Framework;
2-
using System;
3-
using System.Collections.Generic;
4-
using System.Text;
52

6-
namespace System.IO.Abstractions.TestingHelpers.Tests
3+
namespace System.IO.Abstractions.Tests
74
{
85
[TestFixture]
96
public class DirectoryInfoTests

tests/System.IO.Abstractions.TestingHelpers.Tests/FileInfoBaseConversionTests.cs renamed to tests/System.IO.Abstractions.Tests/FileInfoBaseConversionTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
namespace System.IO.Abstractions.TestingHelpers.Tests
1+
namespace System.IO.Abstractions.Tests
22
{
33
using NUnit.Framework;
44

tests/System.IO.Abstractions.TestingHelpers.Tests/FileSystemTests.cs renamed to tests/System.IO.Abstractions.Tests/FileSystemTests.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11

22
using NUnit.Framework;
33

4-
namespace System.IO.Abstractions.TestingHelpers.Tests
4+
namespace System.IO.Abstractions.Tests
55
{
66
[TestFixture]
77
public class FileSystemTests

0 commit comments

Comments
 (0)