Skip to content

Commit 63e58c5

Browse files
committed
.
1 parent 8bfc88f commit 63e58c5

File tree

8 files changed

+265
-34
lines changed

8 files changed

+265
-34
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,3 +21,4 @@ src/Verify.MSTest.Tests/Tests.AutoVerifyHasAttachment.verified.txt
2121
src/Verify.NUnit.Tests/Tests.AutoVerifyHasAttachment.verified.txt
2222
src/Verify.TUnit.Tests/Tests.AutoVerifyHasAttachment.verified.txt
2323
/src/Benchmarks/BenchmarkDotNet.Artifacts
24+
.claude/settings.local.json

src/Verify/Naming/GetFileNames.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,3 @@
1-
delegate FilePair GetFileNames(Target target);
1+
delegate FilePair GetFileNames(ResolvedTarget target);
22

3-
delegate FilePair GetIndexedFileNames(Target target, string index);
3+
delegate FilePair GetIndexedFileNames(ResolvedTarget target, string index);

src/Verify/ResolvedTarget.cs

Lines changed: 96 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
namespace VerifyTests;
2+
3+
public readonly struct ResolvedTarget
4+
{
5+
readonly StringBuilder? stringBuilderData;
6+
readonly Stream? streamData;
7+
public string Extension { get; }
8+
public string? Name { get; }
9+
10+
public string NameOrTarget => Name ?? "target";
11+
12+
public Stream StreamData
13+
{
14+
get
15+
{
16+
if (streamData is null)
17+
{
18+
throw new("Use StringData or StringBuilderData.");
19+
}
20+
21+
return streamData;
22+
}
23+
}
24+
25+
public bool IsStream => streamData is not null;
26+
public bool IsString => stringBuilderData is not null;
27+
28+
internal bool TryGetStringBuilder([NotNullWhen(true)] out StringBuilder? value)
29+
{
30+
if (stringBuilderData is { } builder)
31+
{
32+
value = builder;
33+
return true;
34+
}
35+
36+
value = null;
37+
return false;
38+
}
39+
40+
public ResolvedTarget(string extension, Stream data, string? name = null)
41+
{
42+
Guards.AgainstBadExtension(extension);
43+
44+
if (FileExtensions.IsTextExtension(extension))
45+
{
46+
throw new(
47+
$"""
48+
Don't pass a stream for text.
49+
If {extension} is not a text extension then use `FileExtensions.RemoveTextExtensions("{extension}")` at initialization;
50+
Otherwise use `ResolvedTarget(string extension, string data)` or `ResolvedTarget(string extension, StringBuilder data, string? name)`.
51+
""");
52+
}
53+
54+
Extension = extension;
55+
Name = FileNameCleaner.SanitizeFilePath(name);
56+
streamData = data;
57+
stringBuilderData = null;
58+
}
59+
60+
public ResolvedTarget(string extension, StringBuilder data, string? name = null)
61+
{
62+
ValidateExtension(extension);
63+
64+
Extension = extension;
65+
Name = FileNameCleaner.SanitizeFilePath(name);
66+
streamData = null;
67+
stringBuilderData = data;
68+
}
69+
70+
static void ValidateExtension(string extension)
71+
{
72+
Guards.AgainstBadExtension(extension);
73+
if (extension == "noextension" ||
74+
FileExtensions.IsTextExtension(extension))
75+
{
76+
return;
77+
}
78+
79+
throw new(
80+
$"""
81+
Don't pass text for a binary extension.
82+
If {extension} is a text extension then use `FileExtensions.AddTextExtension("{extension}")` at initialization;
83+
Otherwise use `ResolvedTarget(string extension, Stream data, string? name)`.
84+
""");
85+
}
86+
87+
public ResolvedTarget(string extension, string data, string? name = null)
88+
{
89+
ValidateExtension(extension);
90+
91+
Extension = extension;
92+
Name = FileNameCleaner.SanitizeFilePath(name);
93+
stringBuilderData = new(data);
94+
streamData = null;
95+
}
96+
}

src/Verify/Splitters/ConversionResult.cs

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,4 +38,14 @@ public ConversionResult(object? info, string extension, StringBuilder data, Func
3838
Cleanup = cleanup;
3939
Targets = [new(extension, data)];
4040
}
41+
42+
/// <summary>
43+
/// Creates a ConversionResult with an arbitrary object that will be resolved later in the pipeline.
44+
/// </summary>
45+
public ConversionResult(object? info, object data, Func<Task>? cleanup = null)
46+
{
47+
Info = info;
48+
Cleanup = cleanup;
49+
Targets = [new Target(data)];
50+
}
4151
}

src/Verify/Target.cs

Lines changed: 43 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,9 @@
1-
namespace VerifyTests;
1+
namespace VerifyTests;
22

33
public readonly struct Target
44
{
5-
readonly StringBuilder? stringBuilderData;
6-
readonly Stream? streamData;
7-
public string Extension { get; }
5+
public object? Data { get; }
6+
public string? Extension { get; }
87
public string? Name { get; } = null;
98
public bool PerformConversion { get; } = true;
109
public string NameOrTarget => Name ?? "target";
@@ -13,21 +12,23 @@ public Stream StreamData
1312
{
1413
get
1514
{
16-
if (streamData is null)
15+
if (Data is not Stream stream)
1716
{
18-
throw new("Use StringData or StringBuilderData.");
17+
throw new("Data is not a Stream. Use Data property to access the underlying data.");
1918
}
2019

21-
return streamData;
20+
return stream;
2221
}
2322
}
2423

25-
public bool IsStream => streamData is not null;
26-
public bool IsString => stringBuilderData is not null;
24+
public bool IsStream => Data is Stream;
25+
public bool IsStringBuilder => Data is StringBuilder;
26+
public bool IsString => Data is string;
27+
public bool IsObject => Data is not null && !IsStream && !IsStringBuilder && !IsString;
2728

2829
internal bool TryGetStringBuilder([NotNullWhen(true)] out StringBuilder? value)
2930
{
30-
if (stringBuilderData is { } builder)
31+
if (Data is StringBuilder builder)
3132
{
3233
value = builder;
3334
return true;
@@ -37,6 +38,18 @@ internal bool TryGetStringBuilder([NotNullWhen(true)] out StringBuilder? value)
3738
return false;
3839
}
3940

41+
internal bool TryGetStream([NotNullWhen(true)] out Stream? value)
42+
{
43+
if (Data is Stream stream)
44+
{
45+
value = stream;
46+
return true;
47+
}
48+
49+
value = null;
50+
return false;
51+
}
52+
4053
[OverloadResolutionPriority(-1)]
4154
public Target(string extension, Stream data, string? name = null) :
4255
this(extension, data, name, true)
@@ -52,29 +65,27 @@ public Target(string extension, Stream data, string? name = null, bool performCo
5265
throw new(
5366
$"""
5467
Don't pass a stream for text.
55-
If {extension} is not a text extension then use `FileExtensions.RemoveTextExtensions(\"{extension}\")` at initialization;
68+
If {extension} is not a text extension then use `FileExtensions.RemoveTextExtensions("{extension}")` at initialization;
5669
Otherwise use `Target(string extension, string data)` or `Target(string extension, StringBuilder data, string? name)`.
5770
""");
5871
}
5972

6073
Extension = extension;
6174
Name = FileNameCleaner.SanitizeFilePath(name);
6275
PerformConversion = performConversion;
63-
streamData = data;
64-
stringBuilderData = null;
76+
Data = data;
6577
}
6678

6779
public Target(string extension, StringBuilder data, string? name = null)
6880
{
69-
ValidateExtension(extension);
81+
ValidateTextExtension(extension);
7082

7183
Extension = extension;
7284
Name = FileNameCleaner.SanitizeFilePath(name);
73-
streamData = null;
74-
stringBuilderData = data;
85+
Data = data;
7586
}
7687

77-
static void ValidateExtension(string extension)
88+
static void ValidateTextExtension(string extension)
7889
{
7990
Guards.AgainstBadExtension(extension);
8091
if (extension == "noextension" ||
@@ -93,11 +104,22 @@ static void ValidateExtension(string extension)
93104

94105
public Target(string extension, string data, string? name = null)
95106
{
96-
ValidateExtension(extension);
107+
ValidateTextExtension(extension);
97108

98109
Extension = extension;
99110
Name = FileNameCleaner.SanitizeFilePath(name);
100-
stringBuilderData = new(data);
101-
streamData = null;
111+
Data = new StringBuilder(data);
112+
}
113+
114+
/// <summary>
115+
/// Creates a Target wrapping an arbitrary object.
116+
/// The object will be resolved to a stream or string later in the verification pipeline.
117+
/// </summary>
118+
public Target(object data, string? name = null)
119+
{
120+
Data = data;
121+
Extension = null;
122+
Name = FileNameCleaner.SanitizeFilePath(name);
123+
PerformConversion = true;
102124
}
103-
}
125+
}

0 commit comments

Comments
 (0)