예제 #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);
    }
예제 #2
0
    public void Matches_ReturnsTrue_IfDeclaredMetadataAndActualMetadataHaveSameStatusCode()
    {
        // Arrange
        var declaredMetadata = DeclaredApiResponseMetadata.ForProducesResponseType(302, AttributeData, Mock.Of <IMethodSymbol>());
        var actualMetadata   = new ActualApiResponseMetadata(ReturnExpression, 302, null);

        // Act
        var matches = declaredMetadata.Matches(actualMetadata);

        // Assert
        Assert.True(matches);
    }
예제 #3
0
    public void Matches_ReturnsFalse_IfDeclaredMetadataIs201_AndActualMetadataIs200()
    {
        // Arrange
        var declaredMetadata = DeclaredApiResponseMetadata.ForProducesResponseType(201, AttributeData, Mock.Of <IMethodSymbol>());
        var actualMetadata   = new ActualApiResponseMetadata(ReturnExpression, 200, null);

        // Act
        var matches = declaredMetadata.Matches(actualMetadata);

        // Assert
        Assert.False(matches);
    }
예제 #4
0
    public void Matches_ReturnsFalse_IfDeclaredMetadataIsDefault_AndActualMetadataIsNotErrorStatusCode()
    {
        // Arrange
        var declaredMetadata = DeclaredApiResponseMetadata.ForProducesDefaultResponse(AttributeData, Mock.Of <IMethodSymbol>());
        var actualMetadata   = new ActualApiResponseMetadata(ReturnExpression, 204, null);

        // Act
        var matches = declaredMetadata.Matches(actualMetadata);

        // Assert
        Assert.False(matches);
    }
    internal static bool TryGetDeclaredMetadata(
        IList <DeclaredApiResponseMetadata> declaredApiResponseMetadata,
        ActualApiResponseMetadata actualMetadata,
        out DeclaredApiResponseMetadata result)
    {
        for (var i = 0; i < declaredApiResponseMetadata.Count; i++)
        {
            var declaredMetadata = declaredApiResponseMetadata[i];

            if (declaredMetadata.Matches(actualMetadata))
            {
                result = declaredMetadata;
                return(true);
            }
        }

        result = default;
        return(false);
    }
예제 #6
0
    internal static bool Contains(IList <ActualApiResponseMetadata> actualResponseMetadata, DeclaredApiResponseMetadata declaredMetadata)
    {
        for (var i = 0; i < actualResponseMetadata.Count; i++)
        {
            if (declaredMetadata.Matches(actualResponseMetadata[i]))
            {
                return(true);
            }
        }

        return(false);
    }