Untangle constructor generation a bit (#716)

This commit is contained in:
Pavel Krymets 2020-04-30 10:03:02 -07:00 коммит произвёл GitHub
Родитель 4360b306dd
Коммит 0bacd527e6
Не найден ключ, соответствующий данной подписи
Идентификатор ключа GPG: 4AEE18F83AFDEB23
6 изменённых файлов: 120 добавлений и 92 удалений

Просмотреть файл

@ -22,6 +22,7 @@ namespace Azure.Management.Storage.Models
}
IPAddressOrRange = iPAddressOrRange;
Action = "Allow";
}
/// <summary> Initializes a new instance of IPRule. </summary>

Просмотреть файл

@ -22,6 +22,7 @@ namespace Azure.Management.Storage.Models
}
VirtualNetworkResourceId = virtualNetworkResourceId;
Action = "Allow";
}
/// <summary> Initializes a new instance of VirtualNetworkRule. </summary>

Просмотреть файл

@ -98,23 +98,34 @@ namespace AutoRest.CSharp.V3.Output.Models.Types
private IEnumerable<ObjectTypeConstructor> BuildConstructors()
{
List<Parameter> serializationConstructorParameters = new List<Parameter>();
List<Parameter> defaultCtorParameters = new List<Parameter>();
List<ObjectPropertyInitializer> initializers = new List<ObjectPropertyInitializer>();
List<ObjectPropertyInitializer> defaultCtorInitializers = new List<ObjectPropertyInitializer>();
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<Parameter> serializationConstructorParameters = new List<Parameter>();
List<ObjectPropertyInitializer> serializationInitializers = new List<ObjectPropertyInitializer>();
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<Parameter> defaultCtorParameters = new List<Parameter>();
List<ObjectPropertyInitializer> defaultCtorInitializers = new List<ObjectPropertyInitializer>();
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();

Просмотреть файл

@ -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;

Просмотреть файл

@ -20,6 +20,8 @@ namespace model_flattening.Models
{
throw new ArgumentNullException(nameof(productId));
}
Capacity = "Large";
}
/// <summary> Initializes a new instance of SimpleProduct. </summary>

Просмотреть файл

@ -31,6 +31,7 @@ namespace validation.Models
ConstChild = constChild;
ConstInt = 0;
ConstString = "constant";
ConstStringAsEnum = "constant_string_as_enum";
}
/// <summary> Initializes a new instance of Product. </summary>