Ejemplo n.º 1
0
        internal static bool TryFind(ITypeSymbol type, SemanticModel semanticModel, CancellationToken cancellationToken, [NotNullWhen(true)] out IMethodSymbol?invoker)
        {
            if (PropertyChangedEvent.TryFind(type, out var propertyChangedEvent))
            {
                return(TryFind(propertyChangedEvent, semanticModel, cancellationToken, out invoker));
            }

            invoker = null;
            return(false);
        }
Ejemplo n.º 2
0
        private static void Handle(SyntaxNodeAnalysisContext context)
        {
            if (!context.IsExcludedFromAnalysis() &&
                context.ContainingSymbol is INamedTypeSymbol {
                IsStatic : false
            } type&&
                context.Node is ClassDeclarationSyntax classDeclaration &&
                !IsExcludedType())
            {
                if (classDeclaration.Members.TryFirstOfType(x => Property.ShouldNotify(x, context.SemanticModel, context.CancellationToken), out PropertyDeclarationSyntax _))
                {
                    var properties = string.Join(
                        Environment.NewLine,
                        classDeclaration.Members.OfType <PropertyDeclarationSyntax>()
                        .Where(x => Property.ShouldNotify(x, context.SemanticModel, context.CancellationToken))
                        .Select(x => x.Identifier.ValueText));
                    context.ReportDiagnostic(Diagnostic.Create(Descriptors.INPC001ImplementINotifyPropertyChanged, classDeclaration.Identifier.GetLocation(), $"The class {type.Name} should notify for:{Environment.NewLine}{properties}"));
                }

                if (PropertyChangedEvent.TryFind(type, out var eventSymbol))
                {
                    if (eventSymbol.IsStatic)
                    {
                        return;
                    }

                    context.ReportDiagnostic(Diagnostic.Create(Descriptors.INPC001ImplementINotifyPropertyChanged, classDeclaration.Identifier.GetLocation(), $"The class {type.Name} has event PropertyChanged but does not implement INotifyPropertyChanged."));
                }
            }

            bool IsExcludedType()
            {
                return(type.IsAssignableTo(KnownSymbol.INotifyPropertyChanged, context.Compilation) ||
                       type.IsAssignableTo(KnownSymbol.Attribute, context.Compilation) ||
                       type.IsAssignableTo(KnownSymbol.IEnumerator, context.Compilation) ||
                       type.IsAssignableTo(KnownSymbol.Stream, context.Compilation) ||
                       type.IsAssignableTo(KnownSymbol.MarkupExtension, context.Compilation) ||
                       type.IsAssignableTo(KnownSymbol.IValueConverter, context.Compilation) ||
                       type.IsAssignableTo(KnownSymbol.IMultiValueConverter, context.Compilation) ||
                       type.IsAssignableTo(KnownSymbol.DataTemplateSelector, context.Compilation) ||
                       type.IsAssignableTo(KnownSymbol.DependencyObject, context.Compilation));
            }
        }
        private static void Handle(SyntaxNodeAnalysisContext context)
        {
            if (!context.IsExcludedFromAnalysis() &&
                context.Node is ArgumentSyntax {
                Parent : ArgumentListSyntax argumentList
            } argument)
            {
                if (argument.TryGetStringValue(context.SemanticModel, context.CancellationToken, out var text))
                {
                    if (text == ContainingSymbolName(context.ContainingSymbol) &&
                        context.SemanticModel.GetSymbolSafe(argumentList.Parent, context.CancellationToken) is IMethodSymbol method &&
                        method.TryFindParameter(argument, out var parameter))
                    {
                        if (parameter.IsCallerMemberName())
                        {
                            context.ReportDiagnostic(Diagnostic.Create(Descriptors.INPC004UseCallerMemberName, argument.GetLocation()));
                        }
                        else if (parameter.TrySingleDeclaration <SyntaxNode>(context.CancellationToken, out _) &&
                                 OnPropertyChanged.IsMatch(method, context.SemanticModel, context.CancellationToken) == AnalysisResult.Yes)
                        {
                            context.ReportDiagnostic(Diagnostic.Create(Descriptors.INPC004UseCallerMemberName, argument.GetLocation()));
                        }
                    }

                    if (SyntaxFacts.IsValidIdentifier(text))
                    {
                        if (argumentList.Parent is InvocationExpressionSyntax onPropertyChangedCandidate &&
                            OnPropertyChanged.IsMatch(onPropertyChangedCandidate, context.SemanticModel, context.CancellationToken) != AnalysisResult.No &&
                            !context.ContainingSymbol.ContainingType.TryFindPropertyRecursive(text, out _))
                        {
                            context.ReportDiagnostic(Diagnostic.Create(Descriptors.INPC009DoNotRaiseChangeForMissingProperty, argument.GetLocation()));
                        }

                        if (argumentList.Parent is ObjectCreationExpressionSyntax {
                            Parent : ArgumentSyntax parentArg
                        } objectCreation&&
                            parentArg.FirstAncestor <InvocationExpressionSyntax>() is { } parentInvocation&&
                            context.SemanticModel.TryGetSymbol(objectCreation, KnownSymbol.PropertyChangedEventArgs, context.CancellationToken, out _))
                        {
                            if ((OnPropertyChanged.IsMatch(parentInvocation, context.SemanticModel, context.CancellationToken) != AnalysisResult.No ||
                                 PropertyChangedEvent.IsInvoke(parentInvocation, context.SemanticModel, context.CancellationToken)) &&
                                !context.ContainingSymbol.ContainingType.TryFindPropertyRecursive(text, out _))
                            {
                                context.ReportDiagnostic(Diagnostic.Create(Descriptors.INPC009DoNotRaiseChangeForMissingProperty, argument.GetLocation()));
                            }
                        }

                        if (argument.Expression is LiteralExpressionSyntax literal &&
                            literal.IsKind(SyntaxKind.StringLiteralExpression))
                        {
                            if (context.ContainingSymbol is IMethodSymbol containingMethod &&
                                containingMethod.Parameters.TrySingle(x => x.Name == literal.Token.ValueText, out _))
                            {
                                context.ReportDiagnostic(Diagnostic.Create(Descriptors.INPC013UseNameof, argument.GetLocation()));
                            }

                            if (context.ContainingSymbol.ContainingType.TryFindPropertyRecursive(literal.Token.ValueText, out _))
                            {
                                context.ReportDiagnostic(Diagnostic.Create(Descriptors.INPC013UseNameof, argument.GetLocation()));
                            }
                        }
                    }
                }

                if (argument is { Expression : AnonymousFunctionExpressionSyntax lambda } &&