internal static bool TrySingleReturned(AccessorDeclarationSyntax getter, [NotNullWhen(true)] out ExpressionSyntax?result)
        {
            if (getter.ExpressionBody is { } getterExpressionBody)
            {
                result = getterExpressionBody.Expression;
                return(result != null);
            }

            if (getter.Body is { } body)
            {
                if (body.Statements.Count == 0)
                {
                    result = null;
                    return(false);
                }

                if (body.Statements.TrySingle(out var statement))
                {
                    if (statement is ReturnStatementSyntax returnStatement)
                    {
                        result = returnStatement.Expression;
                        return(result != null);
                    }
                }

                return(ReturnExpressionsWalker.TryGetSingle(getter, out result));
            }

            result = null;
            return(false);
        }
Exemple #2
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 &&
                    IsProperty(expressionBody.Expression, property))
                {
                    context.ReportDiagnostic(Diagnostic.Create(INPC015PropertyIsRecursive.Descriptor, expressionBody.Expression.GetLocation(), "Expression body returns property, infinite recursion"));
                }

                if (propertyDeclaration.TryGetGetter(out var getter))
                {
                    using (var returnWalker = ReturnExpressionsWalker.Borrow(getter))
                    {
                        if (returnWalker.ReturnValues.TryFirst(x => IsProperty(x, property), out var recursiveReturnValue))
                        {
                            context.ReportDiagnostic(Diagnostic.Create(INPC015PropertyIsRecursive.Descriptor, recursiveReturnValue.GetLocation(), "Getter returns property, infinite recursion"));
                        }
                    }
                }

                if (propertyDeclaration.TryGetSetter(out var setter))
                {
                    using (var assignmentWalker = AssignmentWalker.Borrow(setter))
                    {
                        if (assignmentWalker.Assignments.TryFirst(x => IsProperty(x.Left, property), out var recursiveAssignment))
                        {
                            context.ReportDiagnostic(Diagnostic.Create(INPC015PropertyIsRecursive.Descriptor, recursiveAssignment.Left.GetLocation(), "Setter assigns property, infinite recursion"));
                        }

                        if (getter != null)
                        {
                            if (property.ContainingType.Is(KnownSymbol.INotifyPropertyChanged) &&
                                Property.ShouldNotify(propertyDeclaration, property, context.SemanticModel, context.CancellationToken))
                            {
                                context.ReportDiagnostic(Diagnostic.Create(INPC002MutablePublicPropertyShouldNotify.Descriptor, propertyDeclaration.GetLocation(), property.Name));
                            }

                            if (assignmentWalker.Assignments.TrySingle(out var singleAssignment) &&
                                ReturnExpressionsWalker.TryGetSingle(getter, out var singleReturnValue) &&
                                !MemberPath.Uses(singleAssignment.Left, singleReturnValue, context))
                            {
                                context.ReportDiagnostic(Diagnostic.Create(INPC010GetAndSetSame.Descriptor, propertyDeclaration.GetLocation()));
                            }
                        }
                    }
                }
            }
        }