private static bool IsWrongType(BackingFieldOrProperty fieldOrProperty, ArgumentSyntax argument, SyntaxNodeAnalysisContext context, [NotNullWhen(true)] out ITypeSymbol?registeredType) { if (DependencyProperty.TryGetRegisteredType(fieldOrProperty, context.SemanticModel, context.CancellationToken, out registeredType) && !PropertyMetadata.IsValueValidForRegisteredType(argument.Expression, registeredType, context.SemanticModel, context.CancellationToken)) { if (context.SemanticModel.TryGetType(argument.Expression, context.CancellationToken, out var type)) { if (type == KnownSymbols.Object) { return(false); } if (registeredType.IsAssignableTo(KnownSymbols.Freezable, context.Compilation) && type.IsAssignableTo(KnownSymbols.Freezable, context.Compilation)) { return(false); } } return(true); } return(false); }
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)); } } } } } }