Esempio n. 1
0
        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 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 void CollectUsedSymbolsFromCtorInitializerAndCollectEmptyCtors(
            RemovableDeclarationCollector declarationCollector,
            HashSet <ISymbol> usedSymbols, HashSet <ISymbol> emptyConstructors)
        {
            var ctors = declarationCollector.TypeDeclarations
                        .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;
                }

                usedSymbols.UnionWith(GetAllCandidateSymbols(ctor.SemanticModel.GetSymbolInfo(ctor.SyntaxNode.Initializer)));
            }
        }
Esempio n. 4
0
        private static void CheckClassWithOnlyUnusedPrivateConstructors(SymbolAnalysisContext context)
        {
            var namedType = context.Symbol as INamedTypeSymbol;

            if (!IsNonStaticClassWithNoAttributes(namedType))
            {
                return;
            }

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

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

            var typeDeclarations = new RemovableDeclarationCollector(namedType, context.Compilation).TypeDeclarations;

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

                foreach (var classDeclaration in typeDeclarations)
                {
                    context.ReportDiagnosticIfNonGenerated(Diagnostic.Create(Rule, classDeclaration.SyntaxNode.Identifier.GetLocation(),
                                                                             message));
                }
            }
        }
        protected sealed override void Initialize(SonarAnalysisContext context)
        {
            context.RegisterSymbolAction(
                c =>
            {
                var namedType = (INamedTypeSymbol)c.Symbol;
                if (!namedType.IsClassOrStruct() ||
                    namedType.GetAttributes().Any(IsStructLayoutAttribute) ||
                    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);
        }
Esempio n. 6
0
        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.TypeDeclarations
                                .SelectMany(GetMethodsNodesAndModels)
                                .Select(node => node.SemanticModel.GetDeclaredSymbol(node.SyntaxNode) as IMethodSymbol)
                                .Select(symbol => symbol.PartialDefinitionPart ?? symbol)
                                .Where(method => RemovableDeclarationCollector.IsRemovable(method, maxAccessibility));

            declaredPrivateSymbols.UnionWith(methodSymbols);
        }
        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);
        }
Esempio n. 9
0
        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);
            }
        }
        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);
        }
Esempio n. 11
0
        private void RaiseOnUninvokedEventDeclaration(SymbolAnalysisContext context)
        {
            var namedType = (INamedTypeSymbol)context.Symbol;

            if (!namedType.IsClassOrStruct() ||
                namedType.ContainingType != null)
            {
                return;
            }

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

            var removableEventFields = removableDeclarationCollector
                                       .GetRemovableFieldLikeDeclarations(eventSyntax, maxAccessibility)
                                       .ToList();

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

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

            removableEventFields
            .Where(IsNotInvoked)
            .Where(IsNotCopied)
            .ToList()
            .ForEach(x => context.ReportDiagnosticIfNonGenerated(
                         Diagnostic.Create(rule, GetLocation(x.SyntaxNode), x.Symbol.Name)));

            Location GetLocation(SyntaxNode node) =>
            node is VariableDeclaratorSyntax variableDeclarator
                    ? variableDeclarator.Identifier.GetLocation()
                    : ((EventDeclarationSyntax)node).Identifier.GetLocation();

            bool IsNotInvoked(SyntaxNodeSymbolSemanticModelTuple <SyntaxNode, ISymbol> tuple) =>
            !invokedSymbols.Contains(tuple.Symbol);

            bool IsNotCopied(SyntaxNodeSymbolSemanticModelTuple <SyntaxNode, ISymbol> tuple) =>
            !possiblyCopiedSymbols.Contains(tuple.Symbol);

            bool IsUsed(SyntaxNodeSymbolSemanticModelTuple <SyntaxNode, ISymbol> tuple) =>
            usedSymbols.Contains(tuple.Symbol);
        }
Esempio n. 12
0
        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);
        }
Esempio n. 13
0
 private static IEnumerable <SyntaxNodeSymbolSemanticModelTuple <MethodDeclarationSyntax, IMethodSymbol> > CollectRemovableMethods(
     RemovableDeclarationCollector removableDeclarationCollector)
 {
     return(removableDeclarationCollector.TypeDeclarations
            .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)));
 }
Esempio n. 14
0
        private static void CollectRemovableMethods(RemovableDeclarationCollector declarationCollector,
                                                    HashSet <ISymbol> declaredPrivateSymbols)
        {
            var methodSymbols = declarationCollector.TypeDeclarations
                                .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);
        }
Esempio n. 15
0
        protected sealed 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.TypeDeclarations).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);
        }
Esempio n. 16
0
        protected sealed 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>();

                var propertyAccessorAccess = new Dictionary <IPropertySymbol, AccessorAccess>();

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

                ReportIssues(c, usedSymbols, declaredPrivateSymbols, emptyConstructors, fieldLikeSymbols);
                ReportUnusedPropertyAccessors(c, usedSymbols, declaredPrivateSymbols, propertyAccessorAccess);
            },
                SymbolKind.NamedType);
        }
        private static void CollectRemovableNamedTypes(RemovableDeclarationCollector declarationCollector,
                                                       HashSet <ISymbol> declaredPrivateSymbols)
        {
            var symbols = declarationCollector.TypeDeclarations
                          .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, Accessibility.Internal));

            declaredPrivateSymbols.UnionWith(symbols);
        }
        protected override void Initialize(SonarAnalysisContext context)
        {
            context.RegisterSymbolAction(
                analysisContext =>
            {
                var namedType = analysisContext.Symbol as INamedTypeSymbol;
                if (!namedType.IsClass() || namedType.Implements(KnownType.System_IDisposable))
                {
                    return;
                }
                var disposableFields = namedType.GetMembers().OfType <IFieldSymbol>()
                                       .Where(IsNonStaticNonPublicDisposableField).ToHashSet();

                var disposableFieldsWithInitializer = disposableFields
                                                      .Where(f => IsOwnerSinceDeclaration(f));

                var otherInitializationsOfFields = namedType.GetMembers().OfType <IMethodSymbol>().
                                                   SelectMany(m => GetAssignementsToFieldsIn(m, analysisContext.Compilation)).
                                                   Where(f => disposableFields.Contains(f));

                var message = string.Join(", ",
                                          disposableFieldsWithInitializer.
                                          Union(otherInitializationsOfFields).
                                          Distinct().
                                          Select(symbol => $"'{symbol.Name}'").
                                          OrderBy(s => s));

                if (!string.IsNullOrEmpty(message))
                {
                    var typeDeclarations = new RemovableDeclarationCollector(namedType, analysisContext.Compilation).TypeDeclarations;
                    foreach (var classDeclaration in typeDeclarations)
                    {
                        analysisContext.ReportDiagnosticIfNonGenerated(
                            Diagnostic.Create(rule, classDeclaration.SyntaxNode.Identifier.GetLocation(), message));
                    }
                }
            },
                SymbolKind.NamedType);
        }
Esempio n. 19
0
        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.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 = declarationCollector.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);

            if (anyRemovableIndexers)
            {
                var nodes = declarationCollector.TypeDeclarations
                            .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.TypeDeclarations
                            .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);
            }

            var candidateSymbols = allNodes
                                   .Select(n => n.SemanticModel.GetSymbolInfo(n.SyntaxNode))
                                   .SelectMany(s => GetAllCandidateSymbols(s))
                                   .Select(s => GetOriginalSymbol(s))
                                   .Where(s => s != null);

            usedSymbols.UnionWith(candidateSymbols);
        }
        protected sealed override void Initialize(SonarAnalysisContext context)
        {
            context.RegisterCompilationStartAction(
                c =>
            {
                var shouldRaise = true;
                possibleUnusedInternalMembers = new ConcurrentBag <Diagnostic>();

                c.RegisterSemanticModelAction(
                    cc =>
                {
                    var isInternalsVisibleToAttributeFound = cc.SemanticModel.SyntaxTree.GetRoot()
                                                             .DescendantNodes()
                                                             .OfType <AttributeListSyntax>()
                                                             .SelectMany(list => list.Attributes)
                                                             .Any(a => IsInternalVisibleToAttribute(a, cc.SemanticModel));
                    if (isInternalsVisibleToAttributeFound)
                    {
                        shouldRaise = false;
                    }
                });

                c.RegisterSymbolAction(
                    cc =>
                {
                    var namedType = (INamedTypeSymbol)cc.Symbol;
                    if (!namedType.IsClassOrStruct() ||
                        namedType.ContainingType != null)
                    {
                        return;
                    }

                    var declarationCollector = new RemovableDeclarationCollector(namedType, cc.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>();

                    var propertyAccessorAccess = new Dictionary <IPropertySymbol, AccessorAccess>();

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

                    ReportIssues(cc, usedSymbols, declaredPrivateSymbols, emptyConstructors, fieldLikeSymbols);
                    ReportUnusedPropertyAccessors(cc, usedSymbols, declaredPrivateSymbols, propertyAccessorAccess);
                },
                    SymbolKind.NamedType);

                c.RegisterCompilationEndAction(
                    cc =>
                {
                    if (!shouldRaise)
                    {
                        return;
                    }

                    foreach (var diagnostic in possibleUnusedInternalMembers)
                    {
                        cc.ReportDiagnosticIfNonGenerated(diagnostic, cc.Compilation);
                    }
                });
            });
        }
        private static void CollectUsedSymbols(RemovableDeclarationCollector declarationCollector,
                                               HashSet <ISymbol> usedSymbols, HashSet <ISymbol> declaredPrivateSymbols,
                                               Dictionary <IPropertySymbol, AccessorAccess> propertyAccessorAccess)
        {
            var symbolNames          = declaredPrivateSymbols.Select(s => s.Name).ToHashSet();
            var anyRemovableIndexers = declaredPrivateSymbols
                                       .OfType <IPropertySymbol>()
                                       .Any(p => p.IsIndexer);
            var anyRemovableCtors = declaredPrivateSymbols
                                    .OfType <IMethodSymbol>()
                                    .Any(m => m.MethodKind == MethodKind.Constructor);

            var identifiers = declarationCollector.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 <ExpressionSyntax>
            {
                SyntaxNode    = node,
                SemanticModel = container.SemanticModel
            }));

            var generic = declarationCollector.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 <ExpressionSyntax>
            {
                SyntaxNode    = node,
                SemanticModel = container.SemanticModel
            }));

            var allNodes = identifiers.Concat(generic);

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

                allNodes = allNodes.Concat(nodes);
            }

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

                allNodes = allNodes.Concat(nodes);
            }

            var candidateSymbols = allNodes
                                   .Select(n => new { Syntax = n.SyntaxNode, SemanticModel = n.SemanticModel, Symbol = n.SemanticModel.GetSymbolInfo(n.SyntaxNode) })
                                   .Select(n => new
            {
                Syntax        = n.Syntax,
                SemanticModel = n.SemanticModel,
                Symbols       = GetAllCandidateSymbols(n.Symbol)
                                .Select(s => GetOriginalSymbol(s))
                                .Where(s => s != null)
            });

            foreach (var candidateSymbol in candidateSymbols)
            {
                usedSymbols.UnionWith(candidateSymbol.Symbols);

                var accessorKind = GetAccessorAccessKind(candidateSymbol.Syntax, candidateSymbol.SemanticModel);

                foreach (var propertySymbol in candidateSymbol.Symbols.OfType <IPropertySymbol>())
                {
                    if (propertyAccessorAccess.ContainsKey(propertySymbol))
                    {
                        propertyAccessorAccess[propertySymbol] |= accessorKind;
                    }
                    else
                    {
                        propertyAccessorAccess[propertySymbol] = accessorKind;
                    }
                }
            }
        }
Esempio n. 22
0
        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.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 = declarationCollector.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);

            if (anyRemovableIndexers)
            {
                var nodes = declarationCollector.TypeDeclarations
                            .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.TypeDeclarations
                            .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?.MethodKind == MethodKind.ReducedExtension)
                {
                    symbol = methodSymbol.ReducedFrom;
                }

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