Skip to content

Commit 8e451ff

Browse files
67 method with a default enum parameter wich type is byte does not compile (#70)
* feat: Add byte enum to method params * wip: fix tests * feat: add more tests for enums * feat: docs * feat: tests using verify * feat: Use simons idea on how to avoid having two similar SymbolDisplayFormats * feat: better enum testing
1 parent 1afa5e3 commit 8e451ff

15 files changed

+289
-4
lines changed

AutomaticInterface/AutomaticInterface/AutomaticInterface.csproj

+1-1
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@
2525
<PackageLicenseExpression>MIT</PackageLicenseExpression>
2626
<EnableNETAnalyzers>True</EnableNETAnalyzers>
2727
<AnalysisLevel>latest-Recommended</AnalysisLevel>
28-
<Version>5.1.1</Version>
28+
<Version>5.1.2</Version>
2929
<PackageReadmeFile>README.md</PackageReadmeFile>
3030
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
3131
<NoWarn>1701;1702;NU5128</NoWarn>

AutomaticInterface/AutomaticInterface/Builder.cs

+18-3
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,8 @@ private static string InheritDoc(ISymbol source) =>
1515
private static readonly SymbolDisplayFormat FullyQualifiedDisplayFormat =
1616
new(
1717
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
18-
memberOptions: SymbolDisplayMemberOptions.IncludeParameters,
18+
memberOptions: SymbolDisplayMemberOptions.IncludeParameters
19+
| SymbolDisplayMemberOptions.IncludeContainingType,
1920
parameterOptions: SymbolDisplayParameterOptions.IncludeType
2021
| SymbolDisplayParameterOptions.IncludeParamsRefOut
2122
| SymbolDisplayParameterOptions.IncludeDefaultValue
@@ -27,6 +28,20 @@ private static string InheritDoc(ISymbol source) =>
2728
| SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers
2829
);
2930

31+
/// <summary>
32+
/// We do need to be able to group shadowing and new methods/events into a single entry, hence this is missing SymbolDisplayMemberOptions.IncludeContainingType
33+
/// </summary>
34+
private static readonly SymbolDisplayFormat FullyQualifiedDisplayFormatForGrouping =
35+
new(
36+
genericsOptions: FullyQualifiedDisplayFormat.GenericsOptions,
37+
memberOptions: FullyQualifiedDisplayFormat.MemberOptions
38+
& ~SymbolDisplayMemberOptions.IncludeContainingType,
39+
parameterOptions: FullyQualifiedDisplayFormat.ParameterOptions,
40+
typeQualificationStyle: FullyQualifiedDisplayFormat.TypeQualificationStyle,
41+
globalNamespaceStyle: FullyQualifiedDisplayFormat.GlobalNamespaceStyle,
42+
miscellaneousOptions: FullyQualifiedDisplayFormat.MiscellaneousOptions
43+
);
44+
3045
public static string BuildInterfaceFor(ITypeSymbol typeSymbol)
3146
{
3247
if (
@@ -91,7 +106,7 @@ private static void AddMethodsToInterface(List<ISymbol> members, InterfaceBuilde
91106
.Where(x => x.MethodKind == MethodKind.Ordinary)
92107
.Where(x => x.ContainingType.Name != nameof(Object))
93108
.Where(x => !HasIgnoreAttribute(x))
94-
.GroupBy(x => x.ToDisplayString(FullyQualifiedDisplayFormat))
109+
.GroupBy(x => x.ToDisplayString(FullyQualifiedDisplayFormatForGrouping))
95110
.Select(g => g.First())
96111
.ToList()
97112
.ForEach(method => AddMethod(codeGenerator, method));
@@ -182,7 +197,7 @@ private static void AddEventsToInterface(List<ISymbol> members, InterfaceBuilder
182197
members
183198
.Where(x => x.Kind == SymbolKind.Event)
184199
.OfType<IEventSymbol>()
185-
.GroupBy(x => x.ToDisplayString(FullyQualifiedDisplayFormat))
200+
.GroupBy(x => x.ToDisplayString(FullyQualifiedDisplayFormatForGrouping))
186201
.Select(g => g.First())
187202
.ToList()
188203
.ForEach(evt =>

AutomaticInterface/AutomaticInterface/InterfaceBuilder.cs

+2
Original file line numberDiff line numberDiff line change
@@ -121,7 +121,9 @@ public string Build()
121121

122122
cb.Indent();
123123
foreach (var method in methodInfos)
124+
{
124125
BuildMethod(cb, method);
126+
}
125127

126128
cb.Dedent();
127129

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//--------------------------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by a tool.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
6+
// </auto-generated>
7+
//--------------------------------------------------------------------------------------------------
8+
9+
namespace AutomaticInterfaceExample
10+
{
11+
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
12+
public partial interface IDemoClass
13+
{
14+
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
15+
void MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);
16+
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//--------------------------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by a tool.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
6+
// </auto-generated>
7+
//--------------------------------------------------------------------------------------------------
8+
9+
namespace AutomaticInterfaceExample
10+
{
11+
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
12+
public partial interface IDemoClass
13+
{
14+
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
15+
global::AutomaticInterfaceExample.EnumWithByteType MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);
16+
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//--------------------------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by a tool.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
6+
// </auto-generated>
7+
//--------------------------------------------------------------------------------------------------
8+
9+
namespace AutomaticInterfaceExample
10+
{
11+
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
12+
public partial interface IDemoClass
13+
{
14+
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.SomeProperty" />
15+
global::AutomaticInterfaceExample.EnumWithByteType SomeProperty { get; set; }
16+
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//--------------------------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by a tool.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
6+
// </auto-generated>
7+
//--------------------------------------------------------------------------------------------------
8+
9+
namespace AutomaticInterfaceExample
10+
{
11+
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
12+
public partial interface IDemoClass
13+
{
14+
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
15+
void MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);
16+
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//--------------------------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by a tool.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
6+
// </auto-generated>
7+
//--------------------------------------------------------------------------------------------------
8+
9+
namespace AutomaticInterfaceExample
10+
{
11+
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
12+
public partial interface IDemoClass
13+
{
14+
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
15+
void MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);
16+
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//--------------------------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by a tool.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
6+
// </auto-generated>
7+
//--------------------------------------------------------------------------------------------------
8+
9+
namespace AutomaticInterfaceExample
10+
{
11+
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
12+
public partial interface IDemoClass
13+
{
14+
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
15+
void MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);
16+
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//--------------------------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by a tool.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
6+
// </auto-generated>
7+
//--------------------------------------------------------------------------------------------------
8+
9+
namespace AutomaticInterfaceExample
10+
{
11+
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
12+
public partial interface IDemoClass
13+
{
14+
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
15+
void MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);
16+
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+

Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//--------------------------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by a tool.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
6+
// </auto-generated>
7+
//--------------------------------------------------------------------------------------------------
8+
9+
namespace AutomaticInterfaceExample
10+
{
11+
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
12+
public partial interface IDemoClass
13+
{
14+
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
15+
global::AutomaticInterfaceExample.EnumWithByteType MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);
16+
17+
}
18+
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
//--------------------------------------------------------------------------------------------------
2+
// <auto-generated>
3+
// This code was generated by a tool.
4+
//
5+
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
6+
// </auto-generated>
7+
//--------------------------------------------------------------------------------------------------
8+
9+
namespace AutomaticInterfaceExample
10+
{
11+
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
12+
public partial interface IDemoClass
13+
{
14+
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
15+
void MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);
16+
17+
}
18+
}
+101
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
namespace Tests.Enums;
2+
3+
public class Enums
4+
{
5+
[Theory]
6+
[InlineData("byte")]
7+
[InlineData("int")]
8+
[InlineData("long")]
9+
public async Task WorksWithEnum(string enumName)
10+
{
11+
var code = $$"""
12+
13+
using AutomaticInterface;
14+
using System;
15+
16+
namespace AutomaticInterfaceExample;
17+
18+
public enum EnumWithByteType : {{enumName}} { A = 1, B = 2, C = 3 };
19+
20+
[GenerateAutomaticInterface]
21+
public class DemoClass
22+
{
23+
public void MethodWithDefaultParameter(EnumWithByteType a = EnumWithByteType.B) { }
24+
}
25+
26+
""";
27+
28+
await Verify(Infrastructure.GenerateCode(code))
29+
.UseMethodName($"{nameof(WorksWithEnum)}-{enumName}");
30+
}
31+
32+
[Fact]
33+
public async Task WorksWithFlagEnum()
34+
{
35+
const string code = """
36+
37+
using AutomaticInterface;
38+
using System;
39+
40+
namespace AutomaticInterfaceExample;
41+
42+
[Flags]
43+
public enum EnumWithByteType { A = 1, B = 2, C = 3 };
44+
45+
[GenerateAutomaticInterface]
46+
public class DemoClass
47+
{
48+
public void MethodWithDefaultParameter(EnumWithByteType a = EnumWithByteType.B) { }
49+
}
50+
51+
""";
52+
53+
await Verify(Infrastructure.GenerateCode(code));
54+
}
55+
56+
[Fact]
57+
public async Task WorksWithEnumsAsReturnType()
58+
{
59+
const string code = """
60+
61+
using AutomaticInterface;
62+
using System;
63+
64+
namespace AutomaticInterfaceExample;
65+
66+
public enum EnumWithByteType { A = 1, B = 2, C = 3 };
67+
68+
[GenerateAutomaticInterface]
69+
public class DemoClass
70+
{
71+
public EnumWithByteType MethodWithDefaultParameter(EnumWithByteType a = EnumWithByteType.B) { return a; }
72+
}
73+
74+
""";
75+
76+
await Verify(Infrastructure.GenerateCode(code));
77+
}
78+
79+
[Fact]
80+
public async Task WorksWithByteEnumsProperties()
81+
{
82+
const string code = """
83+
84+
using AutomaticInterface;
85+
using System;
86+
87+
namespace AutomaticInterfaceExample;
88+
89+
public enum EnumWithByteType : byte { A = 1, B = 2, C = 3 };
90+
91+
[GenerateAutomaticInterface]
92+
public class DemoClass
93+
{
94+
public EnumWithByteType SomeProperty { get; set; }
95+
}
96+
97+
""";
98+
99+
await Verify(Infrastructure.GenerateCode(code));
100+
}
101+
}

README.md

+4
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,10 @@ Note that we use [Verify](https://github.com/VerifyTests/Verify) for testing. It
186186

187187
## Changelog
188188

189+
### 5.1.2
190+
191+
- Fixing enums in method signatures
192+
189193
### 5.1.1
190194

191195
- Emit `new()` type constraints on generic type parameters; emit `params` keyword for method parameters. Thanks, @simonmckenzie!

0 commit comments

Comments
 (0)