private void WriteDiagnosticScope(CodeWriter writer, Diagnostic diagnostic, CodeWriterDelegate inner) { var scopeVariable = new CodeWriterDeclaration("scope"); writer.Line($"using var {scopeVariable:D} = {ClientDiagnosticsField}.CreateScope({diagnostic.ScopeName:L});"); foreach (DiagnosticAttribute diagnosticScopeAttributes in diagnostic.Attributes) { writer.Append($"{scopeVariable}.AddAttribute({diagnosticScopeAttributes.Name:L},"); writer.WriteReferenceOrConstant(diagnosticScopeAttributes.Value); writer.Line($");"); } writer.Line($"{scopeVariable}.Start();"); using (writer.Scope($"try")) { inner(writer); } using (writer.Scope($"catch ({typeof(Exception)} e)")) { writer.Line($"{scopeVariable}.Failed(e);"); writer.Line($"throw;"); } }
/// Collects a list of properties being read from all level of object hierarchy private static void CollectProperties(Dictionary <ObjectTypeProperty, CodeWriterDeclaration> propertyVariables, JsonObjectSerialization obj) { foreach (JsonPropertySerialization jsonProperty in obj.Properties) { ObjectTypeProperty?objectProperty = jsonProperty.Property; if (objectProperty != null) { var propertyDeclaration = new CodeWriterDeclaration(jsonProperty.Name.ToVariableName()); propertyVariables.Add(objectProperty, propertyDeclaration); } else if (jsonProperty.ValueSerialization is JsonObjectSerialization objectSerialization) { CollectProperties(propertyVariables, objectSerialization); } } var additionalPropertiesProperty = obj.AdditionalProperties?.Property; if (additionalPropertiesProperty != null) { var propertyDeclaration = new CodeWriterDeclaration(additionalPropertiesProperty.Declaration.Name.ToVariableName()); propertyVariables.Add(additionalPropertiesProperty, propertyDeclaration); } }
private static void WriteSerializeContent(CodeWriter writer, CodeWriterDeclaration request, ObjectSerialization bodySerialization, CodeWriterDelegate valueDelegate) { switch (bodySerialization) { case JsonSerialization jsonSerialization: { var content = new CodeWriterDeclaration("content"); writer.Line($"using var {content:D} = new {typeof(Utf8JsonRequestContent)}();"); writer.ToSerializeCall( jsonSerialization, valueDelegate, writerName: w => w.Append($"{content}.{nameof(Utf8JsonRequestContent.JsonWriter)}")); writer.Line($"{request}.Content = {content};"); break; } case XmlElementSerialization xmlSerialization: { var content = new CodeWriterDeclaration("content"); writer.Line($"using var {content:D} = new {typeof(XmlWriterContent)}();"); writer.ToSerializeCall( xmlSerialization, valueDelegate, writerName: w => w.Append($"{content}.{nameof(XmlWriterContent.XmlWriter)}")); writer.Line($"{request}.Content = {content};"); break; } default: throw new NotImplementedException(bodySerialization.ToString()); } }
private static void DeserializeIntoVariable(this CodeWriter writer, JsonSerialization serialization, Action <CodeWriter, CodeWriterDelegate> valueCallback, CodeWriterDelegate element) { switch (serialization) { case JsonArraySerialization array: var arrayVariable = new CodeWriterDeclaration("array"); writer.Line($"{array.Type} {arrayVariable:D} = new {array.Type}();"); var collectionItemVariable = new CodeWriterDeclaration("item"); using (writer.Scope($"foreach (var {collectionItemVariable:D} in {element}.EnumerateArray())")) { writer.DeserializeValue( array.ValueSerialization, w => w.Append($"{collectionItemVariable}"), (w, returnValue) => writer.Append($"{arrayVariable}.Add({returnValue});")); } valueCallback(writer, w => w.Append(arrayVariable)); return; case JsonDictionarySerialization dictionary: var dictionaryVariable = new CodeWriterDeclaration("dictionary"); writer.Line($"{dictionary.Type} {dictionaryVariable:D} = new {dictionary.Type}();"); var dictionaryItemVariable = new CodeWriterDeclaration("property"); using (writer.Scope($"foreach (var {dictionaryItemVariable:D} in {element}.EnumerateObject())")) { writer.DeserializeValue( dictionary.ValueSerialization, w => w.Append($"{dictionaryItemVariable}.Value"), (w, returnValue) => writer.Append($"{dictionaryVariable}.Add({dictionaryItemVariable}.Name, {returnValue});")); } valueCallback(writer, w => w.Append(dictionaryVariable)); return; case JsonValueSerialization valueSerialization: valueCallback(writer, w => w.DeserializeValue(valueSerialization, element)); return; } }
private static void DeserializeIntoVariableMayBeObject(this CodeWriter writer, JsonSerialization serialization, Action <CodeWriter, CodeWriterDelegate> valueCallback, CodeWriterDelegate element, Dictionary <ObjectTypeProperty, CodeWriterDeclaration>?propertyVariables = null) { if (serialization is JsonObjectSerialization obj) { var itemVariable = new CodeWriterDeclaration("property"); if (propertyVariables == null) { // this is the first level of object hierarchy // collect all properties and initialize the dictionary propertyVariables = new Dictionary <ObjectTypeProperty, CodeWriterDeclaration>(); CollectProperties(propertyVariables, obj); foreach (var variable in propertyVariables) { var objectTypeProperty = variable.Key; writer.Line($"{objectTypeProperty.Declaration.Type} {variable.Value:D} = default;"); } } var dictionaryVariable = new CodeWriterDeclaration("additionalPropertiesDictionary"); var objAdditionalProperties = obj.AdditionalProperties; if (objAdditionalProperties != null) { writer.Line($"{objAdditionalProperties.Type} {dictionaryVariable:D} = default;"); } using (writer.Scope($"foreach (var {itemVariable:D} in {element}.EnumerateObject())")) { foreach (JsonPropertySerialization property in obj.Properties) { CSharpType?type = property.Property?.Declaration.Type; bool hasNullableType = type != null && type.IsNullable; void WriteNullCheck() { using (writer.Scope($"if ({itemVariable.ActualName}.Value.ValueKind == {typeof(JsonValueKind)}.Null)")) { writer.Append($"continue;"); } } writer.Append($"if({itemVariable.ActualName}.NameEquals({property.Name:L}))"); using (writer.Scope()) { if (hasNullableType) { WriteNullCheck(); } if (property.Property != null) { // Reading a property value writer.DeserializeIntoVariable( property.ValueSerialization, (w, v) => w.Line($"{propertyVariables[property.Property]} = {v};"), w => w.Append($"{itemVariable.ActualName}.Value")); } else { // Reading a nested object writer.DeserializeIntoVariableMayBeObject( property.ValueSerialization, (w, v) => { }, w => w.Append($"{itemVariable.ActualName}.Value"), propertyVariables); } writer.Line($"continue;"); } } if (objAdditionalProperties != null) { writer.Line($"{dictionaryVariable} ??= new {objAdditionalProperties.Type}();"); writer.DeserializeValue( objAdditionalProperties.ValueSerialization, w => w.Append($"{itemVariable}.Value"), (w, v) => w.Line($"{dictionaryVariable}.Add({itemVariable}.Name, {v});")); } } if (objAdditionalProperties != null) { writer.Line($"{propertyVariables[objAdditionalProperties.Property]} = {dictionaryVariable};"); } if (obj.Type != null) { var initializers = new List <ObjectPropertyInitializer>(); foreach (var variable in propertyVariables) { var property = variable.Key; initializers.Add(new ObjectPropertyInitializer( property, new Reference(variable.Value.ActualName, property.Declaration.Type))); } valueCallback(writer, w => w.WriteInitialization((ObjectType)obj.Type.Implementation, initializers)); } } else { writer.DeserializeIntoVariableWithNullHandling(serialization, valueCallback, element); } }
public static void ToSerializeCall(this CodeWriter writer, JsonSerialization serialization, CodeWriterDelegate name, CodeWriterDelegate?writerName = null) { writerName ??= w => w.AppendRaw("writer"); switch (serialization) { case JsonArraySerialization array: writer.Line($"{writerName}.WriteStartArray();"); var collectionItemVariable = new CodeWriterDeclaration("item"); using (writer.Scope($"foreach (var {collectionItemVariable:D} in {name})")) { writer.ToSerializeCall( array.ValueSerialization, w => w.Append(collectionItemVariable), writerName); } writer.Line($"{writerName}.WriteEndArray();"); return; case JsonDictionarySerialization dictionary: writer.Line($"{writerName}.WriteStartObject();"); var dictionaryItemVariable = new CodeWriterDeclaration("item"); using (writer.Scope($"foreach (var {dictionaryItemVariable:D} in {name})")) { writer.Line($"{writerName}.WritePropertyName({dictionaryItemVariable}.Key);"); writer.ToSerializeCall( dictionary.ValueSerialization, w => w.Append($"{dictionaryItemVariable}.Value"), writerName); } writer.Line($"{writerName}.WriteEndObject();"); return; case JsonObjectSerialization obj: writer.Line($"{writerName}.WriteStartObject();"); foreach (JsonPropertySerialization property in obj.Properties) { bool hasNullableType = property.Property?.Declaration.Type.IsNullable == true; bool emptyAsUndefined = property.Property?.EmptyAsUndefined == true; CodeWriter.CodeWriterScope?scope = default; if (hasNullableType || emptyAsUndefined) { var propertyName = property.Property !.Declaration.Name; writer.Append($"if ("); if (hasNullableType) { writer.Append($"{propertyName} != null"); } if (emptyAsUndefined) { if (hasNullableType) { writer.Append($" && "); } writer.UseNamespace(typeof(Enumerable).Namespace !); writer.Append($"{propertyName}.Any()"); } writer.Append($")"); scope = writer.Scope(); } using (scope) { writer.Line($"{writerName}.WritePropertyName({property.Name:L});"); writer.ToSerializeCall( property.ValueSerialization, w => w.Append($"{property.Property?.Declaration.Name}")); } } if (obj.AdditionalProperties != null) { var itemVariable = new CodeWriterDeclaration("item"); using (writer.Scope($"foreach (var {itemVariable:D} in {obj.AdditionalProperties.Property.Declaration.Name})")) { writer.Line($"{writerName}.WritePropertyName({itemVariable}.Key);"); writer.ToSerializeCall( obj.AdditionalProperties.ValueSerialization, w => w.Append($"{itemVariable}.Value"), writerName); } } writer.Line($"{writerName}.WriteEndObject();"); return; case JsonValueSerialization valueSerialization: writer.UseNamespace(typeof(Utf8JsonWriterExtensions).Namespace !); if (valueSerialization.Type.IsFrameworkType) { var frameworkType = valueSerialization.Type.FrameworkType; if (frameworkType == typeof(JsonElement)) { writer.Line($"{name}.WriteTo({writerName});"); return; } bool writeFormat = false; writer.Append($"{writerName}."); if (frameworkType == typeof(decimal) || frameworkType == typeof(double) || frameworkType == typeof(float) || frameworkType == typeof(long) || frameworkType == typeof(int) || frameworkType == typeof(short)) { writer.AppendRaw("WriteNumberValue"); } else if (frameworkType == typeof(object)) { writer.AppendRaw("WriteObjectValue"); } else if (frameworkType == typeof(string) || frameworkType == typeof(char) || frameworkType == typeof(Guid)) { writer.AppendRaw("WriteStringValue"); } else if (frameworkType == typeof(bool)) { writer.AppendRaw("WriteBooleanValue"); } else if (frameworkType == typeof(byte[])) { writer.AppendRaw("WriteBase64StringValue"); writeFormat = true; } else if (frameworkType == typeof(DateTimeOffset) || frameworkType == typeof(DateTime) || frameworkType == typeof(TimeSpan)) { if (valueSerialization.Format == SerializationFormat.DateTime_Unix) { writer.AppendRaw("WriteNumberValue"); } else { writer.AppendRaw("WriteStringValue"); } writeFormat = true; } writer.Append($"({name}") .AppendNullableValue(valueSerialization.Type); if (writeFormat && valueSerialization.Format.ToFormatSpecifier() is string formatString) { writer.Append($", {formatString:L}"); } writer.LineRaw(");"); return; } switch (valueSerialization.Type.Implementation) { case ObjectType _: writer.Line($"{writerName}.WriteObjectValue({name});"); return; case EnumType clientEnum: writer.Append($"{writerName}.WriteStringValue({name}") .AppendNullableValue(valueSerialization.Type) .AppendEnumToString(clientEnum) .Line($");"); return; } throw new NotSupportedException(); default: throw new NotSupportedException(); } }
public static void ToSerializeCall(this CodeWriter writer, XmlElementSerialization serialization, CodeWriterDelegate name, CodeWriterDelegate?writerName = null, CodeWriterDelegate?nameHint = null) { writerName ??= w => w.AppendRaw("writer"); switch (serialization) { case XmlArraySerialization array: if (array.Wrapped) { writer.Line($"{writerName}.WriteStartElement({array.Name:L});"); } var itemVariable = new CodeWriterDeclaration("item"); using (writer.Scope($"foreach (var {itemVariable:D} in {name})")) { writer.ToSerializeCall( array.ValueSerialization, w => w.Append($"{itemVariable}"), writerName); } if (array.Wrapped) { writer.Line($"{writerName}.WriteEndElement();"); } break; case XmlDictionarySerialization dictionarySerialization: var pairVariable = new CodeWriterDeclaration("pair"); using (writer.Scope($"foreach (var {pairVariable:D} in {name})")) { writer.ToSerializeCall( dictionarySerialization.ValueSerialization, w => w.Append($"{pairVariable}.Value"), writerName); } break; case XmlObjectSerialization objectSerialization: if (nameHint != null) { writer.Line($"{writerName}.WriteStartElement({nameHint} ?? {objectSerialization.Name:L});"); } else { writer.Line($"{writerName}.WriteStartElement({objectSerialization.Name:L});"); } CodeWriter.CodeWriterScope?CheckPropertyForNull(ObjectTypeProperty objectTypeProperty) { return(objectTypeProperty.Declaration.Type.IsNullable ? writer.Scope($"if ({objectTypeProperty.Declaration.Name} != null)") : default); } foreach (XmlObjectAttributeSerialization property in objectSerialization.Attributes) { using (CheckPropertyForNull(property.Property)) { writer.Line($"{writerName}.WriteStartAttribute({property.Name:L});"); writer.ToSerializeValueCall( w => w.Append($"{property.Property.Declaration.Name}"), writerName, property.ValueSerialization); writer.Line($"{writerName}.WriteEndAttribute();"); } } foreach (XmlObjectElementSerialization property in objectSerialization.Elements) { using (CheckPropertyForNull(property.Property)) { writer.ToSerializeCall( property.ValueSerialization, w => w.Append($"{property.Property.Declaration.Name}")); } } foreach (XmlObjectArraySerialization property in objectSerialization.EmbeddedArrays) { using (CheckPropertyForNull(property.Property)) { writer.ToSerializeCall( property.ArraySerialization, w => w.Append($"{property.Property.Declaration.Name}")); } } writer.Line($"{writerName}.WriteEndElement();"); return;
private void WriteRequestCreation(CodeWriter writer, RestClientMethod clientMethod) { using var methodScope = writer.AmbientScope(); var methodName = CreateRequestMethodName(clientMethod.Name); writer.Append($"internal {typeof(HttpMessage)} {methodName}("); var parameters = clientMethod.Parameters; foreach (Parameter clientParameter in parameters) { writer.Append($"{clientParameter.Type} {clientParameter.Name:D},"); } writer.RemoveTrailingComma(); writer.Line($")"); using (writer.Scope()) { var message = new CodeWriterDeclaration("message"); var request = new CodeWriterDeclaration("request"); var uri = new CodeWriterDeclaration("uri"); writer.Line($"var {message:D} = {PipelineField}.CreateMessage();"); writer.Line($"var {request:D} = {message}.Request;"); var method = clientMethod.Request.HttpMethod; writer.Line($"{request}.Method = {typeof(RequestMethod)}.{method.ToRequestMethodName()};"); writer.Line($"var {uri:D} = new RawRequestUriBuilder();"); foreach (var segment in clientMethod.Request.PathSegments) { if (!segment.Value.IsConstant && segment.Value.Reference.Name == "nextLink") { if (segment.IsRaw) { // Artificial nextLink needs additional logic for relative versus absolute links WritePathSegment(writer, uri, segment, "AppendRawNextLink"); } else { // Natural nextLink parameters need to use a different method to parse path and query elements WritePathSegment(writer, uri, segment, "AppendRaw"); } } else { WritePathSegment(writer, uri, segment); } } //TODO: Duplicate code between query and header parameter processing logic foreach (var queryParameter in clientMethod.Request.Query) { WriteQueryParameter(writer, uri, queryParameter); } writer.Line($"{request}.Uri = {uri};"); foreach (var header in clientMethod.Request.Headers) { WriteHeader(writer, request, header); } switch (clientMethod.Request.Body) { case SchemaRequestBody body: using (WriteValueNullCheck(writer, body.Value)) { WriteSerializeContent( writer, request, body.Serialization, w => WriteConstantOrParameter(w, body.Value, ignoreNullability: true)); } break; case BinaryRequestBody binaryBody: using (WriteValueNullCheck(writer, binaryBody.Value)) { writer.Append($"{request}.Content = {typeof(RequestContent)}.Create("); WriteConstantOrParameter(writer, binaryBody.Value); writer.Line($");"); } break; case TextRequestBody textBody: using (WriteValueNullCheck(writer, textBody.Value)) { writer.Append($"{request}.Content = new {typeof(StringRequestContent)}("); WriteConstantOrParameter(writer, textBody.Value); writer.Line($");"); } break; case FlattenedSchemaRequestBody flattenedSchemaRequestBody: var modelVariable = new CodeWriterDeclaration("model"); writer.Append($"var {modelVariable:D} = ") .WriteInitialization(flattenedSchemaRequestBody.ObjectType, flattenedSchemaRequestBody.Initializers) .Line($";"); WriteSerializeContent( writer, request, flattenedSchemaRequestBody.Serialization, w => w.Append(modelVariable)); break; case null: break; default: throw new NotImplementedException(clientMethod.Request.Body?.GetType().FullName); } writer.Line($"return {message};"); } writer.Line(); }