/// <summary>
        /// Called during Razor's code generation process to generate code that instantiates the value of the tag
        /// helper's property. Last value written should not be or end with a semicolon.
        /// </summary>
        /// <param name="attributeDescriptor">
        /// The <see cref="TagHelperAttributeDescriptor"/> to generate code for.
        /// </param>
        /// <param name="writer">The <see cref="CSharpCodeWriter"/> that's used to write code.</param>
        /// <param name="context">A <see cref="Chunks.Generators.ChunkGeneratorContext"/> instance that contains
        /// information about the current code generation process.</param>
        /// <param name="renderAttributeValue">
        /// <see cref="Action"/> that renders the raw value of the HTML attribute.
        /// </param>
        /// <param name="complexValue">
        /// Indicates whether or not the source attribute value contains more than simple text. <c>false</c> for plain
        /// C# expressions e.g. <c>"PropertyName"</c>. <c>true</c> if the attribute value contain at least one in-line
        /// Razor construct e.g. <c>"@(@readonly)"</c>.
        /// </param>
        public virtual void RenderAttributeValue(
            TagHelperAttributeDescriptor attributeDescriptor,
            CSharpCodeWriter writer,
            CodeGeneratorContext context,
            Action<CSharpCodeWriter> renderAttributeValue,
            bool complexValue)
        {
            if (attributeDescriptor == null)
            {
                throw new ArgumentNullException(nameof(attributeDescriptor));
            }

            if (writer == null)
            {
                throw new ArgumentNullException(nameof(writer));
            }

            if (context == null)
            {
                throw new ArgumentNullException(nameof(context));
            }

            if (renderAttributeValue == null)
            {
                throw new ArgumentNullException(nameof(renderAttributeValue));
            }

            renderAttributeValue(writer);
        }
        /// <inheritdoc />
        /// <remarks>If the attribute being rendered is of the type
        /// <see cref="GeneratedTagHelperAttributeContext.ModelExpressionTypeName"/>, then a model expression will be
        /// created by calling into <see cref="GeneratedTagHelperAttributeContext.CreateModelExpressionMethodName"/>.
        /// </remarks>
        public override void RenderAttributeValue(
            TagHelperAttributeDescriptor attributeDescriptor,
            CSharpCodeWriter writer,
            CodeGeneratorContext codeGeneratorContext,
            Action<CSharpCodeWriter> renderAttributeValue,
            bool complexValue)
        {
            if (attributeDescriptor == null)
            {
                throw new ArgumentNullException(nameof(attributeDescriptor));
            }

            if (writer == null)
            {
                throw new ArgumentNullException(nameof(writer));
            }

            if (codeGeneratorContext == null)
            {
                throw new ArgumentNullException(nameof(codeGeneratorContext));
            }

            if (renderAttributeValue == null)
            {
                throw new ArgumentNullException(nameof(renderAttributeValue));
            }

            if (attributeDescriptor.TypeName.Equals(_context.ModelExpressionTypeName, StringComparison.Ordinal))
            {
                writer
                    .WriteStartMethodInvocation(_context.CreateModelExpressionMethodName)
                    .Write(ModelLambdaVariableName)
                    .Write(" => ");
                if (!complexValue)
                {
                    writer
                        .Write(ModelLambdaVariableName)
                        .Write(".");

                }

                renderAttributeValue(writer);

                writer.WriteEndMethodInvocation(endLine: false);
            }
            else
            {
                base.RenderAttributeValue(
                    attributeDescriptor,
                    writer,
                    codeGeneratorContext,
                    renderAttributeValue,
                    complexValue);
            }
        }
        public void RenderAttributeValue_RendersModelExpressionsCorrectly(
            string modelExpressionType,
            string propertyType,
            string expectedValue)
        {
            // Arrange
            var renderer = new MvcTagHelperAttributeValueCodeRenderer(
                new GeneratedTagHelperAttributeContext
                {
                    ModelExpressionTypeName = modelExpressionType,
                    CreateModelExpressionMethodName = "SomeMethod"
                });
            var attributeDescriptor = new TagHelperAttributeDescriptor
            {
                Name = "MyAttribute",
                PropertyName = "SomeProperty",
                TypeName = propertyType,
            };
            var writer = new CSharpCodeWriter();
            var generatorContext = new ChunkGeneratorContext(
                host: null,
                className: string.Empty,
                rootNamespace: string.Empty,
                sourceFile: string.Empty,
                shouldGenerateLinePragmas: true);
            var errorSink = new ErrorSink();
            var context = new CodeGeneratorContext(generatorContext, errorSink);

            // Act
            renderer.RenderAttributeValue(attributeDescriptor, writer, context,
            (codeWriter) =>
            {
                codeWriter.Write("MyValue");
            },
            complexValue: false);

            // Assert
            Assert.Equal(expectedValue, writer.GenerateCode());
        }