Ejemplo n.º 1
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>();

                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))
                    {
                        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))
                    {
                        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)
                    {
                        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);
                    }
                });
            });
        }
Ejemplo n.º 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>();

            c.RegisterSymbolAction(
                cc =>
            {
                var namedType = (INamedTypeSymbol)cc.Symbol;

                if (namedType.TypeKind != TypeKind.Struct &&
                    namedType.TypeKind != TypeKind.Class &&
                    namedType.TypeKind != TypeKind.Delegate &&
                    namedType.TypeKind != TypeKind.Enum &&
                    namedType.TypeKind != TypeKind.Interface)
                {
                    return;
                }

                if (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, includeGeneratedFile: false))
                {
                    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, removableSymbolsCollector.PrivateSymbols);
                if (!VisitDeclaringReferences(namedType, usageCollector, c.Compilation, includeGeneratedFile: true))
                {
                    return;
                }

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

            c.RegisterCompilationEndAction(
                cc =>
            {
                var foundInternalsVisibleTo = cc.Compilation.Assembly.HasAttribute(KnownType.System_Runtime_CompilerServices_InternalsVisibleToAttribute);
                if (foundInternalsVisibleTo || removableInternalTypes.Count == 0)
                {
                    return;
                }

                var usageCollector = new CSharpSymbolUsageCollector(c.Compilation, removableInternalTypes.ToHashSet());
                foreach (var syntaxTree in c.Compilation.SyntaxTrees.Where(tree => !tree.IsGenerated(CSharpGeneratedCodeRecognizer.Instance, c.Compilation)))
                {
                    usageCollector.SafeVisit(syntaxTree.GetRoot());
                }

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