Exemplo n.º 1
0
    private void InitializeWorker(CompilationStartAnalysisContext compilationStartAnalysisContext, ApiControllerSymbolCache symbolCache)
    {
        compilationStartAnalysisContext.RegisterOperationAction(operationStartContext =>
        {
            var method = (IMethodSymbol)operationStartContext.ContainingSymbol;
            if (!ApiControllerFacts.IsApiControllerAction(symbolCache, method))
            {
                return;
            }

            var declaredResponseMetadata = SymbolApiResponseMetadataProvider.GetDeclaredResponseMetadata(symbolCache, method);
            var hasUnreadableStatusCodes = !ActualApiResponseMetadataFactory.TryGetActualResponseMetadata(symbolCache, (IMethodBodyOperation)operationStartContext.Operation, operationStartContext.CancellationToken, out var actualResponseMetadata);

            var hasUndocumentedStatusCodes = false;
            foreach (var actualMetadata in actualResponseMetadata)
            {
                var location = actualMetadata.ReturnOperation.ReturnedValue.Syntax.GetLocation();

                if (!DeclaredApiResponseMetadata.Contains(declaredResponseMetadata, actualMetadata))
                {
                    hasUndocumentedStatusCodes = true;
                    if (actualMetadata.IsDefaultResponse)
                    {
                        operationStartContext.ReportDiagnostic(Diagnostic.Create(
                                                                   ApiDiagnosticDescriptors.API1001_ActionReturnsUndocumentedSuccessResult,
                                                                   location));
                    }
                    else
                    {
                        operationStartContext.ReportDiagnostic(Diagnostic.Create(
                                                                   ApiDiagnosticDescriptors.API1000_ActionReturnsUndocumentedStatusCode,
                                                                   location,
                                                                   actualMetadata.StatusCode));
                    }
                }
            }

            if (hasUndocumentedStatusCodes || hasUnreadableStatusCodes)
            {
                // If we produced analyzer warnings about undocumented status codes, don't attempt to determine
                // if there are documented status codes that are missing from the method body.
                return;
            }

            for (var i = 0; i < declaredResponseMetadata.Count; i++)
            {
                var declaredMetadata = declaredResponseMetadata[i];
                if (!Contains(actualResponseMetadata, declaredMetadata))
                {
                    operationStartContext.ReportDiagnostic(Diagnostic.Create(
                                                               ApiDiagnosticDescriptors.API1002_ActionDoesNotReturnDocumentedStatusCode,
                                                               method.Locations[0],
                                                               declaredMetadata.StatusCode));
                }
            }
        }, OperationKind.MethodBody);
    }
Exemplo n.º 2
0
    public async Task GetDefaultStatusCode_ReturnsValueDefinedUsingHttpStatusCast()
    {
        // Arrange
        var compilation = await GetCompilation("GetDefaultStatusCodeTest");

        var attribute = compilation.GetTypeByMetadataName(typeof(TestActionResultUsingHttpStatusCodeCast).FullName).GetAttributes()[0];

        // Act
        var actual = ActualApiResponseMetadataFactory.GetDefaultStatusCode(attribute);

        // Assert
        Assert.Equal(302, actual);
    }
Exemplo n.º 3
0
    private async Task <ActualApiResponseMetadata?> RunInspectReturnStatementSyntax(string source, string test)
    {
        var project     = MvcDiagnosticAnalyzerRunner.CreateProjectWithReferencesInBinDir(GetType().Assembly, new[] { source });
        var compilation = await project.GetCompilationAsync();

        Assert.True(ApiControllerSymbolCache.TryCreate(compilation, out var symbolCache));

        var returnType = compilation.GetTypeByMetadataName($"{Namespace}.{test}");
        var syntaxTree = returnType.DeclaringSyntaxReferences[0].SyntaxTree;

        var method          = (IMethodSymbol)returnType.GetMembers().First();
        var methodSyntax    = syntaxTree.GetRoot().FindNode(method.Locations[0].SourceSpan);
        var returnStatement = methodSyntax.DescendantNodes().OfType <ReturnStatementSyntax>().First();
        var returnOperation = (IReturnOperation)compilation.GetSemanticModel(syntaxTree).GetOperation(returnStatement);

        return(ActualApiResponseMetadataFactory.InspectReturnOperation(
                   symbolCache,
                   returnOperation));
    }
Exemplo n.º 4
0
    private async Task <ActualApiResponseMetadata?> RunInspectReturnStatementSyntax([CallerMemberName] string test = null)
    {
        // Arrange
        var compilation = await GetCompilation("InspectReturnExpressionTests");

        Assert.True(ApiControllerSymbolCache.TryCreate(compilation, out var symbolCache));

        var controllerType = compilation.GetTypeByMetadataName(typeof(TestFiles.InspectReturnExpressionTests.TestController).FullName);
        var syntaxTree     = controllerType.DeclaringSyntaxReferences[0].SyntaxTree;

        var method          = (IMethodSymbol)Assert.Single(controllerType.GetMembers(test));
        var methodSyntax    = syntaxTree.GetRoot().FindNode(method.Locations[0].SourceSpan);
        var returnStatement = methodSyntax.DescendantNodes().OfType <ReturnStatementSyntax>().First();
        var returnOperation = (IReturnOperation)compilation.GetSemanticModel(syntaxTree).GetOperation(returnStatement);

        return(ActualApiResponseMetadataFactory.InspectReturnOperation(
                   symbolCache,
                   returnOperation));
    }
Exemplo n.º 5
0
    private async Task <(bool result, IList <ActualApiResponseMetadata> responseMetadatas, TestSource testSource)> TryGetActualResponseMetadata(string typeName, string methodName)
    {
        var testSource = MvcTestSource.Read(GetType().Name, "TryGetActualResponseMetadataTests");
        var project    = MvcDiagnosticAnalyzerRunner.CreateProjectWithReferencesInBinDir(GetType().Assembly, new[] { testSource.Source });

        var compilation = await GetCompilation("TryGetActualResponseMetadataTests");

        var type   = compilation.GetTypeByMetadataName(typeName);
        var method = (IMethodSymbol)type.GetMembers(methodName).First();

        Assert.True(ApiControllerSymbolCache.TryCreate(compilation, out var symbolCache));

        var syntaxTree      = method.DeclaringSyntaxReferences[0].SyntaxTree;
        var methodSyntax    = (MethodDeclarationSyntax)syntaxTree.GetRoot().FindNode(method.Locations[0].SourceSpan);
        var methodOperation = (IMethodBodyBaseOperation)compilation.GetSemanticModel(syntaxTree).GetOperation(methodSyntax);

        var result = ActualApiResponseMetadataFactory.TryGetActualResponseMetadata(symbolCache, methodOperation, CancellationToken.None, out var responseMetadatas);

        return(result, responseMetadatas, testSource);
    }
Exemplo n.º 6
0
    public async Task InspectReturnExpression_ReturnsNull_IfReturnExpressionCannotBeFound()
    {
        // Arrange & Act
        var source      = @"
            using Microsoft.AspNetCore.Mvc;

namespace Microsoft.AspNetCore.Mvc.Api.Analyzers
{
    [ApiController]
    public class TestController : ControllerBase
    {
        public IActionResult Get(int id)
        {
            return new DoesNotExist(id);
        }
    }
}";
        var project     = MvcDiagnosticAnalyzerRunner.CreateProjectWithReferencesInBinDir(GetType().Assembly, new[] { source });
        var compilation = await project.GetCompilationAsync();

        Assert.True(ApiControllerSymbolCache.TryCreate(compilation, out var symbolCache));

        var returnType = compilation.GetTypeByMetadataName($"{Namespace}.TestController");
        var syntaxTree = returnType.DeclaringSyntaxReferences[0].SyntaxTree;

        var method          = (IMethodSymbol)returnType.GetMembers().First();
        var methodSyntax    = syntaxTree.GetRoot().FindNode(method.Locations[0].SourceSpan);
        var returnStatement = methodSyntax.DescendantNodes().OfType <ReturnStatementSyntax>().First();
        var returnOperation = (IReturnOperation)compilation.GetSemanticModel(syntaxTree).GetOperation(returnStatement);

        var actualResponseMetadata = ActualApiResponseMetadataFactory.InspectReturnOperation(
            symbolCache,
            returnOperation);

        // Assert
        Assert.Null(actualResponseMetadata);
    }