Skip to content

Commit c8280c0

Browse files
authored
feat(cadl): support literal type model property (#3036)
- change json cnoverter for `InputModelProperty` to set the `DefaultValue` property if the property type is a literal type - update `ObjectTypeProperty` so that `DefaultValue` is set if it's from literal type - change `ModelTypeProviderFields`: - exclude literal properties from constructor parameter list - literal properties are `internal readonly` - change `ModelTypeProvider`: - update the criteria on properties to be serialized, now literal type property will be serialized regardless it's read-only - skip deserialization for literal type properties - fix an issue in emitter that boolean literal type is not identified - in emitter, set literal parameters in operations to constant parameter types - minor refactoring - update test projects resolve #3035
1 parent 5f5738b commit c8280c0

File tree

24 files changed

+2281
-375
lines changed

24 files changed

+2281
-375
lines changed

src/AutoRest.CSharp/Common/Generation/Writers/JsonCodeWriterExtensions.cs

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -286,7 +286,7 @@ private static void ToSerializeCall(this CodeWriter writer, FormattableString wr
286286

287287
private static void DeserializeIntoObjectProperties(this CodeWriter writer, IEnumerable<JsonPropertySerialization> propertySerializations, FormattableString itemVariable, Dictionary<JsonPropertySerialization, ObjectPropertyVariable> propertyVariables)
288288
{
289-
foreach (JsonPropertySerialization property in propertySerializations)
289+
foreach (JsonPropertySerialization property in propertySerializations.Where(p => !p.ShouldSkipDeserialization))
290290
{
291291
writer.Append($"if({itemVariable}.NameEquals({property.SerializedName:L}u8))");
292292
using (writer.Scope())
@@ -379,9 +379,9 @@ private static FormattableString GetOptionalFormattable(JsonPropertySerializatio
379379
}
380380

381381
/// Collects a list of properties being read from all level of object hierarchy
382-
private static void CollectProperties(Dictionary<JsonPropertySerialization, ObjectPropertyVariable> propertyVariables, IEnumerable<JsonPropertySerialization> jsonProperties)
382+
private static void CollectPropertiesForDeserialization(Dictionary<JsonPropertySerialization, ObjectPropertyVariable> propertyVariables, IEnumerable<JsonPropertySerialization> jsonProperties)
383383
{
384-
foreach (JsonPropertySerialization jsonProperty in jsonProperties)
384+
foreach (JsonPropertySerialization jsonProperty in jsonProperties.Where(p => !p.ShouldSkipDeserialization))
385385
{
386386
if (jsonProperty.ValueType != null)
387387
{
@@ -399,7 +399,7 @@ private static void CollectProperties(Dictionary<JsonPropertySerialization, Obje
399399
}
400400
else if (jsonProperty.PropertySerializations != null)
401401
{
402-
CollectProperties(propertyVariables, jsonProperty.PropertySerializations);
402+
CollectPropertiesForDeserialization(propertyVariables, jsonProperty.PropertySerializations);
403403
}
404404
}
405405
}
@@ -492,7 +492,7 @@ public static void WriteObjectInitialization(this CodeWriter writer, JsonObjectS
492492
// collect all properties and initialize the dictionary
493493
var propertyVariables = new Dictionary<JsonPropertySerialization, ObjectPropertyVariable>();
494494

495-
CollectProperties(propertyVariables, serialization.Properties);
495+
CollectPropertiesForDeserialization(propertyVariables, serialization.Properties);
496496

497497
var additionalProperties = serialization.AdditionalProperties;
498498
if (additionalProperties != null)

src/AutoRest.CSharp/Common/Generation/Writers/ModelWriter.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -309,7 +309,7 @@ protected virtual void AddCtorAttribute(CodeWriter writer, ObjectType schema, Ob
309309
{
310310
}
311311

312-
public void WriteConstructor(CodeWriter writer, ObjectType schema)
312+
private void WriteConstructor(CodeWriter writer, ObjectType schema)
313313
{
314314
foreach (var constructor in schema.Constructors)
315315
{

src/AutoRest.CSharp/Common/Input/CadlInputLiteralTypeConverter.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -85,28 +85,28 @@ public static object ReadLiteralValue(ref Utf8JsonReader reader, string property
8585
Object? value = null;
8686
switch (type)
8787
{
88-
case InputPrimitiveType primitype:
89-
switch (primitype.Kind)
88+
case InputPrimitiveType primitiveType:
89+
switch (primitiveType.Kind)
9090
{
9191
case InputTypeKind.String:
9292
value = reader.GetString() ?? throw new JsonException();
9393
break;
9494
case InputTypeKind.Int32:
9595
value = reader.GetInt32();
9696
break;
97-
case InputTypeKind.Int64:
98-
value = reader.GetInt64();
97+
case InputTypeKind.Float64:
98+
value = reader.GetDouble();
9999
break;
100100
case InputTypeKind.Boolean:
101101
value = reader.GetBoolean();
102102
break;
103103
default:
104-
throw new JsonException($"Not supported litreal type {primitype.Kind}.");
104+
throw new JsonException($"Not supported literal type {primitiveType.Kind}.");
105105

106106
}
107107
break;
108108
default:
109-
throw new JsonException($"Not supported litreal type {type.Name}.");
109+
throw new JsonException($"Not supported literal type {type.Name}.");
110110
}
111111
reader.Read();
112112
return value;

src/AutoRest.CSharp/Common/Input/CadlInputModelPropertyConverter.cs

Lines changed: 23 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -55,13 +55,35 @@ private static InputModelProperty ReadInputModelProperty(ref Utf8JsonReader read
5555
description = BuilderHelpers.EscapeXmlDocDescription(description);
5656
propertyType = propertyType ?? throw new JsonException($"{nameof(InputModelProperty)} must have a property type.");
5757

58-
var property = new InputModelProperty(name, serializedName ?? name, description, propertyType, isRequired, isReadOnly, isDiscriminator);
58+
var property = new InputModelProperty(name, serializedName ?? name, description, propertyType, isRequired, isReadOnly, isDiscriminator, GetDefaultValue(propertyType));
5959
if (id != null)
6060
{
6161
resolver.AddReference(id, property);
6262
}
6363

6464
return property;
6565
}
66+
67+
private static FormattableString? GetDefaultValue(InputType propertyType)
68+
{
69+
if (propertyType is not InputLiteralType literalType)
70+
{
71+
return null;
72+
}
73+
74+
return literalType.LiteralValueType switch
75+
{
76+
InputPrimitiveType primitiveType => primitiveType.Kind switch
77+
{
78+
InputTypeKind.Boolean => $"{literalType.Value.ToString()!.ToLower()}",
79+
InputTypeKind.Float32 or InputTypeKind.Float64 or InputTypeKind.Float128
80+
or InputTypeKind.Int32 or InputTypeKind.Int64 => $"{literalType.Value.ToString()}",
81+
InputTypeKind.String => $"\"{(literalType.Value).ToString()}\"",
82+
_ => throw new Exception($"Unsupported literal value type: {primitiveType}"),
83+
84+
},
85+
_ => throw new Exception($"Unsupported literal value type: {literalType.LiteralValueType}"),
86+
};
87+
}
6688
}
6789
}

src/AutoRest.CSharp/Common/Output/Builders/SerializationBuilder.cs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -267,6 +267,7 @@ private IEnumerable<JsonPropertySerialization> GetPropertySerializationsFromBag(
267267
BuildSerialization(property.Schema, objectProperty.ValueType),
268268
property.IsRequired,
269269
property.IsReadOnly,
270+
false,
270271
objectProperty.OptionalViaNullability);
271272
}
272273

src/AutoRest.CSharp/Common/Output/Models/RestClientBuilder.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -351,7 +351,7 @@ private ReferenceOrConstant CreateReference(InputParameter operationParameter, P
351351
return (ReferenceOrConstant)_parameters[operationParameter.Name];
352352
}
353353

354-
if (operationParameter.Kind == InputOperationParameterKind.Constant && parameter.DefaultValue != null)
354+
if (operationParameter is { Kind:InputOperationParameterKind.Constant } && parameter.DefaultValue is not null)
355355
{
356356
return (ReferenceOrConstant)parameter.DefaultValue;
357357
}

src/AutoRest.CSharp/Common/Output/Models/Serialization/Json/JsonAdditionalPropertiesSerialization.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,7 +12,7 @@ internal class JsonAdditionalPropertiesSerialization : JsonPropertySerialization
1212
public CSharpType Type { get; }
1313

1414
public JsonAdditionalPropertiesSerialization(ObjectTypeProperty property, JsonSerialization valueSerialization, CSharpType type)
15-
: base(property.Declaration.Name.ToVariableName(), property.Declaration.Name, property.Declaration.Name, property.Declaration.Type, property.ValueType, valueSerialization, true, property.IsReadOnly, property.OptionalViaNullability)
15+
: base(property.Declaration.Name.ToVariableName(), property.Declaration.Name, property.Declaration.Name, property.Declaration.Type, property.ValueType, valueSerialization, true, property.IsReadOnly, false, property.OptionalViaNullability)
1616
{
1717
Type = type;
1818
}

src/AutoRest.CSharp/Common/Output/Models/Serialization/Json/JsonPropertySerialization.cs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@ namespace AutoRest.CSharp.Output.Models.Serialization.Json
88
{
99
internal class JsonPropertySerialization : PropertySerialization
1010
{
11-
public JsonPropertySerialization(string parameterName, string propertyName, string serializedName, CSharpType propertyType, CSharpType? valueType, JsonSerialization valueSerialization, bool isRequired, bool shouldSkipSerialization, bool optionalViaNullability)
12-
: base(propertyName, serializedName, propertyType, valueType, isRequired, shouldSkipSerialization)
11+
public JsonPropertySerialization(string parameterName, string propertyName, string serializedName, CSharpType propertyType, CSharpType? valueType, JsonSerialization valueSerialization, bool isRequired, bool shouldSkipSerialization, bool shouldSkipDeserialization, bool optionalViaNullability)
12+
: base(propertyName, serializedName, propertyType, valueType, isRequired, shouldSkipSerialization, shouldSkipDeserialization)
1313
{
1414
ParameterName = parameterName;
1515
OptionalViaNullability = optionalViaNullability;

src/AutoRest.CSharp/Common/Output/Models/Serialization/PropertySerialization.cs

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,15 +13,22 @@ internal abstract class PropertySerialization
1313
public CSharpType? ValueType { get; }
1414
public bool IsRequired { get; }
1515
public bool ShouldSkipSerialization { get; }
16+
public bool ShouldSkipDeserialization { get; }
1617

17-
protected PropertySerialization(string propertyName, string serializedName, CSharpType propertyType, CSharpType? valueType, bool isRequired, bool shouldSkipSerialization)
18+
protected PropertySerialization(string propertyName, string serializedName, CSharpType propertyType, CSharpType? valueType, bool isRequired, bool shouldSkipSerialization) :
19+
this(propertyName, serializedName, propertyType, valueType, isRequired, shouldSkipSerialization, false)
20+
{
21+
}
22+
23+
protected PropertySerialization(string propertyName, string serializedName, CSharpType propertyType, CSharpType? valueType, bool isRequired, bool shouldSkipSerialization, bool shouldSkipDeserialization)
1824
{
1925
PropertyName = propertyName;
2026
SerializedName = serializedName;
2127
PropertyType = propertyType;
2228
ValueType = valueType;
2329
IsRequired = isRequired;
2430
ShouldSkipSerialization = shouldSkipSerialization;
31+
ShouldSkipDeserialization = shouldSkipDeserialization;
2532
}
2633
}
2734
}

src/AutoRest.CSharp/Common/Output/Models/Types/ModelTypeProvider.cs

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -147,6 +147,7 @@ private IEnumerable<JsonPropertySerialization> CreatePropertySerializations()
147147
valueSerialization,
148148
property.IsRequired,
149149
shouldSkipSerialization,
150+
ShouldSkipDeserialization(property),
150151
optionalViaNullability));
151152
}
152153
}
@@ -160,6 +161,11 @@ private bool ShouldSkipSerialization(ObjectTypeProperty property)
160161
return false;
161162
}
162163

164+
if (property.InputModelProperty.Type is InputLiteralType)
165+
{
166+
return false;
167+
}
168+
163169
if (property.InputModelProperty!.IsReadOnly)
164170
{
165171
return true;
@@ -173,6 +179,8 @@ private bool ShouldSkipSerialization(ObjectTypeProperty property)
173179
return property.IsReadOnly && _inputModel.Usage is not InputModelTypeUsage.Input;
174180
}
175181

182+
private bool ShouldSkipDeserialization(ObjectTypeProperty property) => property.InputModelProperty?.Type is InputLiteralType;
183+
176184
private ConstructorSignature? CreateSerializationConstructorSignature(string name, IReadOnlyList<Parameter> publicParameters, IReadOnlyList<Parameter> serializationParameters)
177185
{
178186
if (!serializationParameters.Any(p => TypeFactory.IsList(p.Type)) && publicParameters.SequenceEqual(serializationParameters))

0 commit comments

Comments
 (0)