public async Task GetResponseMetadata_ReturnsValuesFromApiConventionMethodAttribute() { // Arrange var compilation = await GetResponseMetadataCompilation(); var controller = compilation.GetTypeByMetadataName($"{Namespace}.{nameof(GetResponseMetadata_ControllerActionWithAttributes)}"); var method = (IMethodSymbol)controller.GetMembers(nameof(GetResponseMetadata_ControllerActionWithAttributes.GetResponseMetadata_ReturnsValuesFromApiConventionMethodAttribute)).First(); var symbolCache = new ApiControllerSymbolCache(compilation); // Act var result = SymbolApiResponseMetadataProvider.GetDeclaredResponseMetadata(symbolCache, method); // Assert Assert.Collection( result, metadata => { Assert.Equal(200, metadata.StatusCode); Assert.NotNull(metadata.Attribute); }, metadata => { Assert.Equal(404, metadata.StatusCode); Assert.NotNull(metadata.Attribute); }, metadata => { Assert.True(metadata.IsDefault); }); }
protected override async Task <Document> GetChangedDocumentAsync(CancellationToken cancellationToken) { var context = await CreateCodeActionContext(cancellationToken).ConfigureAwait(false); var declaredResponseMetadata = SymbolApiResponseMetadataProvider.GetDeclaredResponseMetadata(context.SymbolCache, context.Method); var statusCodes = CalculateStatusCodesToApply(context, declaredResponseMetadata); if (statusCodes.Count == 0) { return(_document); } var documentEditor = await DocumentEditor.CreateAsync(_document, cancellationToken).ConfigureAwait(false); var addUsingDirective = false; foreach (var statusCode in statusCodes.OrderBy(s => s)) { documentEditor.AddAttribute(context.MethodSyntax, CreateProducesResponseTypeAttribute(context, statusCode, out var addUsing)); addUsingDirective |= addUsing; } if (!declaredResponseMetadata.Any(m => m.IsDefault && 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)); }
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); }
private async Task GetStatusCodeTest(string actionName, int expected) { var compilation = await GetResponseMetadataCompilation(); var controller = compilation.GetTypeByMetadataName($"{Namespace}.{nameof(GetResponseMetadata_ControllerActionWithAttributes)}"); var method = (IMethodSymbol)controller.GetMembers(actionName).First(); var attribute = method.GetAttributes().First(); var statusCode = SymbolApiResponseMetadataProvider.GetStatusCode(attribute); Assert.Equal(expected, statusCode); }
public async Task GetDefaultStatusCode_ReturnsValueDefinedUsingHttpStatusCast() { // Arrange var compilation = await GetCompilation("GetDefaultStatusCodeTest"); var attribute = compilation.GetTypeByMetadataName(typeof(TestActionResultUsingHttpStatusCodeCast).FullName).GetAttributes()[0]; // Act var actual = SymbolApiResponseMetadataProvider.GetDefaultStatusCode(attribute); // Assert Assert.Equal(302, actual); }
public async Task GetResponseMetadata_IgnoresProducesAttribute() { // Arrange var compilation = await GetResponseMetadataCompilation(); var controller = compilation.GetTypeByMetadataName($"{Namespace}.{nameof(GetResponseMetadata_ControllerActionWithAttributes)}"); var method = (IMethodSymbol)controller.GetMembers(nameof(GetResponseMetadata_ControllerActionWithAttributes.ActionWithProducesAttribute)).First(); var symbolCache = new ApiControllerSymbolCache(compilation); // Act var result = SymbolApiResponseMetadataProvider.GetDeclaredResponseMetadata(symbolCache, method); // Assert Assert.Collection( result, metadata => Assert.True(metadata.IsImplicit)); }
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); }
public async Task GetResponseMetadata_ReturnsEmptySequence_IfNoAttributesArePresent_ForPostAction() { // Arrange var compilation = await GetResponseMetadataCompilation(); var controller = compilation.GetTypeByMetadataName($"{Namespace}.{nameof(GetResponseMetadata_ControllerWithoutConvention)}"); var method = (IMethodSymbol)controller.GetMembers(nameof(GetResponseMetadata_ControllerWithoutConvention.PostPerson)).First(); var symbolCache = new ApiControllerSymbolCache(compilation); // Act var result = SymbolApiResponseMetadataProvider.GetDeclaredResponseMetadata(symbolCache, method); // Assert Assert.Collection( result, metadata => Assert.True(metadata.IsImplicit)); }
private async Task <(bool result, IList <ActualApiResponseMetadata> responseMetadatas, TestSource testSource)> TryGetActualResponseMetadata(string typeName, string methodName) { var testSource = MvcTestSource.Read(GetType().Name, "TryGetActualResponseMetadataTests"); var project = DiagnosticProject.Create(GetType().Assembly, new[] { testSource.Source }); var compilation = await GetCompilation("TryGetActualResponseMetadataTests"); var type = compilation.GetTypeByMetadataName(typeName); var method = (IMethodSymbol)type.GetMembers(methodName).First(); var symbolCache = new ApiControllerSymbolCache(compilation); var syntaxTree = method.DeclaringSyntaxReferences[0].SyntaxTree; var methodSyntax = (MethodDeclarationSyntax)syntaxTree.GetRoot().FindNode(method.Locations[0].SourceSpan); var semanticModel = compilation.GetSemanticModel(syntaxTree); var result = SymbolApiResponseMetadataProvider.TryGetActualResponseMetadata(symbolCache, semanticModel, methodSyntax, CancellationToken.None, out var responseMetadatas); return(result, responseMetadatas, testSource); }
private async Task <ActualApiResponseMetadata?> RunInspectReturnStatementSyntax(string source, string test) { var project = DiagnosticProject.Create(GetType().Assembly, new[] { source }); var compilation = await project.GetCompilationAsync(); var symbolCache = new ApiControllerSymbolCache(compilation); 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(); return(SymbolApiResponseMetadataProvider.InspectReturnStatementSyntax( symbolCache, compilation.GetSemanticModel(syntaxTree), returnStatement, CancellationToken.None)); }
protected override async Task <Document> GetChangedDocumentAsync(CancellationToken cancellationToken) { var context = await CreateCodeActionContext(cancellationToken).ConfigureAwait(false); var declaredResponseMetadata = SymbolApiResponseMetadataProvider.GetDeclaredResponseMetadata(context.SymbolCache, context.Method); var statusCodes = CalculateStatusCodesToApply(context, declaredResponseMetadata); if (statusCodes.Count == 0) { return(_document); } var documentEditor = await DocumentEditor.CreateAsync(_document, cancellationToken).ConfigureAwait(false); foreach (var statusCode in statusCodes.OrderBy(s => s)) { documentEditor.AddAttribute(context.MethodSyntax, CreateProducesResponseTypeAttribute(statusCode)); } if (!declaredResponseMetadata.Any(m => m.IsDefault && 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); } return(documentEditor.GetChangedDocument()); }
private async Task GetResponseMetadata_WorksForInvalidOrUnsupportedAttributes(string typeName, string methodName) { // Arrange var compilation = await GetResponseMetadataCompilation(); var controller = compilation.GetTypeByMetadataName($"{Namespace}.{typeName}"); var method = (IMethodSymbol)controller.GetMembers(methodName).First(); var symbolCache = new ApiControllerSymbolCache(compilation); // Act var result = SymbolApiResponseMetadataProvider.GetDeclaredResponseMetadata(symbolCache, method); // Assert Assert.Collection( result, metadata => { Assert.Equal(200, metadata.StatusCode); Assert.Same(method, metadata.AttributeSource); }); }
public async Task GetDeclaredResponseMetadata_ApiConventionTypeAttributeOnBaseType_Works() { // Arrange var type = typeof(GetDeclaredResponseMetadata_ApiConventionTypeAttributeOnBaseType); var compilation = await GetResponseMetadataCompilation(); var controller = compilation.GetTypeByMetadataName(type.FullName); var method = (IMethodSymbol)controller.GetMembers().First(); var symbolCache = new ApiControllerSymbolCache(compilation); // Act var result = SymbolApiResponseMetadataProvider.GetDeclaredResponseMetadata(symbolCache, method); // Assert // We should expect 3 entries specified by DefaultApiConventions.Post Assert.Collection( result.OrderBy(r => r.StatusCode), metadata => Assert.True(metadata.IsDefault), metadata => Assert.Equal(201, metadata.StatusCode), metadata => Assert.Equal(400, metadata.StatusCode)); }
public async Task GetResponseMetadata_ReturnsValueFromProducesResponseType_WhenStatusCodeIsSpecifiedInConstructorWithResponseType() { // Arrange var compilation = await GetResponseMetadataCompilation(); var controller = compilation.GetTypeByMetadataName($"{Namespace}.{nameof(GetResponseMetadata_ControllerActionWithAttributes)}"); var method = (IMethodSymbol)controller.GetMembers(nameof(GetResponseMetadata_ControllerActionWithAttributes.ActionWithProducesResponseType_StatusCodeAndTypeInConstructor)).First(); var symbolCache = new ApiControllerSymbolCache(compilation); // Act var result = SymbolApiResponseMetadataProvider.GetDeclaredResponseMetadata(symbolCache, method); // Assert Assert.Collection( result, metadata => { Assert.Equal(202, metadata.StatusCode); Assert.NotNull(metadata.Attribute); Assert.Equal(method, metadata.AttributeSource); }); }
public async Task GetResponseMetadata_WithProducesResponseTypeAndApiConventionMethod() { // Arrange var compilation = await GetResponseMetadataCompilation(); var controller = compilation.GetTypeByMetadataName($"{Namespace}.{nameof(GetResponseMetadata_ControllerActionWithAttributes)}"); var method = (IMethodSymbol)controller.GetMembers(nameof(GetResponseMetadata_ControllerActionWithAttributes.GetResponseMetadata_WithProducesResponseTypeAndApiConventionMethod)).First(); Assert.True(ApiControllerSymbolCache.TryCreate(compilation, out var symbolCache)); // Act var result = SymbolApiResponseMetadataProvider.GetDeclaredResponseMetadata(symbolCache, method); // Assert Assert.Collection( result, metadata => { Assert.Equal(204, metadata.StatusCode); Assert.NotNull(metadata.Attribute); }); }
private ICollection <int> CalculateStatusCodesToApply(CodeActionContext context, IList <DeclaredApiResponseMetadata> declaredResponseMetadata) { if (!SymbolApiResponseMetadataProvider.TryGetActualResponseMetadata(context.SymbolCache, context.SemanticModel, context.MethodSyntax, context.CancellationToken, out var actualResponseMetadata)) { // If we cannot parse metadata correctly, don't offer fixes. return(Array.Empty <int>()); } var statusCodes = new HashSet <int>(); foreach (var metadata in actualResponseMetadata) { if (DeclaredApiResponseMetadata.TryGetDeclaredMetadata(declaredResponseMetadata, metadata, result: out var declaredMetadata) && declaredMetadata.AttributeSource == context.Method) { // A ProducesResponseType attribute is declared on the method for the current status code. continue; } statusCodes.Add(metadata.IsDefaultResponse ? 200 : metadata.StatusCode); } return(statusCodes); }
private void InitializeWorker(CompilationStartAnalysisContext context, ApiControllerSymbolCache symbolCache) { context.RegisterOperationAction(operationAnalysisContext => { var ifOperation = (IConditionalOperation)operationAnalysisContext.Operation; if (!(ifOperation.Syntax is IfStatementSyntax ifStatement)) { return; } if (ifOperation.WhenTrue == null || ifOperation.WhenFalse != null) { // We only support expressions of the format // if (!ModelState.IsValid) // or // if (ModelState.IsValid == false) // If the conditional is misisng a true condition or has an else expression, skip this operation. return; } var parent = ifOperation.Parent; if (parent?.Kind == OperationKind.Block) { parent = parent?.Parent; } if (parent?.Kind != OperationKind.MethodBodyOperation) { // Only support top-level ModelState IsValid checks. return; } var trueStatement = UnwrapSingleStatementBlock(ifOperation.WhenTrue); if (trueStatement.Kind != OperationKind.Return) { // We need to verify that the if statement does a ModelState.IsValid check and that the block inside contains // a single return statement returning a 400. We'l get to it in just a bit return; } if (!(parent.Syntax is MethodDeclarationSyntax methodSyntax)) { return; } var semanticModel = operationAnalysisContext.Compilation.GetSemanticModel(methodSyntax.SyntaxTree); var methodSymbol = semanticModel.GetDeclaredSymbol(methodSyntax, operationAnalysisContext.CancellationToken); if (!ApiControllerFacts.IsApiControllerAction(symbolCache, methodSymbol)) { // Not a ApiController. Nothing to do here. return; } if (!IsModelStateIsValidCheck(symbolCache, ifOperation.Condition)) { return; } var returnOperation = (IReturnOperation)trueStatement; var returnValue = returnOperation.ReturnedValue; if (returnValue == null || !symbolCache.IActionResult.IsAssignableFrom(returnValue.Type)) { return; } var returnStatementSyntax = (ReturnStatementSyntax)returnOperation.Syntax; var actualMetadata = SymbolApiResponseMetadataProvider.InspectReturnStatementSyntax( symbolCache, semanticModel, returnStatementSyntax, operationAnalysisContext.CancellationToken); if (actualMetadata == null || actualMetadata.Value.StatusCode != 400) { return; } var additionalLocations = new[] { ifStatement.GetLocation(), returnStatementSyntax.GetLocation(), }; operationAnalysisContext.ReportDiagnostic( Diagnostic.Create( ApiDiagnosticDescriptors.API1003_ApiActionsDoNotRequireExplicitModelValidationCheck, ifStatement.GetLocation(), additionalLocations: additionalLocations)); }, OperationKind.Conditional); }
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))); } } if (root == null) { throw new ArgumentNullException(nameof(root)); } return(document.WithSyntaxRoot(root)); }
private void InitializeWorker(CompilationStartAnalysisContext compilationStartAnalysisContext, ApiControllerSymbolCache symbolCache) { compilationStartAnalysisContext.RegisterSyntaxNodeAction(syntaxNodeContext => { var cancellationToken = syntaxNodeContext.CancellationToken; var methodSyntax = (MethodDeclarationSyntax)syntaxNodeContext.Node; var semanticModel = syntaxNodeContext.SemanticModel; var method = semanticModel.GetDeclaredSymbol(methodSyntax, syntaxNodeContext.CancellationToken); if (!ApiControllerFacts.IsApiControllerAction(symbolCache, method)) { return; } var declaredResponseMetadata = SymbolApiResponseMetadataProvider.GetDeclaredResponseMetadata(symbolCache, method); var hasUnreadableStatusCodes = !ActualApiResponseMetadataFactory.TryGetActualResponseMetadata(symbolCache, semanticModel, methodSyntax, cancellationToken, out var actualResponseMetadata); var hasUndocumentedStatusCodes = false; foreach (var actualMetadata in actualResponseMetadata) { var location = actualMetadata.ReturnStatement.GetLocation(); if (!DeclaredApiResponseMetadata.Contains(declaredResponseMetadata, actualMetadata)) { hasUndocumentedStatusCodes = true; if (actualMetadata.IsDefaultResponse) { syntaxNodeContext.ReportDiagnostic(Diagnostic.Create( ApiDiagnosticDescriptors.API1001_ActionReturnsUndocumentedSuccessResult, location)); } else { syntaxNodeContext.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)) { syntaxNodeContext.ReportDiagnostic(Diagnostic.Create( ApiDiagnosticDescriptors.API1002_ActionDoesNotReturnDocumentedStatusCode, methodSyntax.Identifier.GetLocation(), declaredMetadata.StatusCode)); } } }, SyntaxKind.MethodDeclaration); }