Handle replacement properties (#4325)
Supports https://github.com/microsoft/typespec/issues/3981 These cadl ranch tests have models which use replacement properties in extended types that we need to handle.
This commit is contained in:
Родитель
93377fd7dd
Коммит
06c0bb5dca
|
@ -403,9 +403,9 @@ namespace Microsoft.Generator.CSharp.ClientModel.Providers
|
|||
null,
|
||||
[]),
|
||||
// return Volatile.Read(ref _cachedClient) ?? Interlocked.CompareExchange(ref _cachedClient, new Client(_pipeline, _keyCredential, _endpoint), null) ?? _cachedClient;
|
||||
Return(NullCoalescing(
|
||||
Static(typeof(Volatile)).Invoke(nameof(Volatile.Read), cachedClientFieldVar),
|
||||
NullCoalescing(interlockedCompareExchange, subClientInstance._clientCachingField))),
|
||||
Return(
|
||||
Static(typeof(Volatile)).Invoke(nameof(Volatile.Read), cachedClientFieldVar)
|
||||
.NullCoalesce(interlockedCompareExchange.NullCoalesce(subClientInstance._clientCachingField))),
|
||||
this);
|
||||
methods.Add(factoryMethod);
|
||||
}
|
||||
|
|
|
@ -408,7 +408,7 @@ namespace Microsoft.Generator.CSharp.ClientModel.Providers
|
|||
cases.Add(
|
||||
BuildWriteObjectValueSwitchCase(new CSharpType(typeof(IJsonModel<>), _t), "jsonModel", jsonModel => new MethodBodyStatement[]
|
||||
{
|
||||
jsonModel.Invoke(nameof(IJsonModel<object>.Write), writer, NullCoalescing(options, ModelSerializationExtensionsSnippets.Wire)).Terminate(),
|
||||
jsonModel.Invoke(nameof(IJsonModel<object>.Write), writer, options.NullCoalesce(ModelSerializationExtensionsSnippets.Wire)).Terminate(),
|
||||
Break
|
||||
}));
|
||||
cases.AddRange(new[]
|
||||
|
|
|
@ -184,9 +184,8 @@ namespace Microsoft.Generator.CSharp.ClientModel.Providers
|
|||
var interfaceType = param.Property!.WireInfo?.IsReadOnly == true
|
||||
? new CSharpType(typeof(IReadOnlyList<>), convenienceParam.Type.Arguments)
|
||||
: new CSharpType(typeof(IList<>), convenienceParam.Type.Arguments);
|
||||
expressions.Add(NullCoalescing(
|
||||
new AsExpression(convenienceParam.NullConditional().ToList(), interfaceType),
|
||||
New.Instance(convenienceParam.Type.PropertyInitializationType, [])));
|
||||
expressions.Add(new AsExpression(convenienceParam.NullConditional().ToList(), interfaceType)
|
||||
.NullCoalesce(New.Instance(convenienceParam.Type.PropertyInitializationType, [])));
|
||||
}
|
||||
else
|
||||
{
|
||||
|
|
|
@ -34,7 +34,7 @@ namespace Microsoft.Generator.CSharp.ClientModel.Snippets
|
|||
var changeTrackingType = collection.Type.Arguments.Count == 1
|
||||
? ClientModelPlugin.Instance.TypeFactory.ListInitializationType.MakeGenericType(collection.Type.Arguments)
|
||||
: ClientModelPlugin.Instance.TypeFactory.DictionaryInitializationType.MakeGenericType(collection.Type.Arguments);
|
||||
return NullCoalescing(collection, New.Instance(changeTrackingType));
|
||||
return collection.NullCoalesce(New.Instance(changeTrackingType));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -10,12 +10,12 @@ namespace Microsoft.Generator.CSharp.Expressions
|
|||
/// </summary>
|
||||
/// <param name="Variable">The variable that is being assigned.</param>
|
||||
/// <param name="Value">The value that <paramref name="Variable"/> is being assigned.</param>
|
||||
public sealed record AssignmentExpression(ValueExpression Variable, ValueExpression Value, bool NullCoalesce = false) : ValueExpression
|
||||
public sealed record AssignmentExpression(ValueExpression Variable, ValueExpression Value, bool UseNullCoalesce = false) : ValueExpression
|
||||
{
|
||||
internal override void Write(CodeWriter writer)
|
||||
{
|
||||
Variable.Write(writer);
|
||||
if (NullCoalesce)
|
||||
if (UseNullCoalesce)
|
||||
{
|
||||
writer.Append($" ??= ");
|
||||
}
|
||||
|
|
|
@ -120,6 +120,8 @@ namespace Microsoft.Generator.CSharp.Expressions
|
|||
|
||||
public AssignmentExpression Assign(ValueExpression value, bool nullCoalesce = false) => new AssignmentExpression(this, value, nullCoalesce);
|
||||
|
||||
public ValueExpression NullCoalesce(ValueExpression right) => new BinaryOperatorExpression("??", this, right);
|
||||
|
||||
public string ToDisplayString() => GetDebuggerDisplay();
|
||||
|
||||
private string GetDebuggerDisplay()
|
||||
|
|
|
@ -85,7 +85,7 @@ namespace Microsoft.Generator.CSharp.Providers
|
|||
{
|
||||
new IfStatement(value.NotEqual(Null))
|
||||
{
|
||||
ThrowArgumentException(NullCoalescing(message, Literal("Value must be null.")))
|
||||
ThrowArgumentException(message.NullCoalesce(Literal("Value must be null.")))
|
||||
}
|
||||
},
|
||||
this);
|
||||
|
|
|
@ -1,11 +1,9 @@
|
|||
// Copyright (c) Microsoft Corporation. All rights reserved.
|
||||
// Licensed under the MIT License.
|
||||
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.Generator.CSharp.Expressions;
|
||||
using Microsoft.Generator.CSharp.Primitives;
|
||||
using Microsoft.Generator.CSharp.Statements;
|
||||
using static Microsoft.Generator.CSharp.Snippets.ArgumentSnippets;
|
||||
|
||||
namespace Microsoft.Generator.CSharp.Providers
|
||||
{
|
||||
|
|
|
@ -114,7 +114,47 @@ namespace Microsoft.Generator.CSharp.Providers
|
|||
/// <returns>The list of <see cref="FieldProvider"/> for the model.</returns>
|
||||
protected override FieldProvider[] BuildFields()
|
||||
{
|
||||
return RawDataField != null ? [RawDataField] : [];
|
||||
List<FieldProvider> fields = [];
|
||||
if (RawDataField != null)
|
||||
{
|
||||
fields.Add(RawDataField);
|
||||
}
|
||||
foreach (var property in _inputModel.Properties)
|
||||
{
|
||||
if (property.IsDiscriminator)
|
||||
continue;
|
||||
|
||||
var derivedProperty = InputDerivedProperties.FirstOrDefault(p => p.Value.ContainsKey(property.Name)).Value?[property.Name];
|
||||
if (derivedProperty is not null)
|
||||
{
|
||||
if (!derivedProperty.Type.Equals(property.Type) || !DomainEqual(property, derivedProperty))
|
||||
{
|
||||
fields.Add(new FieldProvider(
|
||||
FieldModifiers.Private | FieldModifiers.Protected,
|
||||
CodeModelPlugin.Instance.TypeFactory.CreateCSharpType(property.Type)!,
|
||||
$"_{property.Name.ToVariableName()}",
|
||||
this));
|
||||
}
|
||||
}
|
||||
}
|
||||
return [.. fields];
|
||||
}
|
||||
|
||||
private Dictionary<InputModelType, Dictionary<string, InputModelProperty>>? _inputDerivedProperties;
|
||||
private Dictionary<InputModelType, Dictionary<string, InputModelProperty>> InputDerivedProperties => _inputDerivedProperties ??= BuildDerivedProperties();
|
||||
|
||||
private Dictionary<InputModelType, Dictionary<string, InputModelProperty>> BuildDerivedProperties()
|
||||
{
|
||||
Dictionary<InputModelType, Dictionary<string, InputModelProperty>> derivedProperties = [];
|
||||
foreach (var derivedModel in _inputModel.DerivedModels)
|
||||
{
|
||||
var derivedModelProperties = derivedModel.Properties;
|
||||
if (derivedModelProperties.Count > 0)
|
||||
{
|
||||
derivedProperties[derivedModel] = derivedModelProperties.ToDictionary(p => p.Name);
|
||||
}
|
||||
}
|
||||
return derivedProperties;
|
||||
}
|
||||
|
||||
protected override PropertyProvider[] BuildProperties()
|
||||
|
@ -122,6 +162,8 @@ namespace Microsoft.Generator.CSharp.Providers
|
|||
var propertiesCount = _inputModel.Properties.Count;
|
||||
var properties = new List<PropertyProvider>(propertiesCount + 1);
|
||||
|
||||
Dictionary<string, InputModelProperty> baseProperties = _inputModel.BaseModel?.Properties.ToDictionary(p => p.Name) ?? [];
|
||||
|
||||
for (int i = 0; i < propertiesCount; i++)
|
||||
{
|
||||
var property = _inputModel.Properties[i];
|
||||
|
@ -132,6 +174,34 @@ namespace Microsoft.Generator.CSharp.Providers
|
|||
var outputProperty = CodeModelPlugin.Instance.TypeFactory.CreatePropertyProvider(property, this);
|
||||
if (outputProperty != null)
|
||||
{
|
||||
if (!property.IsDiscriminator)
|
||||
{
|
||||
var derivedProperty = InputDerivedProperties.FirstOrDefault(p => p.Value.ContainsKey(property.Name)).Value?[property.Name];
|
||||
if (derivedProperty is not null)
|
||||
{
|
||||
if (derivedProperty.Type.Equals(property.Type) && DomainEqual(property, derivedProperty))
|
||||
{
|
||||
outputProperty.Modifiers |= MethodSignatureModifiers.Virtual;
|
||||
}
|
||||
}
|
||||
var baseProperty = baseProperties.GetValueOrDefault(property.Name);
|
||||
if (baseProperty is not null)
|
||||
{
|
||||
if (baseProperty.Type.Equals(property.Type) && DomainEqual(baseProperty, property))
|
||||
{
|
||||
outputProperty.Modifiers |= MethodSignatureModifiers.Override;
|
||||
}
|
||||
else
|
||||
{
|
||||
outputProperty.Modifiers |= MethodSignatureModifiers.New;
|
||||
var fieldName = $"_{baseProperty.Name.ToVariableName()}";
|
||||
outputProperty.Body = new ExpressionPropertyBody(
|
||||
This.Property(fieldName).NullCoalesce(Default),
|
||||
outputProperty.Body.HasSetter ? This.Property(fieldName).Assign(Value) : null);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
properties.Add(outputProperty);
|
||||
}
|
||||
}
|
||||
|
@ -144,6 +214,14 @@ namespace Microsoft.Generator.CSharp.Providers
|
|||
return [.. properties];
|
||||
}
|
||||
|
||||
private static bool DomainEqual(InputModelProperty baseProperty, InputModelProperty derivedProperty)
|
||||
{
|
||||
if (baseProperty.IsRequired != derivedProperty.IsRequired)
|
||||
return false;
|
||||
var baseNullable = baseProperty.Type is InputNullableType;
|
||||
return baseNullable ? derivedProperty.Type is InputNullableType : derivedProperty.Type is not InputNullableType;
|
||||
}
|
||||
|
||||
protected override ConstructorProvider[] BuildConstructors()
|
||||
{
|
||||
if (_inputModel.IsUnknownDiscriminatorModel)
|
||||
|
@ -273,7 +351,7 @@ namespace Microsoft.Generator.CSharp.Providers
|
|||
else
|
||||
{
|
||||
/* kind ?? "unknown" */
|
||||
return NullCoalescing(discriminatorExpression, Literal(_inputModel.DiscriminatorValue));
|
||||
return discriminatorExpression.NullCoalesce(Literal(_inputModel.DiscriminatorValue));
|
||||
}
|
||||
}
|
||||
else
|
||||
|
|
|
@ -20,10 +20,10 @@ namespace Microsoft.Generator.CSharp.Providers
|
|||
|
||||
public FormattableString Description { get; }
|
||||
public XmlDocSummaryStatement XmlDocSummary { get; }
|
||||
public MethodSignatureModifiers Modifiers { get; }
|
||||
public MethodSignatureModifiers Modifiers { get; internal set; }
|
||||
public CSharpType Type { get; }
|
||||
public string Name { get; }
|
||||
public PropertyBody Body { get; private set; }
|
||||
public string Name { get; internal set; }
|
||||
public PropertyBody Body { get; internal set; }
|
||||
public CSharpType? ExplicitInterface { get; }
|
||||
public XmlDocProvider XmlDocs { get; private set; }
|
||||
public PropertyWireInformation? WireInfo { get; }
|
||||
|
|
|
@ -20,6 +20,8 @@ namespace Microsoft.Generator.CSharp.Snippets
|
|||
|
||||
public static ValueExpression NullConditional(this ParameterProvider parameter) => new NullConditionalExpression(parameter);
|
||||
|
||||
public static ValueExpression NullCoalesce(this ParameterProvider parameter, ValueExpression value) => parameter.AsExpression.NullCoalesce(value);
|
||||
|
||||
public static DictionaryExpression AsDictionary(this FieldProvider field, CSharpType keyType, CSharpType valueType) => new(new KeyValuePairType(keyType, valueType), field);
|
||||
public static DictionaryExpression AsDictionary(this ParameterProvider parameter, CSharpType keyType, CSharpType valueType) => new(new KeyValuePairType(keyType, valueType), parameter);
|
||||
|
||||
|
@ -56,8 +58,6 @@ namespace Microsoft.Generator.CSharp.Snippets
|
|||
public static ValueExpression Nameof(ValueExpression expression) => new InvokeMethodExpression(null, "nameof", new[] { expression });
|
||||
public static ValueExpression ThrowExpression(ValueExpression expression) => new KeywordExpression("throw", expression);
|
||||
|
||||
public static ValueExpression NullCoalescing(ValueExpression left, ValueExpression right) => new BinaryOperatorExpression("??", left, right);
|
||||
|
||||
// TO-DO: Migrate remaining class as part of output classes migration : https://github.com/Azure/autorest.csharp/issues/4198
|
||||
//public static ValueExpression EnumValue(EnumType type, EnumTypeValue value) => new MemberExpression(new TypeReference(type.Type), value.Declaration.Name);
|
||||
public static ValueExpression FrameworkEnumValue<TEnum>(TEnum value) where TEnum : struct, Enum => new MemberExpression(TypeReferenceExpression.FromType(typeof(TEnum)), Enum.GetName(value)!);
|
||||
|
|
|
@ -18,7 +18,7 @@ namespace Microsoft.Generator.CSharp.Tests.Providers.ModelProviders
|
|||
private static readonly InputModelType _catModel = InputFactory.Model("cat", discriminatedKind: "cat", properties:
|
||||
[
|
||||
InputFactory.Property("kind", InputPrimitiveType.String, isRequired: true, isDiscriminator: true),
|
||||
InputFactory.Property("willScratchOwner", InputPrimitiveType.Boolean, isRequired: true, isDiscriminator: true)
|
||||
InputFactory.Property("willScratchOwner", InputPrimitiveType.Boolean, isRequired: true)
|
||||
]);
|
||||
private static readonly InputModelType _dogModel = InputFactory.Model("dog", discriminatedKind: "dog", properties:
|
||||
[
|
||||
|
@ -30,6 +30,26 @@ namespace Microsoft.Generator.CSharp.Tests.Providers.ModelProviders
|
|||
properties: [InputFactory.Property("kind", InputPrimitiveType.String, isRequired: true, isDiscriminator: true)],
|
||||
discriminatedModels: new Dictionary<string, InputModelType>() { { "cat", _catModel }, { "dog", _dogModel } });
|
||||
|
||||
private static readonly InputEnumType _petEnum = InputFactory.Enum("pet", InputPrimitiveType.String, isExtensible: true, values:
|
||||
[
|
||||
InputFactory.EnumMember.String("cat", "cat"),
|
||||
InputFactory.EnumMember.String("dog", "dog")
|
||||
]);
|
||||
private static readonly InputModelType _catEnumModel = InputFactory.Model("cat", discriminatedKind: "cat", properties:
|
||||
[
|
||||
InputFactory.Property("kind", _petEnum, isRequired: true, isDiscriminator: true),
|
||||
InputFactory.Property("willScratchOwner", InputPrimitiveType.Boolean, isRequired: true)
|
||||
]);
|
||||
private static readonly InputModelType _dogEnumModel = InputFactory.Model("dog", discriminatedKind: "dog", properties:
|
||||
[
|
||||
InputFactory.Property("kind", _petEnum, isRequired: true, isDiscriminator: true),
|
||||
InputFactory.Property("likesBones", InputPrimitiveType.Boolean, isRequired: true)
|
||||
]);
|
||||
private static readonly InputModelType _baseEnumModel = InputFactory.Model(
|
||||
"pet",
|
||||
properties: [InputFactory.Property("kind", _petEnum, isRequired: true, isDiscriminator: true)],
|
||||
discriminatedModels: new Dictionary<string, InputModelType>() { { "cat", _catEnumModel }, { "dog", _dogEnumModel } });
|
||||
|
||||
[Test]
|
||||
public void BaseShouldBeAbstract()
|
||||
{
|
||||
|
@ -154,5 +174,38 @@ namespace Microsoft.Generator.CSharp.Tests.Providers.ModelProviders
|
|||
Assert.IsNotNull(serializationCtor);
|
||||
Assert.AreEqual("kind", serializationCtor!.Signature.Parameters[0].Name);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BaseDoesNotHaveDiscriminatorField()
|
||||
{
|
||||
MockHelpers.LoadMockPlugin(inputModelTypes: [_baseEnumModel, _catEnumModel, _dogEnumModel]);
|
||||
var outputLibrary = CodeModelPlugin.Instance.OutputLibrary;
|
||||
var baseModel = outputLibrary.TypeProviders.OfType<ModelProvider>().FirstOrDefault(t => t.Name == "Pet");
|
||||
Assert.IsNotNull(baseModel);
|
||||
Assert.IsFalse(baseModel!.Fields.Any(f => f.Name == "_kind"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BaseKindPropertyIsNotVirtual()
|
||||
{
|
||||
MockHelpers.LoadMockPlugin(inputModelTypes: [_baseEnumModel, _catEnumModel, _dogEnumModel]);
|
||||
var outputLibrary = CodeModelPlugin.Instance.OutputLibrary;
|
||||
var baseModel = outputLibrary.TypeProviders.OfType<ModelProvider>().FirstOrDefault(t => t.Name == "Pet");
|
||||
Assert.IsNotNull(baseModel);
|
||||
var kindProperty = baseModel!.Properties.FirstOrDefault(p => p.Name == "Kind");
|
||||
Assert.IsNotNull(kindProperty);
|
||||
Assert.IsFalse(kindProperty!.Modifiers.HasFlag(MethodSignatureModifiers.Virtual));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DerivedHasNoKindProperty()
|
||||
{
|
||||
MockHelpers.LoadMockPlugin(inputModelTypes: [_baseEnumModel, _catEnumModel, _dogEnumModel]);
|
||||
var outputLibrary = CodeModelPlugin.Instance.OutputLibrary;
|
||||
var catModel = outputLibrary.TypeProviders.OfType<ModelProvider>().FirstOrDefault(t => t.Name == "Cat");
|
||||
Assert.IsNotNull(catModel);
|
||||
var kindProperty = catModel!.Properties.FirstOrDefault(p => p.Name == "Kind");
|
||||
Assert.IsNull(kindProperty);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -303,7 +303,7 @@ namespace Microsoft.Generator.CSharp.Tests.Providers.ModelProviders
|
|||
var param = constructorSignature?.Parameters[0];
|
||||
Assert.IsNotNull(param);
|
||||
Assert.AreEqual("serializedAdditionalRawData", param?.Name);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
|
@ -403,5 +403,142 @@ namespace Microsoft.Generator.CSharp.Tests.Providers.ModelProviders
|
|||
yield return new TestCaseData(InputFactory.Model("foo"), true);
|
||||
}
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DuplicatePropertyHasVirtualAndOverrideKeyword()
|
||||
{
|
||||
MockHelpers.LoadMockPlugin();
|
||||
var derivedInputModel = InputFactory.Model("derivedModel", properties: [InputFactory.Property("prop1", InputPrimitiveType.String)]);
|
||||
var baseInputModel = InputFactory.Model("baseModel", properties: [InputFactory.Property("prop1", InputPrimitiveType.String)], derivedModels: [derivedInputModel]);
|
||||
var derivedModel = CodeModelPlugin.Instance.TypeFactory.CreateModel(derivedInputModel);
|
||||
var baseModel = CodeModelPlugin.Instance.TypeFactory.CreateModel(baseInputModel);
|
||||
|
||||
Assert.IsNotNull(derivedModel);
|
||||
Assert.IsNotNull(baseModel);
|
||||
|
||||
var derivedProp = derivedModel!.Properties[0];
|
||||
var baseProp = baseModel!.Properties[0];
|
||||
|
||||
Assert.AreEqual(baseProp.Name, derivedProp.Name);
|
||||
Assert.AreEqual(baseProp.Type, derivedProp.Type);
|
||||
Assert.IsNotNull(baseProp.WireInfo);
|
||||
Assert.IsNotNull(derivedProp.WireInfo);
|
||||
Assert.AreEqual(baseProp.WireInfo!.IsRequired, derivedProp.WireInfo!.IsRequired);
|
||||
Assert.IsTrue(baseProp.Modifiers.HasFlag(MethodSignatureModifiers.Virtual));
|
||||
Assert.IsTrue(derivedProp.Modifiers.HasFlag(MethodSignatureModifiers.Override));
|
||||
Assert.IsFalse(baseProp.Modifiers.HasFlag(MethodSignatureModifiers.Override));
|
||||
Assert.IsFalse(derivedProp.Modifiers.HasFlag(MethodSignatureModifiers.Virtual));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void OptionalityChangeNarrowPropertyHasNewKeyword()
|
||||
{
|
||||
MockHelpers.LoadMockPlugin();
|
||||
var derivedInputModel = InputFactory.Model("derivedModel", properties: [InputFactory.Property("prop1", InputPrimitiveType.String, isRequired: true)]);
|
||||
var baseInputModel = InputFactory.Model("baseModel", properties: [InputFactory.Property("prop1", InputPrimitiveType.String)], derivedModels: [derivedInputModel]);
|
||||
var derivedModel = CodeModelPlugin.Instance.TypeFactory.CreateModel(derivedInputModel);
|
||||
var baseModel = CodeModelPlugin.Instance.TypeFactory.CreateModel(baseInputModel);
|
||||
|
||||
Assert.IsNotNull(derivedModel);
|
||||
Assert.IsNotNull(baseModel);
|
||||
|
||||
var derivedProp = derivedModel!.Properties[0];
|
||||
var baseProp = baseModel!.Properties[0];
|
||||
Assert.AreEqual(baseProp.Name, derivedProp.Name);
|
||||
Assert.IsTrue(baseProp.Type.Equals(derivedProp.Type, ignoreNullable: true));
|
||||
Assert.IsNotNull(baseProp.WireInfo);
|
||||
Assert.IsNotNull(derivedProp.WireInfo);
|
||||
Assert.IsFalse(baseProp.WireInfo!.IsRequired);
|
||||
Assert.IsTrue(derivedProp.WireInfo!.IsRequired);
|
||||
Assert.IsTrue(derivedProp.Modifiers.HasFlag(MethodSignatureModifiers.New));
|
||||
Assert.IsFalse(baseProp.Modifiers.HasFlag(MethodSignatureModifiers.Virtual));
|
||||
Assert.IsFalse(baseProp.Modifiers.HasFlag(MethodSignatureModifiers.New));
|
||||
Assert.IsFalse(derivedProp.Modifiers.HasFlag(MethodSignatureModifiers.Override));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void TypeChangeNarrowPropertyHasNewKeyWord()
|
||||
{
|
||||
MockHelpers.LoadMockPlugin();
|
||||
var derivedInputModel = InputFactory.Model("derivedModel", properties: [InputFactory.Property("prop1", InputPrimitiveType.Int32)]);
|
||||
var baseInputModel = InputFactory.Model("baseModel", properties: [InputFactory.Property("prop1", InputPrimitiveType.Int64)], derivedModels: [derivedInputModel]);
|
||||
var derivedModel = CodeModelPlugin.Instance.TypeFactory.CreateModel(derivedInputModel);
|
||||
var baseModel = CodeModelPlugin.Instance.TypeFactory.CreateModel(baseInputModel);
|
||||
|
||||
Assert.IsNotNull(derivedModel);
|
||||
Assert.IsNotNull(baseModel);
|
||||
|
||||
var derivedProp = derivedModel!.Properties[0];
|
||||
var baseProp = baseModel!.Properties[0];
|
||||
Assert.AreEqual(baseProp.Name, derivedProp.Name);
|
||||
Assert.IsFalse(baseProp.Type.Equals(derivedProp.Type, ignoreNullable: true));
|
||||
Assert.IsNotNull(baseProp.WireInfo);
|
||||
Assert.IsNotNull(derivedProp.WireInfo);
|
||||
Assert.AreEqual(baseProp.WireInfo!.IsRequired, derivedProp.WireInfo!.IsRequired);
|
||||
Assert.IsTrue(derivedProp.Modifiers.HasFlag(MethodSignatureModifiers.New));
|
||||
Assert.IsFalse(baseProp.Modifiers.HasFlag(MethodSignatureModifiers.Virtual));
|
||||
Assert.IsFalse(baseProp.Modifiers.HasFlag(MethodSignatureModifiers.New));
|
||||
Assert.IsFalse(derivedProp.Modifiers.HasFlag(MethodSignatureModifiers.Override));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void BaseHasFieldWhenPropertyIsNarrowed()
|
||||
{
|
||||
MockHelpers.LoadMockPlugin();
|
||||
var derivedInputModel = InputFactory.Model("derivedModel", properties: [InputFactory.Property("prop1", InputPrimitiveType.Int32)]);
|
||||
var baseInputModel = InputFactory.Model("baseModel", properties: [InputFactory.Property("prop1", InputPrimitiveType.Int64)], derivedModels: [derivedInputModel]);
|
||||
var derivedModel = CodeModelPlugin.Instance.TypeFactory.CreateModel(derivedInputModel);
|
||||
var baseModel = CodeModelPlugin.Instance.TypeFactory.CreateModel(baseInputModel);
|
||||
|
||||
Assert.IsNotNull(derivedModel);
|
||||
Assert.IsNotNull(baseModel);
|
||||
|
||||
var baseField = baseModel!.Fields.FirstOrDefault(f => f.Name == "_prop1");
|
||||
Assert.IsNotNull(baseField);
|
||||
Assert.AreEqual(new CSharpType(typeof(long)), baseField!.Type);
|
||||
Assert.AreEqual(FieldModifiers.Private | FieldModifiers.Protected, baseField.Modifiers);
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DerivedUsesExpressionBodyPropertyWhenNarrowed()
|
||||
{
|
||||
MockHelpers.LoadMockPlugin();
|
||||
var derivedInputModel = InputFactory.Model("derivedModel", properties: [InputFactory.Property("prop1", InputPrimitiveType.Int32)]);
|
||||
var baseInputModel = InputFactory.Model("baseModel", properties: [InputFactory.Property("prop1", InputPrimitiveType.Int64)], derivedModels: [derivedInputModel]);
|
||||
var derivedModel = CodeModelPlugin.Instance.TypeFactory.CreateModel(derivedInputModel);
|
||||
var baseModel = CodeModelPlugin.Instance.TypeFactory.CreateModel(baseInputModel);
|
||||
|
||||
Assert.IsNotNull(derivedModel);
|
||||
Assert.IsNotNull(baseModel);
|
||||
|
||||
var derivedProp = derivedModel!.Properties[0];
|
||||
Assert.IsNotNull(derivedProp);
|
||||
var expressionBody = derivedProp.Body as ExpressionPropertyBody;
|
||||
Assert.IsNotNull(expressionBody);
|
||||
Assert.IsTrue(expressionBody!.Getter.ToDisplayString().Contains("_prop1 ?? default"));
|
||||
Assert.IsTrue(expressionBody.HasSetter);
|
||||
Assert.IsTrue(expressionBody.Setter!.ToDisplayString().Contains("_prop1 = value"));
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void DerivedExpressionBodyDoesNotHaveSetterWhenNarrowed()
|
||||
{
|
||||
MockHelpers.LoadMockPlugin();
|
||||
var derivedInputModel = InputFactory.Model("derivedModel", usage: InputModelTypeUsage.Output, properties: [InputFactory.Property("prop1", InputPrimitiveType.Int32, isReadOnly: true)]);
|
||||
var baseInputModel = InputFactory.Model("baseModel", usage: InputModelTypeUsage.Output, properties: [InputFactory.Property("prop1", InputPrimitiveType.Int64, isReadOnly: true)], derivedModels: [derivedInputModel]);
|
||||
var derivedModel = CodeModelPlugin.Instance.TypeFactory.CreateModel(derivedInputModel);
|
||||
var baseModel = CodeModelPlugin.Instance.TypeFactory.CreateModel(baseInputModel);
|
||||
|
||||
Assert.IsNotNull(derivedModel);
|
||||
Assert.IsNotNull(baseModel);
|
||||
|
||||
var derivedProp = derivedModel!.Properties[0];
|
||||
Assert.IsNotNull(derivedProp);
|
||||
var expressionBody = derivedProp.Body as ExpressionPropertyBody;
|
||||
Assert.IsNotNull(expressionBody);
|
||||
Assert.IsTrue(expressionBody!.Getter.ToDisplayString().Contains("_prop1 ?? default"));
|
||||
Assert.IsFalse(expressionBody.HasSetter);
|
||||
Assert.IsNull(expressionBody.Setter);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -121,12 +121,13 @@ namespace Microsoft.Generator.CSharp.Tests.Common
|
|||
bool isRequired = false,
|
||||
bool isReadOnly = false,
|
||||
bool isDiscriminator = false,
|
||||
string? wireName = null)
|
||||
string? wireName = null,
|
||||
string? description = null)
|
||||
{
|
||||
return new InputModelProperty(
|
||||
name,
|
||||
wireName ?? name.ToVariableName(),
|
||||
$"Description for {name}",
|
||||
description ?? $"Description for {name}",
|
||||
type,
|
||||
isRequired,
|
||||
isReadOnly,
|
||||
|
|
Загрузка…
Ссылка в новой задаче