示例#1
0
        private static void AnalyzeTypeDeclaration(SyntaxNodeAnalysisContext context)
        {
            var typeDeclaration = (TypeDeclarationSyntax)context.Node;

            if (typeDeclaration.Modifiers.Contains(SyntaxKind.PartialKeyword))
                return;

            SemanticModel semanticModel = context.SemanticModel;
            CancellationToken cancellationToken = context.CancellationToken;

            INamedTypeSymbol declarationSymbol = null;
            ImmutableArray<AttributeData> attributes = default;

            if (typeDeclaration.IsKind(SyntaxKind.StructDeclaration))
            {
                declarationSymbol = semanticModel.GetDeclaredSymbol(typeDeclaration, cancellationToken);

                attributes = declarationSymbol.GetAttributes();

                if (attributes.Any(f => f.AttributeClass.HasMetadataName(MetadataNames.System_Runtime_InteropServices_StructLayoutAttribute)))
                    return;
            }

            bool? canContainUnityScriptMethods = null;

            SyntaxList<MemberDeclarationSyntax> members = typeDeclaration.Members;

            UnusedMemberWalker walker = null;

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

                if (member.ContainsUnbalancedIfElseDirectives(member.Span))
                    continue;

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

                            if (SyntaxAccessibility<DelegateDeclarationSyntax>.Instance.GetAccessibility(declaration) == Accessibility.Private)
                            {
                                if (walker == null)
                                    walker = UnusedMemberWalker.GetInstance();

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

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

                            if (declaration.ExplicitInterfaceSpecifier == null
                                && SyntaxAccessibility<EventDeclarationSyntax>.Instance.GetAccessibility(declaration) == Accessibility.Private)
                            {
                                if (walker == null)
                                    walker = UnusedMemberWalker.GetInstance();

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

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

                            if (SyntaxAccessibility<EventFieldDeclarationSyntax>.Instance.GetAccessibility(declaration) == Accessibility.Private)
                            {
                                if (walker == null)
                                    walker = UnusedMemberWalker.GetInstance();

                                walker.AddNodes(declaration.Declaration);
                            }

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

                            if (SyntaxAccessibility<FieldDeclarationSyntax>.Instance.GetAccessibility(declaration) == Accessibility.Private)
                            {
                                if (walker == null)
                                    walker = UnusedMemberWalker.GetInstance();

                                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<MethodDeclarationSyntax>.Instance.GetAccessibility(declaration) != Accessibility.Private)
                            {
                                break;
                            }

                            string methodName = declaration.Identifier.ValueText;

                            if (IsMainMethod(declaration, modifiers, methodName))
                                break;

                            if (declaration.ReturnsVoid()
                                && AnalyzerOptions.SuppressUnityScriptMethods.IsEnabled(context))
                            {
                                if (canContainUnityScriptMethods == null)
                                {
                                    if (declarationSymbol == null)
                                        declarationSymbol = semanticModel.GetDeclaredSymbol(typeDeclaration, context.CancellationToken);

                                    canContainUnityScriptMethods = declarationSymbol.InheritsFrom(UnityScriptMethods.MonoBehaviourClassName);
                                }

                                if (canContainUnityScriptMethods == true
                                    && UnityScriptMethods.MethodNames.Contains(methodName))
                                {
                                    break;
                                }
                            }

                            if (walker == null)
                                walker = UnusedMemberWalker.GetInstance();

                            walker.AddNode(methodName, declaration);

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

                            if (declaration.ExplicitInterfaceSpecifier == null
                                && SyntaxAccessibility<PropertyDeclarationSyntax>.Instance.GetAccessibility(declaration) == Accessibility.Private)
                            {
                                if (walker == null)
                                    walker = UnusedMemberWalker.GetInstance();

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

                            break;
                        }
                }
            }

            if (walker == null)
                return;

            try
            {
                Collection<NodeSymbolInfo> nodes = walker.Nodes;

                if (ShouldAnalyzeDebuggerDisplayAttribute()
                    && nodes.Any(f => f.CanBeInDebuggerDisplayAttribute))
                {
                    if (attributes.IsDefault)
                        attributes = semanticModel.GetDeclaredSymbol(typeDeclaration, cancellationToken).GetAttributes();

                    string value = attributes
                        .FirstOrDefault(f => f.AttributeClass.HasMetadataName(MetadataNames.System_Diagnostics_DebuggerDisplayAttribute))?
                        .ConstructorArguments
                        .SingleOrDefault(shouldThrow: false)
                        .Value?
                        .ToString();

                    if (value != null)
                        RemoveMethodsAndPropertiesThatAreInDebuggerDisplayAttributeValue(value, ref nodes);
                }

                if (nodes.Count > 0)
                {
                    walker.SemanticModel = semanticModel;
                    walker.CancellationToken = cancellationToken;

                    walker.Visit(typeDeclaration);

                    foreach (NodeSymbolInfo node in nodes)
                        ReportDiagnostic(context, node.Node);
                }
            }
            finally
            {
                UnusedMemberWalker.Free(walker);
            }

            bool ShouldAnalyzeDebuggerDisplayAttribute()
            {
                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;
            }
        }
示例#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;
            SemanticModel      semanticModel     = context.SemanticModel;
            CancellationToken  cancellationToken = context.CancellationToken;

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

                if (member.ContainsUnbalancedIfElseDirectives(member.Span))
                {
                    continue;
                }

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

                    if (SyntaxAccessibility <DelegateDeclarationSyntax> .Instance.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        if (walker == null)
                        {
                            walker = UnusedMemberWalkerCache.GetInstance();
                        }

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

                    break;
                }

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

                    if (declaration.ExplicitInterfaceSpecifier == null &&
                        SyntaxAccessibility <EventDeclarationSyntax> .Instance.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        if (walker == null)
                        {
                            walker = UnusedMemberWalkerCache.GetInstance();
                        }

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

                    break;
                }

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

                    if (SyntaxAccessibility <EventFieldDeclarationSyntax> .Instance.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        if (walker == null)
                        {
                            walker = UnusedMemberWalkerCache.GetInstance();
                        }

                        walker.AddNodes(declaration.Declaration);
                    }

                    break;
                }

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

                    if (SyntaxAccessibility <FieldDeclarationSyntax> .Instance.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        if (walker == null)
                        {
                            walker = UnusedMemberWalkerCache.GetInstance();
                        }

                        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 <MethodDeclarationSyntax> .Instance.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        string methodName = declaration.Identifier.ValueText;

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

                            walker.AddNode(methodName, declaration);
                        }
                    }

                    break;
                }

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

                    if (declaration.ExplicitInterfaceSpecifier == null &&
                        SyntaxAccessibility <PropertyDeclarationSyntax> .Instance.GetAccessibility(declaration) == Accessibility.Private)
                    {
                        if (walker == null)
                        {
                            walker = UnusedMemberWalkerCache.GetInstance();
                        }

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

                    break;
                }
                }
            }

            if (walker == null)
            {
                return;
            }

            Collection <NodeSymbolInfo> nodes = walker.Nodes;

            if (ShouldAnalyzeDebuggerDisplayAttribute() &&
                nodes.Any(f => f.CanBeInDebuggerDisplayAttribute))
            {
                string value = semanticModel
                               .GetDeclaredSymbol(typeDeclaration, cancellationToken)
                               .GetAttribute(MetadataNames.System_Diagnostics_DebuggerDisplayAttribute)?
                               .ConstructorArguments
                               .SingleOrDefault(shouldThrow: false)
                               .Value?
                               .ToString();

                if (value != null)
                {
                    RemoveMethodsAndPropertiesThatAreInDebuggerDisplayAttributeValue(value, ref nodes);
                }

                if (nodes.Count == 0)
                {
                    UnusedMemberWalkerCache.Free(walker);
                    return;
                }
            }

            walker.SemanticModel     = semanticModel;
            walker.CancellationToken = cancellationToken;

            walker.Visit(typeDeclaration);

            foreach (NodeSymbolInfo info in nodes)
            {
                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));
                }
            }

            UnusedMemberWalkerCache.Free(walker);

            bool ShouldAnalyzeDebuggerDisplayAttribute()
            {
                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);
            }
        }