Skip to content

remove another constrait on model factory #3996

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
18 commits
Select commit Hold shift + click to select a range
863295f
remove another constrait on model factory
ArcturusZhang Dec 1, 2023
bcbe853
Merge branch 'feature/v3' into remove-extra-constraint-of-model-factory
ArcturusZhang Dec 1, 2023
17b8a63
Regenerate all code (any successful run even without change will have…
actions-user Dec 1, 2023
45d9073
fix the discriminator issue
ArcturusZhang Dec 2, 2023
72e9e66
Regenerate all code (any successful run even without change will have…
actions-user Dec 2, 2023
6acf3cd
Merge branch 'feature/v3' into remove-extra-constraint-of-model-factory
ArcturusZhang Dec 7, 2023
f4a2c0b
Merge branch 'feature/v3' into remove-extra-constraint-of-model-factory
ArcturusZhang Dec 8, 2023
860ec13
refactor
ArcturusZhang Dec 8, 2023
38b22c5
Merge remote-tracking branch 'origin/feature/v3' into remove-extra-co…
ArcturusZhang Dec 8, 2023
466584f
Merge remote-tracking branch 'origin/feature/v3' into remove-extra-co…
ArcturusZhang Dec 11, 2023
e91d45a
Merge branch 'feature/v3' into remove-extra-constraint-of-model-factory
ArcturusZhang Dec 11, 2023
5c38599
fix after merge
ArcturusZhang Dec 11, 2023
c84192b
Merge branch 'feature/v3' into remove-extra-constraint-of-model-factory
ArcturusZhang Dec 12, 2023
d1aafd7
Merge branch 'feature/v3' into remove-extra-constraint-of-model-factory
ArcturusZhang Dec 13, 2023
a3ac8b9
fix the test cases
ArcturusZhang Dec 13, 2023
1a4c2c5
add a cast to ensure we never have ambigious calls because of null or…
ArcturusZhang Dec 13, 2023
520e5c3
Merge branch 'feature/v3' into remove-extra-constraint-of-model-factory
ArcturusZhang Dec 13, 2023
36e6ad9
Merge branch 'feature/v3' into remove-extra-constraint-of-model-factory
ArcturusZhang Dec 14, 2023
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -20,32 +20,47 @@
using AutoRest.CSharp.Utilities;
using Azure.Core.Expressions.DataFactory;
using Azure.ResourceManager.Models;
using Microsoft.CodeAnalysis;
using static AutoRest.CSharp.Common.Output.Models.Snippets;

namespace AutoRest.CSharp.Output.Models.Types
{
internal sealed class ModelFactoryTypeProvider : TypeProvider
{
private static readonly IReadOnlySet<MethodInfo> ExistingModelFactoryMethods;

static ModelFactoryTypeProvider()
{
var methods = new HashSet<MethodInfo>();
foreach (var method in typeof(ResourceManagerModelFactory).GetMethods(BindingFlags.Static | BindingFlags.Public))
{
methods.Add(method);
}
foreach (var method in typeof(DataFactoryModelFactory).GetMethods(BindingFlags.Static | BindingFlags.Public))
{
methods.Add(method);
}

ExistingModelFactoryMethods = methods;
}

protected override string DefaultName { get; }
protected override string DefaultAccessibility { get; }

private IEnumerable<Method>? _methods;
public IEnumerable<Method> Methods => _methods ??= Models.Select(CreateMethod);
public IEnumerable<Method> Methods => _methods ??= _models.Select(CreateMethod);

public IEnumerable<SerializableObjectType> Models { get; }
private readonly IEnumerable<SerializableObjectType> _models;

public FormattableString Description => $"Model factory for models.";

internal string FullName => $"{Type.Namespace}.{Type.Name}";

private ModelFactoryTypeProvider(IEnumerable<SerializableObjectType> objectTypes, string defaultClientName, string defaultNamespace, SourceInputModel? sourceInputModel) : base(defaultNamespace, sourceInputModel)
{
Models = objectTypes;

_models = objectTypes;
DefaultName = $"{defaultClientName}ModelFactory".ToCleanName();
DefaultAccessibility = "public";
ExistingModelFactoryMethods = typeof(ResourceManagerModelFactory).GetMethods(BindingFlags.Static | BindingFlags.Public).ToHashSet();
ExistingModelFactoryMethods.UnionWith(typeof(DataFactoryModelFactory).GetMethods(BindingFlags.Static | BindingFlags.Public).ToHashSet());
}

public static ModelFactoryTypeProvider? TryCreate(IEnumerable<TypeProvider> models, SourceInputModel? sourceInputModel)
Expand Down Expand Up @@ -86,9 +101,7 @@ private static string GetDefaultNamespace()
return Configuration.Namespace;
}

public HashSet<MethodInfo> ExistingModelFactoryMethods { get; }

private ValueExpression BuildPropertyAssignmentExpression(Parameter parameter, ObjectTypeProperty property)
private static ValueExpression BuildPropertyAssignmentExpression(Parameter parameter, ObjectTypeProperty property)
{
ValueExpression p = parameter;
var propertyStack = property.BuildHierarchyStack();
Expand Down Expand Up @@ -154,7 +167,7 @@ private ValueExpression BuildPropertyAssignmentExpression(Parameter parameter, O
return result;
}

private Method CreateMethod(SerializableObjectType model)
private static Method CreateMethod(SerializableObjectType model)
{
var ctor = model.SerializationConstructor;
var ctorToCall = ctor;
Expand All @@ -173,13 +186,20 @@ private Method CreateMethod(SerializableObjectType model)
if (property == null)
{
// if the property is not found, in order not to introduce compilation errors, we need to add a `default` into the argument list
methodArguments.Add(new PositionalParameterReference(ctorParameter.Name, Default));
methodArguments.Add(new PositionalParameterReference(ctorParameter.Name, Default.CastTo(ctorParameter.Type)));
continue;
}

if (property.FlattenedProperty != null)
property = property.FlattenedProperty;

// for the parameter corresponding to non-public property, we just add default or null
if (property.Declaration.Accessibility != "public" && property != model.Discriminator?.Property)
{
methodArguments.Add(new PositionalParameterReference(ctorParameter.Name, ctorParameter.Type.IsValueType ? Default.CastTo(ctorParameter.Type) : Null.CastTo(ctorParameter.Type)));
continue;
}

var parameterName = property.Declaration.Name.ToVariableName();
var inputType = property.Declaration.Type;
Constant? overriddenDefaultValue = null;
Expand Down Expand Up @@ -263,12 +283,6 @@ private static bool RequiresModelFactory(SerializableObjectType model)
}

var properties = model.EnumerateHierarchy().SelectMany(obj => obj.Properties);
// we skip the models with internal properties when the internal property is neither a discriminator or safe flattened
if (properties.Any(p => p.Declaration.Accessibility != "public" && (model.Discriminator?.Property != p && p.FlattenedProperty == null)))
{
return false;
}

if (!properties.Any(p => p.IsReadOnly && !TypeFactory.IsReadWriteDictionary(p.ValueType) && !TypeFactory.IsReadWriteList(p.ValueType)))
{
return false;
Expand Down
3 changes: 1 addition & 2 deletions test/AutoRest.TestServer.Tests/TypeSchemaMappingTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -218,7 +218,6 @@ public void GuidPropertyDeserializedCorrectly()
[Test]
public void UriPropertyDeserializedCorrectly()
{
DateTime date = DateTime.UtcNow;
ModelWithUriProperty model = ModelWithUriProperty.DeserializeModelWithUriProperty(JsonDocument.Parse("{\"Uri\":\"http://localhost\"}").RootElement);

Assert.AreEqual("http://localhost/", model.Uri.AbsoluteUri);
Expand Down Expand Up @@ -263,7 +262,7 @@ public void ModelFactoryIsInternal()
[Test]
public void ModelFactoryPublicMethods()
{
TypeAsserts.TypeOnlyDeclaresThesePublicMethods(typeof(MainModelFactory), nameof(ModelWithGuidProperty), nameof(ModelWithAbstractModel));
TypeAsserts.TypeOnlyDeclaresThesePublicMethods(typeof(MainModelFactory), nameof(ModelWithGuidProperty), nameof(ModelWithAbstractModel), nameof(PublicModelWithInternalProperty));
}

[Test]
Expand Down

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.