Esempio n. 1
0
        private static void Handle(SyntaxNodeAnalysisContext context)
        {
            if (!context.IsExcludedFromAnalysis() &&
                context.Node is PropertyDeclarationSyntax propertyDeclaration &&
                context.ContainingSymbol is IPropertySymbol property)
            {
                using (var walker = ReturnExpressions(propertyDeclaration))
                {
                    foreach (var returnValue in walker.ReturnValues)
                    {
                        if (IsProperty(returnValue))
                        {
                            context.ReportDiagnostic(Diagnostic.Create(Descriptors.INPC015PropertyIsRecursive, returnValue.GetLocation(), "Getter returns property, infinite recursion"));
                        }
                    }

                    if (walker.ReturnValues.TrySingle(out var single))
                    {
                        if (single.IsEither(SyntaxKind.SimpleMemberAccessExpression, SyntaxKind.IdentifierName) &&
                            MemberPath.TrySingle(single, out var path) &&
                            context.SemanticModel.TryGetSymbol(path, context.CancellationToken, out IFieldSymbol? backingField))
                        {
                            if (!HasMatchingName(backingField, property))
                            {
                                context.ReportDiagnostic(Diagnostic.Create(Descriptors.INPC017BackingFieldNameMisMatch, path.GetLocation()));
                            }

                            if (propertyDeclaration.TryGetSetter(out var setAccessor))
                            {
                                using var mutationWalker = MutationWalker.Borrow(setAccessor, SearchScope.Member, context.SemanticModel, context.CancellationToken);
                                if (mutationWalker.IsEmpty)
                                {
                                    context.ReportDiagnostic(Diagnostic.Create(Descriptors.INPC021SetBackingField, setAccessor.GetLocation()));
                                }
                            }
                        }

                        if (single is LiteralExpressionSyntax &&
                            propertyDeclaration.TryGetSetter(out var set) &&
                            Setter.TryFindSingleMutation(set, context.SemanticModel, context.CancellationToken, out var fieldAccess))
                        {
                            context.ReportDiagnostic(
                                Diagnostic.Create(
                                    Descriptors.INPC019GetBackingField,
                                    single.GetLocation(),
                                    additionalLocations: new[] { fieldAccess.GetLocation() }));
                        }
                    }
                }

                if (propertyDeclaration.TryGetSetter(out var setter))
                {
                    if (ShouldBeExpressionBody(setter))
                    {
                        context.ReportDiagnostic(Diagnostic.Create(Descriptors.INPC020PreferExpressionBodyAccessor, setter.GetLocation()));
                    }

                    if (Property.GetsAndSetsSame(propertyDeclaration, context.SemanticModel, context.CancellationToken, out _, out _) == false)
                    {
                        context.ReportDiagnostic(Diagnostic.Create(Descriptors.INPC010GetAndSetSame, propertyDeclaration.Identifier.GetLocation()));
                    }

                    using (var assignmentWalker = AssignmentWalker.Borrow(setter))
                    {
                        if (assignmentWalker.Assignments.TryFirst(x => IsProperty(x.Left) && !x.Parent.IsKind(SyntaxKind.ObjectInitializerExpression), out var recursiveAssignment))
                        {
                            context.ReportDiagnostic(Diagnostic.Create(Descriptors.INPC015PropertyIsRecursive, recursiveAssignment.Left.GetLocation(), "Setter assigns property, infinite recursion"));
                        }
                    }

                    if (propertyDeclaration.TryGetGetter(out var getter))
                    {
                        if (ShouldBeExpressionBody(getter))
                        {
                            context.ReportDiagnostic(Diagnostic.Create(Descriptors.INPC020PreferExpressionBodyAccessor, getter.GetLocation()));
                        }
                    }
                }

                bool IsProperty(ExpressionSyntax expression)
                {
                    if (property.ExplicitInterfaceImplementations.Any())
                    {
                        return(false);
                    }

                    return(expression switch
                    {
                        IdentifierNameSyntax {
                            Identifier: { ValueText : { } name }
                        } => property.Name == name,
                        MemberAccessExpressionSyntax {
                            Expression : ThisExpressionSyntax _, Name : { Identifier : { ValueText : { } name } }
                        } => property.Name == name,