Esempio n. 1
0
 private static bool IsMentionedInDebuggerDisplay(ISymbol symbol, CSharpSymbolUsageCollector usageCollector) =>
 usageCollector.DebuggerDisplayValues.Any(value => value.Contains(symbol.Name));
        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>();

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

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

                    if (!VisitDeclaringReferences(namedType, removableSymbolsCollector, c.Compilation))
                    {
                        return;
                    }

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

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

                    if (!VisitDeclaringReferences(namedType, usageCollector, c.Compilation))
                    {
                        return;
                    }

                    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 CSharpSymbolUsageCollector(
                        c.Compilation.GetSemanticModel,
                        removableInternalTypes.Select(s => s.Name).ToHashSet());

                    foreach (var syntaxTree in c.Compilation.SyntaxTrees.Where(tree => !tree.IsGenerated(c.Compilation)))
                    {
                        usageCollector.SafeVisit(syntaxTree.GetRoot());
                    }

                    var diagnostics = GetDiagnostics(usageCollector, removableInternalTypes.ToHashSet(), "internal",
                                                     new BidirectionalDictionary <ISymbol, SyntaxNode>());
                    foreach (var diagnostic in diagnostics)
                    {
                        cc.ReportDiagnosticIfNonGenerated(diagnostic, cc.Compilation);
                    }
                });
            });
        }
Esempio n. 3
0
        private static IEnumerable <Diagnostic> GetDiagnosticsForUnusedPrivateMembers(CSharpSymbolUsageCollector usageCollector, ISet <ISymbol> removableSymbols, string accessibility,
                                                                                      BidirectionalDictionary <ISymbol, SyntaxNode> fieldLikeSymbols)
        {
            var unusedSymbols = GetUnusedSymbols(usageCollector, removableSymbols);

            var propertiesWithUnusedAccessor = removableSymbols
                                               .Intersect(usageCollector.UsedSymbols)
                                               .OfType <IPropertySymbol>()
                                               .Where(usageCollector.PropertyAccess.ContainsKey)
                                               .Where(symbol => !IsMentionedInDebuggerDisplay(symbol, usageCollector))
                                               .Select(symbol => GetDiagnosticsForProperty(symbol, usageCollector.PropertyAccess))
                                               .WhereNotNull();

            return(GetDiagnosticsForMembers(unusedSymbols, accessibility, fieldLikeSymbols).Concat(propertiesWithUnusedAccessor));
        }
Esempio n. 4
0
 private static HashSet <ISymbol> GetUnusedSymbols(CSharpSymbolUsageCollector usageCollector, ISet <ISymbol> removableSymbols) =>
 removableSymbols
 .Except(usageCollector.UsedSymbols)
 .Where(symbol => !IsMentionedInDebuggerDisplay(symbol, usageCollector))
 .ToHashSet();