private static void AnalyzeTypeDeclaration(SyntaxNodeAnalysisContext context, TypeDeclarationSyntax typeDeclaration, INamedTypeSymbol debuggerDisplayAttribute)
        {
            if (typeDeclaration.Modifiers.Contains(SyntaxKind.PartialKeyword))
            {
                return;
            }

            SyntaxList <MemberDeclarationSyntax> members = typeDeclaration.Members;

            UnusedMemberWalker walker = null;

            foreach (MemberDeclarationSyntax member in members)
            {
                if (member.ContainsDiagnostics)
                {
                    continue;
                }

                if (member.ContainsDirectives)
                {
                    continue;
                }

                switch (member.Kind())
                {
                case SyntaxKind.DelegateDeclaration:
                {
                    var declaration = (DelegateDeclarationSyntax)member;

                    if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        if (walker == null)
                        {
                            walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken);
                        }

                        walker.AddDelegate(declaration.Identifier.ValueText, declaration);
                    }

                    break;
                }

                case SyntaxKind.EventDeclaration:
                {
                    var declaration = (EventDeclarationSyntax)member;

                    if (declaration.ExplicitInterfaceSpecifier == null &&
                        SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        if (walker == null)
                        {
                            walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken);
                        }

                        walker.AddNode(declaration.Identifier.ValueText, declaration);
                    }

                    break;
                }

                case SyntaxKind.EventFieldDeclaration:
                {
                    var declaration = (EventFieldDeclarationSyntax)member;

                    if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        if (walker == null)
                        {
                            walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken);
                        }

                        walker.AddNodes(declaration.Declaration);
                    }

                    break;
                }

                case SyntaxKind.FieldDeclaration:
                {
                    var             declaration = (FieldDeclarationSyntax)member;
                    SyntaxTokenList modifiers   = declaration.Modifiers;

                    if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        if (walker == null)
                        {
                            walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken);
                        }

                        walker.AddNodes(declaration.Declaration, isConst: modifiers.Contains(SyntaxKind.ConstKeyword));
                    }

                    break;
                }

                case SyntaxKind.MethodDeclaration:
                {
                    var declaration = (MethodDeclarationSyntax)member;

                    SyntaxTokenList modifiers = declaration.Modifiers;

                    if (declaration.ExplicitInterfaceSpecifier == null &&
                        !declaration.AttributeLists.Any() &&
                        SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        string methodName = declaration.Identifier.ValueText;

                        if (!IsMainMethod(declaration, modifiers, methodName))
                        {
                            if (walker == null)
                            {
                                walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken);
                            }

                            walker.AddNode(methodName, declaration);
                        }
                    }

                    break;
                }

                case SyntaxKind.PropertyDeclaration:
                {
                    var declaration = (PropertyDeclarationSyntax)member;

                    if (declaration.ExplicitInterfaceSpecifier == null &&
                        SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        if (walker == null)
                        {
                            walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken);
                        }

                        walker.AddNode(declaration.Identifier.ValueText, declaration);
                    }

                    break;
                }
                }
            }

            if (walker == null)
            {
                return;
            }

            if (debuggerDisplayAttribute != null &&
                walker.Nodes.Any(f => f.CanBeInDebuggerDisplayAttribute) &&
                ShouldAnalyzeDebuggerDisplayAttribute())
            {
                string value = context.SemanticModel
                               .GetDeclaredSymbol(typeDeclaration, context.CancellationToken)
                               .GetAttribute(debuggerDisplayAttribute)?
                               .ConstructorArguments
                               .SingleOrDefault(shouldThrow: false)
                               .Value?
                               .ToString();

                if (value != null)
                {
                    RemoveMethodsAndPropertiesThatAreInDebuggerDisplayAttributeValue(walker.Nodes, value);
                }

                if (walker.Nodes.Count == 0)
                {
                    return;
                }
            }

            walker.Visit(typeDeclaration);

            foreach (NodeSymbolInfo info in UnusedMemberWalkerCache.GetNodesAndFree(walker))
            {
                SyntaxNode node = info.Node;

                if (node is VariableDeclaratorSyntax variableDeclarator)
                {
                    var variableDeclaration = (VariableDeclarationSyntax)variableDeclarator.Parent;

                    if (variableDeclaration.Variables.Count == 1)
                    {
                        ReportDiagnostic(context, variableDeclaration.Parent, CSharpFacts.GetTitle(variableDeclaration.Parent));
                    }
                    else
                    {
                        ReportDiagnostic(context, variableDeclarator, CSharpFacts.GetTitle(variableDeclaration.Parent));
                    }
                }
                else
                {
                    ReportDiagnostic(context, node, CSharpFacts.GetTitle(node));
                }
            }

            bool ShouldAnalyzeDebuggerDisplayAttribute()
            {
                if (typeDeclaration.Modifiers.Contains(SyntaxKind.PartialKeyword))
                {
                    return(true);
                }

                foreach (AttributeListSyntax attributeList in typeDeclaration.AttributeLists)
                {
                    foreach (AttributeSyntax attribute in attributeList.Attributes)
                    {
                        if (attribute.ArgumentList?.Arguments.Count(f => f.NameEquals == null) == 1)
                        {
                            return(true);
                        }
                    }
                }

                return(false);
            }
        }
Beispiel #2
0
        private static void AnalyzeTypeDeclaration(SyntaxNodeAnalysisContext context, TypeDeclarationSyntax typeDeclaration)
        {
            if (typeDeclaration.Modifiers.Contains(SyntaxKind.PartialKeyword))
            {
                return;
            }

            SyntaxList <MemberDeclarationSyntax> members = typeDeclaration.Members;

            UnusedMemberWalker walker = null;

            foreach (MemberDeclarationSyntax member in members)
            {
                if (member.ContainsDiagnostics)
                {
                    continue;
                }

                if (member.ContainsDirectives)
                {
                    continue;
                }

                switch (member.Kind())
                {
                case SyntaxKind.DelegateDeclaration:
                {
                    var declaration = (DelegateDeclarationSyntax)member;

                    if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        if (walker == null)
                        {
                            walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken);
                        }

                        walker.AddNode(declaration.Identifier.ValueText, declaration);
                    }

                    break;
                }

                case SyntaxKind.EventDeclaration:
                {
                    var declaration = (EventDeclarationSyntax)member;

                    if (declaration.ExplicitInterfaceSpecifier == null &&
                        SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        if (walker == null)
                        {
                            walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken);
                        }

                        walker.AddNode(declaration.Identifier.ValueText, declaration);
                    }

                    break;
                }

                case SyntaxKind.EventFieldDeclaration:
                {
                    var declaration = (EventFieldDeclarationSyntax)member;

                    if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        if (walker == null)
                        {
                            walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken);
                        }

                        walker.AddNodes(declaration.Declaration);
                    }

                    break;
                }

                case SyntaxKind.FieldDeclaration:
                {
                    var             declaration = (FieldDeclarationSyntax)member;
                    SyntaxTokenList modifiers   = declaration.Modifiers;

                    if (SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        if (walker == null)
                        {
                            walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken);
                        }

                        walker.AddNodes(declaration.Declaration, isConst: modifiers.Contains(SyntaxKind.ConstKeyword));
                    }

                    break;
                }

                case SyntaxKind.MethodDeclaration:
                {
                    var declaration = (MethodDeclarationSyntax)member;

                    SyntaxTokenList modifiers = declaration.Modifiers;

                    if (declaration.ExplicitInterfaceSpecifier == null &&
                        !declaration.AttributeLists.Any() &&
                        SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        string methodName = declaration.Identifier.ValueText;

                        if (!IsMainMethod(declaration, modifiers, methodName))
                        {
                            if (walker == null)
                            {
                                walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken);
                            }

                            walker.AddNode(methodName, declaration);
                        }
                    }

                    break;
                }

                case SyntaxKind.PropertyDeclaration:
                {
                    var declaration = (PropertyDeclarationSyntax)member;

                    if (declaration.ExplicitInterfaceSpecifier == null &&
                        SyntaxAccessibility.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        if (walker == null)
                        {
                            walker = UnusedMemberWalkerCache.GetInstance(context.SemanticModel, context.CancellationToken);
                        }

                        walker.AddNode(declaration.Identifier.ValueText, declaration);
                    }

                    break;
                }
                }
            }

            if (walker == null)
            {
                return;
            }

            walker.Visit(typeDeclaration);

            foreach (NodeSymbolInfo info in UnusedMemberWalkerCache.GetNodesAndFree(walker))
            {
                SyntaxNode node = info.Node;

                if (node is VariableDeclaratorSyntax variableDeclarator)
                {
                    var variableDeclaration = (VariableDeclarationSyntax)variableDeclarator.Parent;

                    if (variableDeclaration.Variables.Count == 1)
                    {
                        ReportDiagnostic(context, variableDeclaration.Parent, CSharpFacts.GetTitle(variableDeclaration.Parent));
                    }
                    else
                    {
                        ReportDiagnostic(context, variableDeclarator, CSharpFacts.GetTitle(variableDeclaration.Parent));
                    }
                }
                else
                {
                    ReportDiagnostic(context, node, CSharpFacts.GetTitle(node));
                }
            }
        }
        public static void AnalyzeClassDeclaration(SyntaxNodeAnalysisContext context)
        {
            var classDeclaration = (ClassDeclarationSyntax)context.Node;

            if (!classDeclaration.Identifier.ValueText.EndsWith("Extensions", StringComparison.Ordinal))
            {
                return;
            }

            if (!classDeclaration.Modifiers.Contains(SyntaxKind.StaticKeyword))
            {
                return;
            }

            if (!classDeclaration.IsParentKind(SyntaxKind.NamespaceDeclaration, SyntaxKind.CompilationUnit))
            {
                return;
            }

            if (!SyntaxAccessibility.GetAccessibility(classDeclaration).Is(Accessibility.Public, Accessibility.Internal))
            {
                return;
            }

            foreach (MemberDeclarationSyntax member in classDeclaration.Members)
            {
                if (!member.IsKind(SyntaxKind.MethodDeclaration))
                {
                    continue;
                }

                var methodDeclaration = (MethodDeclarationSyntax)member;

                if (!methodDeclaration.Modifiers.Contains(SyntaxKind.StaticKeyword))
                {
                    continue;
                }

                if (!SyntaxAccessibility.GetAccessibility(methodDeclaration).Is(Accessibility.Public, Accessibility.Internal))
                {
                    continue;
                }

                ParameterSyntax parameter = methodDeclaration.ParameterList?.Parameters.FirstOrDefault();

                if (parameter == null)
                {
                    continue;
                }

                bool isThis = false;
                bool isIn   = false;
                bool isRef  = false;

                foreach (SyntaxToken modifier in parameter.Modifiers)
                {
                    SyntaxKind kind = modifier.Kind();

                    if (kind == SyntaxKind.ThisKeyword)
                    {
                        isThis = true;
                        break;
                    }
                    else if (kind == SyntaxKind.InKeyword)
                    {
                        isIn = true;
                    }
                    else if (kind == SyntaxKind.RefKeyword)
                    {
                        isRef = true;
                    }

                    if (isThis)
                    {
                        break;
                    }
                }

                if (isThis)
                {
                    continue;
                }

                if (isIn)
                {
                    IParameterSymbol parameterSymbol = context.SemanticModel.GetDeclaredSymbol(parameter, context.CancellationToken);

                    ITypeSymbol typeSymbol = parameterSymbol.Type;

                    if (!typeSymbol.IsValueType)
                    {
                        continue;
                    }

                    if (typeSymbol.Kind == SymbolKind.TypeParameter)
                    {
                        continue;
                    }
                }
                else if (isRef)
                {
                    IParameterSymbol parameterSymbol = context.SemanticModel.GetDeclaredSymbol(parameter, context.CancellationToken);

                    if (!parameterSymbol.Type.IsValueType)
                    {
                        continue;
                    }
                }

                context.ReportDiagnostic(DiagnosticDescriptors.MakeMethodExtensionMethod, methodDeclaration.Identifier);
            }
        }