private static bool CanIgnore(InvocationExpressionSyntax invocation, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (!(invocation.Parent is StatementSyntax))
            {
                return(true);
            }

            if (invocation.Parent is ExpressionStatementSyntax &&
                invocation.Parent.Parent is BlockSyntax &&
                semanticModel.GetSymbolSafe(invocation, cancellationToken) is IMethodSymbol method)
            {
                if (method.ReturnsVoid)
                {
                    return(true);
                }

                if (method == KnownSymbol.StringBuilder.Append ||
                    method == KnownSymbol.StringBuilder.AppendLine ||
                    method == KnownSymbol.StringBuilder.AppendFormat ||
                    method == KnownSymbol.IList.Add ||
                    method == KnownSymbol.IList.Remove)
                {
                    return(true);
                }

                if (method.TryGetSingleDeclaration(cancellationToken, out MethodDeclarationSyntax declaration))
                {
                    using (var walker = ReturnValueWalker.Borrow(declaration, Search.Recursive, semanticModel, cancellationToken))
                    {
                        if (method.IsExtensionMethod)
                        {
                            var identifier = declaration.ParameterList.Parameters[0].Identifier;
                            foreach (var returnValue in walker)
                            {
                                if ((returnValue as IdentifierNameSyntax)?.Identifier.ValueText != identifier.ValueText)
                                {
                                    return(false);
                                }
                            }

                            return(true);
                        }

                        foreach (var returnValue in walker)
                        {
                            if (!returnValue.IsKind(SyntaxKind.ThisExpression))
                            {
                                return(false);
                            }
                        }

                        return(true);
                    }
                }

                return(method.ReturnsVoid);
            }

            return(true);
        }
Beispiel #2
0
        private static bool CanIgnore(InvocationExpressionSyntax invocation, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (semanticModel.GetSymbolSafe(invocation, cancellationToken) is IMethodSymbol method)
            {
                if (method.ReturnsVoid ||
                    method.ReturnType == KnownSymbol.MoqIReturnsResult)
                {
                    return(true);
                }

                if (ReferenceEquals(method.ContainingType, method.ReturnType) &&
                    method.ContainingType == KnownSymbol.StringBuilder)
                {
                    return(true);
                }

                if ((method.Name == "Add" ||
                     method.Name == "Remove" ||
                     method.Name == "RemoveAll" ||
                     method.Name == "TryAdd" ||
                     method.Name == "TryRemove") &&
                    method.ReturnType.IsEither(KnownSymbol.Boolean, KnownSymbol.Int32, KnownSymbol.Int64))
                {
                    return(true);
                }

                if (method.IsExtensionMethod)
                {
                    method = method.ReducedFrom;
                }

                if (method.TrySingleDeclaration(cancellationToken, out MethodDeclarationSyntax declaration))
                {
                    using (var walker = ReturnValueWalker.Borrow(declaration, Search.Recursive, semanticModel, cancellationToken))
                    {
                        foreach (var returnValue in walker)
                        {
                            if (returnValue is IdentifierNameSyntax identifierName &&
                                method.Parameters.TryFirst(x => x.Name == identifierName.Identifier.ValueText, out _))
                            {
                                return(true);
                            }

                            if (returnValue is InstanceExpressionSyntax)
                            {
                                return(true);
                            }
                        }
                    }
                }

                return(false);
            }

            return(true);
        }
Beispiel #3
0
        private static void Handle(SyntaxNodeAnalysisContext context)
        {
            if (context.IsExcludedFromAnalysis())
            {
                return;
            }

            if (context.Node is PropertyDeclarationSyntax propertyDeclaration &&
                context.ContainingSymbol is IPropertySymbol property)
            {
                {
                    if (propertyDeclaration.ExpressionBody is ArrowExpressionClauseSyntax expressionBody)
                    {
                        if (property.Type.IsReferenceType &&
                            expressionBody.Expression is ObjectCreationExpressionSyntax)
                        {
                            context.ReportDiagnostic(Diagnostic.Create(GU0021CalculatedPropertyAllocates.Descriptor, expressionBody.GetLocation()));
                        }
                        else if (expressionBody.Expression is MemberAccessExpressionSyntax memberAccess &&
                                 IsRelayReturn(memberAccess, context.SemanticModel, context.CancellationToken))
                        {
                            context.ReportDiagnostic(Diagnostic.Create(GU0008AvoidRelayProperties.Descriptor, memberAccess.GetLocation()));
                        }
                    }
                    else if (propertyDeclaration.TryGetGetter(out var getter))
                    {
                        using (var walker = ReturnValueWalker.Borrow(getter, Search.Recursive, context.SemanticModel, context.CancellationToken))
                        {
                            if (walker.TrySingle(out var returnValue))
                            {
                                if (property.Type.IsReferenceType &&
                                    returnValue is ObjectCreationExpressionSyntax)
                                {
                                    if (getter.Contains(returnValue) &&
                                        returnValue.FirstAncestor <ReturnStatementSyntax>() is ReturnStatementSyntax returnStatement)
                                    {
                                        context.ReportDiagnostic(Diagnostic.Create(GU0021CalculatedPropertyAllocates.Descriptor, returnStatement.GetLocation()));
                                    }
                                    else
                                    {
                                        context.ReportDiagnostic(Diagnostic.Create(GU0021CalculatedPropertyAllocates.Descriptor, getter.GetLocation()));
                                    }
                                }
                                else if (returnValue is MemberAccessExpressionSyntax memberAccess &&
                                         IsRelayReturn(memberAccess, context.SemanticModel, context.CancellationToken))
                                {
                                    if (getter.Contains(returnValue) &&
                                        returnValue.FirstAncestor <ReturnStatementSyntax>() is ReturnStatementSyntax returnStatement)
                                    {
                                        context.ReportDiagnostic(Diagnostic.Create(GU0008AvoidRelayProperties.Descriptor, returnStatement.GetLocation()));
                                    }
                                    else
                                    {
                                        context.ReportDiagnostic(Diagnostic.Create(GU0008AvoidRelayProperties.Descriptor, getter.GetLocation()));
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }