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