private static void Handle(SyntaxNodeAnalysisContext context) { if (!context.IsExcludedFromAnalysis() && context.Node is ObjectCreationExpressionSyntax objectCreation && context.ContainingSymbol.IsStatic && PropertyMetadata.TryGetConstructor(objectCreation, context.SemanticModel, context.CancellationToken, out _)) { if (PropertyMetadata.TryGetRegisteredName(objectCreation, context.SemanticModel, context.CancellationToken, out _, out var registeredName)) { if (PropertyMetadata.TryGetPropertyChangedCallback(objectCreation, context.SemanticModel, context.CancellationToken, out var propertyChangedCallback) && Callback.TryGetTarget(propertyChangedCallback, KnownSymbols.PropertyChangedCallback, context.SemanticModel, context.CancellationToken, out var callbackIdentifier, out var target)) { if (target.ContainingType.Equals(context.ContainingSymbol.ContainingType) && !target.Name.IsParts("On", registeredName, "Changed") && target.DeclaredAccessibility.IsEither(Accessibility.Private, Accessibility.Protected)) { using (var walker = InvocationWalker.InContainingClass(target, context.SemanticModel, context.CancellationToken)) { if (walker.IdentifierNames.Count == 1) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0005PropertyChangedCallbackShouldMatchRegisteredName, callbackIdentifier.GetLocation(), ImmutableDictionary <string, string> .Empty.Add("ExpectedName", $"On{registeredName}Changed"), callbackIdentifier, $"On{registeredName}Changed")); } else if (target.Name.StartsWith("On") && target.Name.EndsWith("Changed")) { foreach (var identifierName in walker.IdentifierNames) { if (identifierName.TryFirstAncestor(out ArgumentSyntax argument) && argument != propertyChangedCallback && MatchesPropertyChangedCallbackName(argument, target, context)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0005PropertyChangedCallbackShouldMatchRegisteredName, callbackIdentifier.GetLocation(), callbackIdentifier, $"On{registeredName}Changed")); break; } } } } } if (target.TrySingleMethodDeclaration(context.CancellationToken, out var declaration) && Callback.IsSingleExpression(declaration)) { context.ReportDiagnostic(Diagnostic.Create(Descriptors.WPF0023ConvertToLambda, propertyChangedCallback.GetLocation())); } } if (PropertyMetadata.TryGetCoerceValueCallback(objectCreation, context.SemanticModel, context.CancellationToken, out var coerceValueCallback) && Callback.TryGetTarget(coerceValueCallback, KnownSymbols.CoerceValueCallback, context.SemanticModel, context.CancellationToken, out callbackIdentifier, out target)) { if (target.ContainingType.Equals(context.ContainingSymbol.ContainingType) && !target.Name.IsParts("Coerce", registeredName)) { using (var walker = InvocationWalker.InContainingClass(target, context.SemanticModel, context.CancellationToken)) { if (walker.IdentifierNames.Count == 1) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0006CoerceValueCallbackShouldMatchRegisteredName, callbackIdentifier.GetLocation(), ImmutableDictionary <string, string> .Empty.Add("ExpectedName", $"Coerce{registeredName}"), callbackIdentifier, $"Coerce{registeredName}")); } else if (target.Name.StartsWith("Coerce")) { foreach (var identifierName in walker.IdentifierNames) { if (identifierName.TryFirstAncestor(out ArgumentSyntax argument) && argument != propertyChangedCallback && MatchesCoerceValueCallbackName(argument, target, context)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0006CoerceValueCallbackShouldMatchRegisteredName, callbackIdentifier.GetLocation(), callbackIdentifier, $"Coerce{registeredName}")); break; } } } } } if (target.TrySingleMethodDeclaration(context.CancellationToken, out var declaration) && Callback.IsSingleExpression(declaration)) { context.ReportDiagnostic(Diagnostic.Create(Descriptors.WPF0023ConvertToLambda, propertyChangedCallback.GetLocation())); } } } if (PropertyMetadata.TryGetDependencyProperty(objectCreation, context.SemanticModel, context.CancellationToken, out var fieldOrProperty) && DependencyProperty.TryGetRegisteredType(fieldOrProperty, context.SemanticModel, context.CancellationToken, out var registeredType) && PropertyMetadata.TryGetDefaultValue(objectCreation, context.SemanticModel, context.CancellationToken, out var defaultValueArg)) { if (!PropertyMetadata.IsValueValidForRegisteredType(defaultValueArg.Expression, registeredType, context.SemanticModel, context.CancellationToken)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0010DefaultValueMustMatchRegisteredType, defaultValueArg.GetLocation(), fieldOrProperty.Symbol, registeredType)); } if (registeredType.IsReferenceType) { var defaultValue = defaultValueArg.Expression; if (defaultValue != null && !defaultValue.IsKind(SyntaxKind.NullLiteralExpression) && registeredType != KnownSymbols.FontFamily) { if (IsNonEmptyArrayCreation(defaultValue as ArrayCreationExpressionSyntax, context) || IsReferenceTypeCreation(defaultValue as ObjectCreationExpressionSyntax, context)) { context.ReportDiagnostic(Diagnostic.Create(Descriptors.WPF0016DefaultValueIsSharedReferenceType, defaultValueArg.GetLocation(), fieldOrProperty.Symbol)); } } } } } }
private static void Handle(SyntaxNodeAnalysisContext context) { if (!context.IsExcludedFromAnalysis() && context.Node is InvocationExpressionSyntax registerCall && context.ContainingSymbol.IsStatic && TryGetAnyRegisterCall(registerCall, context, out var registerMethod) && DependencyProperty.TryGetRegisteredName(registerCall, context.SemanticModel, context.CancellationToken, out var nameArg, out var registeredName)) { if (registerMethod.TryFindParameter(KnownSymbols.ValidateValueCallback, out var parameter) && registerCall.TryFindArgument(parameter, out var validateValueCallback) && Callback.TryGetTarget(validateValueCallback, KnownSymbols.ValidateValueCallback, context.SemanticModel, context.CancellationToken, out var callBackIdentifier, out var target)) { if (target.ContainingType.Equals(context.ContainingSymbol.ContainingType) && !MatchesValidateValueCallbackName(validateValueCallback, target, context)) { using var walker = InvocationWalker.InContainingClass(target, context.SemanticModel, context.CancellationToken); if (walker.IdentifierNames.Count == 1) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0007ValidateValueCallbackCallbackShouldMatchRegisteredName, callBackIdentifier.GetLocation(), ImmutableDictionary <string, string> .Empty.Add("ExpectedName", $"Validate{registeredName}"), callBackIdentifier, $"Validate{registeredName}")); } else if (target.Name.StartsWith("Validate", StringComparison.Ordinal)) { foreach (var identifierName in walker.IdentifierNames) { if (identifierName.TryFirstAncestor(out ArgumentSyntax? argument) && argument != validateValueCallback && MatchesValidateValueCallbackName(argument, target, context)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0007ValidateValueCallbackCallbackShouldMatchRegisteredName, callBackIdentifier.GetLocation(), callBackIdentifier, $"Validate{registeredName}")); break; } } } } if (target.TrySingleMethodDeclaration(context.CancellationToken, out var declaration) && Callback.IsSingleExpression(declaration)) { context.ReportDiagnostic(Diagnostic.Create(Descriptors.WPF0023ConvertToLambda, validateValueCallback.GetLocation())); } } if (nameArg.Expression is { } nameExpression&& nameExpression.IsNameof() == false && context.ContainingSymbol.ContainingType.TryFindProperty(registeredName, out var property)) { if (nameArg.Expression.IsKind(SyntaxKind.StringLiteralExpression)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0150UseNameofInsteadOfLiteral, nameArg.GetLocation(), ImmutableDictionary <string, string> .Empty.Add(nameof(IdentifierNameSyntax), property.Name), property.Name)); } else { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0151UseNameofInsteadOfConstant, nameExpression.GetLocation(), ImmutableDictionary <string, string> .Empty.Add(nameof(IdentifierNameSyntax), property.Name), property.Name)); } } } }