diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ExtensibleEnumSerializationProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ExtensibleEnumSerializationProvider.cs new file mode 100644 index 0000000000..4f2a880bf5 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/ExtensibleEnumSerializationProvider.cs @@ -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 +{ + /// + /// 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 + /// + 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(), + 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(); + } + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/FixedEnumSerializationProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/FixedEnumSerializationProvider.cs similarity index 67% rename from packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/FixedEnumSerializationProvider.cs rename to packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/FixedEnumSerializationProvider.cs index 77d7bc1288..928951b3ea 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/FixedEnumSerializationProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/Providers/FixedEnumSerializationProvider.cs @@ -7,34 +7,40 @@ using System.IO; using System.Linq; using Microsoft.Generator.CSharp.Expressions; +using Microsoft.Generator.CSharp.Input; using Microsoft.Generator.CSharp.Primitives; +using Microsoft.Generator.CSharp.Providers; using Microsoft.Generator.CSharp.Snippets; using Microsoft.Generator.CSharp.Statements; using static Microsoft.Generator.CSharp.Snippets.Snippet; -namespace Microsoft.Generator.CSharp.Providers +namespace Microsoft.Generator.CSharp.ClientModel.Providers { /// /// 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 /// internal class FixedEnumSerializationProvider : TypeProvider { - private readonly EnumProvider _enumType; + private readonly InputEnumType _enumType; + private TypeProvider _enumProvider; - public FixedEnumSerializationProvider(EnumProvider enumType) + public FixedEnumSerializationProvider(InputEnumType enumType) { Debug.Assert(!enumType.IsExtensible); - _enumType = enumType; + _enumProvider = ClientModelPlugin.Instance.TypeFactory.CreateEnum(_enumType); } - protected override string GetNamespace() => _enumType.Type.Namespace; - - protected override TypeSignatureModifiers GetDeclarationModifiers() => TypeSignatureModifiers.Internal | TypeSignatureModifiers.Static | TypeSignatureModifiers.Partial; + protected override string GetNamespace() => _enumProvider.Type.Namespace; + protected override TypeSignatureModifiers GetDeclarationModifiers() + => TypeSignatureModifiers.Internal | TypeSignatureModifiers.Static | TypeSignatureModifiers.Partial | TypeSignatureModifiers.Class; - protected override string BuildRelativeFilePath() => Path.Combine("src", "Generated", "Models", $"{Name}.cs"); + protected override string BuildRelativeFilePath() + { + return Path.Combine("src", "Generated", "Models", $"{_enumProvider.Name}.Serialization.cs"); + } - protected override string BuildName() => $"{_enumType.Name}Extensions"; + protected override string BuildName() => $"{_enumProvider.Name}Extensions"; /// /// Returns if this enum type needs an extension method for serialization @@ -43,7 +49,8 @@ public FixedEnumSerializationProvider(EnumProvider enumType) private bool NeedsSerializationMethod() { // fixed enum with int based types, we do not write a method for serialization because it was embedded in the definition - if (_enumType is { IsExtensible: false, IsIntValueType: true }) + bool isIntValueType = _enumProvider.EnumUnderlyingType.Equals(typeof(int)) || _enumProvider.EnumUnderlyingType.Equals(typeof(long)); + if (!_enumType.IsExtensible && isIntValueType) return false; // otherwise we need a serialization method with the name of `ToSerial{UnderlyingTypeName}` @@ -56,32 +63,32 @@ protected override MethodProvider[] BuildMethods() // serialization method (in some cases we do not need serialization) if (NeedsSerializationMethod()) { - var serializationValueParameter = new ParameterProvider("value", $"The value to serialize.", _enumType.Type); + var serializationValueParameter = new ParameterProvider("value", $"The value to serialize.", _enumProvider.Type); var serializationSignature = new MethodSignature( - Name: $"ToSerial{_enumType.ValueType.Name}", + Name: $"ToSerial{_enumProvider.EnumUnderlyingType.Name}", Modifiers: MethodSignatureModifiers.Public | MethodSignatureModifiers.Static | MethodSignatureModifiers.Extension, - ReturnType: _enumType.ValueType, + ReturnType: _enumProvider.EnumUnderlyingType, Parameters: [serializationValueParameter], Description: null, ReturnDescription: null); // the fields of an enum type are the values of the enum type - var knownCases = new SwitchCaseExpression[_enumType.Members.Count]; + var knownCases = new SwitchCaseExpression[_enumProvider.EnumValues.Count]; for (int i = 0; i < knownCases.Length; i++) { - var enumValue = _enumType.Members[i]; - knownCases[i] = new SwitchCaseExpression(new MemberExpression(_enumType.Type, enumValue.Field.Name), Literal(enumValue.Value)); + var enumValue = _enumProvider.EnumValues[i]; + knownCases[i] = new SwitchCaseExpression(new MemberExpression(_enumProvider.Type, enumValue.Field.Name), Literal(enumValue.Value)); } - var defaultCase = SwitchCaseExpression.Default(ThrowExpression(New.ArgumentOutOfRangeException(_enumType, serializationValueParameter))); + var defaultCase = SwitchCaseExpression.Default(ThrowExpression(New.ArgumentOutOfRangeException(_enumProvider, serializationValueParameter))); var serializationBody = new SwitchExpression(serializationValueParameter, [.. knownCases, defaultCase]); methods.Add(new(serializationSignature, serializationBody, this)); } // deserialization method (we always need a deserialization) - var deserializationValueParameter = new ParameterProvider("value", $"The value to deserialize.", _enumType.ValueType); + var deserializationValueParameter = new ParameterProvider("value", $"The value to deserialize.", _enumProvider.EnumUnderlyingType); var deserializationSignature = new MethodSignature( - Name: $"To{_enumType.Type.Name}", + Name: $"To{_enumProvider.Name}", Modifiers: MethodSignatureModifiers.Public | MethodSignatureModifiers.Static | MethodSignatureModifiers.Extension, - ReturnType: _enumType.Type, + ReturnType: _enumProvider.Type, Parameters: [deserializationValueParameter], Description: null, ReturnDescription: null); @@ -92,12 +99,12 @@ protected override MethodProvider[] BuildMethods() // in general, this loop builds up if statements for each value, it looks like: // if () { return EnumType.TheValue; } // the condition could be different depending on the type of the underlying value type of the enum - for (int i = 0; i < _enumType.Fields.Count; i++) + for (int i = 0; i < _enumProvider.Fields.Count; i++) { - var enumField = _enumType.Fields[i]; - var enumValue = _enumType.Members[i]; + var enumField = _enumProvider.Fields[i]; + var enumValue = _enumProvider.EnumValues[i]; ScopedApi condition; - if (_enumType.IsStringValueType) + if (_enumProvider.EnumUnderlyingType.Equals(typeof(string))) { // when the values are strings, we compare them case-insensitively // this is either @@ -106,7 +113,7 @@ protected override MethodProvider[] BuildMethods() // string.Equals(value, "", StringComparison.InvariantCultureIgnoreCase) condition = (enumValue.Value is string strValue && strValue.All(char.IsAscii) ? stringComparer.Invoke(nameof(IEqualityComparer.Equals), value, Literal(strValue)) - : Static(_enumType.ValueType).Invoke(nameof(Equals), [value, Literal(enumValue.Value), FrameworkEnumValue(StringComparison.InvariantCultureIgnoreCase)])) + : Static(_enumProvider.EnumUnderlyingType).Invoke(nameof(Equals), [value, Literal(enumValue.Value), FrameworkEnumValue(StringComparison.InvariantCultureIgnoreCase)])) .As(); } else @@ -116,12 +123,12 @@ protected override MethodProvider[] BuildMethods() } deserializationBody.Add(new IfStatement(condition) { - Return(new MemberExpression(_enumType.Type, enumField.Name)) + Return(new MemberExpression(_enumProvider.Type, enumField.Name)) }); } // add a fallback throw statement to ensure every path of this method returns a value - deserializationBody.Add(Throw(New.ArgumentOutOfRangeException(_enumType, deserializationValueParameter))); + deserializationBody.Add(Throw(New.ArgumentOutOfRangeException(_enumProvider, deserializationValueParameter))); methods.Add(new(deserializationSignature, deserializationBody, this)); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/ScmTypeFactory.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/ScmTypeFactory.cs index bdd132e101..0856bf4d60 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/ScmTypeFactory.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/src/ScmTypeFactory.cs @@ -1,9 +1,11 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System; using System.ClientModel; using System.ClientModel.Primitives; using System.Collections.Generic; +using Microsoft.CodeAnalysis.CSharp.Syntax; using Microsoft.Generator.CSharp.ClientModel.Providers; using Microsoft.Generator.CSharp.Input; using Microsoft.Generator.CSharp.Primitives; @@ -38,6 +40,14 @@ protected override IReadOnlyList CreateSerializationsCore(InputTyp { case InputModelType inputModel when inputModel.Usage.HasFlag(InputModelTypeUsage.Json): return [new MrwSerializationTypeDefinition(inputModel)]; + case InputEnumType inputEnumType when inputEnumType.IsExtensible: + if (ClientModelPlugin.Instance.TypeFactory.CreateCSharpType(inputEnumType).UnderlyingEnumType.Equals(typeof(string))) + { + return []; + } + return [new ExtensibleEnumSerializationProvider(inputEnumType)]; + case InputEnumType inputEnumType: + return [new FixedEnumSerializationProvider(inputEnumType)]; default: return base.CreateSerializationsCore(inputType); } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Microsoft.Generator.CSharp.ClientModel.Tests.csproj b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Microsoft.Generator.CSharp.ClientModel.Tests.csproj index a78947f335..27196b77d5 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Microsoft.Generator.CSharp.ClientModel.Tests.csproj +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Microsoft.Generator.CSharp.ClientModel.Tests.csproj @@ -24,5 +24,4 @@ PreserveNewest - diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/EnumProviderSerializationTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/EnumProviderSerializationTests.cs new file mode 100644 index 0000000000..7d38fcab66 --- /dev/null +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp.ClientModel/test/Providers/EnumProviderSerializationTests.cs @@ -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 values = new List + { + 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()); + } + } + } +} diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Primitives/CSharpType.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Primitives/CSharpType.cs index d25aadde77..eaaee6179b 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Primitives/CSharpType.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Primitives/CSharpType.cs @@ -146,7 +146,7 @@ internal CSharpType( implementation.DeclarationModifiers.HasFlag(TypeSignatureModifiers.Public) && arguments.All(t => t.IsPublic), implementation.DeclarationModifiers.HasFlag(TypeSignatureModifiers.Struct), baseType, - implementation is EnumProvider enumProvider ? enumProvider.ValueType.FrameworkType : null) + implementation.IsEnum? implementation.EnumUnderlyingType.FrameworkType : null) { } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/EnumProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/EnumProvider.cs index 90bad93cd7..c300fa2f25 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/EnumProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/EnumProvider.cs @@ -4,14 +4,17 @@ using System; using System.Collections.Generic; using System.IO; +using System.Linq; using Microsoft.Generator.CSharp.Expressions; using Microsoft.Generator.CSharp.Input; using Microsoft.Generator.CSharp.Primitives; namespace Microsoft.Generator.CSharp.Providers { - public abstract class EnumProvider : TypeProvider + internal abstract class EnumProvider : TypeProvider { + private readonly InputEnumType _inputType; + public static EnumProvider Create(InputEnumType input) => input.IsExtensible ? new ExtensibleEnumProvider(input) @@ -19,48 +22,33 @@ public static EnumProvider Create(InputEnumType input) protected EnumProvider(InputEnumType input) { + _inputType = input; _deprecated = input.Deprecated; - _input = input; - IsExtensible = input.IsExtensible; - ValueType = CodeModelPlugin.Instance.TypeFactory.CreateCSharpType(input.ValueType); - IsStringValueType = ValueType.Equals(typeof(string)); - IsIntValueType = ValueType.Equals(typeof(int)) || ValueType.Equals(typeof(long)); - IsFloatValueType = ValueType.Equals(typeof(float)) || ValueType.Equals(typeof(double)); - IsNumericValueType = IsIntValueType || IsFloatValueType; - Description = input.Description != null ? FormattableStringHelpers.FromString(input.Description) : $"The {Name}."; } - public CSharpType ValueType { get; } public bool IsExtensible { get; } - internal bool IsIntValueType { get; } - internal bool IsFloatValueType { get; } - internal bool IsStringValueType { get; } - internal bool IsNumericValueType { get; } + private bool? _isIntValue; + internal bool IsIntValueType => _isIntValue ??= EnumUnderlyingType.Equals(typeof(int)) || EnumUnderlyingType.Equals(typeof(long)); + private bool? _isFloatValue; + internal bool IsFloatValueType => _isFloatValue ??= EnumUnderlyingType.Equals(typeof(float)) || EnumUnderlyingType.Equals(typeof(double)); + private bool? _isStringValue; + internal bool IsStringValueType => _isStringValue ??= EnumUnderlyingType.Equals(typeof(string)); + internal bool IsNumericValueType => IsIntValueType || IsFloatValueType; protected override string BuildRelativeFilePath() => Path.Combine("src", "Generated", "Models", $"{Name}.cs"); - protected override string BuildName() => _input.Name.ToCleanName(); + protected override string BuildName() => _inputType.Name.ToCleanName(); protected override FormattableString Description { get; } - private IReadOnlyList? _members; - private readonly InputEnumType _input; - public IReadOnlyList Members => _members ??= BuildMembers(); - - protected abstract IReadOnlyList BuildMembers(); - - public abstract ValueExpression ToSerial(ValueExpression enumExpression); - - public abstract ValueExpression ToEnum(ValueExpression valueExpression); - - protected override string GetNamespace() => CodeModelPlugin.Instance.Configuration.ModelNamespace; - - protected override bool GetIsEnum() => true; - protected override TypeProvider[] BuildSerializationProviders() { - return [.. CodeModelPlugin.Instance.TypeFactory.CreateSerializations(_input)]; + return CodeModelPlugin.Instance.TypeFactory.CreateSerializations(_inputType).ToArray(); } + protected override string GetNamespace() => CodeModelPlugin.Instance.Configuration.ModelNamespace; + + protected override bool GetIsEnum() => true; + protected override CSharpType BuildEnumUnderlyingType() => CodeModelPlugin.Instance.TypeFactory.CreateCSharpType(_inputType.ValueType); } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ExtensibleEnumProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ExtensibleEnumProvider.cs index 1581cb9ab0..e70a102811 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ExtensibleEnumProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/ExtensibleEnumProvider.cs @@ -19,11 +19,11 @@ internal sealed class ExtensibleEnumProvider : EnumProvider { private readonly IReadOnlyList _allowedValues; private readonly TypeSignatureModifiers _modifiers; - + private readonly InputEnumType _inputType; internal ExtensibleEnumProvider(InputEnumType input): base(input) { + _inputType = input; _allowedValues = input.Values; - // extensible enums are implemented as readonly structs _modifiers = TypeSignatureModifiers.Partial | TypeSignatureModifiers.ReadOnly | TypeSignatureModifiers.Struct; if (input.Accessibility == "internal") @@ -31,14 +31,14 @@ internal ExtensibleEnumProvider(InputEnumType input): base(input) _modifiers |= TypeSignatureModifiers.Internal; } - _valueField = new FieldProvider(FieldModifiers.Private | FieldModifiers.ReadOnly, ValueType, "_value"); + _valueField = new FieldProvider(FieldModifiers.Private | FieldModifiers.ReadOnly, EnumUnderlyingType, "_value"); } private readonly FieldProvider _valueField; protected override TypeSignatureModifiers GetDeclarationModifiers() => _modifiers; - protected override IReadOnlyList BuildMembers() + protected override IReadOnlyList BuildEnumValues() { var values = new EnumTypeMember[_allowedValues.Count]; @@ -54,7 +54,7 @@ protected override IReadOnlyList BuildMembers() var initializationValue = Literal(inputValue.Value); var field = new FieldProvider( modifiers, - ValueType, + EnumUnderlyingType, name, FormattableStringHelpers.FromString(inputValue.Description), initializationValue); @@ -69,14 +69,14 @@ protected override CSharpType[] BuildImplements() => [new CSharpType(typeof(IEquatable<>), Type)]; // extensible enums implement IEquatable protected override FieldProvider[] BuildFields() - => [_valueField, .. Members.Select(v => v.Field)]; + => [_valueField, .. EnumValues.Select(v => v.Field)]; protected override PropertyProvider[] BuildProperties() { - var properties = new PropertyProvider[Members.Count]; + var properties = new PropertyProvider[EnumValues.Count]; var index = 0; - foreach (var enumValue in Members) + foreach (var enumValue in EnumValues) { var name = enumValue.Name; var value = enumValue.Value; @@ -94,9 +94,9 @@ protected override PropertyProvider[] BuildProperties() protected override ConstructorProvider[] BuildConstructors() { - var valueParameter = new ParameterProvider("value", $"The value.", ValueType) + var valueParameter = new ParameterProvider("value", $"The value.", EnumUnderlyingType) { - Validation = ValueType.IsValueType ? ParameterValidationType.None : ParameterValidationType.AssertNotNull + Validation = EnumUnderlyingType.IsValueType ? ParameterValidationType.None : ParameterValidationType.AssertNotNull }; var signature = new ConstructorSignature( Type: Type, @@ -141,7 +141,7 @@ protected override MethodProvider[] BuildMethods() methods.Add(new(inequalitySignature, Not(left.InvokeEquals(right)), this)); - var valueParameter = new ParameterProvider("value", $"The value.", ValueType); + var valueParameter = new ParameterProvider("value", $"The value.", EnumUnderlyingType); var castSignature = new MethodSignature( Name: string.Empty, Description: $"Converts a string to a {Type:C}", @@ -185,11 +185,11 @@ protected override MethodProvider[] BuildMethods() // public bool Equals(EnumType other) => string.Equals(_value, other._value, StringComparison.InvariantCultureIgnoreCase); // or // public bool Equals(EnumType other) => int/float.Equals(_value, other._value); - var valueField = new VariableExpression(ValueType.WithNullable(!ValueType.IsValueType), _valueField.Declaration); + var valueField = new VariableExpression(EnumUnderlyingType.WithNullable(!EnumUnderlyingType.IsValueType), _valueField.Declaration); var otherValue = ((ValueExpression)otherParameter).Property(_valueField.Name); var equalsExpressionBody = IsStringValueType - ? Static(ValueType).Invoke(nameof(object.Equals), [valueField, otherValue, FrameworkEnumValue(StringComparison.InvariantCultureIgnoreCase)]) - : Static(ValueType).Invoke(nameof(object.Equals), [valueField, otherValue]); + ? Static(EnumUnderlyingType).Invoke(nameof(object.Equals), [valueField, otherValue, FrameworkEnumValue(StringComparison.InvariantCultureIgnoreCase)]) + : Static(EnumUnderlyingType).Invoke(nameof(object.Equals), [valueField, otherValue]); methods.Add(new(equalsSignature, equalsExpressionBody, this)); var getHashCodeSignature = new MethodSignature( @@ -231,35 +231,14 @@ protected override MethodProvider[] BuildMethods() : valueField.Invoke(nameof(object.ToString), new MemberExpression(typeof(CultureInfo), nameof(CultureInfo.InvariantCulture))); methods.Add(new(toStringSignature, toStringExpressionBody, this, XmlDocProvider.InheritDocs)); - // 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 (!IsStringValueType) - { - var toSerialSignature = new MethodSignature( - Name: $"ToSerial{ValueType.Name}", - Modifiers: MethodSignatureModifiers.Internal, - ReturnType: ValueType, - Parameters: Array.Empty(), - Description: null, - ReturnDescription: null); - - // writes the method: - // internal float ToSerialSingle() => _value; // when ValueType is float - // internal int ToSerialInt32() => _value; // when ValueType is int - // etc - methods.Add(new(toSerialSignature, valueField, this)); - } - return methods.ToArray(); } - - public override ValueExpression ToSerial(ValueExpression enumExpression) + protected override TypeProvider[] BuildSerializationProviders() { - var serialMethodName = IsStringValueType ? nameof(object.ToString) : $"ToSerial{ValueType.Name}"; - return enumExpression.Invoke(serialMethodName); + return CodeModelPlugin.Instance.TypeFactory.CreateSerializations(_inputType).ToArray(); } + protected override bool GetIsEnum() => true; - public override ValueExpression ToEnum(ValueExpression valueExpression) - => New.Instance(Type, valueExpression); + protected override CSharpType BuildEnumUnderlyingType() => CodeModelPlugin.Instance.TypeFactory.CreateCSharpType(_inputType.ValueType); } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/FixedEnumProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/FixedEnumProvider.cs index c56b92fa05..f2e56850da 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/FixedEnumProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/FixedEnumProvider.cs @@ -15,11 +15,12 @@ internal sealed class FixedEnumProvider : EnumProvider { private readonly IReadOnlyList _allowedValues; private readonly TypeSignatureModifiers _modifiers; + private readonly InputEnumType _inputType; internal FixedEnumProvider(InputEnumType input) : base(input) { + _inputType = input; _allowedValues = input.Values; - // fixed enums are implemented by enum in C# _modifiers = TypeSignatureModifiers.Enum; if (input.Accessibility == "internal") @@ -28,10 +29,15 @@ internal FixedEnumProvider(InputEnumType input) : base(input) } } + protected override TypeProvider[] BuildSerializationProviders() + { + return CodeModelPlugin.Instance.TypeFactory.CreateSerializations(_inputType).ToArray(); + } + protected override TypeSignatureModifiers GetDeclarationModifiers() => _modifiers; // we have to build the values first, because the corresponding fieldDeclaration of the values might need all of the existing values to avoid name conflicts - protected override IReadOnlyList BuildMembers() + protected override IReadOnlyList BuildEnumValues() { var values = new EnumTypeMember[_allowedValues.Count]; for (int i = 0; i < _allowedValues.Count; i++) @@ -44,7 +50,7 @@ protected override IReadOnlyList BuildMembers() var initializationValue = IsIntValueType ? Literal(inputValue.Value) : null; var field = new FieldProvider( modifiers, - ValueType, + EnumUnderlyingType, name, inputValue.Description is null ? $"{name}" : FormattableStringHelpers.FromString(inputValue.Description), initializationValue); @@ -55,22 +61,9 @@ protected override IReadOnlyList BuildMembers() } protected override FieldProvider[] BuildFields() - => Members.Select(v => v.Field).ToArray(); - - public override ValueExpression ToSerial(ValueExpression enumExpression) - { - if (IsIntValueType) - { - // when the fixed enum is implemented as int, we cast to the value - return enumExpression.CastTo(ValueType); - } - - // otherwise we call the corresponding extension method to convert the value - CSharpType? serializationType = SerializationProviders.FirstOrDefault()?.Type; - return enumExpression.Invoke($"ToSerial{ValueType.Name}"); - } + => EnumValues.Select(v => v.Field).ToArray(); - public override ValueExpression ToEnum(ValueExpression valueExpression) - => valueExpression.Invoke($"To{Type.Name}"); + protected override bool GetIsEnum() => true; + protected override CSharpType BuildEnumUnderlyingType() => CodeModelPlugin.Instance.TypeFactory.CreateCSharpType(_inputType.ValueType); } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/TypeProvider.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/TypeProvider.cs index 601954696f..d5f4eb337f 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/TypeProvider.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Providers/TypeProvider.cs @@ -52,6 +52,7 @@ public string? Deprecated GetBaseType()); protected virtual bool GetIsEnum() => false; + public bool IsEnum => GetIsEnum(); protected virtual string GetNamespace() => CodeModelPlugin.Instance.Configuration.RootNamespace; @@ -142,6 +143,12 @@ private TypeSignatureModifiers GetDeclarationModifiersInternal() protected virtual TypeProvider[] BuildSerializationProviders() => Array.Empty(); + protected virtual CSharpType BuildEnumUnderlyingType() => throw new InvalidOperationException("Not an EnumProvider type"); + + private CSharpType? _enumUnderlyingType; + + public CSharpType EnumUnderlyingType => _enumUnderlyingType ??= BuildEnumUnderlyingType(); // Each member in the EnumProvider has to have this type + protected virtual XmlDocProvider BuildXmlDocs() { var docs = new XmlDocProvider(); @@ -190,5 +197,10 @@ public void Update( XmlDocs = xmlDocs; } } + public IReadOnlyList EnumValues => _enumValues ??= BuildEnumValues(); + + protected virtual IReadOnlyList BuildEnumValues() => throw new InvalidOperationException("Not an EnumProvider type"); + + private IReadOnlyList? _enumValues; } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.New.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.New.cs index bcf17264df..ba772a9b11 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.New.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/Snippets/Snippet.New.cs @@ -3,6 +3,7 @@ using System; using System.Collections.Generic; +using System.Diagnostics; using System.IO; using System.Linq; using System.Text.Json; @@ -16,8 +17,11 @@ public static partial class Snippet { public static class New { - public static ValueExpression ArgumentOutOfRangeException(EnumProvider enumType, ParameterProvider valueParameter) - => Instance(typeof(ArgumentOutOfRangeException), Nameof(valueParameter), valueParameter, Literal($"Unknown {enumType.Name} value.")); + public static ValueExpression ArgumentOutOfRangeException(TypeProvider provider, ParameterProvider valueParameter) + { + Debug.Assert(provider.IsEnum); + return Instance(typeof(ArgumentOutOfRangeException), Nameof(valueParameter), valueParameter, Literal($"Unknown {provider.Name} value.")); + } public static ValueExpression ArgumentOutOfRangeException(ValueExpression valueParameter, string message, bool wrapInNameOf = true) => Instance(typeof(ArgumentOutOfRangeException), wrapInNameOf ? Nameof(valueParameter) : valueParameter, Literal(message)); diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/TypeFactory.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/TypeFactory.cs index e9b876723f..d26cef38c5 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/TypeFactory.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/src/TypeFactory.cs @@ -234,15 +234,6 @@ public IReadOnlyList CreateSerializations(InputType inputType) protected virtual IReadOnlyList CreateSerializationsCore(InputType inputType) { - if (inputType is InputEnumType enumType) - { - var provider = CreateEnum(enumType); - if (provider is EnumProvider { IsExtensible: false } enumProvider) - { - return [new FixedEnumSerializationProvider(enumProvider)]; - } - } - return []; } } diff --git a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/Providers/EnumProviderTests.cs b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/Providers/EnumProviderTests.cs index d0c906d80d..e0b1fee4d5 100644 --- a/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/Providers/EnumProviderTests.cs +++ b/packages/http-client-csharp/generator/Microsoft.Generator.CSharp/test/Providers/EnumProviderTests.cs @@ -35,26 +35,6 @@ public void BuildEnumType_ValidateIntBasedFixedEnum() var value2 = fields[1].InitializationValue as LiteralExpression; Assert.IsNotNull(value2); Assert.AreEqual(2, value2?.Literal); - - // int based fixed enum does not have serialization method therefore we only have one method - var serialization = enumType.SerializationProviders.FirstOrDefault(); - Assert.IsNotNull(serialization); - Assert.AreEqual(1, serialization?.Methods.Count); - - // validate the expression is working fine - using var writer = new CodeWriter(); - var enumVar = new VariableExpression(enumType.Type, new TestCodeWriterDeclaration("e")); - enumType.ToSerial(enumVar).Write(writer); - writer.WriteLine(); - enumType.ToEnum(Snippet.Literal(1)).Write(writer); - - var result = writer.ToString(false); - var builder = new StringBuilder(); - builder.Append($"((int)e)").Append(NewLine) - .Append($"1.ToMockInputEnum()"); - var expected = builder.ToString(); - - Assert.AreEqual(expected, result); } // Validates the float based fixed enum @@ -73,26 +53,6 @@ public void BuildEnumType_ValidateFloatBasedFixedEnum() // non-int based enum does not initialization values. Assert.IsNull(fields[0].InitializationValue); Assert.IsNull(fields[1].InitializationValue); - - // int float fixed enum has serialization method and deserialization method therefore we only have two methods - var serialization = enumType.SerializationProviders.FirstOrDefault(); - Assert.IsNotNull(serialization); - Assert.AreEqual(2, serialization?.Methods.Count); - - // validate the expression is working fine - using var writer = new CodeWriter(); - var enumVar = new VariableExpression(enumType.Type, new TestCodeWriterDeclaration("e")); - enumType.ToSerial(enumVar).Write(writer); - writer.WriteLine(); - enumType.ToEnum(Snippet.Literal(1f)).Write(writer); - - var result = writer.ToString(false); - var builder = new StringBuilder(); - builder.Append($"e.ToSerialSingle()").Append(NewLine) - .Append($"1F.ToMockInputEnum()"); - var expected = builder.ToString(); - - Assert.AreEqual(expected, result); } // Validates the string based fixed enum @@ -111,26 +71,6 @@ public void BuildEnumType_ValidateStringBasedFixedEnum() // non-int based enum does not initialization values. Assert.IsNull(fields[0].InitializationValue); Assert.IsNull(fields[1].InitializationValue); - - // int float fixed enum has serialization method and deserialization method therefore we only have two methods - var serialization = enumType.SerializationProviders.FirstOrDefault(); - Assert.IsNotNull(serialization); - Assert.AreEqual(2, serialization?.Methods.Count); - - // validate the expression is working fine - using var writer = new CodeWriter(); - var enumVar = new VariableExpression(enumType.Type, new TestCodeWriterDeclaration("e")); - enumType.ToSerial(enumVar).Write(writer); - writer.WriteLine(); - enumType.ToEnum(Snippet.Literal("1")).Write(writer); - - var result = writer.ToString(false); - var builder = new StringBuilder(); - builder.Append($"e.ToSerialString()").Append(NewLine) - .Append($"\"1\".ToMockInputEnum()"); - var expected = builder.ToString(); - - Assert.AreEqual(expected, result); } // Validates the int based extensible enum @@ -169,25 +109,6 @@ public void BuildEnumType_ValidateIntBasedExtensibleEnum() Assert.IsInstanceOf(properties[1].Body); var propertyValue2 = (properties[1].Body as AutoPropertyBody)?.InitializationExpression; Assert.IsNotNull(propertyValue2); - - // extensible enums do not have serialization - var serialization = enumType.SerializationProviders.FirstOrDefault(); - Assert.IsNull(serialization); - - // validate the expression is working fine - using var writer = new CodeWriter(); - var enumVar = new VariableExpression(enumType.Type, new TestCodeWriterDeclaration("e")); - enumType.ToSerial(enumVar).Write(writer); - writer.WriteLine(); - enumType.ToEnum(Snippet.Literal(1)).Write(writer); - - var result = writer.ToString(false); - var builder = new StringBuilder(); - builder.Append($"e.ToSerialInt32()").Append(NewLine) - .Append($"new global::Sample.Models.MockInputEnum(1)"); - var expected = builder.ToString(); - - Assert.AreEqual(expected, result); } // Validates the float based extensible enum @@ -226,25 +147,6 @@ public void BuildEnumType_ValidateFloatBasedExtensibleEnum() Assert.IsInstanceOf(properties[1].Body); var propertyValue2 = (properties[1].Body as AutoPropertyBody)?.InitializationExpression; Assert.IsNotNull(propertyValue2); - - // extensible enums do not have serialization - var serialization = enumType.SerializationProviders.FirstOrDefault(); - Assert.IsNull(serialization); - - // validate the expression is working fine - using var writer = new CodeWriter(); - var enumVar = new VariableExpression(enumType.Type, new TestCodeWriterDeclaration("e")); - enumType.ToSerial(enumVar).Write(writer); - writer.WriteLine(); - enumType.ToEnum(Snippet.Literal(1f)).Write(writer); - - var result = writer.ToString(false); - var builder = new StringBuilder(); - builder.Append($"e.ToSerialSingle()").Append(NewLine) - .Append($"new global::Sample.Models.MockInputEnum(1F)"); - var expected = builder.ToString(); - - Assert.AreEqual(expected, result); } // Validates the string based extensible enum @@ -283,25 +185,6 @@ public void BuildEnumType_ValidateStringBasedExtensibleEnum() Assert.IsInstanceOf(properties[1].Body); var propertyValue2 = (properties[1].Body as AutoPropertyBody)?.InitializationExpression; Assert.IsNotNull(propertyValue2); - - // extensible enums do not have serialization - var serialization = enumType.SerializationProviders.FirstOrDefault(); - Assert.IsNull(serialization); - - // validate the expression is working fine - using var writer = new CodeWriter(); - var enumVar = new VariableExpression(enumType.Type, new TestCodeWriterDeclaration("e")); - enumType.ToSerial(enumVar).Write(writer); - writer.WriteLine(); - enumType.ToEnum(Snippet.Literal("1")).Write(writer); - - var result = writer.ToString(false); - var builder = new StringBuilder(); - builder.Append($"e.ToString()").Append(NewLine) - .Append($"new global::Sample.Models.MockInputEnum(\"1\")"); - var expected = builder.ToString(); - - Assert.AreEqual(expected, result); } } } diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestOptionalLiteralFloat.Serialization.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestOptionalLiteralFloat.Serialization.cs new file mode 100644 index 0000000000..febd945df2 --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestOptionalLiteralFloat.Serialization.cs @@ -0,0 +1,12 @@ +// + +#nullable disable + +namespace UnbrandedTypeSpec.Models +{ + /// + public readonly partial struct AnonymousBodyRequestOptionalLiteralFloat + { + internal float ToSerialSingle() => _value; + } +} diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestOptionalLiteralFloat.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestOptionalLiteralFloat.cs index 72158746d5..11c5b3d662 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestOptionalLiteralFloat.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestOptionalLiteralFloat.cs @@ -51,7 +51,5 @@ public AnonymousBodyRequestOptionalLiteralFloat(float value) /// public override string ToString() => _value.ToString(CultureInfo.InvariantCulture); - - internal float ToSerialSingle() => _value; } } diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestOptionalLiteralInt.Serialization.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestOptionalLiteralInt.Serialization.cs new file mode 100644 index 0000000000..7c4a796aff --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestOptionalLiteralInt.Serialization.cs @@ -0,0 +1,12 @@ +// + +#nullable disable + +namespace UnbrandedTypeSpec.Models +{ + /// + public readonly partial struct AnonymousBodyRequestOptionalLiteralInt + { + internal int ToSerialInt32() => _value; + } +} diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestOptionalLiteralInt.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestOptionalLiteralInt.cs index 0eb1341eb5..776242170f 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestOptionalLiteralInt.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestOptionalLiteralInt.cs @@ -51,7 +51,5 @@ public AnonymousBodyRequestOptionalLiteralInt(int value) /// public override string ToString() => _value.ToString(CultureInfo.InvariantCulture); - - internal int ToSerialInt32() => _value; } } diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestRequiredLiteralFloat.Serialization.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestRequiredLiteralFloat.Serialization.cs new file mode 100644 index 0000000000..66d470aef9 --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestRequiredLiteralFloat.Serialization.cs @@ -0,0 +1,12 @@ +// + +#nullable disable + +namespace UnbrandedTypeSpec.Models +{ + /// + public readonly partial struct AnonymousBodyRequestRequiredLiteralFloat + { + internal float ToSerialSingle() => _value; + } +} diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestRequiredLiteralFloat.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestRequiredLiteralFloat.cs index cbdad0a478..bcbcfee230 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestRequiredLiteralFloat.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestRequiredLiteralFloat.cs @@ -51,7 +51,5 @@ public AnonymousBodyRequestRequiredLiteralFloat(float value) /// public override string ToString() => _value.ToString(CultureInfo.InvariantCulture); - - internal float ToSerialSingle() => _value; } } diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestRequiredLiteralInt.Serialization.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestRequiredLiteralInt.Serialization.cs new file mode 100644 index 0000000000..9d0e39342d --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestRequiredLiteralInt.Serialization.cs @@ -0,0 +1,12 @@ +// + +#nullable disable + +namespace UnbrandedTypeSpec.Models +{ + /// + public readonly partial struct AnonymousBodyRequestRequiredLiteralInt + { + internal int ToSerialInt32() => _value; + } +} diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestRequiredLiteralInt.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestRequiredLiteralInt.cs index ddc2cbd76c..bdf57f3e45 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestRequiredLiteralInt.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/AnonymousBodyRequestRequiredLiteralInt.cs @@ -51,7 +51,5 @@ public AnonymousBodyRequestRequiredLiteralInt(int value) /// public override string ToString() => _value.ToString(CultureInfo.InvariantCulture); - - internal int ToSerialInt32() => _value; } } diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatExtensibleEnum.Serialization.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatExtensibleEnum.Serialization.cs new file mode 100644 index 0000000000..956cb7a2dc --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatExtensibleEnum.Serialization.cs @@ -0,0 +1,12 @@ +// + +#nullable disable + +namespace UnbrandedTypeSpec.Models +{ + /// + public readonly partial struct FloatExtensibleEnum + { + internal float ToSerialSingle() => _value; + } +} diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatExtensibleEnum.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatExtensibleEnum.cs index a2834b06ed..fca2c0da28 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatExtensibleEnum.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatExtensibleEnum.cs @@ -58,7 +58,5 @@ public FloatExtensibleEnum(float value) /// public override string ToString() => _value.ToString(CultureInfo.InvariantCulture); - - internal float ToSerialSingle() => _value; } } diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatExtensibleEnumWithIntValue.Serialization.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatExtensibleEnumWithIntValue.Serialization.cs new file mode 100644 index 0000000000..88300214e2 --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatExtensibleEnumWithIntValue.Serialization.cs @@ -0,0 +1,12 @@ +// + +#nullable disable + +namespace UnbrandedTypeSpec.Models +{ + /// + public readonly partial struct FloatExtensibleEnumWithIntValue + { + internal float ToSerialSingle() => _value; + } +} diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatExtensibleEnumWithIntValue.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatExtensibleEnumWithIntValue.cs index f84dcb4ccb..4269f9144c 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatExtensibleEnumWithIntValue.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatExtensibleEnumWithIntValue.cs @@ -58,7 +58,5 @@ public FloatExtensibleEnumWithIntValue(float value) /// public override string ToString() => _value.ToString(CultureInfo.InvariantCulture); - - internal float ToSerialSingle() => _value; } } diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatFixedEnumExtensions.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatFixedEnum.Serialization.cs similarity index 100% rename from packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatFixedEnumExtensions.cs rename to packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatFixedEnum.Serialization.cs diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatFixedEnumWithIntValueExtensions.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatFixedEnumWithIntValue.Serialization.cs similarity index 100% rename from packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatFixedEnumWithIntValueExtensions.cs rename to packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/FloatFixedEnumWithIntValue.Serialization.cs diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/IntExtensibleEnum.Serialization.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/IntExtensibleEnum.Serialization.cs new file mode 100644 index 0000000000..5f92623cca --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/IntExtensibleEnum.Serialization.cs @@ -0,0 +1,12 @@ +// + +#nullable disable + +namespace UnbrandedTypeSpec.Models +{ + /// + public readonly partial struct IntExtensibleEnum + { + internal int ToSerialInt32() => _value; + } +} diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/IntExtensibleEnum.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/IntExtensibleEnum.cs index 33b8096b0a..172c9fc2bd 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/IntExtensibleEnum.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/IntExtensibleEnum.cs @@ -58,7 +58,5 @@ public IntExtensibleEnum(int value) /// public override string ToString() => _value.ToString(CultureInfo.InvariantCulture); - - internal int ToSerialInt32() => _value; } } diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/IntFixedEnumExtensions.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/IntFixedEnum.Serialization.cs similarity index 100% rename from packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/IntFixedEnumExtensions.cs rename to packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/IntFixedEnum.Serialization.cs diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/StringFixedEnumExtensions.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/StringFixedEnum.Serialization.cs similarity index 100% rename from packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/StringFixedEnumExtensions.cs rename to packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/StringFixedEnum.Serialization.cs diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingOptionalLiteralFloat.Serialization.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingOptionalLiteralFloat.Serialization.cs new file mode 100644 index 0000000000..d9239e6290 --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingOptionalLiteralFloat.Serialization.cs @@ -0,0 +1,12 @@ +// + +#nullable disable + +namespace UnbrandedTypeSpec.Models +{ + /// + public readonly partial struct ThingOptionalLiteralFloat + { + internal float ToSerialSingle() => _value; + } +} diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingOptionalLiteralFloat.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingOptionalLiteralFloat.cs index 07d545a9fa..ff2a824901 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingOptionalLiteralFloat.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingOptionalLiteralFloat.cs @@ -51,7 +51,5 @@ public ThingOptionalLiteralFloat(float value) /// public override string ToString() => _value.ToString(CultureInfo.InvariantCulture); - - internal float ToSerialSingle() => _value; } } diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingOptionalLiteralInt.Serialization.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingOptionalLiteralInt.Serialization.cs new file mode 100644 index 0000000000..e498f97ed1 --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingOptionalLiteralInt.Serialization.cs @@ -0,0 +1,12 @@ +// + +#nullable disable + +namespace UnbrandedTypeSpec.Models +{ + /// + public readonly partial struct ThingOptionalLiteralInt + { + internal int ToSerialInt32() => _value; + } +} diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingOptionalLiteralInt.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingOptionalLiteralInt.cs index 0bb5abbb7c..705a41a01d 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingOptionalLiteralInt.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingOptionalLiteralInt.cs @@ -51,7 +51,5 @@ public ThingOptionalLiteralInt(int value) /// public override string ToString() => _value.ToString(CultureInfo.InvariantCulture); - - internal int ToSerialInt32() => _value; } } diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingRequiredLiteralFloat.Serialization.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingRequiredLiteralFloat.Serialization.cs new file mode 100644 index 0000000000..c2b1deae37 --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingRequiredLiteralFloat.Serialization.cs @@ -0,0 +1,12 @@ +// + +#nullable disable + +namespace UnbrandedTypeSpec.Models +{ + /// + public readonly partial struct ThingRequiredLiteralFloat + { + internal float ToSerialSingle() => _value; + } +} diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingRequiredLiteralFloat.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingRequiredLiteralFloat.cs index 8b0713c99e..bbd25a140b 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingRequiredLiteralFloat.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingRequiredLiteralFloat.cs @@ -51,7 +51,5 @@ public ThingRequiredLiteralFloat(float value) /// public override string ToString() => _value.ToString(CultureInfo.InvariantCulture); - - internal float ToSerialSingle() => _value; } } diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingRequiredLiteralInt.Serialization.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingRequiredLiteralInt.Serialization.cs new file mode 100644 index 0000000000..d0e1af2a01 --- /dev/null +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingRequiredLiteralInt.Serialization.cs @@ -0,0 +1,12 @@ +// + +#nullable disable + +namespace UnbrandedTypeSpec.Models +{ + /// + public readonly partial struct ThingRequiredLiteralInt + { + internal int ToSerialInt32() => _value; + } +} diff --git a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingRequiredLiteralInt.cs b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingRequiredLiteralInt.cs index 2a067b2625..ade27db4a9 100644 --- a/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingRequiredLiteralInt.cs +++ b/packages/http-client-csharp/generator/TestProjects/Local/Unbranded-TypeSpec/src/Generated/Models/ThingRequiredLiteralInt.cs @@ -51,7 +51,5 @@ public ThingRequiredLiteralInt(int value) /// public override string ToString() => _value.ToString(CultureInfo.InvariantCulture); - - internal int ToSerialInt32() => _value; } }