/// <summary>
        /// Checks if a given method implements IEqualityComparer.Equals or IEquatable.Equals.
        /// </summary>
        private static bool IsEqualsInterfaceImplementation(IMethodSymbol method, Compilation compilation)
        {
            if (method.Name != WellKnownMemberNames.ObjectEquals)
            {
                return(false);
            }

            int paramCount = method.Parameters.Length;

            if (method.ReturnType.SpecialType == SpecialType.System_Boolean &&
                (paramCount == 1 || paramCount == 2))
            {
                // Substitute the type of the first parameter of Equals in the generic interface and then check if that
                // interface method is implemented by the given method.
                INamedTypeSymbol iEqualityComparer = WellKnownTypes.GenericIEqualityComparer(compilation);
                if (method.IsImplementationOfInterfaceMethod(method.Parameters.First().Type, iEqualityComparer, WellKnownMemberNames.ObjectEquals))
                {
                    return(true);
                }

                // Substitute the type of the first parameter of Equals in the generic interface and then check if that
                // interface method is implemented by the given method.
                INamedTypeSymbol iEquatable = WellKnownTypes.GenericIEquatable(compilation);
                if (method.IsImplementationOfInterfaceMethod(method.Parameters.First().Type, iEquatable, WellKnownMemberNames.ObjectEquals))
                {
                    return(true);
                }
            }

            return(false);
        }
        /// <summary>
        /// Checks if a given method implements IEqualityComparer.GetHashCode or IHashCodeProvider.GetHashCode.
        /// </summary>
        /// <param name="method"></param>
        /// <param name="compilation"></param>
        /// <returns></returns>
        private static bool IsGetHashCodeInterfaceImplementation(IMethodSymbol method, Compilation compilation)
        {
            if (method.Name != WellKnownMemberNames.ObjectGetHashCode)
            {
                return(false);
            }

            if (method.ReturnType.SpecialType == SpecialType.System_Int32 && method.Parameters.Length == 1)
            {
                // Substitute the type of the first parameter of Equals in the generic interface and then check if that
                // interface method is implemented by the given method.
                INamedTypeSymbol iEqualityComparer = WellKnownTypes.GenericIEqualityComparer(compilation);
                if (method.IsImplementationOfInterfaceMethod(method.Parameters.First().Type, iEqualityComparer, WellKnownMemberNames.ObjectGetHashCode))
                {
                    return(true);
                }


                INamedTypeSymbol iHashCodeProvider = WellKnownTypes.IHashCodeProvider(compilation);
                if (method.IsImplementationOfInterfaceMethod(null, iHashCodeProvider, WellKnownMemberNames.ObjectGetHashCode))
                {
                    return(true);
                }
            }

            return(false);
        }
        public override void Initialize(AnalysisContext analysisContext)
        {
            analysisContext.EnableConcurrentExecution();
            analysisContext.ConfigureGeneratedCodeAnalysis(GeneratedCodeAnalysisFlags.None);

            analysisContext.RegisterCompilationStartAction(compilationStartAnalysisContext =>
            {
                INamedTypeSymbol equalityComparerType            = WellKnownTypes.GenericIEqualityComparer(compilationStartAnalysisContext.Compilation);
                IMethodSymbol iEqualityComparerGetHashCodeMethod = equalityComparerType?.GetMembers("GetHashCode").Single() as IMethodSymbol;

                // Analyze named types and fields.
                compilationStartAnalysisContext.RegisterSymbolAction(symbolContext =>
                {
                    AnalyzeSymbol(symbolContext.Symbol, symbolContext);
                }, SymbolKind.NamedType, SymbolKind.Field);

                // Analyze properties and methods, and their parameters.
                compilationStartAnalysisContext.RegisterSymbolAction(symbolContext =>
                {
                    var method = symbolContext.Symbol as IMethodSymbol;
                    if (method != null)
                    {
                        if (method.IsEqualsOverride())
                        {
                            // Ignore, given the method signature and parameter names are auto-generated by the IDE:
                            // public override bool Equals(object obj)
                            return;
                        }

                        if (IsIEqualityComparerGetHashCodeInterfaceImplementation(method, iEqualityComparerGetHashCodeMethod))
                        {
                            // Ignore, given the method signature and parameter names are auto-generated by the IDE:
                            // public int GetHashCode(SomeType obj)
                            return;
                        }
                    }

                    AnalyzeSymbol(symbolContext.Symbol, symbolContext);

                    ImmutableArray <IParameterSymbol> parameters = symbolContext.Symbol.Kind == SymbolKind.Property ?
                                                                   ((IPropertySymbol)symbolContext.Symbol).Parameters :
                                                                   ((IMethodSymbol)symbolContext.Symbol).Parameters;

                    foreach (IParameterSymbol param in parameters)
                    {
                        AnalyzeSymbol(param, symbolContext);
                    }
                }, SymbolKind.Property, SymbolKind.Method);
            });
        }