private static void AnalyzeType(SymbolAnalysisContext context, SymbolCache symbols)
        {
            var namedTypeSymbol = (INamedTypeSymbol)context.Symbol;

            if (!WebApiFacts.IsWebApiController(namedTypeSymbol, symbols.IHttpControllerAttribute))
            {
                return;
            }

            context.ReportDiagnostic(Diagnostic.Create(Rule, namedTypeSymbol.Locations.FirstOrDefault()));
        }
        public override void Initialize(AnalysisContext context)
        {
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
            context.EnableConcurrentExecution();
            SymbolCache?symbolCache = null;

            context.RegisterCompilationStartAction(compilationStartAction =>
            {
                if (symbolCache is null)
                {
                    if (!SymbolCache.TryCreate(compilationStartAction.Compilation, out var createdSymbolCache))
                    {
                        // No-op if we can't find types we care about.
                        return;
                    }

                    symbolCache = createdSymbolCache;
                }

                compilationStartAction.RegisterOperationBlockAction(operationBlockContext =>
                {
                    if (operationBlockContext.OwningSymbol is not IMethodSymbol method ||
                        method.ContainingType is not INamedTypeSymbol type ||
                        !WebApiFacts.IsWebApiController(type, symbolCache.IHttpControllerAttribute) ||
                        !WebApiFacts.IsWebApiAction(method, symbolCache.NonActionAttribute))
                    {
                        return;
                    }

                    if (method.HasAttribute(symbolCache.IActionHttpMethodProvider))
                    {
                        // Method has already been annotated. We're cool.
                        return;
                    }

                    var verb = SupportedHttpMethodConventions.FirstOrDefault(v => method.Name.StartsWith(v, StringComparison.OrdinalIgnoreCase));
                    // If no verb is inferred, POST is implied.  Either way, we need to tell the user to annotate it to get the correct Mvc behavior.
                    verb ??= "POST";

                    var properties = ImmutableDictionary.Create <string, string>()
                                     .Add("HttpMethodAttribute", $"Http{verb}Attribute");

                    operationBlockContext.ReportDiagnostic(Diagnostic.Create(
                                                               Rule,
                                                               method.Locations.First(),
                                                               properties,
                                                               $"Annotate method with HTTP{verb}Attribute."));
                });
            });
        }
        public override void Initialize(AnalysisContext context)
        {
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
            context.EnableConcurrentExecution();
            SymbolCache?symbolCache = null;

            context.RegisterOperationBlockStartAction(operationBlockContext =>
            {
                if (symbolCache is null)
                {
                    if (!SymbolCache.TryCreate(operationBlockContext.Compilation, out var createdSymbolCache))
                    {
                        // No-op if we can't find types we care about.
                        return;
                    }

                    symbolCache = createdSymbolCache;
                }

                if (operationBlockContext.OwningSymbol is not IMethodSymbol method ||
                    method.ContainingType is not INamedTypeSymbol type ||
                    !WebApiFacts.IsWebApiController(type, symbolCache.IHttpControllerAttribute) ||
                    !WebApiFacts.IsWebApiAction(method, symbolCache.NonActionAttribute))
                {
                    return;
                }

                var returnType = method.ReturnType;

                if (!SymbolEqualityComparer.Default.Equals(returnType, symbolCache.HttpResponseMessage) &&
                    !(SymbolEqualityComparer.Default.Equals(returnType.OriginalDefinition, symbolCache.TaskOfT) &&
                      returnType is INamedTypeSymbol {
                    TypeParameters: { Length: > 0 }
                } namedType&&
                      SymbolEqualityComparer.Default.Equals(namedType.TypeArguments[0], symbolCache.HttpResponseMessage)))
                {
                    // Method does not return HttpResponseMessage
                    return;
                }

                operationBlockContext.RegisterOperationAction(operationContext =>
                {
                    operationContext.ReportDiagnostic(Diagnostic.Create(
                                                          Rule,
                                                          operationContext.Operation.Syntax.GetLocation()));
                }, OperationKind.Return);
            });
        }
        public override void Initialize(AnalysisContext context)
        {
            context.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);
            context.EnableConcurrentExecution();
            SymbolCache?symbolCache = null;

            context.RegisterCompilationStartAction(compilationStartAction =>
            {
                if (symbolCache is null)
                {
                    if (!SymbolCache.TryCreate(compilationStartAction.Compilation, out var createdSymbolCache))
                    {
                        // No-op if we can't find types we care about.
                        return;
                    }

                    symbolCache = createdSymbolCache;
                }

                compilationStartAction.RegisterSymbolAction(symbolAnalysisContext =>
                {
                    if (symbolAnalysisContext.Symbol is not INamedTypeSymbol {
                        TypeKind: TypeKind.Class
                    } type || !WebApiFacts.IsWebApiController(type, symbolCache.ApiController))
                    {
                        return;
                    }

                    var groupedActions = type.GetMembers()
                                         .OfType <IMethodSymbol>()
                                         .Where(m => WebApiFacts.IsWebApiAction(m, symbolCache.NonActionAttribute) && !HasAttributeRoute(symbolCache, m))
                                         .GroupBy(m => m.Name) // Oops, we're not looking at ActionName attribute
                                         .Where(g => g.Count() > 1);

                    foreach (var group in groupedActions)
                    {
                        foreach (var item in group)
                        {
                            symbolAnalysisContext.ReportDiagnostic(Diagnostic.Create(
                                                                       Rule,
                                                                       item.Locations.First(),
                                                                       group.Select(m => m.Locations.First())));
                        }
                    }

                    static bool HasAttributeRoute(SymbolCache symbolCache, IMethodSymbol methodSymbol)
                    {
                        var routeAttributes = methodSymbol.GetAttributes(symbolCache.IRouteTemplateProvider);
                        foreach (var attribute in routeAttributes)
                        {
                            var args = attribute.ConstructorArguments;
                            // This is probably a RouteAttribute or a Http*Attribute. Both of these have exactly one ctor that accepts any value viz the literal template.
                            // Therefore if any value is supplied, it's a value for the route template.
                            if (args.Length > 0 && !args[0].IsNull)
                            {
                                return(true);
                            }
                        }

                        return(false);
                    }
                }, SymbolKind.NamedType);