Skip to content

Commit 847359f

Browse files
authored
Add optional Guard API (#201)
1 parent d651bb4 commit 847359f

16 files changed

+1026
-34
lines changed

apiCount.include.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
**API count: 302**
1+
**API count: 326**

api_guard.include.md

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
#### Guard
2+
3+
* `void DirectoryExists(String)`
4+
* `void FileExists(String)`
5+
* `void NotEmpty(String)`
6+
* `void NotEmpty<T>(ReadOnlySpan<T>)`
7+
* `void NotEmpty<T>(Span<T>)`
8+
* `void NotEmpty<T>(Nullable<Memory<T>>)`
9+
* `void NotEmpty<T>(Memory<T>)`
10+
* `void NotEmpty<T>(Nullable<ReadOnlyMemory<T>>)`
11+
* `void NotEmpty<T>(ReadOnlyMemory<T>)`
12+
* `void NotEmpty<T>(T) where T : Collections.IEnumerable`
13+
* `T NotNull<T>(T)`
14+
* `String NotNull(String)`
15+
* `String NotNullOrEmpty(String)`
16+
* `T NotNullOrEmpty<T>(T) where T : Collections.IEnumerable`
17+
* `Memory<Char> NotNullOrEmpty(Nullable<Memory<Char>>)`
18+
* `ReadOnlyMemory<Char> NotNullOrEmpty(Nullable<ReadOnlyMemory<Char>>)`
19+
* `String NotNullOrWhitespace(String)`
20+
* `Memory<Char> NotNullOrWhitespace(Nullable<Memory<Char>>)`
21+
* `ReadOnlyMemory<Char> NotNullOrWhitespace(Nullable<ReadOnlyMemory<Char>>)`
22+
* `void NotWhitespace(String)`
23+
* `void NotWhitespace(ReadOnlySpan<Char>)`
24+
* `void NotWhitespace(Nullable<Memory<Char>>)`
25+
* `void NotWhitespace(Nullable<ReadOnlyMemory<Char>>)`
26+
* `void NotWhitespace(Span<Char>)`
27+
28+

api_list.include.md

Lines changed: 38 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -194,7 +194,7 @@
194194

195195
#### ReadOnlySpan<T>
196196

197-
* `Boolean Contains<T>(T)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.memoryextensions.contains#system-memoryextensions-contains-1(system-readonlyspan((-0))-0))
197+
* `Boolean Contains<T>(T) where T : IEquatable<T>` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.memoryextensions.contains#system-memoryextensions-contains-1(system-readonlyspan((-0))-0))
198198

199199

200200
#### Reflection.EventInfo
@@ -269,7 +269,7 @@
269269

270270
#### Span<T>
271271

272-
* `Boolean Contains<T>(T)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.memoryextensions.contains#system-memoryextensions-contains-1(system-span((-0))-0))
272+
* `Boolean Contains<T>(T) where T : IEquatable<T>` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.memoryextensions.contains#system-memoryextensions-contains-1(system-span((-0))-0))
273273

274274

275275
#### Stream
@@ -391,14 +391,14 @@
391391

392392
#### EnumPolyfill
393393

394-
* `String[] GetNames<TEnum>()` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.getnames)
395-
* `TEnum[] GetValues<TEnum>()` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.getvalues)
396-
* `TEnum Parse<TEnum>(String)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-string-system-boolean))
397-
* `TEnum Parse<TEnum>(String, Boolean)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-string-system-boolean))
398-
* `TEnum Parse<TEnum>(ReadOnlySpan<Char>)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-readonlyspan((system-char))))
399-
* `TEnum Parse<TEnum>(ReadOnlySpan<Char>, Boolean)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-readonlyspan((system-char))-system-boolean))
400-
* `Boolean TryParse<TEnum>(ReadOnlySpan<Char>, TEnum&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.tryparse#system-enum-tryparse-1(system-readonlyspan((system-char))-0@))
401-
* `Boolean TryParse<TEnum>(ReadOnlySpan<Char>, Boolean, TEnum&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.tryparse#system-enum-tryparse-1(system-readonlyspan((system-char))-system-boolean-0@))
394+
* `String[] GetNames<TEnum>() where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.getnames)
395+
* `TEnum[] GetValues<TEnum>() where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.getvalues)
396+
* `TEnum Parse<TEnum>(String) where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-string-system-boolean))
397+
* `TEnum Parse<TEnum>(String, Boolean) where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-string-system-boolean))
398+
* `TEnum Parse<TEnum>(ReadOnlySpan<Char>) where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-readonlyspan((system-char))))
399+
* `TEnum Parse<TEnum>(ReadOnlySpan<Char>, Boolean) where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-readonlyspan((system-char))-system-boolean))
400+
* `Boolean TryParse<TEnum>(ReadOnlySpan<Char>, TEnum&) where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.tryparse#system-enum-tryparse-1(system-readonlyspan((system-char))-0@))
401+
* `Boolean TryParse<TEnum>(ReadOnlySpan<Char>, Boolean, TEnum&) where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.tryparse#system-enum-tryparse-1(system-readonlyspan((system-char))-system-boolean-0@))
402402

403403

404404
#### RegexPolyfill
@@ -521,3 +521,31 @@
521521
* `Boolean TryParse(ReadOnlySpan<Char>, Globalization.NumberStyles, IFormatProvider, UInt16&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.uint16.tryparse#system-uint16-tryparse(system-readonlyspan((system-char))-system-globalization-numberstyles-system-iformatprovider-system-uint16@))
522522

523523

524+
#### Guard
525+
526+
* `void DirectoryExists(String)`
527+
* `void FileExists(String)`
528+
* `void NotEmpty(String)`
529+
* `void NotEmpty<T>(ReadOnlySpan<T>)`
530+
* `void NotEmpty<T>(Span<T>)`
531+
* `void NotEmpty<T>(Nullable<Memory<T>>)`
532+
* `void NotEmpty<T>(Memory<T>)`
533+
* `void NotEmpty<T>(Nullable<ReadOnlyMemory<T>>)`
534+
* `void NotEmpty<T>(ReadOnlyMemory<T>)`
535+
* `void NotEmpty<T>(T) where T : Collections.IEnumerable`
536+
* `T NotNull<T>(T)`
537+
* `String NotNull(String)`
538+
* `String NotNullOrEmpty(String)`
539+
* `T NotNullOrEmpty<T>(T) where T : Collections.IEnumerable`
540+
* `Memory<Char> NotNullOrEmpty(Nullable<Memory<Char>>)`
541+
* `ReadOnlyMemory<Char> NotNullOrEmpty(Nullable<ReadOnlyMemory<Char>>)`
542+
* `String NotNullOrWhitespace(String)`
543+
* `Memory<Char> NotNullOrWhitespace(Nullable<Memory<Char>>)`
544+
* `ReadOnlyMemory<Char> NotNullOrWhitespace(Nullable<ReadOnlyMemory<Char>>)`
545+
* `void NotWhitespace(String)`
546+
* `void NotWhitespace(ReadOnlySpan<Char>)`
547+
* `void NotWhitespace(Nullable<Memory<Char>>)`
548+
* `void NotWhitespace(Nullable<ReadOnlyMemory<Char>>)`
549+
* `void NotWhitespace(Span<Char>)`
550+
551+

readme.md

Lines changed: 88 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ The package targets `netstandard2.0` and is designed to support the following ru
1212
* `net5.0`, `net6.0`, `net7.0`, `net8.0`, `net9.0`
1313

1414

15-
**API count: 302**<!-- singleLineInclude: apiCount. path: /apiCount.include.md -->
15+
**API count: 326**<!-- singleLineInclude: apiCount. path: /apiCount.include.md -->
1616

1717

1818
**See [Milestones](../../milestones?state=closed) for release notes.**
@@ -310,7 +310,7 @@ Reference: [CallerArgumentExpression](https://learn.microsoft.com/en-us/dotnet/c
310310
<!-- snippet: CallerArgumentExpression -->
311311
<a id='snippet-CallerArgumentExpression'></a>
312312
```cs
313-
static class Guard
313+
static class FileUtil
314314
{
315315
public static void FileExists(string path, [CallerArgumentExpression("path")] string argumentName = "")
316316
{
@@ -321,16 +321,16 @@ static class Guard
321321
}
322322
}
323323

324-
static class GuardUsage
324+
static class FileUtilUsage
325325
{
326326
public static string[] Method(string path)
327327
{
328-
Guard.FileExists(path);
328+
FileUtil.FileExists(path);
329329
return File.ReadAllLines(path);
330330
}
331331
}
332332
```
333-
<sup><a href='/src/Tests/Guard.cs#L1-L22' title='Snippet source file'>snippet source</a> | <a href='#snippet-CallerArgumentExpression' title='Start of snippet'>anchor</a></sup>
333+
<sup><a href='/src/Tests/CallerArgumentExpressionUsage.cs#L1-L22' title='Snippet source file'>snippet source</a> | <a href='#snippet-CallerArgumentExpression' title='Start of snippet'>anchor</a></sup>
334334
<!-- endSnippet -->
335335

336336

@@ -603,7 +603,7 @@ The class `Polyfill` includes the following extension methods:
603603

604604
#### ReadOnlySpan<T>
605605

606-
* `Boolean Contains<T>(T)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.memoryextensions.contains#system-memoryextensions-contains-1(system-readonlyspan((-0))-0))
606+
* `Boolean Contains<T>(T) where T : IEquatable<T>` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.memoryextensions.contains#system-memoryextensions-contains-1(system-readonlyspan((-0))-0))
607607

608608

609609
#### Reflection.EventInfo
@@ -678,7 +678,7 @@ The class `Polyfill` includes the following extension methods:
678678

679679
#### Span<T>
680680

681-
* `Boolean Contains<T>(T)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.memoryextensions.contains#system-memoryextensions-contains-1(system-span((-0))-0))
681+
* `Boolean Contains<T>(T) where T : IEquatable<T>` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.memoryextensions.contains#system-memoryextensions-contains-1(system-span((-0))-0))
682682

683683

684684
#### Stream
@@ -800,14 +800,14 @@ The class `Polyfill` includes the following extension methods:
800800

801801
#### EnumPolyfill
802802

803-
* `String[] GetNames<TEnum>()` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.getnames)
804-
* `TEnum[] GetValues<TEnum>()` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.getvalues)
805-
* `TEnum Parse<TEnum>(String)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-string-system-boolean))
806-
* `TEnum Parse<TEnum>(String, Boolean)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-string-system-boolean))
807-
* `TEnum Parse<TEnum>(ReadOnlySpan<Char>)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-readonlyspan((system-char))))
808-
* `TEnum Parse<TEnum>(ReadOnlySpan<Char>, Boolean)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-readonlyspan((system-char))-system-boolean))
809-
* `Boolean TryParse<TEnum>(ReadOnlySpan<Char>, TEnum&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.tryparse#system-enum-tryparse-1(system-readonlyspan((system-char))-0@))
810-
* `Boolean TryParse<TEnum>(ReadOnlySpan<Char>, Boolean, TEnum&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.tryparse#system-enum-tryparse-1(system-readonlyspan((system-char))-system-boolean-0@))
803+
* `String[] GetNames<TEnum>() where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.getnames)
804+
* `TEnum[] GetValues<TEnum>() where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.getvalues)
805+
* `TEnum Parse<TEnum>(String) where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-string-system-boolean))
806+
* `TEnum Parse<TEnum>(String, Boolean) where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-string-system-boolean))
807+
* `TEnum Parse<TEnum>(ReadOnlySpan<Char>) where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-readonlyspan((system-char))))
808+
* `TEnum Parse<TEnum>(ReadOnlySpan<Char>, Boolean) where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.parse#system-enum-parse-1(system-readonlyspan((system-char))-system-boolean))
809+
* `Boolean TryParse<TEnum>(ReadOnlySpan<Char>, TEnum&) where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.tryparse#system-enum-tryparse-1(system-readonlyspan((system-char))-0@))
810+
* `Boolean TryParse<TEnum>(ReadOnlySpan<Char>, Boolean, TEnum&) where TEnum : Enum, ValueType` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.enum.tryparse#system-enum-tryparse-1(system-readonlyspan((system-char))-system-boolean-0@))
811811

812812

813813
#### RegexPolyfill
@@ -929,6 +929,34 @@ The class `Polyfill` includes the following extension methods:
929929
* `Boolean TryParse(ReadOnlySpan<Byte>, UInt16&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.uint16.tryparse#system-uint16-tryparse(system-readonlyspan((system-char))-system-globalization-numberstyles-system-iformatprovider-system-uint16@))
930930
* `Boolean TryParse(ReadOnlySpan<Char>, Globalization.NumberStyles, IFormatProvider, UInt16&)` [reference](https://learn.microsoft.com/en-us/dotnet/api/system.uint16.tryparse#system-uint16-tryparse(system-readonlyspan((system-char))-system-globalization-numberstyles-system-iformatprovider-system-uint16@))
931931

932+
933+
#### Guard
934+
935+
* `void DirectoryExists(String)`
936+
* `void FileExists(String)`
937+
* `void NotEmpty(String)`
938+
* `void NotEmpty<T>(ReadOnlySpan<T>)`
939+
* `void NotEmpty<T>(Span<T>)`
940+
* `void NotEmpty<T>(Nullable<Memory<T>>)`
941+
* `void NotEmpty<T>(Memory<T>)`
942+
* `void NotEmpty<T>(Nullable<ReadOnlyMemory<T>>)`
943+
* `void NotEmpty<T>(ReadOnlyMemory<T>)`
944+
* `void NotEmpty<T>(T) where T : Collections.IEnumerable`
945+
* `T NotNull<T>(T)`
946+
* `String NotNull(String)`
947+
* `String NotNullOrEmpty(String)`
948+
* `T NotNullOrEmpty<T>(T) where T : Collections.IEnumerable`
949+
* `Memory<Char> NotNullOrEmpty(Nullable<Memory<Char>>)`
950+
* `ReadOnlyMemory<Char> NotNullOrEmpty(Nullable<ReadOnlyMemory<Char>>)`
951+
* `String NotNullOrWhitespace(String)`
952+
* `Memory<Char> NotNullOrWhitespace(Nullable<Memory<Char>>)`
953+
* `ReadOnlyMemory<Char> NotNullOrWhitespace(Nullable<ReadOnlyMemory<Char>>)`
954+
* `void NotWhitespace(String)`
955+
* `void NotWhitespace(ReadOnlySpan<Char>)`
956+
* `void NotWhitespace(Nullable<Memory<Char>>)`
957+
* `void NotWhitespace(Nullable<ReadOnlyMemory<Char>>)`
958+
* `void NotWhitespace(Span<Char>)`
959+
932960
<!-- endInclude -->
933961

934962

@@ -1047,6 +1075,51 @@ Enable by adding and MSBuild property `PolyNullability`
10471075
* Throws an exception if state is `NullabilityState.Unknown`.
10481076

10491077

1078+
## Guard
1079+
1080+
Enable by adding and MSBuild property `PolyGuard`
1081+
1082+
```
1083+
<PropertyGroup>
1084+
...
1085+
<PolyGuard>true</PolyGuard>
1086+
</PropertyGroup>
1087+
```
1088+
1089+
1090+
`Polyfills.Guard` provides the following APIs:
1091+
1092+
1093+
#### Guard<!-- include: api_guard. path: /api_guard.include.md -->
1094+
1095+
* `void DirectoryExists(String)`
1096+
* `void FileExists(String)`
1097+
* `void NotEmpty(String)`
1098+
* `void NotEmpty<T>(ReadOnlySpan<T>)`
1099+
* `void NotEmpty<T>(Span<T>)`
1100+
* `void NotEmpty<T>(Nullable<Memory<T>>)`
1101+
* `void NotEmpty<T>(Memory<T>)`
1102+
* `void NotEmpty<T>(Nullable<ReadOnlyMemory<T>>)`
1103+
* `void NotEmpty<T>(ReadOnlyMemory<T>)`
1104+
* `void NotEmpty<T>(T) where T : Collections.IEnumerable`
1105+
* `T NotNull<T>(T)`
1106+
* `String NotNull(String)`
1107+
* `String NotNullOrEmpty(String)`
1108+
* `T NotNullOrEmpty<T>(T) where T : Collections.IEnumerable`
1109+
* `Memory<Char> NotNullOrEmpty(Nullable<Memory<Char>>)`
1110+
* `ReadOnlyMemory<Char> NotNullOrEmpty(Nullable<ReadOnlyMemory<Char>>)`
1111+
* `String NotNullOrWhitespace(String)`
1112+
* `Memory<Char> NotNullOrWhitespace(Nullable<Memory<Char>>)`
1113+
* `ReadOnlyMemory<Char> NotNullOrWhitespace(Nullable<ReadOnlyMemory<Char>>)`
1114+
* `void NotWhitespace(String)`
1115+
* `void NotWhitespace(ReadOnlySpan<Char>)`
1116+
* `void NotWhitespace(Nullable<Memory<Char>>)`
1117+
* `void NotWhitespace(Nullable<ReadOnlyMemory<Char>>)`
1118+
* `void NotWhitespace(Span<Char>)`
1119+
1120+
<!-- endInclude -->
1121+
1122+
10501123
## Alternatives
10511124

10521125

src/Directory.Build.props

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
<SuppressTfmSupportBuildWarnings>true</SuppressTfmSupportBuildWarnings>
1515
<ResolveAssemblyReferencesSilent>true</ResolveAssemblyReferencesSilent>
1616
<PolyNullability>true</PolyNullability>
17+
<PolyGuard>true</PolyGuard>
1718
<NuGetAuditMode>all</NuGetAuditMode>
1819
<NuGetAuditLevel>low</NuGetAuditLevel>
1920
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>

src/Polyfill/Guard.cs

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,41 @@
1+
// <auto-generated />
2+
3+
namespace Polyfills;
4+
5+
using System.Runtime.CompilerServices;
6+
7+
#pragma warning disable
8+
9+
#if PolyGuard
10+
11+
using System;
12+
using System.IO;
13+
using System.Diagnostics;
14+
using System.Diagnostics.CodeAnalysis;
15+
16+
[ExcludeFromCodeCoverage]
17+
[DebuggerNonUserCode]
18+
#if PolyPublic
19+
public
20+
#endif
21+
static partial class Guard
22+
{
23+
public static void FileExists(string path, [CallerArgumentExpression("path")] string argumentName = "")
24+
{
25+
NotNullOrEmpty(path, argumentName);
26+
if (!File.Exists(path))
27+
{
28+
throw new ArgumentException($"File not found. Path: {path}", argumentName);
29+
}
30+
}
31+
32+
public static void DirectoryExists(string path, [CallerArgumentExpression("path")] string argumentName = "")
33+
{
34+
NotNullOrEmpty(path, argumentName);
35+
if (!Directory.Exists(path))
36+
{
37+
throw new ArgumentException($"Directory not found. Path: {path}", argumentName);
38+
}
39+
}
40+
}
41+
#endif

0 commit comments

Comments
 (0)