Skip to content

Commit

Permalink
67 method with a default enum parameter wich type is byte does not co…
Browse files Browse the repository at this point in the history
…mpile (#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
  • Loading branch information
ChristianSauer authored Jan 28, 2025
1 parent 1afa5e3 commit 8e451ff
Show file tree
Hide file tree
Showing 15 changed files with 289 additions and 4 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<EnableNETAnalyzers>True</EnableNETAnalyzers>
<AnalysisLevel>latest-Recommended</AnalysisLevel>
<Version>5.1.1</Version>
<Version>5.1.2</Version>
<PackageReadmeFile>README.md</PackageReadmeFile>
<TreatWarningsAsErrors>true</TreatWarningsAsErrors>
<NoWarn>1701;1702;NU5128</NoWarn>
Expand Down
21 changes: 18 additions & 3 deletions AutomaticInterface/AutomaticInterface/Builder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,8 @@ private static string InheritDoc(ISymbol source) =>
private static readonly SymbolDisplayFormat FullyQualifiedDisplayFormat =
new(
genericsOptions: SymbolDisplayGenericsOptions.IncludeTypeParameters,
memberOptions: SymbolDisplayMemberOptions.IncludeParameters,
memberOptions: SymbolDisplayMemberOptions.IncludeParameters
| SymbolDisplayMemberOptions.IncludeContainingType,
parameterOptions: SymbolDisplayParameterOptions.IncludeType
| SymbolDisplayParameterOptions.IncludeParamsRefOut
| SymbolDisplayParameterOptions.IncludeDefaultValue
Expand All @@ -27,6 +28,20 @@ private static string InheritDoc(ISymbol source) =>
| SymbolDisplayMiscellaneousOptions.EscapeKeywordIdentifiers
);

/// <summary>
/// We do need to be able to group shadowing and new methods/events into a single entry, hence this is missing SymbolDisplayMemberOptions.IncludeContainingType
/// </summary>
private static readonly SymbolDisplayFormat FullyQualifiedDisplayFormatForGrouping =
new(
genericsOptions: FullyQualifiedDisplayFormat.GenericsOptions,
memberOptions: FullyQualifiedDisplayFormat.MemberOptions
& ~SymbolDisplayMemberOptions.IncludeContainingType,
parameterOptions: FullyQualifiedDisplayFormat.ParameterOptions,
typeQualificationStyle: FullyQualifiedDisplayFormat.TypeQualificationStyle,
globalNamespaceStyle: FullyQualifiedDisplayFormat.GlobalNamespaceStyle,
miscellaneousOptions: FullyQualifiedDisplayFormat.MiscellaneousOptions
);

public static string BuildInterfaceFor(ITypeSymbol typeSymbol)
{
if (
Expand Down Expand Up @@ -91,7 +106,7 @@ private static void AddMethodsToInterface(List<ISymbol> members, InterfaceBuilde
.Where(x => x.MethodKind == MethodKind.Ordinary)
.Where(x => x.ContainingType.Name != nameof(Object))
.Where(x => !HasIgnoreAttribute(x))
.GroupBy(x => x.ToDisplayString(FullyQualifiedDisplayFormat))
.GroupBy(x => x.ToDisplayString(FullyQualifiedDisplayFormatForGrouping))
.Select(g => g.First())
.ToList()
.ForEach(method => AddMethod(codeGenerator, method));
Expand Down Expand Up @@ -182,7 +197,7 @@ private static void AddEventsToInterface(List<ISymbol> members, InterfaceBuilder
members
.Where(x => x.Kind == SymbolKind.Event)
.OfType<IEventSymbol>()
.GroupBy(x => x.ToDisplayString(FullyQualifiedDisplayFormat))
.GroupBy(x => x.ToDisplayString(FullyQualifiedDisplayFormatForGrouping))
.Select(g => g.First())
.ToList()
.ForEach(evt =>
Expand Down
2 changes: 2 additions & 0 deletions AutomaticInterface/AutomaticInterface/InterfaceBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -121,7 +121,9 @@ public string Build()

cb.Indent();
foreach (var method in methodInfos)
{
BuildMethod(cb, method);
}

cb.Dedent();

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//--------------------------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
// </auto-generated>
//--------------------------------------------------------------------------------------------------

namespace AutomaticInterfaceExample
{
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
public partial interface IDemoClass
{
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
void MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//--------------------------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
// </auto-generated>
//--------------------------------------------------------------------------------------------------

namespace AutomaticInterfaceExample
{
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
public partial interface IDemoClass
{
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
global::AutomaticInterfaceExample.EnumWithByteType MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//--------------------------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
// </auto-generated>
//--------------------------------------------------------------------------------------------------

namespace AutomaticInterfaceExample
{
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
public partial interface IDemoClass
{
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.SomeProperty" />
global::AutomaticInterfaceExample.EnumWithByteType SomeProperty { get; set; }

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//--------------------------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
// </auto-generated>
//--------------------------------------------------------------------------------------------------

namespace AutomaticInterfaceExample
{
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
public partial interface IDemoClass
{
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
void MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//--------------------------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
// </auto-generated>
//--------------------------------------------------------------------------------------------------

namespace AutomaticInterfaceExample
{
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
public partial interface IDemoClass
{
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
void MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//--------------------------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
// </auto-generated>
//--------------------------------------------------------------------------------------------------

namespace AutomaticInterfaceExample
{
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
public partial interface IDemoClass
{
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
void MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);

}
}
18 changes: 18 additions & 0 deletions AutomaticInterface/Tests/Enums/Enums.WorksWithEnum.received.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//--------------------------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
// </auto-generated>
//--------------------------------------------------------------------------------------------------

namespace AutomaticInterfaceExample
{
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
public partial interface IDemoClass
{
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
void MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@

Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//--------------------------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
// </auto-generated>
//--------------------------------------------------------------------------------------------------

namespace AutomaticInterfaceExample
{
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
public partial interface IDemoClass
{
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
global::AutomaticInterfaceExample.EnumWithByteType MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);

}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
//--------------------------------------------------------------------------------------------------
// <auto-generated>
// This code was generated by a tool.
//
// Changes to this file may cause incorrect behavior and will be lost if the code is regenerated.
// </auto-generated>
//--------------------------------------------------------------------------------------------------

namespace AutomaticInterfaceExample
{
[global::System.CodeDom.Compiler.GeneratedCode("AutomaticInterface", "")]
public partial interface IDemoClass
{
/// <inheritdoc cref="AutomaticInterfaceExample.DemoClass.MethodWithDefaultParameter(AutomaticInterfaceExample.EnumWithByteType)" />
void MethodWithDefaultParameter(global::AutomaticInterfaceExample.EnumWithByteType a = global::AutomaticInterfaceExample.EnumWithByteType.B);

}
}
101 changes: 101 additions & 0 deletions AutomaticInterface/Tests/Enums/Enums.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,101 @@
namespace Tests.Enums;

public class Enums
{
[Theory]
[InlineData("byte")]
[InlineData("int")]
[InlineData("long")]
public async Task WorksWithEnum(string enumName)
{
var code = $$"""
using AutomaticInterface;
using System;
namespace AutomaticInterfaceExample;
public enum EnumWithByteType : {{enumName}} { A = 1, B = 2, C = 3 };
[GenerateAutomaticInterface]
public class DemoClass
{
public void MethodWithDefaultParameter(EnumWithByteType a = EnumWithByteType.B) { }
}
""";

await Verify(Infrastructure.GenerateCode(code))
.UseMethodName($"{nameof(WorksWithEnum)}-{enumName}");
}

[Fact]
public async Task WorksWithFlagEnum()
{
const string code = """
using AutomaticInterface;
using System;
namespace AutomaticInterfaceExample;
[Flags]
public enum EnumWithByteType { A = 1, B = 2, C = 3 };
[GenerateAutomaticInterface]
public class DemoClass
{
public void MethodWithDefaultParameter(EnumWithByteType a = EnumWithByteType.B) { }
}
""";

await Verify(Infrastructure.GenerateCode(code));
}

[Fact]
public async Task WorksWithEnumsAsReturnType()
{
const string code = """
using AutomaticInterface;
using System;
namespace AutomaticInterfaceExample;
public enum EnumWithByteType { A = 1, B = 2, C = 3 };
[GenerateAutomaticInterface]
public class DemoClass
{
public EnumWithByteType MethodWithDefaultParameter(EnumWithByteType a = EnumWithByteType.B) { return a; }
}
""";

await Verify(Infrastructure.GenerateCode(code));
}

[Fact]
public async Task WorksWithByteEnumsProperties()
{
const string code = """
using AutomaticInterface;
using System;
namespace AutomaticInterfaceExample;
public enum EnumWithByteType : byte { A = 1, B = 2, C = 3 };
[GenerateAutomaticInterface]
public class DemoClass
{
public EnumWithByteType SomeProperty { get; set; }
}
""";

await Verify(Infrastructure.GenerateCode(code));
}
}
4 changes: 4 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -186,6 +186,10 @@ Note that we use [Verify](https://github.com/VerifyTests/Verify) for testing. It

## Changelog

### 5.1.2

- Fixing enums in method signatures

### 5.1.1

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

0 comments on commit 8e451ff

Please sign in to comment.