public async Task GetErrorResponseType_ReturnsTypeDefinedAtAction()
        {
            // Arrange
            var compilation = await GetCompilation(nameof(GetErrorResponseType_ReturnsTypeDefinedAtAction));

            var expected = compilation.GetTypeByMetadataName(typeof(GetErrorResponseType_ReturnsTypeDefinedAtActionModel).FullName);

            var type        = compilation.GetTypeByMetadataName(typeof(GetErrorResponseType_ReturnsTypeDefinedAtActionController).FullName);
            var method      = (IMethodSymbol)type.GetMembers("Action").First();
            var symbolCache = new ApiControllerSymbolCache(compilation);

            // Act
            var result = SymbolApiResponseMetadataProvider.GetErrorResponseType(symbolCache, method);

            // Assert
            Assert.Same(expected, result);
        }
        public async Task GetErrorResponseType_ReturnsProblemDetails_IfNoAttributeIsDiscovered()
        {
            // Arrange
            var compilation = await GetCompilation(nameof(GetErrorResponseType_ReturnsProblemDetails_IfNoAttributeIsDiscovered));

            var expected = compilation.GetTypeByMetadataName(typeof(ProblemDetails).FullName);

            var type        = compilation.GetTypeByMetadataName(typeof(GetErrorResponseType_ReturnsProblemDetails_IfNoAttributeIsDiscoveredController).FullName);
            var method      = (IMethodSymbol)type.GetMembers("Action").First();
            var symbolCache = new ApiControllerSymbolCache(compilation);

            // Act
            var result = SymbolApiResponseMetadataProvider.GetErrorResponseType(symbolCache, method);

            // Assert
            Assert.Same(expected, result);
        }
        protected override async Task <Document> GetChangedDocumentAsync(CancellationToken cancellationToken)
        {
            var nullableContext = await CreateCodeActionContext(cancellationToken).ConfigureAwait(false);

            if (nullableContext == null)
            {
                return(_document);
            }

            var context = nullableContext.Value;

            var declaredResponseMetadata = SymbolApiResponseMetadataProvider.GetDeclaredResponseMetadata(context.SymbolCache, context.Method);
            var errorResponseType        = SymbolApiResponseMetadataProvider.GetErrorResponseType(context.SymbolCache, context.Method);

            var results = CalculateStatusCodesToApply(context, declaredResponseMetadata);

            if (results.Count == 0)
            {
                return(_document);
            }

            var documentEditor = await DocumentEditor.CreateAsync(_document, cancellationToken).ConfigureAwait(false);

            var addUsingDirective = false;

            foreach (var item in results.OrderBy(s => s.statusCode))
            {
                var statusCode = item.statusCode;
                var returnType = item.typeSymbol;

                AttributeSyntax attributeSyntax;
                bool            addUsing;

                if (statusCode >= 400 && returnType != null && !SymbolEqualityComparer.Default.Equals(returnType, errorResponseType))
                {
                    // If a returnType was discovered and is different from the errorResponseType, use it in the result.
                    attributeSyntax = CreateProducesResponseTypeAttribute(context, statusCode, returnType, out addUsing);
                }
                else
                {
                    attributeSyntax = CreateProducesResponseTypeAttribute(context, statusCode, out addUsing);
                }

                documentEditor.AddAttribute(context.MethodSyntax, attributeSyntax);
                addUsingDirective |= addUsing;
            }

            if (!declaredResponseMetadata.Any(m => m.IsDefault && SymbolEqualityComparer.Default.Equals(m.AttributeSource, context.Method)))
            {
                // Add a ProducesDefaultResponseTypeAttribute if the method does not already have one.
                documentEditor.AddAttribute(context.MethodSyntax, CreateProducesDefaultResponseTypeAttribute());
            }

            var apiConventionMethodAttribute = context.Method.GetAttributes(context.SymbolCache.ApiConventionMethodAttribute).FirstOrDefault();

            if (apiConventionMethodAttribute != null)
            {
                // Remove [ApiConventionMethodAttribute] declared on the method since it's no longer required
                var attributeSyntax = await apiConventionMethodAttribute
                                      .ApplicationSyntaxReference
                                      .GetSyntaxAsync(cancellationToken)
                                      .ConfigureAwait(false);

                documentEditor.RemoveNode(attributeSyntax);
            }

            var document = documentEditor.GetChangedDocument();

            var root = await document.GetSyntaxRootAsync(cancellationToken).ConfigureAwait(false);

            if (root is CompilationUnitSyntax compilationUnit && addUsingDirective)
            {
                const string @namespace = "Microsoft.AspNetCore.Http";

                var declaredUsings = new HashSet <string>(compilationUnit.Usings.Select(x => x.Name.ToString()));

                if (!declaredUsings.Contains(@namespace))
                {
                    root = compilationUnit.AddUsings(SyntaxFactory.UsingDirective(SyntaxFactory.ParseName(@namespace)));
                }
            }

            return(document.WithSyntaxRoot(root));
        }