Example #1
0
        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;");
            }
        }
Example #2
0
        /// 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());
            }
        }
Example #4
0
        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;
            }
        }
Example #5
0
        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);
            }
        }
Example #6
0
        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();
            }
        }
Example #7
0
        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();
        }