Skip to content

Commit 198c043

Browse files
committed
#340 added some tests
1 parent f30cf25 commit 198c043

File tree

4 files changed

+260
-2
lines changed

4 files changed

+260
-2
lines changed
Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
It seems like the regression came in with 8.2.0, and it looks like it may be related to [this fix](https://github.com/JasonBock/Rocks/issues/288). The workaround with `InternalsVisibleTo` doesn't seem to workaround the issue.
2+
3+
Try a similar thing with RegEx generation, are there class name
4+
5+
TODO:
6+
* If I'm generating a type, like I'm doing in `9.0.0` with `RefStructArgument`, will this bring in a similar issue where type names may collide. I may need to make sure that these gen'd types are `internal`, **and**, if someone does a `InternalsVisibleTo`, then I may not need to generate them at all.
7+
* `[global::System.CodeDom.Compiler.GeneratedCodeAttribute("System.Text.RegularExpressions.Generator", "8.0.10.36612")]` - probably need to polyfill this, but interesting nonetheless

src/Directory.Build.props

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,6 @@
1414
<Nullable>enable</Nullable>
1515
<TargetFramework>net8.0</TargetFramework>
1616
<TreatWarningsAsErrors>True</TreatWarningsAsErrors>
17-
<Version>8.3.0</Version>
17+
<Version>8.3.1-alpha.1</Version>
1818
</PropertyGroup>
1919
</Project>

src/Rocks.Tests/Generators/NamingGeneratorTests.cs

Lines changed: 251 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,257 @@ namespace Rocks.Tests.Generators;
66

77
public static class NamingGeneratorTests
88
{
9+
[Test]
10+
public static async Task GenerateWhenBothCompilationsUseRocksAsync()
11+
{
12+
var source =
13+
"""
14+
using Rocks;
15+
16+
[assembly: Rock(typeof(Class1), BuildType.Create)]
17+
18+
public class Class1 { }
19+
""";
20+
var sourceReferences = Shared.References.Value
21+
.Cast<MetadataReference>()
22+
.ToList();
23+
var sourceSyntaxTree = CSharpSyntaxTree.ParseText(source);
24+
var sourceCompilation = CSharpCompilation.Create("Source", [sourceSyntaxTree],
25+
sourceReferences,
26+
new CSharpCompilationOptions(OutputKind.DynamicallyLinkedLibrary));
27+
GeneratorDriver sourceDriver = CSharpGeneratorDriver.Create(
28+
generators: [(new RockGenerator()).AsSourceGenerator()]);
29+
30+
sourceDriver = sourceDriver.RunGeneratorsAndUpdateCompilation(sourceCompilation, out var newSourceCompilation, out _);
31+
var sourceReference = newSourceCompilation.ToMetadataReference()!;
32+
sourceReferences.Add(sourceReference);
33+
34+
var code =
35+
"""
36+
using Rocks;
37+
38+
[assembly: Rock(typeof(Class1), BuildType.Create)]
39+
""";
40+
41+
var generatedCode =
42+
"""
43+
// <auto-generated/>
44+
45+
#pragma warning disable CS8618
46+
#pragma warning disable CS8633
47+
#pragma warning disable CS8714
48+
#pragma warning disable CS8775
49+
50+
#nullable enable
51+
52+
using Rocks.Extensions;
53+
54+
[global::System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverage]
55+
internal sealed class Class1CreateExpectations
56+
: global::Rocks.Expectations
57+
{
58+
internal sealed class Handler0
59+
: global::Rocks.Handler<global::System.Func<string?>, string?>
60+
{ }
61+
private global::Rocks.Handlers<global::Class1CreateExpectations.Handler0>? @handlers0;
62+
internal sealed class Handler1
63+
: global::Rocks.Handler<global::System.Func<object?, bool>, bool>
64+
{
65+
public global::Rocks.Argument<object?> @obj { get; set; }
66+
}
67+
private global::Rocks.Handlers<global::Class1CreateExpectations.Handler1>? @handlers1;
68+
internal sealed class Handler2
69+
: global::Rocks.Handler<global::System.Func<int>, int>
70+
{ }
71+
private global::Rocks.Handlers<global::Class1CreateExpectations.Handler2>? @handlers2;
72+
73+
public override void Verify()
74+
{
75+
if (this.WasInstanceInvoked)
76+
{
77+
var failures = new global::System.Collections.Generic.List<string>();
78+
79+
if (this.handlers0 is not null) { failures.AddRange(this.Verify(this.handlers0, 0)); }
80+
if (this.handlers1 is not null) { failures.AddRange(this.Verify(this.handlers1, 1)); }
81+
if (this.handlers2 is not null) { failures.AddRange(this.Verify(this.handlers2, 2)); }
82+
83+
if (failures.Count > 0)
84+
{
85+
throw new global::Rocks.Exceptions.VerificationException(failures);
86+
}
87+
}
88+
}
89+
90+
private sealed class Mock
91+
: global::Class1
92+
{
93+
public Mock(global::Class1CreateExpectations @expectations)
94+
{
95+
this.Expectations = @expectations;
96+
}
97+
98+
[global::Rocks.MemberIdentifier(0)]
99+
public override string? ToString()
100+
{
101+
if (this.Expectations.handlers0 is not null)
102+
{
103+
var @handler = this.Expectations.handlers0.First;
104+
@handler.CallCount++;
105+
var @result = @handler.Callback is not null ?
106+
@handler.Callback() : @handler.ReturnValue;
107+
return @result!;
108+
}
109+
else
110+
{
111+
return base.ToString();
112+
}
113+
}
114+
115+
[global::Rocks.MemberIdentifier(1)]
116+
public override bool Equals(object? @obj)
117+
{
118+
if (this.Expectations.handlers1 is not null)
119+
{
120+
foreach (var @handler in this.Expectations.handlers1)
121+
{
122+
if (@handler.@obj.IsValid(@obj!))
123+
{
124+
@handler.CallCount++;
125+
var @result = @handler.Callback is not null ?
126+
@handler.Callback(@obj!) : @handler.ReturnValue;
127+
return @result!;
128+
}
129+
}
130+
131+
throw new global::Rocks.Exceptions.ExpectationException($"No handlers match for {this.GetType().GetMemberDescription(1)}");
132+
}
133+
else
134+
{
135+
return base.Equals(obj: @obj!);
136+
}
137+
}
138+
139+
[global::Rocks.MemberIdentifier(2)]
140+
public override int GetHashCode()
141+
{
142+
if (this.Expectations.handlers2 is not null)
143+
{
144+
var @handler = this.Expectations.handlers2.First;
145+
@handler.CallCount++;
146+
var @result = @handler.Callback is not null ?
147+
@handler.Callback() : @handler.ReturnValue;
148+
return @result!;
149+
}
150+
else
151+
{
152+
return base.GetHashCode();
153+
}
154+
}
155+
156+
private global::Class1CreateExpectations Expectations { get; }
157+
}
158+
159+
internal sealed class MethodExpectations
160+
{
161+
internal MethodExpectations(global::Class1CreateExpectations expectations) =>
162+
this.Expectations = expectations;
163+
164+
internal new global::Class1CreateExpectations.Adornments.AdornmentsForHandler0 ToString()
165+
{
166+
global::Rocks.Exceptions.ExpectationException.ThrowIf(this.Expectations.WasInstanceInvoked);
167+
var handler = new global::Class1CreateExpectations.Handler0();
168+
if (this.Expectations.handlers0 is null) { this.Expectations.handlers0 = new(handler); }
169+
else { this.Expectations.handlers0.Add(handler); }
170+
return new(handler);
171+
}
172+
173+
internal global::Class1CreateExpectations.Adornments.AdornmentsForHandler1 Equals(global::Rocks.Argument<object?> @obj)
174+
{
175+
global::Rocks.Exceptions.ExpectationException.ThrowIf(this.Expectations.WasInstanceInvoked);
176+
global::System.ArgumentNullException.ThrowIfNull(@obj);
177+
178+
var @handler = new global::Class1CreateExpectations.Handler1
179+
{
180+
@obj = @obj,
181+
};
182+
183+
if (this.Expectations.handlers1 is null) { this.Expectations.handlers1 = new(@handler); }
184+
else { this.Expectations.handlers1.Add(@handler); }
185+
return new(@handler);
186+
}
187+
188+
internal new global::Class1CreateExpectations.Adornments.AdornmentsForHandler2 GetHashCode()
189+
{
190+
global::Rocks.Exceptions.ExpectationException.ThrowIf(this.Expectations.WasInstanceInvoked);
191+
var handler = new global::Class1CreateExpectations.Handler2();
192+
if (this.Expectations.handlers2 is null) { this.Expectations.handlers2 = new(handler); }
193+
else { this.Expectations.handlers2.Add(handler); }
194+
return new(handler);
195+
}
196+
197+
private global::Class1CreateExpectations Expectations { get; }
198+
}
199+
200+
internal global::Class1CreateExpectations.MethodExpectations Methods { get; }
201+
202+
internal Class1CreateExpectations() =>
203+
(this.Methods) = (new(this));
204+
205+
internal global::Class1 Instance()
206+
{
207+
if (!this.WasInstanceInvoked)
208+
{
209+
this.WasInstanceInvoked = true;
210+
var @mock = new Mock(this);
211+
this.MockType = @mock.GetType();
212+
return @mock;
213+
}
214+
else
215+
{
216+
throw new global::Rocks.Exceptions.NewMockInstanceException("Can only create a new mock once.");
217+
}
218+
}
219+
220+
internal static class Adornments
221+
{
222+
public interface IAdornmentsForClass1<TAdornments>
223+
: global::Rocks.IAdornments<TAdornments>
224+
where TAdornments : IAdornmentsForClass1<TAdornments>
225+
{ }
226+
227+
public sealed class AdornmentsForHandler0
228+
: global::Rocks.Adornments<AdornmentsForHandler0, global::Class1CreateExpectations.Handler0, global::System.Func<string?>, string?>, IAdornmentsForClass1<AdornmentsForHandler0>
229+
{
230+
public AdornmentsForHandler0(global::Class1CreateExpectations.Handler0 handler)
231+
: base(handler) { }
232+
}
233+
public sealed class AdornmentsForHandler1
234+
: global::Rocks.Adornments<AdornmentsForHandler1, global::Class1CreateExpectations.Handler1, global::System.Func<object?, bool>, bool>, IAdornmentsForClass1<AdornmentsForHandler1>
235+
{
236+
public AdornmentsForHandler1(global::Class1CreateExpectations.Handler1 handler)
237+
: base(handler) { }
238+
}
239+
public sealed class AdornmentsForHandler2
240+
: global::Rocks.Adornments<AdornmentsForHandler2, global::Class1CreateExpectations.Handler2, global::System.Func<int>, int>, IAdornmentsForClass1<AdornmentsForHandler2>
241+
{
242+
public AdornmentsForHandler2(global::Class1CreateExpectations.Handler2 handler)
243+
: base(handler) { }
244+
}
245+
}
246+
}
247+
248+
#pragma warning restore CS8618
249+
#pragma warning restore CS8633
250+
#pragma warning restore CS8714
251+
#pragma warning restore CS8775
252+
""";
253+
254+
await TestAssistants.RunGeneratorAsync<RockGenerator>(code,
255+
[(typeof(RockGenerator), "Class1_Rock_Create.g.cs", generatedCode)],
256+
[],
257+
additionalReferences: sourceReferences);
258+
}
259+
9260
[Test]
10261
public static async Task CreateWithDuplicateExpectationsPropertyNameAsync()
11262
{

src/Rocks/Extensions/CompilationExtensions.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ internal static (string name, string nameNoGenerics, string nameFQN) GetExpectat
1717

1818
var existingType = self.GetTypeByMetadataName(expectationsFQN);
1919

20-
while (existingType is not null)
20+
while (existingType is not null && existingType.CanBeSeenByContainingAssembly(self.Assembly))
2121
{
2222
id = id is null ? 2 : id++;
2323
expectationsFQN = type.Namespace is null ?

0 commit comments

Comments
 (0)