diff --git a/samples/Azure.Management.Storage/Azure.Management.Storage/Generated/Models/IPRule.cs b/samples/Azure.Management.Storage/Azure.Management.Storage/Generated/Models/IPRule.cs index b5a0006f..5c6be489 100644 --- a/samples/Azure.Management.Storage/Azure.Management.Storage/Generated/Models/IPRule.cs +++ b/samples/Azure.Management.Storage/Azure.Management.Storage/Generated/Models/IPRule.cs @@ -22,6 +22,7 @@ namespace Azure.Management.Storage.Models } IPAddressOrRange = iPAddressOrRange; + Action = "Allow"; } /// Initializes a new instance of IPRule. diff --git a/samples/Azure.Management.Storage/Azure.Management.Storage/Generated/Models/VirtualNetworkRule.cs b/samples/Azure.Management.Storage/Azure.Management.Storage/Generated/Models/VirtualNetworkRule.cs index a544745f..d09d1cd3 100644 --- a/samples/Azure.Management.Storage/Azure.Management.Storage/Generated/Models/VirtualNetworkRule.cs +++ b/samples/Azure.Management.Storage/Azure.Management.Storage/Generated/Models/VirtualNetworkRule.cs @@ -22,6 +22,7 @@ namespace Azure.Management.Storage.Models } VirtualNetworkResourceId = virtualNetworkResourceId; + Action = "Allow"; } /// Initializes a new instance of VirtualNetworkRule. diff --git a/src/AutoRest.CSharp.V3/Output/Models/Types/ObjectType.cs b/src/AutoRest.CSharp.V3/Output/Models/Types/ObjectType.cs index 02b8fbd4..e4dc7b24 100644 --- a/src/AutoRest.CSharp.V3/Output/Models/Types/ObjectType.cs +++ b/src/AutoRest.CSharp.V3/Output/Models/Types/ObjectType.cs @@ -98,23 +98,34 @@ namespace AutoRest.CSharp.V3.Output.Models.Types private IEnumerable BuildConstructors() { - List serializationConstructorParameters = new List(); - List defaultCtorParameters = new List(); - List initializers = new List(); - List defaultCtorInitializers = new List(); + var initializationCtor = BuildInitializationConstructor(); + var serializationCtor = BuildSerializationConstructor(); - ObjectTypeConstructor? baseCtor = null; + yield return initializationCtor; + + // Skip serialization ctor if they are the same + if (!initializationCtor.Parameters + .Select(p => p.Type) + .SequenceEqual(serializationCtor.Parameters.Select(p => p.Type))) + { + yield return serializationCtor; + } + } + + private ObjectTypeConstructor BuildSerializationConstructor() + { + bool ownsDiscriminatorProperty = false; + + List serializationConstructorParameters = new List(); + List serializationInitializers = new List(); ObjectTypeConstructor? baseSerializationCtor = null; + if (Inherits != null && !Inherits.IsFrameworkType && Inherits.Implementation is ObjectType objectType) { - baseCtor = objectType.Constructors.First(); baseSerializationCtor = objectType.Constructors.Last(); - - defaultCtorParameters.AddRange(baseCtor.Parameters); serializationConstructorParameters.AddRange(baseSerializationCtor.Parameters); } - bool ownsDiscriminatorProperty = false; foreach (var property in Properties) { var deserializationParameter = new Parameter( @@ -125,79 +136,13 @@ namespace AutoRest.CSharp.V3.Output.Models.Types false ); - bool isDiscriminatorProperty = false; - ReferenceOrConstant? fallbackValue = null; - if (property == Discriminator?.Property) - { - isDiscriminatorProperty = true; - ownsDiscriminatorProperty = true; - if (Discriminator.Value != null) - { - fallbackValue = BuilderHelpers.StringConstant(Discriminator.Value); - } - } - else - { - var initializeWithType = property.InitializeWithType; - fallbackValue = initializeWithType != null ? - Constant.NewInstanceOf(initializeWithType) : (ReferenceOrConstant?) null; - } + ownsDiscriminatorProperty |= property == Discriminator?.Property; serializationConstructorParameters.Add(deserializationParameter); - initializers.Add(new ObjectPropertyInitializer(property, deserializationParameter, fallbackValue)); - - // Only required properties that are not discriminators go into default ctor - if (isDiscriminatorProperty) - { - continue; - } - - // For structs all properties become required - if (!IsStruct && property.SchemaProperty?.Required != true) - { - // Initialize properties even if they are not required - if (fallbackValue != null) - { - defaultCtorInitializers.Add(new ObjectPropertyInitializer(property, fallbackValue.Value)); - } - continue; - } - - // Turn constants into initializers - if (property.SchemaProperty?.Schema is ConstantSchema constantSchema) - { - var constantValue = constantSchema.Value.Value != null ? - BuilderHelpers.ParseConstant(constantSchema.Value.Value, property.Declaration.Type) : - Constant.NewInstanceOf(property.Declaration.Type); - - defaultCtorInitializers.Add(new ObjectPropertyInitializer( - property, - constantValue)); - - continue; - } - - Constant? defaultValue = null; - - if (property.SchemaProperty?.ClientDefaultValue is object defaultValueObject) - { - defaultValue = BuilderHelpers.ParseConstant(defaultValueObject, property.Declaration.Type); - } - - var defaultCtorParameter = new Parameter( - property.Declaration.Name.ToVariableName(), - property.Description, - TypeFactory.GetInputType(property.Declaration.Type), - defaultValue, - true - ); - - defaultCtorParameters.Add(defaultCtorParameter); - defaultCtorInitializers.Add(new ObjectPropertyInitializer(property, defaultCtorParameter)); + serializationInitializers.Add(new ObjectPropertyInitializer(property, deserializationParameter, GetPropertyDefaultValue(property))); } - if (Discriminator != null) { // Add discriminator initializer to constructor at every level of hierarchy @@ -207,12 +152,102 @@ namespace AutoRest.CSharp.V3.Output.Models.Types var discriminatorParameter = baseSerializationCtor.FindParameterByInitializedProperty(Discriminator.Property); Debug.Assert(discriminatorParameter != null); - initializers.Add(new ObjectPropertyInitializer(Discriminator.Property, discriminatorParameter, BuilderHelpers.StringConstant(Discriminator.Value))); + serializationInitializers.Add(new ObjectPropertyInitializer(Discriminator.Property, discriminatorParameter, BuilderHelpers.StringConstant(Discriminator.Value))); } + } + + return new ObjectTypeConstructor( + BuilderHelpers.CreateMemberDeclaration(Type.Name, Type, "internal", null, _typeFactory), + serializationConstructorParameters.ToArray(), + serializationInitializers.ToArray(), + baseSerializationCtor + ); + } + + private ReferenceOrConstant? GetPropertyDefaultValue(ObjectTypeProperty property) + { + if (property == Discriminator?.Property) + { + if (Discriminator.Value != null) + { + return BuilderHelpers.StringConstant(Discriminator.Value); + } + } + else + { + var initializeWithType = property.InitializeWithType; + return initializeWithType != null ? Constant.NewInstanceOf(initializeWithType) : (ReferenceOrConstant?) null; + } + + return null; + } + + private ObjectTypeConstructor BuildInitializationConstructor() + { + List defaultCtorParameters = new List(); + List defaultCtorInitializers = new List(); + + ObjectTypeConstructor? baseCtor = null; + if (Inherits != null && !Inherits.IsFrameworkType && Inherits.Implementation is ObjectType objectType) + { + baseCtor = objectType.Constructors.First(); + defaultCtorParameters.AddRange(baseCtor.Parameters); + } + + foreach (var property in Properties) + { + // Only required properties that are not discriminators go into default ctor + if (property == Discriminator?.Property) + { + continue; + } + + ReferenceOrConstant? initializationValue; + + if (property.SchemaProperty?.Schema is ConstantSchema constantSchema) + { + // Turn constants into initializers + initializationValue = constantSchema.Value.Value != null ? + BuilderHelpers.ParseConstant(constantSchema.Value.Value, property.Declaration.Type) : + Constant.NewInstanceOf(property.Declaration.Type); + } + else if (IsStruct || property.SchemaProperty?.Required == true) + { + // For structs all properties become required + Constant? defaultParameterValue = null; + if (property.SchemaProperty?.ClientDefaultValue is object defaultValueObject) + { + defaultParameterValue = BuilderHelpers.ParseConstant(defaultValueObject, property.Declaration.Type); + } + + var defaultCtorParameter = new Parameter( + property.Declaration.Name.ToVariableName(), + property.Description, + TypeFactory.GetInputType(property.Declaration.Type), + defaultParameterValue, + true + ); + + defaultCtorParameters.Add(defaultCtorParameter); + initializationValue = defaultCtorParameter; + } + else + { + initializationValue = GetPropertyDefaultValue(property); + } + + if (initializationValue != null) + { + defaultCtorInitializers.Add(new ObjectPropertyInitializer(property, initializationValue.Value)); + } + } + + if (Discriminator != null) + { defaultCtorInitializers.Add(new ObjectPropertyInitializer(Discriminator.Property, BuilderHelpers.StringConstant(Discriminator.Value))); } - yield return new ObjectTypeConstructor( + return new ObjectTypeConstructor( BuilderHelpers.CreateMemberDeclaration( Type.Name, Type, @@ -223,19 +258,6 @@ namespace AutoRest.CSharp.V3.Output.Models.Types defaultCtorParameters.ToArray(), defaultCtorInitializers.ToArray(), baseCtor); - - // Skip serialization ctor if they are the same - if (!defaultCtorParameters - .Select(p => p.Type) - .SequenceEqual(serializationConstructorParameters.Select(p => p.Type))) - { - yield return new ObjectTypeConstructor( - BuilderHelpers.CreateMemberDeclaration(Type.Name, Type, "internal", null, _typeFactory), - serializationConstructorParameters.ToArray(), - initializers.ToArray(), - baseSerializationCtor - ); - } } public ObjectTypeDiscriminator? Discriminator => _discriminator ??= BuildDiscriminator(); diff --git a/test/AutoRest.TestServer.Tests/ModelShapeTests.cs b/test/AutoRest.TestServer.Tests/ModelShapeTests.cs index 2844350f..008bca83 100644 --- a/test/AutoRest.TestServer.Tests/ModelShapeTests.cs +++ b/test/AutoRest.TestServer.Tests/ModelShapeTests.cs @@ -1,6 +1,7 @@ // Copyright (c) Microsoft Corporation. All rights reserved. // Licensed under the MIT License. +using System.Linq; using System.Reflection; using ModelShapes.Models; using NUnit.Framework; diff --git a/test/TestServerProjects/model-flattening/Generated/Models/SimpleProduct.cs b/test/TestServerProjects/model-flattening/Generated/Models/SimpleProduct.cs index f3dbbc6e..5cc5af06 100644 --- a/test/TestServerProjects/model-flattening/Generated/Models/SimpleProduct.cs +++ b/test/TestServerProjects/model-flattening/Generated/Models/SimpleProduct.cs @@ -20,6 +20,8 @@ namespace model_flattening.Models { throw new ArgumentNullException(nameof(productId)); } + + Capacity = "Large"; } /// Initializes a new instance of SimpleProduct. diff --git a/test/TestServerProjects/validation/Generated/Models/Product.cs b/test/TestServerProjects/validation/Generated/Models/Product.cs index 0078cde0..559da5da 100644 --- a/test/TestServerProjects/validation/Generated/Models/Product.cs +++ b/test/TestServerProjects/validation/Generated/Models/Product.cs @@ -31,6 +31,7 @@ namespace validation.Models ConstChild = constChild; ConstInt = 0; ConstString = "constant"; + ConstStringAsEnum = "constant_string_as_enum"; } /// Initializes a new instance of Product.