-
Notifications
You must be signed in to change notification settings - Fork 199
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Move ToSerial and ToEnum to SerializationProviders (#3795)
Fixes: [#3651](#3651) --------- Co-authored-by: m-nash <[email protected]> Co-authored-by: JoshLove-msft <[email protected]>
- Loading branch information
1 parent
5a8b2cc
commit 1d43455
Showing
39 changed files
with
371 additions
and
267 deletions.
There are no files selected for viewing
66 changes: 66 additions & 0 deletions
66
...crosoft.Generator.CSharp.ClientModel/src/Providers/ExtensibleEnumSerializationProvider.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,66 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Diagnostics; | ||
using System.IO; | ||
using Microsoft.Generator.CSharp.Input; | ||
using Microsoft.Generator.CSharp.Primitives; | ||
using Microsoft.Generator.CSharp.Providers; | ||
|
||
namespace Microsoft.Generator.CSharp.ClientModel.Providers | ||
{ | ||
/// <summary> | ||
/// This defines a class with extension methods for enums to convert an enum to its underlying value, or from its underlying value to an instance of the enum | ||
/// </summary> | ||
internal partial class ExtensibleEnumSerializationProvider : TypeProvider | ||
{ | ||
private readonly InputEnumType _enumType; | ||
private TypeProvider _enumProvider; | ||
|
||
protected override string GetNamespace() => _enumProvider.Type.Namespace; | ||
|
||
public ExtensibleEnumSerializationProvider(InputEnumType enumType) | ||
{ | ||
Debug.Assert(enumType.IsExtensible); | ||
_enumType = enumType; | ||
_enumProvider = ClientModelPlugin.Instance.TypeFactory.CreateEnum(_enumType); | ||
} | ||
|
||
protected override string BuildRelativeFilePath() | ||
{ | ||
return Path.Combine("src", "Generated", "Models", $"{_enumProvider.Name}.Serialization.cs"); | ||
} | ||
|
||
protected override string BuildName() => _enumProvider.Name; | ||
|
||
protected override TypeSignatureModifiers GetDeclarationModifiers() => _enumProvider.DeclarationModifiers; | ||
|
||
protected override MethodProvider[] BuildMethods() | ||
{ | ||
// for string-based extensible enums, we are using `ToString` as its serialization | ||
// for non-string-based extensible enums, we need a method to serialize them | ||
if (!_enumProvider.EnumUnderlyingType.Equals(typeof(string))) | ||
{ | ||
var toSerialSignature = new MethodSignature( | ||
Name: $"ToSerial{_enumProvider.EnumUnderlyingType.Name}", | ||
Modifiers: MethodSignatureModifiers.Internal, | ||
ReturnType: _enumProvider.EnumUnderlyingType, | ||
Parameters: Array.Empty<ParameterProvider>(), | ||
Description: null, | ||
ReturnDescription: null); | ||
|
||
// writes the method: | ||
// internal float ToSerialSingle() => _value; // when ValueType is float | ||
// internal int ToSerialInt32() => _value; // when ValueType is int | ||
// etc | ||
var valueField = new FieldProvider(FieldModifiers.Private | FieldModifiers.ReadOnly, _enumProvider.EnumUnderlyingType, "_value"); | ||
return [new MethodProvider(toSerialSignature, valueField, this)]; | ||
} | ||
else | ||
{ | ||
return Array.Empty<MethodProvider>(); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,5 +24,4 @@ | |
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory> | ||
</None> | ||
</ItemGroup> | ||
|
||
</Project> |
62 changes: 62 additions & 0 deletions
62
...r/Microsoft.Generator.CSharp.ClientModel/test/Providers/EnumProviderSerializationTests.cs
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,62 @@ | ||
// Copyright (c) Microsoft Corporation. All rights reserved. | ||
// Licensed under the MIT License. | ||
|
||
using System; | ||
using System.Collections.Generic; | ||
using System.Linq; | ||
using Microsoft.Generator.CSharp.Expressions; | ||
using Microsoft.Generator.CSharp.Input; | ||
using Microsoft.Generator.CSharp.Providers; | ||
using Microsoft.Generator.CSharp.Statements; | ||
using NUnit.Framework; | ||
|
||
namespace Microsoft.Generator.CSharp.ClientModel.Tests.Providers | ||
{ | ||
public class EnumProviderSerializationTests | ||
{ | ||
[OneTimeSetUp] | ||
public void Setup() | ||
{ | ||
MockHelpers.LoadMockPlugin(); | ||
} | ||
|
||
public static object[] ValidateTestCases = | ||
{ | ||
new object[] {"One", 1, "Two", 2} | ||
}; | ||
|
||
private TypeProvider? CreateEnumSerializationProvider(string stringA, int intA, string stringB, int intB) | ||
{ | ||
IReadOnlyList<InputEnumTypeValue> values = new List<InputEnumTypeValue> | ||
{ | ||
new InputEnumTypeValue(stringA, intA, null), | ||
new InputEnumTypeValue(stringB, intB, null) | ||
}; | ||
var input = new InputEnumType("mockInputEnum", "mockNamespace", "public", null, "The mock enum", InputModelTypeUsage.Input | InputModelTypeUsage.Output, new InputPrimitiveType(InputPrimitiveTypeKind.Int32), values, false); | ||
TypeProvider enumType = ClientModelPlugin.Instance.TypeFactory.CreateEnum(input); | ||
return enumType.SerializationProviders.FirstOrDefault(); | ||
} | ||
|
||
[TestCaseSource(nameof(ValidateTestCases))] | ||
public void ValidateToSerial(string stringA, int intA, string stringB, int intB) | ||
{ | ||
var serialization = CreateEnumSerializationProvider(stringA, intA, stringB, intB); | ||
MethodProvider? method = serialization!.Methods.Where(m => m.Signature.Name.Contains("ToSerial")).FirstOrDefault(); | ||
// Cast method.BodyExpression to SwitchCaseExpression | ||
Assert.IsNull(method); | ||
} | ||
|
||
[TestCaseSource(nameof(ValidateTestCases))] | ||
public void ValidateToEnum(string stringA, int intA, string stringB, int intB) | ||
{ | ||
var serialization = CreateEnumSerializationProvider(stringA, intA, stringB, intB); | ||
MethodProvider? method = serialization!.Methods.Where(m => m.Signature.Name.Contains("Enum")).FirstOrDefault(); | ||
// Cast method.BodyExpression to SwitchCaseExpression | ||
if (method!.BodyStatements is MethodBodyStatements methodBodyStatements) | ||
{ | ||
// Verify that the switch case expression has the correct number of cases (values + 1 for throw) | ||
Assert.AreEqual(3, methodBodyStatements.Statements.Count()); | ||
} | ||
} | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Oops, something went wrong.