Example #1
0
        private static IEnumerable <Diagnostic> GetDiagnostics(SymbolUsageCollector usageCollector, ISet <ISymbol> removableSymbols,
                                                               string accessibility, BidirectionalDictionary <ISymbol, SyntaxNode> fieldLikeSymbols)
        {
            var unusedSymbols = removableSymbols
                                .Except(usageCollector.UsedSymbols)
                                .Where(symbol => !MentionedInDebuggerDisplay(symbol))
                                .ToHashSet();

            var propertiesWithUnusedAccessor = removableSymbols
                                               .Intersect(usageCollector.UsedSymbols)
                                               .OfType <IPropertySymbol>()
                                               .Where(usageCollector.PropertyAccess.ContainsKey)
                                               .Where(symbol => !MentionedInDebuggerDisplay(symbol));

            return(GetDiagnosticsForMembers(unusedSymbols, accessibility, fieldLikeSymbols)
                   .Concat(propertiesWithUnusedAccessor.SelectMany(propertySymbol => GetDiagnosticsForProperty(propertySymbol, usageCollector.PropertyAccess))));

            bool MentionedInDebuggerDisplay(ISymbol symbol) =>
            usageCollector.DebuggerDisplayValues.Any(value => value.Contains(symbol.Name));
        }
Example #2
0
        protected override void Initialize(SonarAnalysisContext context)
        {
            context.RegisterCompilationStartAction(
                c =>
            {
                // Collect potentially removable internal types from the project to evaluate when
                // the compilation is over, depending on whether InternalsVisibleTo attribute is present
                // or not.
                var removableInternalTypes = new ConcurrentBag <ISymbol>();
                // Collect here all named types from the project to look for internal member usages.
                var allNamedTypes = new ConcurrentBag <INamedTypeSymbol>();

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

                    // Collect all symbols to try to look for used internal members when the compilation ends
                    allNamedTypes.Add(namedType);

                    // Collect symbols of private members that could potentially be removed
                    var removableSymbolsCollector = new RemovableSymbolCollector(c.Compilation.GetSemanticModel);

                    VisitDeclaringReferences(namedType, removableSymbolsCollector);

                    // Keep the removable internal types for when the compilation ends
                    foreach (var internalSymbol in removableSymbolsCollector.InternalSymbols.OfType <INamedTypeSymbol>())
                    {
                        removableInternalTypes.Add(internalSymbol);
                    }

                    var usageCollector = new SymbolUsageCollector(
                        c.Compilation.GetSemanticModel,
                        removableSymbolsCollector.PrivateSymbols.Select(s => s.Name).ToHashSet());

                    VisitDeclaringReferences(namedType, usageCollector);

                    var diagnostics = GetDiagnostics(usageCollector, removableSymbolsCollector.PrivateSymbols, "private",
                                                     removableSymbolsCollector.FieldLikeSymbols);
                    foreach (var diagnostic in diagnostics)
                    {
                        cc.ReportDiagnosticIfNonGenerated(diagnostic, cc.Compilation);
                    }
                },
                    SymbolKind.NamedType);

                c.RegisterCompilationEndAction(
                    cc =>
                {
                    var foundInternalsVisibleTo = cc.Compilation.Assembly
                                                  .GetAttributes(KnownType.System_Runtime_CompilerServices_InternalsVisibleToAttribute)
                                                  .Any();

                    if (foundInternalsVisibleTo ||
                        removableInternalTypes.Count == 0)
                    {
                        return;
                    }

                    var usageCollector = new SymbolUsageCollector(
                        c.Compilation.GetSemanticModel,
                        removableInternalTypes.Select(s => s.Name).ToHashSet());

                    foreach (var symbol in allNamedTypes)
                    {
                        VisitDeclaringReferences(symbol, usageCollector);
                    }

                    var diagnostics = GetDiagnostics(usageCollector, removableInternalTypes.ToHashSet(), "internal",
                                                     new BidirectionalDictionary <ISymbol, SyntaxNode>());
                    foreach (var diagnostic in diagnostics)
                    {
                        cc.ReportDiagnosticIfNonGenerated(diagnostic, cc.Compilation);
                    }
                });
            });
        }