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)); }