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
10 changes: 10 additions & 0 deletions IntegrationTests/IntegrationTests/ComsumeTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -62,6 +62,16 @@ public void Nested()
IsTrue(File.Exists(ProjectFiles.Config.appsettings_json));
}

[Test]
public void AddOperators()
{
AreEqual("RecursiveDirectory/SomeFile.txt", ProjectFiles.RecursiveDirectory + "SomeFile.txt");
IsTrue(File.Exists(ProjectFiles.RecursiveDirectory + "SomeFile.txt"));
IsTrue(File.Exists(ProjectFiles.ProjectDirectory + ProjectFiles.RecursiveDirectory.SomeFile_txt));
IsTrue(Directory.Exists(ProjectFiles.ProjectDirectory + ProjectFiles.RecursiveDirectory));
AreEqual("Prefix/RecursiveDirectory/SomeFile.txt", ("Prefix" + ProjectFiles.RecursiveDirectory.SomeFile_txt).Path);
}

[Test]
public void EmbeddedResource()
{
Expand Down
104 changes: 102 additions & 2 deletions readme.md
Original file line number Diff line number Diff line change
Expand Up @@ -534,6 +534,49 @@ partial class ProjectDirectory(string path)
public static implicit operator FileInfo(ProjectDirectory temp) =>
new(temp.Path);

public static string operator +(ProjectDirectory directory, string suffix) =>
JoinPaths(directory.Path, suffix);

public static ProjectDirectory operator +(string prefix, ProjectDirectory directory) =>
new(JoinPaths(prefix, directory.Path));

public static ProjectDirectory operator +(ProjectDirectory parent, ProjectDirectory child) =>
new(JoinPaths(parent.Path, child.Path));

public static ProjectFile operator +(ProjectDirectory directory, ProjectFile file) =>
new(JoinPaths(directory.Path, file.Path));

public static ProjectDirectory operator +(ProjectFile file, ProjectDirectory directory) =>
new(JoinPaths(file.Path, directory.Path));

internal static string JoinPaths(string left, string right)
{
if (left.Length == 0)
{
return right;
}

if (right.Length == 0)
{
return left;
}

var leftEndsWithSeparator = left[left.Length - 1] is '/' or '\\';
var rightStartsWithSeparator = right[0] is '/' or '\\';

if (leftEndsWithSeparator && rightStartsWithSeparator)
{
return left.TrimEnd('/', '\\') + right;
}

if (leftEndsWithSeparator || rightStartsWithSeparator)
{
return left + right;
}

return left + "/" + right;
}

public IEnumerable<string> EnumerateDirectories() =>
Directory.EnumerateDirectories(Path);

Expand All @@ -549,7 +592,7 @@ partial class ProjectDirectory(string path)
public DirectoryInfo Info => new(Path);
}
```
<sup><a href='/src/Templates/ProjectDirectory.cs#L1-L33' title='Snippet source file'>snippet source</a> | <a href='#snippet-ProjectDirectory.cs' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Templates/ProjectDirectory.cs#L1-L76' title='Snippet source file'>snippet source</a> | <a href='#snippet-ProjectDirectory.cs' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand Down Expand Up @@ -581,6 +624,15 @@ partial class ProjectFile(string path)
public static implicit operator FileInfo(ProjectFile temp) =>
new(temp.Path);

public static string operator +(ProjectFile file, string suffix) =>
ProjectDirectory.JoinPaths(file.Path, suffix);

public static ProjectFile operator +(string prefix, ProjectFile file) =>
new(ProjectDirectory.JoinPaths(prefix, file.Path));

public static ProjectFile operator +(ProjectFile prefix, ProjectFile suffix) =>
new(ProjectDirectory.JoinPaths(prefix.Path, suffix.Path));

public FileStream OpenRead() =>
File.OpenRead(Path);

Expand Down Expand Up @@ -610,7 +662,7 @@ partial class ProjectFile(string path)
#endif
}
```
<sup><a href='/src/Templates/ProjectFile.cs#L1-L49' title='Snippet source file'>snippet source</a> | <a href='#snippet-ProjectFile.cs' title='Start of snippet'>anchor</a></sup>
<sup><a href='/src/Templates/ProjectFile.cs#L1-L58' title='Snippet source file'>snippet source</a> | <a href='#snippet-ProjectFile.cs' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


Expand Down Expand Up @@ -687,6 +739,54 @@ partial class EmbeddedResource(string name)
<!-- endSnippet -->


### Combining paths

`ProjectDirectory`, `ProjectFile`, and `string` values can be combined with the `+` operator. The two paths are joined with a single `/` separator at the boundary (an existing trailing or leading separator is respected). The right operand determines the result type: combining with a `ProjectFile` produces a `ProjectFile`, with a `ProjectDirectory` produces a `ProjectDirectory`, and with a `string` produces a `string`.

<!-- snippet: AddOperators -->
<a id='snippet-AddOperators'></a>
```cs
[Test]
public void Combinations()
{
// ProjectDirectory + string
var fileInDirectory = ProjectFiles.RecursiveDirectory + "SomeFile.txt";
AreEqual("RecursiveDirectory/SomeFile.txt", fileInDirectory);
IsTrue(File.Exists(fileInDirectory));

// string + ProjectDirectory
var prefixedDirectory = "Prefix" + ProjectFiles.RecursiveDirectory;
AreEqual("Prefix/RecursiveDirectory", prefixedDirectory.Path);

// ProjectDirectory + ProjectDirectory
var directoryInProject = ProjectFiles.ProjectDirectory + ProjectFiles.RecursiveDirectory;
IsTrue(Directory.Exists(directoryInProject), directoryInProject.Path);

// ProjectDirectory + ProjectFile
var fileInProject = ProjectFiles.ProjectDirectory + ProjectFiles.fileAtRoot_txt;
IsTrue(File.Exists(fileInProject), fileInProject.Path);

// ProjectFile + string
var suffixedFile = ProjectFiles.RecursiveDirectory.SomeFile_txt + "Suffix.txt";
AreEqual("RecursiveDirectory/SomeFile.txt/Suffix.txt", suffixedFile);

// string + ProjectFile
var prefixedFile = "Prefix" + ProjectFiles.RecursiveDirectory.SomeFile_txt;
AreEqual("Prefix/RecursiveDirectory/SomeFile.txt", prefixedFile.Path);

// ProjectFile + ProjectDirectory
var fileThenDirectory = ProjectFiles.fileAtRoot_txt + ProjectFiles.RecursiveDirectory;
AreEqual("fileAtRoot.txt/RecursiveDirectory", fileThenDirectory.Path);

// ProjectFile + ProjectFile
var fileThenFile = ProjectFiles.fileAtRoot_txt + ProjectFiles.globFileAtRoot_txt;
AreEqual("fileAtRoot.txt/globFileAtRoot.txt", fileThenFile.Path);
}
```
<sup><a href='/src/ConsumingTests/AddOperatorTests.cs#L4-L41' title='Snippet source file'>snippet source</a> | <a href='#snippet-AddOperators' title='Start of snippet'>anchor</a></sup>
<!-- endSnippet -->


### Extending base class

These base classes can be extended with additional functionality by creating partial class definitions.
Expand Down
55 changes: 55 additions & 0 deletions src/ConsumingTests/AddOperatorTests.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
[TestFixture]
public class AddOperatorTests
{
// begin-snippet: AddOperators
[Test]
public void Combinations()
{
// ProjectDirectory + string
var fileInDirectory = ProjectFiles.RecursiveDirectory + "SomeFile.txt";
AreEqual("RecursiveDirectory/SomeFile.txt", fileInDirectory);
IsTrue(File.Exists(fileInDirectory));

// string + ProjectDirectory
var prefixedDirectory = "Prefix" + ProjectFiles.RecursiveDirectory;
AreEqual("Prefix/RecursiveDirectory", prefixedDirectory.Path);

// ProjectDirectory + ProjectDirectory
var directoryInProject = ProjectFiles.ProjectDirectory + ProjectFiles.RecursiveDirectory;
IsTrue(Directory.Exists(directoryInProject), directoryInProject.Path);

// ProjectDirectory + ProjectFile
var fileInProject = ProjectFiles.ProjectDirectory + ProjectFiles.fileAtRoot_txt;
IsTrue(File.Exists(fileInProject), fileInProject.Path);

// ProjectFile + string
var suffixedFile = ProjectFiles.RecursiveDirectory.SomeFile_txt + "Suffix.txt";
AreEqual("RecursiveDirectory/SomeFile.txt/Suffix.txt", suffixedFile);

// string + ProjectFile
var prefixedFile = "Prefix" + ProjectFiles.RecursiveDirectory.SomeFile_txt;
AreEqual("Prefix/RecursiveDirectory/SomeFile.txt", prefixedFile.Path);

// ProjectFile + ProjectDirectory
var fileThenDirectory = ProjectFiles.fileAtRoot_txt + ProjectFiles.RecursiveDirectory;
AreEqual("fileAtRoot.txt/RecursiveDirectory", fileThenDirectory.Path);

// ProjectFile + ProjectFile
var fileThenFile = ProjectFiles.fileAtRoot_txt + ProjectFiles.globFileAtRoot_txt;
AreEqual("fileAtRoot.txt/globFileAtRoot.txt", fileThenFile.Path);
}
// end-snippet

[Test]
public void SeparatorHandling()
{
AreEqual("a/b", ProjectDirectory.JoinPaths("a", "b"));
AreEqual("a/b", ProjectDirectory.JoinPaths("a/", "b"));
AreEqual("a/b", ProjectDirectory.JoinPaths("a", "/b"));
AreEqual("a/b", ProjectDirectory.JoinPaths("a/", "/b"));
AreEqual(@"a\b", ProjectDirectory.JoinPaths(@"a\", "b"));
AreEqual(@"a\b", ProjectDirectory.JoinPaths("a", @"\b"));
AreEqual("b", ProjectDirectory.JoinPaths("", "b"));
AreEqual("a", ProjectDirectory.JoinPaths("a", ""));
}
}
2 changes: 1 addition & 1 deletion src/Directory.Build.props
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
<Project>
<PropertyGroup>
<NoWarn>CS1591;NU1608;NU1109;RS2008;RS1041</NoWarn>
<Version>1.2.0</Version>
<Version>1.3.0</Version>
<LangVersion>preview</LangVersion>
<AssemblyVersion>1.0.0</AssemblyVersion>
<ResolveAssemblyReferencesSilent>true</ResolveAssemblyReferencesSilent>
Expand Down
43 changes: 43 additions & 0 deletions src/Templates/ProjectDirectory.cs
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,49 @@ public static implicit operator string(ProjectDirectory temp) =>
public static implicit operator FileInfo(ProjectDirectory temp) =>
new(temp.Path);

public static string operator +(ProjectDirectory directory, string suffix) =>
JoinPaths(directory.Path, suffix);

public static ProjectDirectory operator +(string prefix, ProjectDirectory directory) =>
new(JoinPaths(prefix, directory.Path));

public static ProjectDirectory operator +(ProjectDirectory parent, ProjectDirectory child) =>
new(JoinPaths(parent.Path, child.Path));

public static ProjectFile operator +(ProjectDirectory directory, ProjectFile file) =>
new(JoinPaths(directory.Path, file.Path));

public static ProjectDirectory operator +(ProjectFile file, ProjectDirectory directory) =>
new(JoinPaths(file.Path, directory.Path));

internal static string JoinPaths(string left, string right)
{
if (left.Length == 0)
{
return right;
}

if (right.Length == 0)
{
return left;
}

var leftEndsWithSeparator = left[left.Length - 1] is '/' or '\\';
var rightStartsWithSeparator = right[0] is '/' or '\\';

if (leftEndsWithSeparator && rightStartsWithSeparator)
{
return left.TrimEnd('/', '\\') + right;
}

if (leftEndsWithSeparator || rightStartsWithSeparator)
{
return left + right;
}

return left + "/" + right;
}

public IEnumerable<string> EnumerateDirectories() =>
Directory.EnumerateDirectories(Path);

Expand Down
9 changes: 9 additions & 0 deletions src/Templates/ProjectFile.cs
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,15 @@ public static implicit operator string(ProjectFile temp) =>
public static implicit operator FileInfo(ProjectFile temp) =>
new(temp.Path);

public static string operator +(ProjectFile file, string suffix) =>
ProjectDirectory.JoinPaths(file.Path, suffix);

public static ProjectFile operator +(string prefix, ProjectFile file) =>
new(ProjectDirectory.JoinPaths(prefix, file.Path));

public static ProjectFile operator +(ProjectFile prefix, ProjectFile suffix) =>
new(ProjectDirectory.JoinPaths(prefix.Path, suffix.Path));

public FileStream OpenRead() =>
File.OpenRead(Path);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,49 @@ public static implicit operator string(ProjectDirectory temp) =>
public static implicit operator FileInfo(ProjectDirectory temp) =>
new(temp.Path);

public static string operator +(ProjectDirectory directory, string suffix) =>
JoinPaths(directory.Path, suffix);

public static ProjectDirectory operator +(string prefix, ProjectDirectory directory) =>
new(JoinPaths(prefix, directory.Path));

public static ProjectDirectory operator +(ProjectDirectory parent, ProjectDirectory child) =>
new(JoinPaths(parent.Path, child.Path));

public static ProjectFile operator +(ProjectDirectory directory, ProjectFile file) =>
new(JoinPaths(directory.Path, file.Path));

public static ProjectDirectory operator +(ProjectFile file, ProjectDirectory directory) =>
new(JoinPaths(file.Path, directory.Path));

internal static string JoinPaths(string left, string right)
{
if (left.Length == 0)
{
return right;
}

if (right.Length == 0)
{
return left;
}

var leftEndsWithSeparator = left[left.Length - 1] is '/' or '\\';
var rightStartsWithSeparator = right[0] is '/' or '\\';

if (leftEndsWithSeparator && rightStartsWithSeparator)
{
return left.TrimEnd('/', '\\') + right;
}

if (leftEndsWithSeparator || rightStartsWithSeparator)
{
return left + right;
}

return left + "/" + right;
}

public IEnumerable<string> EnumerateDirectories() =>
Directory.EnumerateDirectories(Path);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,15 @@ public static implicit operator string(ProjectFile temp) =>
public static implicit operator FileInfo(ProjectFile temp) =>
new(temp.Path);

public static string operator +(ProjectFile file, string suffix) =>
ProjectDirectory.JoinPaths(file.Path, suffix);

public static ProjectFile operator +(string prefix, ProjectFile file) =>
new(ProjectDirectory.JoinPaths(prefix, file.Path));

public static ProjectFile operator +(ProjectFile prefix, ProjectFile suffix) =>
new(ProjectDirectory.JoinPaths(prefix.Path, suffix.Path));

public FileStream OpenRead() =>
File.OpenRead(Path);

Expand Down
Loading
Loading