private static void CheckClassWithOnlyUnusedPrivateConstructors(SymbolAnalysisContext context)
        {
            var namedType = context.Symbol as INamedTypeSymbol;
            if (!namedType.IsClass() ||
                namedType.IsStatic)
            {
                return;
            }

            var members = namedType.GetMembers();
            var constructors = GetConstructors(members).ToList();

            if (!constructors.Any() ||
                HasNonPrivateConstructor(constructors) ||
                HasOnlyStaticMembers(members.Except(constructors).ToList()))
            {
                return;
            }

            var classDeclarations = new RemovableDeclarationCollector(namedType, context.Compilation).ClassDeclarations;

            if (!IsAnyConstructorCalled(namedType, classDeclarations))
            {
                var message = constructors.Count > 1
                    ? "at least one of its constructors"
                    : "its constructor";

                foreach (var classDeclaration in classDeclarations)
                {
                    context.ReportDiagnosticIfNonGenerated(Diagnostic.Create(Rule, classDeclaration.SyntaxNode.Identifier.GetLocation(),
                        message));
                }
            }
        }
        protected override void Initialize(SonarAnalysisContext context)
        {
            context.RegisterSymbolAction(
                c =>
                {
                    var namedType = (INamedTypeSymbol)c.Symbol;
                    if (!namedType.IsClassOrStruct() ||
                        namedType.ContainingType != null)
                    {
                        return;
                    }

                    var removableDeclarationCollector = new RemovableDeclarationCollector(namedType, c.Compilation);

                    var candidateFields = removableDeclarationCollector.GetRemovableFieldLikeDeclarations(
                        ImmutableHashSet.Create(SyntaxKind.FieldDeclaration), maxAccessibility)
                        .Where(tuple => !IsInitializedOrFixed(((VariableDeclaratorSyntax)tuple.SyntaxNode)));

                    var candidateProperties = removableDeclarationCollector.GetRemovableDeclarations(
                        ImmutableHashSet.Create(SyntaxKind.PropertyDeclaration), maxAccessibility)
                        .Where(tuple => IsAutoPropertyWithNoInitializer((PropertyDeclarationSyntax)tuple.SyntaxNode));

                    var allCandidateMembers = candidateFields.Concat(candidateProperties).ToList();
                    if (!allCandidateMembers.Any())
                    {
                        return;
                    }

                    var usedMembers = GetMemberUsages(removableDeclarationCollector, new HashSet<ISymbol>(allCandidateMembers.Select(t => t.Symbol)));
                    var usedMemberSymbols = new HashSet<ISymbol>(usedMembers.Select(tuple => tuple.Symbol));

                    var assignedMemberSymbols = GetAssignedMemberSymbols(usedMembers);

                    foreach (var candidateMember in allCandidateMembers)
                    {
                        if (!usedMemberSymbols.Contains(candidateMember.Symbol))
                        {
                            /// reported by <see cref="UnusedPrivateMember"/>
                            continue;
                        }

                        if (!assignedMemberSymbols.Contains(candidateMember.Symbol))
                        {
                            var field = candidateMember.SyntaxNode as VariableDeclaratorSyntax;
                            var property = candidateMember.SyntaxNode as PropertyDeclarationSyntax;

                            var memberType = field != null ? "field" : "auto-property";

                            var location = field != null
                                ? field.Identifier.GetLocation()
                                : property.Identifier.GetLocation();

                            c.ReportDiagnosticIfNonGenerated(Diagnostic.Create(Rule, location, memberType, candidateMember.Symbol.Name));
                        }
                    }
                },
                SymbolKind.NamedType);
        }
        protected override void Initialize(SonarAnalysisContext context)
        {
            context.RegisterSymbolAction(
                c =>
                {
                    var namedType = (INamedTypeSymbol)c.Symbol;
                    if (!namedType.IsClassOrStruct() ||
                        namedType.ContainingType != null)
                    {
                        return;
                    }

                    var removableDeclarationCollector = new RemovableDeclarationCollector(namedType, c.Compilation);

                    var removableEvents = removableDeclarationCollector.GetRemovableDeclarations(
                        ImmutableHashSet.Create(SyntaxKind.EventDeclaration), maxAccessibility);
                    var removableEventFields = removableDeclarationCollector.GetRemovableFieldLikeDeclarations(
                        ImmutableHashSet.Create(SyntaxKind.EventFieldDeclaration), maxAccessibility);

                    var allRemovableEvents = removableEvents.Concat(removableEventFields).ToList();
                    if (!allRemovableEvents.Any())
                    {
                        return;
                    }

                    var symbolNames = allRemovableEvents.Select(t => t.Symbol.Name).ToImmutableHashSet();
                    var usedSymbols = GetReferencedSymbolsWithMatchingNames(removableDeclarationCollector, symbolNames);
                    var invokedSymbols = GetInvokedEventSymbols(removableDeclarationCollector);
                    var possiblyCopiedSymbols = GetPossiblyCopiedSymbols(removableDeclarationCollector);

                    foreach (var removableEvent in allRemovableEvents)
                    {
                        if (!usedSymbols.Contains(removableEvent.Symbol))
                        {
                            /// reported by <see cref="UnusedPrivateMember"/>
                            continue;
                        }

                        if (!invokedSymbols.Contains(removableEvent.Symbol) &&
                            !possiblyCopiedSymbols.Contains(removableEvent.Symbol))
                        {
                            var eventField = removableEvent.SyntaxNode as VariableDeclaratorSyntax;
                            var location = eventField != null
                                ? eventField.Identifier.GetLocation()
                                : ((EventDeclarationSyntax)removableEvent.SyntaxNode).Identifier.GetLocation();

                            c.ReportDiagnosticIfNonGenerated(Diagnostic.Create(Rule, location));
                        }
                    }
                },
                SymbolKind.NamedType);
        }
        protected override void Initialize(SonarAnalysisContext context)
        {
            context.RegisterSymbolAction(
                c =>
                {
                    var namedType = (INamedTypeSymbol)c.Symbol;
                    if (!namedType.IsClassOrStruct() ||
                        namedType.ContainingType != null)
                    {
                        return;
                    }

                    var removableDeclarationCollector = new RemovableDeclarationCollector(namedType, c.Compilation);

                    var declaredPrivateMethodsWithReturn = CollectRemovableMethods(removableDeclarationCollector).ToList();
                    if (!declaredPrivateMethodsWithReturn.Any())
                    {
                        return;
                    }

                    var invocations = CollectInvocations(removableDeclarationCollector.ClassDeclarations).ToList();

                    foreach (var declaredPrivateMethodWithReturn in declaredPrivateMethodsWithReturn)
                    {
                        var matchingInvocations = invocations
                            .Where(inv => object.Equals(inv.Symbol.OriginalDefinition, declaredPrivateMethodWithReturn.Symbol))
                            .ToList();

                        if (!matchingInvocations.Any())
                        {
                            /// this is handled by S1144 <see cref="UnusedPrivateMember"/>
                            continue;
                        }

                        if (!IsReturnValueUsed(matchingInvocations))
                        {
                            c.ReportDiagnostic(Diagnostic.Create(Rule, declaredPrivateMethodWithReturn.SyntaxNode.ReturnType.GetLocation()));
                        }
                    }
                },
                SymbolKind.NamedType);
        }
        protected override void Initialize(SonarAnalysisContext context)
        {
            context.RegisterSymbolAction(
                c =>
                {
                    var namedType = (INamedTypeSymbol)c.Symbol;
                    if (!namedType.IsClassOrStruct() ||
                        namedType.ContainingType != null)
                    {
                        return;
                    }

                    var declarationCollector = new RemovableDeclarationCollector(namedType, c.Compilation);

                    var declaredPrivateSymbols = new HashSet<ISymbol>();
                    var fieldLikeSymbols = new BidirectionalDictionary<ISymbol, SyntaxNode>();

                    CollectRemovableNamedTypes(declarationCollector, declaredPrivateSymbols);
                    CollectRemovableFieldLikeDeclarations(declarationCollector, declaredPrivateSymbols, fieldLikeSymbols);
                    CollectRemovableEventsAndProperties(declarationCollector, declaredPrivateSymbols);
                    CollectRemovableMethods(declarationCollector, declaredPrivateSymbols);

                    if (!declaredPrivateSymbols.Any())
                    {
                        return;
                    }

                    var usedSymbols = new HashSet<ISymbol>();
                    var emptyConstructors = new HashSet<ISymbol>();

                    CollectUsedSymbols(declarationCollector, usedSymbols, declaredPrivateSymbols);
                    CollectUsedSymbolsFromCtorInitializerAndCollectEmptyCtors(declarationCollector,
                        usedSymbols, emptyConstructors);

                    ReportIssues(c, usedSymbols, declaredPrivateSymbols, emptyConstructors, fieldLikeSymbols);
                },
                SymbolKind.NamedType);
        }
        private static IList<MemberUsage> GetMemberUsages(RemovableDeclarationCollector removableDeclarationCollector,
            HashSet<ISymbol> declaredPrivateSymbols)
        {
            var symbolNames = declaredPrivateSymbols.Select(s => s.Name).ToImmutableHashSet();

            var identifiers = removableDeclarationCollector.TypeDeclarations
                .SelectMany(container => container.SyntaxNode.DescendantNodes()
                    .Where(node => node.IsKind(SyntaxKind.IdentifierName))
                    .Cast<IdentifierNameSyntax>()
                    .Where(node => symbolNames.Contains(node.Identifier.ValueText))
                    .Select(node =>
                        new MemberUsage
                        {
                            SyntaxNode = node,
                            SemanticModel = container.SemanticModel,
                            Symbol = container.SemanticModel.GetSymbolInfo(node).Symbol
                        }));

            var generic = removableDeclarationCollector.TypeDeclarations
                .SelectMany(container => container.SyntaxNode.DescendantNodes()
                    .Where(node => node.IsKind(SyntaxKind.GenericName))
                    .Cast<GenericNameSyntax>()
                    .Where(node => symbolNames.Contains(node.Identifier.ValueText))
                    .Select(node =>
                        new MemberUsage
                        {
                            SyntaxNode = node,
                            SemanticModel = container.SemanticModel,
                            Symbol = container.SemanticModel.GetSymbolInfo(node).Symbol
                        }));

            return identifiers.Concat(generic)
                .Where(tuple => tuple.Symbol is IFieldSymbol || tuple.Symbol is IPropertySymbol)
                .ToList();
        }
        private static ISet<ISymbol> GetPossiblyCopiedSymbols(RemovableDeclarationCollector removableDeclarationCollector)
        {
            var usedSymbols = new HashSet<ISymbol>();

            var arguments = removableDeclarationCollector.TypeDeclarations
                .SelectMany(container => container.SyntaxNode.DescendantNodes()
                    .Where(node =>
                        node.IsKind(SyntaxKind.Argument))
                    .Cast<ArgumentSyntax>()
                    .Select(node =>
                        new SyntaxNodeSemanticModelTuple<SyntaxNode>
                        {
                            SyntaxNode = node.Expression,
                            SemanticModel = container.SemanticModel
                        }));

            var equalsValue = removableDeclarationCollector.TypeDeclarations
                .SelectMany(container => container.SyntaxNode.DescendantNodes()
                    .OfType<EqualsValueClauseSyntax>()
                    .Select(node =>
                        new SyntaxNodeSemanticModelTuple<SyntaxNode>
                        {
                            SyntaxNode = node.Value,
                            SemanticModel = container.SemanticModel
                        }));

            var assignment = removableDeclarationCollector.TypeDeclarations
                .SelectMany(container => container.SyntaxNode.DescendantNodes()
                    .Where(node =>
                        node.IsKind(SyntaxKind.SimpleAssignmentExpression))
                    .Cast<AssignmentExpressionSyntax>()
                    .Select(node =>
                        new SyntaxNodeSemanticModelTuple<SyntaxNode>
                        {
                            SyntaxNode = node.Right,
                            SemanticModel = container.SemanticModel
                        }));

            var allNodes = arguments
                .Concat(equalsValue)
                .Concat(assignment);

            foreach (var node in allNodes)
            {
                var symbol = node.SemanticModel.GetSymbolInfo(node.SyntaxNode).Symbol as IEventSymbol;

                if (symbol != null)
                {
                    usedSymbols.Add(symbol.OriginalDefinition);
                }
            }

            return usedSymbols;
        }
        private static ISet<ISymbol> GetInvokedEventSymbols(RemovableDeclarationCollector removableDeclarationCollector)
        {
            var delegateInvocations = removableDeclarationCollector.TypeDeclarations
                .SelectMany(container => container.SyntaxNode.DescendantNodes()
                    .Where(node => node.IsKind(SyntaxKind.InvocationExpression))
                    .Cast<InvocationExpressionSyntax>()
                    .Select(node =>
                        new SyntaxNodeSymbolSemanticModelTuple<InvocationExpressionSyntax, IMethodSymbol>
                        {
                            SyntaxNode = node,
                            SemanticModel = container.SemanticModel,
                            Symbol = container.SemanticModel.GetSymbolInfo(node).Symbol as IMethodSymbol
                        }))
                 .Where(tuple => tuple.Symbol != null &&
                    tuple.Symbol.MethodKind == MethodKind.DelegateInvoke);

            var invokedEventSymbols = delegateInvocations
                .Select(tuple =>
                    new SyntaxNodeSemanticModelTuple<ExpressionSyntax>
                    {
                        SyntaxNode = GetEventExpressionFromInvocation(tuple.SyntaxNode, tuple.Symbol),
                        SemanticModel = tuple.SemanticModel
                    })
                .Select(tuple =>
                    new SyntaxNodeSymbolSemanticModelTuple<ExpressionSyntax, IEventSymbol>
                    {
                        SyntaxNode = tuple.SyntaxNode,
                        SemanticModel = tuple.SemanticModel,
                        Symbol = tuple.SemanticModel.GetSymbolInfo(tuple.SyntaxNode).Symbol as IEventSymbol
                    })
                .Where(tuple => tuple.Symbol != null)
                .Select(tuple => tuple.Symbol.OriginalDefinition);

            return new HashSet<ISymbol>(invokedEventSymbols);
        }
        private static ISet<ISymbol> GetReferencedSymbolsWithMatchingNames(RemovableDeclarationCollector removableDeclarationCollector,
            ISet<string> symbolNames)
        {
            var usedSymbols = new HashSet<ISymbol>();

            var identifiers = removableDeclarationCollector.TypeDeclarations
                .SelectMany(container => container.SyntaxNode.DescendantNodes()
                    .Where(node =>
                        node.IsKind(SyntaxKind.IdentifierName))
                    .Cast<IdentifierNameSyntax>()
                    .Where(node => symbolNames.Contains(node.Identifier.ValueText))
                    .Select(node =>
                        new SyntaxNodeSemanticModelTuple<SyntaxNode>
                        {
                            SyntaxNode = node,
                            SemanticModel = container.SemanticModel
                        }));

            var generic = removableDeclarationCollector.TypeDeclarations
                .SelectMany(container => container.SyntaxNode.DescendantNodes()
                    .Where(node =>
                        node.IsKind(SyntaxKind.GenericName))
                    .Cast<GenericNameSyntax>()
                    .Where(node => symbolNames.Contains(node.Identifier.ValueText))
                    .Select(node =>
                        new SyntaxNodeSemanticModelTuple<SyntaxNode>
                        {
                            SyntaxNode = node,
                            SemanticModel = container.SemanticModel
                        }));

            var allNodes = identifiers.Concat(generic);

            foreach (var node in allNodes)
            {
                var symbol = node.SemanticModel.GetSymbolInfo(node.SyntaxNode).Symbol;

                if (symbol != null)
                {
                    usedSymbols.Add(symbol.OriginalDefinition);
                }
            }

            return usedSymbols;
        }
        private static void CollectUsedSymbols(RemovableDeclarationCollector declarationCollector,
            HashSet<ISymbol> usedSymbols, HashSet<ISymbol> declaredPrivateSymbols)
        {
            var symbolNames = declaredPrivateSymbols.Select(s => s.Name).ToImmutableHashSet();
            var anyRemovableIndexers = declaredPrivateSymbols
                .OfType<IPropertySymbol>()
                .Any(p => p.IsIndexer);
            var anyRemovableCtors = declaredPrivateSymbols
                .OfType<IMethodSymbol>()
                .Any(m => m.MethodKind == MethodKind.Constructor);

            var identifiers = declarationCollector.ClassDeclarations
                .SelectMany(container => container.SyntaxNode.DescendantNodes()
                    .Where(node =>
                        node.IsKind(SyntaxKind.IdentifierName))
                    .Cast<IdentifierNameSyntax>()
                    .Where(node => symbolNames.Contains(node.Identifier.ValueText))
                    .Select(node =>
                        new SyntaxNodeSemanticModelTuple<SyntaxNode>
                        {
                            SyntaxNode = node,
                            SemanticModel = container.SemanticModel
                        }));

            var generic = declarationCollector.ClassDeclarations
                .SelectMany(container => container.SyntaxNode.DescendantNodes()
                    .Where(node =>
                        node.IsKind(SyntaxKind.GenericName))
                    .Cast<GenericNameSyntax>()
                    .Where(node => symbolNames.Contains(node.Identifier.ValueText))
                    .Select(node =>
                        new SyntaxNodeSemanticModelTuple<SyntaxNode>
                        {
                            SyntaxNode = node,
                            SemanticModel = container.SemanticModel
                        }));

            var allNodes = identifiers.Concat(generic);

            if (anyRemovableIndexers)
            {
                var nodes = declarationCollector.ClassDeclarations
                    .SelectMany(container => container.SyntaxNode.DescendantNodes()
                        .Where(node => node.IsKind(SyntaxKind.ElementAccessExpression))
                        .Select(node =>
                            new SyntaxNodeSemanticModelTuple<SyntaxNode>
                            {
                                SyntaxNode = node,
                                SemanticModel = container.SemanticModel
                            }));

                allNodes = allNodes.Concat(nodes);
            }

            if (anyRemovableCtors)
            {
                var nodes = declarationCollector.ClassDeclarations
                    .SelectMany(container => container.SyntaxNode.DescendantNodes()
                        .Where(node => node.IsKind(SyntaxKind.ObjectCreationExpression))
                        .Select(node =>
                            new SyntaxNodeSemanticModelTuple<SyntaxNode>
                            {
                                SyntaxNode = node,
                                SemanticModel = container.SemanticModel
                            }));

                allNodes = allNodes.Concat(nodes);
            }

            foreach (var node in allNodes)
            {
                var symbol = node.SemanticModel.GetSymbolInfo(node.SyntaxNode).Symbol;
                var methodSymbol = symbol as IMethodSymbol;

                if (methodSymbol != null &&
                    methodSymbol.MethodKind == MethodKind.ReducedExtension)
                {
                    symbol = methodSymbol.ReducedFrom;
                }

                if (symbol != null)
                {
                    usedSymbols.Add(symbol.OriginalDefinition);
                }
            }
        }
        private static void CollectUsedSymbolsFromCtorInitializerAndCollectEmptyCtors(
            RemovableDeclarationCollector declarationCollector,
            HashSet<ISymbol> usedSymbols, HashSet<ISymbol> emptyConstructors)
        {
            var ctors = declarationCollector.ClassDeclarations
                .SelectMany(container => container.SyntaxNode.DescendantNodes(RemovableDeclarationCollector.IsNodeStructOrClassDeclaration)
                    .Where(node => node.IsKind(SyntaxKind.ConstructorDeclaration))
                    .Select(node =>
                        new SyntaxNodeSemanticModelTuple<ConstructorDeclarationSyntax>
                        {
                            SyntaxNode = (ConstructorDeclarationSyntax)node,
                            SemanticModel = container.SemanticModel
                        }));

            foreach (var ctor in ctors)
            {
                if (ctor.SyntaxNode.Body == null ||
                    !ctor.SyntaxNode.Body.Statements.Any())
                {
                    var ctorSymbol = ctor.SemanticModel.GetDeclaredSymbol(ctor.SyntaxNode);
                    if (ctorSymbol != null &&
                        !ctorSymbol.Parameters.Any())
                    {
                        emptyConstructors.Add(ctorSymbol.OriginalDefinition);
                    }
                }

                if (ctor.SyntaxNode.Initializer == null)
                {
                    continue;
                }

                var baseCtor = ctor.SemanticModel.GetSymbolInfo(ctor.SyntaxNode.Initializer).Symbol;
                if (baseCtor != null)
                {
                    usedSymbols.Add(baseCtor);
                }
            }
        }
        private static void CollectRemovableNamedTypes(RemovableDeclarationCollector declarationCollector,
            HashSet<ISymbol> declaredPrivateSymbols)
        {
            var symbols = declarationCollector.ClassDeclarations
                .SelectMany(container => container.SyntaxNode.DescendantNodes(RemovableDeclarationCollector.IsNodeContainerTypeDeclaration)
                    .Where(node =>
                        node.IsKind(SyntaxKind.ClassDeclaration) ||
                        node.IsKind(SyntaxKind.InterfaceDeclaration) ||
                        node.IsKind(SyntaxKind.StructDeclaration) ||
                        node.IsKind(SyntaxKind.DelegateDeclaration))
                    .Select(node =>
                        new SyntaxNodeSemanticModelTuple<SyntaxNode>
                        {
                            SyntaxNode = node,
                            SemanticModel = container.SemanticModel
                        }))
                    .Select(node => node.SemanticModel.GetDeclaredSymbol(node.SyntaxNode))
                    .Where(symbol => RemovableDeclarationCollector.IsRemovable(symbol, maxAccessibility));

            declaredPrivateSymbols.UnionWith(symbols);
        }
        private static void CollectRemovableFieldLikeDeclarations(RemovableDeclarationCollector declarationCollector,
            HashSet<ISymbol> declaredPrivateSymbols, BidirectionalDictionary<ISymbol, SyntaxNode> fieldLikeSymbols)
        {
            var declarationKinds = ImmutableHashSet.Create(SyntaxKind.FieldDeclaration, SyntaxKind.EventFieldDeclaration);
            var removableFieldsDefinitions = declarationCollector.GetRemovableFieldLikeDeclarations(declarationKinds, maxAccessibility);

            foreach (var fieldsDefinitions in removableFieldsDefinitions)
            {
                declaredPrivateSymbols.Add(fieldsDefinitions.Symbol);
                fieldLikeSymbols.Add(fieldsDefinitions.Symbol, fieldsDefinitions.SyntaxNode);
            }
        }
 private static void CollectRemovableEventsAndProperties(RemovableDeclarationCollector helper,
     HashSet<ISymbol> declaredPrivateSymbols)
 {
     var declarationKinds = ImmutableHashSet.Create(SyntaxKind.EventDeclaration, SyntaxKind.PropertyDeclaration, SyntaxKind.IndexerDeclaration);
     var declarations = helper.GetRemovableDeclarations(declarationKinds, maxAccessibility);
     declaredPrivateSymbols.UnionWith(declarations.Select(d => d.Symbol));
 }
        private static void CollectRemovableMethods(RemovableDeclarationCollector declarationCollector,
            HashSet<ISymbol> declaredPrivateSymbols)
        {
            var methodSymbols = declarationCollector.ClassDeclarations
                .SelectMany(container => container.SyntaxNode.DescendantNodes(RemovableDeclarationCollector.IsNodeContainerTypeDeclaration)
                    .Where(node =>
                        node.IsKind(SyntaxKind.MethodDeclaration) ||
                        node.IsKind(SyntaxKind.ConstructorDeclaration))
                    .Select(node =>
                        new SyntaxNodeSemanticModelTuple<SyntaxNode>
                        {
                            SyntaxNode = node,
                            SemanticModel = container.SemanticModel
                        }))
                    .Select(node => node.SemanticModel.GetDeclaredSymbol(node.SyntaxNode) as IMethodSymbol)
                    .Where(method => RemovableDeclarationCollector.IsRemovable(method, maxAccessibility));

            declaredPrivateSymbols.UnionWith(methodSymbols);
        }
 private static IEnumerable<SyntaxNodeSymbolSemanticModelTuple<MethodDeclarationSyntax, IMethodSymbol>> CollectRemovableMethods(
     RemovableDeclarationCollector removableDeclarationCollector)
 {
     return removableDeclarationCollector.ClassDeclarations
         .SelectMany(container => container.SyntaxNode.DescendantNodes(RemovableDeclarationCollector.IsNodeContainerTypeDeclaration)
             .OfType<MethodDeclarationSyntax>()
             .Select(node =>
                 new SyntaxNodeSymbolSemanticModelTuple<MethodDeclarationSyntax, IMethodSymbol>
                 {
                     SyntaxNode = node,
                     SemanticModel = container.SemanticModel,
                     Symbol = container.SemanticModel.GetDeclaredSymbol(node)
                 }))
             .Where(node =>
                 node.Symbol != null &&
                 !node.Symbol.ReturnsVoid &&
                 RemovableDeclarationCollector.IsRemovable(node.Symbol, Accessibility.Private));
 }