Skip to content

Commit e8feca6

Browse files
linkdotnetegil
authored andcommitted
feat: Create stub generator in public project
1 parent a12c50b commit e8feca6

20 files changed

Lines changed: 788 additions & 34 deletions

bunit.sln

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -72,6 +72,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "bunit.generators.internal",
7272
EndProject
7373
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "bunit.generators.tests", "tests\bunit.generators.tests\bunit.generators.tests.csproj", "{09046981-D9EC-4295-8502-721AC54E1F12}"
7474
EndProject
75+
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "bunit.generators", "src\bunit.generators\bunit.generators.csproj", "{A7C6A2AA-FF8F-4ED1-8590-5324FC566059}"
76+
EndProject
7577
Global
7678
GlobalSection(SolutionConfigurationPlatforms) = preSolution
7779
Debug|Any CPU = Debug|Any CPU
@@ -126,6 +128,10 @@ Global
126128
{09046981-D9EC-4295-8502-721AC54E1F12}.Debug|Any CPU.Build.0 = Debug|Any CPU
127129
{09046981-D9EC-4295-8502-721AC54E1F12}.Release|Any CPU.ActiveCfg = Release|Any CPU
128130
{09046981-D9EC-4295-8502-721AC54E1F12}.Release|Any CPU.Build.0 = Release|Any CPU
131+
{A7C6A2AA-FF8F-4ED1-8590-5324FC566059}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
132+
{A7C6A2AA-FF8F-4ED1-8590-5324FC566059}.Debug|Any CPU.Build.0 = Debug|Any CPU
133+
{A7C6A2AA-FF8F-4ED1-8590-5324FC566059}.Release|Any CPU.ActiveCfg = Release|Any CPU
134+
{A7C6A2AA-FF8F-4ED1-8590-5324FC566059}.Release|Any CPU.Build.0 = Release|Any CPU
129135
EndGlobalSection
130136
GlobalSection(SolutionProperties) = preSolution
131137
HideSolutionNode = FALSE
@@ -144,6 +150,7 @@ Global
144150
{DE975A0C-0672-4248-913E-D267C1001801} = {6EA09ED4-B714-4E6F-B0E1-4D987F8AE520}
145151
{AE3DFB52-2BF4-4806-AD82-7FB7B38AC17F} = {9A2B3B34-D41C-43E8-BC7D-246BEBE48D59}
146152
{09046981-D9EC-4295-8502-721AC54E1F12} = {6EA09ED4-B714-4E6F-B0E1-4D987F8AE520}
153+
{A7C6A2AA-FF8F-4ED1-8590-5324FC566059} = {9A2B3B34-D41C-43E8-BC7D-246BEBE48D59}
147154
EndGlobalSection
148155
GlobalSection(ExtensibilityGlobals) = postSolution
149156
SolutionGuid = {24106918-1C86-4769-BDA6-9C80E64CD260}
Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,4 @@
1+
<?xml version="1.0" encoding="utf-8"?>
2+
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
3+
<!-- here to stop props inheritance from folders above -->
4+
</Project>
Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
# Tips for developing with the generator
2+
3+
When changing the source generator, to see the effect, clearing the build cache may be necessary:
4+
5+
```
6+
dotnet build-server shutdown
7+
```
8+
9+
A good way to quickly see if the generate is producing output:
10+
11+
```
12+
dotnet build-server shutdown && dotnet clean && dotnet test -p:TargetFramework=net8.0
13+
```
Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
using Microsoft.CodeAnalysis;
2+
3+
namespace Bunit.Web.AngleSharp;
4+
5+
internal static class GeneratorConfig
6+
{
7+
internal static readonly SymbolDisplayFormat SymbolFormat = new SymbolDisplayFormat(
8+
globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Included,
9+
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
10+
genericsOptions:
11+
SymbolDisplayGenericsOptions.IncludeTypeParameters |
12+
SymbolDisplayGenericsOptions.IncludeTypeConstraints |
13+
SymbolDisplayGenericsOptions.IncludeVariance,
14+
memberOptions:
15+
SymbolDisplayMemberOptions.IncludeType |
16+
SymbolDisplayMemberOptions.IncludeModifiers |
17+
SymbolDisplayMemberOptions.IncludeAccessibility |
18+
SymbolDisplayMemberOptions.IncludeParameters |
19+
SymbolDisplayMemberOptions.IncludeConstantValue |
20+
SymbolDisplayMemberOptions.IncludeRef,
21+
kindOptions: SymbolDisplayKindOptions.IncludeMemberKeyword,
22+
parameterOptions:
23+
SymbolDisplayParameterOptions.IncludeName |
24+
SymbolDisplayParameterOptions.IncludeType |
25+
SymbolDisplayParameterOptions.IncludeParamsRefOut |
26+
SymbolDisplayParameterOptions.IncludeDefaultValue |
27+
SymbolDisplayParameterOptions.IncludeModifiers,
28+
localOptions: SymbolDisplayLocalOptions.IncludeType,
29+
miscellaneousOptions:
30+
SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers |
31+
SymbolDisplayMiscellaneousOptions.UseSpecialTypes |
32+
SymbolDisplayMiscellaneousOptions.IncludeNullableReferenceTypeModifier |
33+
SymbolDisplayMiscellaneousOptions.AllowDefaultLiteral);
34+
35+
internal static readonly SymbolDisplayFormat SymbolFormatDefaultValue = new SymbolDisplayFormat(
36+
globalNamespaceStyle: SymbolDisplayGlobalNamespaceStyle.Included,
37+
typeQualificationStyle: SymbolDisplayTypeQualificationStyle.NameAndContainingTypesAndNamespaces,
38+
memberOptions: SymbolDisplayMemberOptions.IncludeType,
39+
parameterOptions: SymbolDisplayParameterOptions.IncludeType);
40+
}
Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
#nullable enable
2+
using AngleSharp.Dom;
3+
using System.CodeDom.Compiler;
4+
5+
namespace Bunit.Web.AngleSharp;
6+
7+
/// <summary>
8+
/// Represents a wrapper around an <typeparamref name="TElement"/>.
9+
/// </summary>
10+
[GeneratedCodeAttribute("Bunit.Web.AngleSharp", "1.0.0.0")]
11+
internal interface IElementWrapper<out TElement> where TElement : class, IElement
12+
{
13+
/// <summary>
14+
/// Gets the wrapped element.
15+
/// </summary>
16+
TElement WrappedElement { get; }
17+
}
18+
#nullable restore
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
#nullable enable
2+
using AngleSharp.Dom;
3+
using System;
4+
using System.CodeDom.Compiler;
5+
6+
namespace Bunit.Web.AngleSharp;
7+
8+
/// <summary>
9+
/// Represents an <see cref="IElement"/> factory, used by a <see cref="WrapperBase{TElement}"/>.
10+
/// </summary>
11+
[GeneratedCodeAttribute("Bunit.Web.AngleSharp", "1.0.0.0")]
12+
internal interface IElementWrapperFactory
13+
{
14+
/// <summary>
15+
/// A method that returns the latest version of the element to wrap.
16+
/// </summary>
17+
/// <remarks>
18+
/// This method should throw if the element is not found or is not of the correct type (<typeparamref name="TElement"/>).
19+
/// </remarks>
20+
TElement GetElement<TElement>() where TElement : class, IElement;
21+
22+
/// <summary>
23+
/// Subscribe to updates to the wrapped elements.
24+
/// </summary>
25+
Action? OnElementReplaced { get; set; }
26+
}
27+
#nullable restore
Lines changed: 83 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,83 @@
1+
#nullable enable
2+
using System.CodeDom.Compiler;
3+
using System.Diagnostics;
4+
using System.Runtime.CompilerServices;
5+
using AngleSharp.Dom;
6+
7+
namespace Bunit.Web.AngleSharp;
8+
9+
/// <summary>
10+
/// Represents a wrapper <see cref="IElement"/>.
11+
/// </summary>
12+
[DebuggerNonUserCode]
13+
[GeneratedCodeAttribute("Bunit.Web.AngleSharp", "1.0.0.0")]
14+
internal abstract class WrapperBase<TElement> : IElementWrapper<TElement>
15+
where TElement : class, IElement
16+
{
17+
private readonly IElementWrapperFactory elementFactory;
18+
private TElement? element;
19+
20+
/// <summary>
21+
/// Gets the wrapped element.
22+
/// </summary>
23+
[DebuggerNonUserCode]
24+
public TElement WrappedElement
25+
{
26+
[MethodImpl(MethodImplOptions.AggressiveInlining)]
27+
get
28+
{
29+
if (element is null)
30+
element = elementFactory.GetElement<TElement>();
31+
32+
return element;
33+
}
34+
}
35+
36+
/// <summary>
37+
/// Creates an instance of the <see cref="WrapperBase{T}"/> class.
38+
/// </summary>
39+
protected WrapperBase(
40+
TElement element,
41+
IElementWrapperFactory elementFactory)
42+
{
43+
this.element = element;
44+
this.elementFactory = elementFactory;
45+
elementFactory.OnElementReplaced = () => this.element = null;
46+
}
47+
48+
/// <inheritdoc/>
49+
public override bool Equals(object? obj)
50+
=> WrappedElement.Equals(obj);
51+
52+
/// <inheritdoc/>
53+
public override int GetHashCode() => WrappedElement.GetHashCode();
54+
55+
/// <inheritdoc/>
56+
public static bool operator ==(WrapperBase<TElement> x, TElement y)
57+
{
58+
if (x is null)
59+
return y is null;
60+
return x.WrappedElement == y;
61+
}
62+
63+
/// <inheritdoc/>
64+
public static bool operator !=(WrapperBase<TElement> x, TElement y)
65+
{
66+
return !(x == y);
67+
}
68+
69+
/// <inheritdoc/>
70+
public static bool operator ==(TElement x, WrapperBase<TElement> y)
71+
{
72+
if (y is null)
73+
return x is null;
74+
return x == y.WrappedElement;
75+
}
76+
77+
/// <inheritdoc/>
78+
public static bool operator !=(TElement x, WrapperBase<TElement> y)
79+
{
80+
return !(x == y);
81+
}
82+
}
83+
#nullable restore

0 commit comments

Comments
 (0)