/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var document = context.Document; var syntaxRoot = await document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var semanticModel = await document.GetSemanticModelAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { var token = syntaxRoot.FindToken(diagnostic.Location.SourceSpan.Start); if (string.IsNullOrEmpty(token.ValueText)) { continue; } if (syntaxRoot.TryFindNodeOrAncestor(diagnostic, out MemberDeclarationSyntax member) && semanticModel.TryGetSymbol(member, context.CancellationToken, out ISymbol symbol) && BackingFieldOrProperty.TryCreateForDependencyProperty(symbol, out var fieldOrProperty) && DependencyProperty.TryGetRegisteredName(fieldOrProperty, semanticModel, context.CancellationToken, out var name)) { context.RegisterCodeFix( "Add standard documentation.", (editor, _) => editor.ReplaceNode(member, x => x.WithDocumentationText($"/// <summary>Identifies the <see cref=\"{name}\"/> dependency property.</summary>")), this.GetType(), diagnostic); } } }
internal static bool TryGetRegisteredName(ObjectCreationExpressionSyntax objectCreation, SemanticModel semanticModel, CancellationToken cancellationToken, [NotNullWhen(true)] out ArgumentSyntax?nameArg, out string registeredName) { nameArg = null; registeredName = null; return(TryGetConstructor(objectCreation, semanticModel, cancellationToken, out _) && objectCreation.TryFirstAncestor(out InvocationExpressionSyntax? invocation) && DependencyProperty.TryGetRegisteredName(invocation, semanticModel, cancellationToken, out nameArg, out registeredName)); }
private static void Handle(SyntaxNodeAnalysisContext context) { if (!context.IsExcludedFromAnalysis() && context.Node is MemberDeclarationSyntax memberDeclaration) { if (BackingFieldOrProperty.TryCreateForDependencyProperty(context.ContainingSymbol, out var backingMember)) { if (DependencyProperty.TryGetRegisteredName(backingMember, context.SemanticModel, context.CancellationToken, out _, out var registeredName)) { if (backingMember.Type == KnownSymbols.DependencyProperty && !backingMember.Name.IsParts(registeredName, "Property")) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0001BackingFieldShouldMatchRegisteredName, BackingFieldOrProperty.FindIdentifier(memberDeclaration).GetLocation(), ImmutableDictionary <string, string> .Empty.Add("ExpectedName", registeredName + "Property"), backingMember.Name, registeredName)); } if (backingMember.Type == KnownSymbols.DependencyPropertyKey && !backingMember.Name.IsParts(registeredName, "PropertyKey")) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0002BackingFieldShouldMatchRegisteredName, BackingFieldOrProperty.FindIdentifier(memberDeclaration).GetLocation(), ImmutableDictionary <string, string> .Empty.Add("ExpectedName", registeredName + "PropertyKey"), backingMember.Name, registeredName)); } if (context.ContainingSymbol.ContainingType.TryFindProperty(registeredName, out _) && context.ContainingSymbol.DeclaredAccessibility.IsEither(Accessibility.Protected, Accessibility.Internal, Accessibility.Public) && !HasStandardText(memberDeclaration, registeredName, out var comment)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0060DocumentDependencyPropertyBackingMember, comment == null ? BackingFieldOrProperty.FindIdentifier(memberDeclaration).GetLocation() : comment.GetLocation(), properties: ImmutableDictionary <string, string> .Empty.Add(nameof(CrefParameterSyntax), registeredName))); } if (DependencyProperty.TryGetRegisteredType(backingMember, context.SemanticModel, context.CancellationToken, out var type) && type.Is(KnownSymbols.Style) && !TryFindStyleTypedPropertyAttribute(memberDeclaration, registeredName, context.SemanticModel, context.CancellationToken) && backingMember.FieldOrProperty.Symbol.DeclaredAccessibility.IsEither(Accessibility.Public, Accessibility.Internal)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0176StyleTypedPropertyMissing, BackingFieldOrProperty.FindIdentifier(memberDeclaration).GetLocation(), ImmutableDictionary <string, string> .Empty.Add( nameof(AttributeListSyntax), $"[StyleTypedProperty(Property = {(context.ContainingSymbol.ContainingType.TryFindProperty(registeredName, out _) ? $"nameof({registeredName})" : $"\"{registeredName}\"")}, StyleTargetType = typeof(TYPE))]"),
private static bool MatchesValidateValueCallbackName(ArgumentSyntax validateValueCallback, IMethodSymbol target, SyntaxNodeAnalysisContext context) { return(validateValueCallback.Parent is ArgumentListSyntax argumentList && argumentList.Parent is InvocationExpressionSyntax invocation && TryGetAnyRegisterCall(invocation, context, out _) && target.ContainingType.Equals(context.ContainingSymbol.ContainingType) && DependencyProperty.TryGetRegisteredName(invocation, context.SemanticModel, context.CancellationToken, out var registeredName) && target.Name.IsParts("Validate", registeredName)); }
private static void Handle(SyntaxNodeAnalysisContext context) { if (!context.IsExcludedFromAnalysis() && context.Node is InvocationExpressionSyntax registerCall && context.ContainingSymbol.IsStatic && TryGetAnyRegisterCall(registerCall, context, out var registerMethod) && registerMethod.TryFindParameter(KnownSymbol.ValidateValueCallback, out var parameter) && registerCall.TryFindArgument(parameter, out var validateValueCallback) && Callback.TryGetTarget(validateValueCallback, KnownSymbol.ValidateValueCallback, context.SemanticModel, context.CancellationToken, out var callBackIdentifier, out var target)) { if (target.ContainingType.Equals(context.ContainingSymbol.ContainingType) && !MatchesValidateValueCallbackName(validateValueCallback, target, context) && DependencyProperty.TryGetRegisteredName(registerCall, context.SemanticModel, context.CancellationToken, out var registeredName)) { using (var walker = InvocationWalker.InContainingClass(target, context.SemanticModel, context.CancellationToken)) { if (walker.IdentifierNames.Count == 1) { context.ReportDiagnostic( Diagnostic.Create( WPF0007ValidateValueCallbackCallbackShouldMatchRegisteredName.Descriptor, callBackIdentifier.GetLocation(), ImmutableDictionary <string, string> .Empty.Add("ExpectedName", $"Validate{registeredName}"), callBackIdentifier, $"Validate{registeredName}")); } else if (target.Name.StartsWith("Validate")) { foreach (var identifierName in walker.IdentifierNames) { if (identifierName.TryFirstAncestor(out ArgumentSyntax argument) && argument != validateValueCallback && MatchesValidateValueCallbackName(argument, target, context)) { context.ReportDiagnostic( Diagnostic.Create( WPF0007ValidateValueCallbackCallbackShouldMatchRegisteredName.Descriptor, callBackIdentifier.GetLocation(), callBackIdentifier, $"Validate{registeredName}")); break; } } } } } if (target.TrySingleMethodDeclaration(context.CancellationToken, out var declaration) && Callback.IsSingleExpression(declaration)) { context.ReportDiagnostic(Diagnostic.Create(WPF0023ConvertToLambda.Descriptor, validateValueCallback.GetLocation())); } } }
/// <inheritdoc/> protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context) { var document = context.Document; var syntaxRoot = await document.GetSyntaxRootAsync(context.CancellationToken) .ConfigureAwait(false); var semanticModel = await document.GetSemanticModelAsync(context.CancellationToken) .ConfigureAwait(false); foreach (var diagnostic in context.Diagnostics) { if (syntaxRoot.TryFindNodeOrAncestor(diagnostic, out MethodDeclarationSyntax methodDeclaration) && semanticModel.TryGetSymbol(methodDeclaration, context.CancellationToken, out var method)) { if (ClrMethod.IsAttachedGet(method, semanticModel, context.CancellationToken, out var fieldOrProperty) && DependencyProperty.TryGetRegisteredName(fieldOrProperty, semanticModel, context.CancellationToken, out var registeredName)) { var parameter = method.Parameters[0]; var text = StringBuilderPool.Borrow() .AppendLine($"/// <summary>Helper for getting <see cref=\"{fieldOrProperty.Name}\"/> from <paramref name=\"{parameter.Name}\"/>.</summary>") .AppendLine($"/// <param name=\"{parameter.Name}\"><see cref=\"{parameter.Type.ToMinimalDisplayString(semanticModel, methodDeclaration.SpanStart, SymbolDisplayFormat.MinimallyQualifiedFormat)}\"/> to read <see cref=\"{fieldOrProperty.Name}\"/> from.</param>") .AppendLine($"/// <returns>{registeredName} property value.</returns>") .Return(); context.RegisterCodeFix( "Add standard documentation.", (editor, _) => editor.ReplaceNode(methodDeclaration, x => x.WithDocumentationText(text)), this.GetType(), diagnostic); } else if (ClrMethod.IsAttachedSet(method, semanticModel, context.CancellationToken, out fieldOrProperty) && DependencyProperty.TryGetRegisteredName(fieldOrProperty, semanticModel, context.CancellationToken, out registeredName)) { var parameter = method.Parameters[0]; var text = StringBuilderPool.Borrow() .AppendLine($"/// <summary>Helper for setting <see cref=\"{fieldOrProperty.Name}\"/> on <paramref name=\"{parameter.Name}\"/>.</summary>") .AppendLine($"/// <param name=\"{parameter.Name}\"><see cref=\"{parameter.Type.ToMinimalDisplayString(semanticModel, methodDeclaration.SpanStart, SymbolDisplayFormat.MinimallyQualifiedFormat)}\"/> to set <see cref=\"{fieldOrProperty.Name}\"/> on.</param>") .AppendLine($"/// <param name=\"{method.Parameters[1].Name}\">{registeredName} property value.</param>") .Return(); context.RegisterCodeFix( "Add standard documentation.", (editor, _) => editor.ReplaceNode(methodDeclaration, x => x.WithDocumentationText(text)), this.GetType(), diagnostic); } } } }
private static void Handle(SyntaxNodeAnalysisContext context) { if (!context.IsExcludedFromAnalysis() && context.Node is MethodDeclarationSyntax methodDeclaration && context.ContainingSymbol is IMethodSymbol { IsStatic : true } method&& method.Parameters.TryElementAt(0, out var parameter) && parameter.Type.IsAssignableTo(KnownSymbols.DependencyObject, context.Compilation)) { if (ClrMethod.IsAttachedGet(methodDeclaration, context.SemanticModel, context.CancellationToken, out var getValueCall, out var fieldOrProperty)) { if (DependencyProperty.TryGetRegisteredName(fieldOrProperty, context.SemanticModel, context.CancellationToken, out _, out var registeredName)) { if (!method.Name.IsParts("Get", registeredName)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0004ClrMethodShouldMatchRegisteredName, methodDeclaration.Identifier.GetLocation(), ImmutableDictionary <string, string> .Empty.Add("ExpectedName", "Get" + registeredName), method.Name, "Get" + registeredName)); } if (method.DeclaredAccessibility.IsEither(Accessibility.Protected, Accessibility.Internal, Accessibility.Public) && !HasStandardText(methodDeclaration, fieldOrProperty, registeredName, out var location)) { context.ReportDiagnostic(Diagnostic.Create(Descriptors.WPF0061DocumentClrMethod, location)); } } if (DependencyProperty.TryGetRegisteredType(fieldOrProperty, context.SemanticModel, context.CancellationToken, out var registeredType) && !Equals(method.ReturnType, registeredType)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0013ClrMethodMustMatchRegisteredType, methodDeclaration.ReturnType.GetLocation(), "Return type", registeredType)); } if (Attribute.TryFind(methodDeclaration, KnownSymbols.AttachedPropertyBrowsableForTypeAttribute, context.SemanticModel, context.CancellationToken, out var attribute)) { if (attribute.TrySingleArgument(out var argument) && argument.Expression is TypeOfExpressionSyntax typeOf && TypeOf.TryGetType(typeOf, method.ContainingType, context.SemanticModel, context.CancellationToken, out var argumentType) && !argumentType.IsAssignableTo(parameter.Type, context.Compilation)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0034AttachedPropertyBrowsableForTypeAttributeArgument, argument.GetLocation(), parameter.Type.ToMinimalDisplayString( context.SemanticModel, argument.SpanStart))); } } else { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0033UseAttachedPropertyBrowsableForTypeAttribute, methodDeclaration.Identifier.GetLocation(), parameter.Type.ToMinimalDisplayString(context.SemanticModel, methodDeclaration.SpanStart))); } if (methodDeclaration.Body is { } body&& TryGetSideEffect(body, getValueCall, out var sideEffect)) { context.ReportDiagnostic(Diagnostic.Create(Descriptors.WPF0042AvoidSideEffectsInClrAccessors, sideEffect.GetLocation())); } }
private static void Handle(SyntaxNodeAnalysisContext context) { if (!context.IsExcludedFromAnalysis() && !context.ContainingSymbol.IsStatic && context.ContainingSymbol is IPropertySymbol property && property.ContainingType.IsAssignableTo(KnownSymbol.DependencyObject, context.Compilation) && context.Node is PropertyDeclarationSyntax propertyDeclaration && PropertyDeclarationWalker.TryGetCalls(propertyDeclaration, out var getCall, out var setCall)) { if (setCall != null && propertyDeclaration.TryGetSetter(out var setter) && setter.Body != null && setter.Body.Statements.TryFirst(x => !x.Contains(setCall), out var statement)) { context.ReportDiagnostic(Diagnostic.Create(WPF0036AvoidSideEffectsInClrAccessors.Descriptor, statement.GetLocation())); } if (getCall != null && propertyDeclaration.TryGetGetter(out var getter) && getter.Body != null && getter.Body.Statements.TryFirst(x => !x.Contains(getCall), out statement)) { context.ReportDiagnostic(Diagnostic.Create(WPF0036AvoidSideEffectsInClrAccessors.Descriptor, statement.GetLocation())); } if (getCall.TryGetArgumentAtIndex(0, out var getArg) && getArg.Expression is IdentifierNameSyntax getIdentifier && setCall.TryGetArgumentAtIndex(0, out var setArg) && setArg.Expression is IdentifierNameSyntax setIdentifier && getIdentifier.Identifier.ValueText != setIdentifier.Identifier.ValueText && !setIdentifier.Identifier.ValueText.IsParts(getIdentifier.Identifier.ValueText, "Key")) { context.ReportDiagnostic( Diagnostic.Create( WPF0032ClrPropertyGetAndSetSameDependencyProperty.Descriptor, propertyDeclaration.GetLocation(), context.ContainingSymbol.Name)); } if (setCall.TryGetMethodName(out var setCallName) && setCallName != "SetValue") { //// ReSharper disable once PossibleNullReferenceException context.ReportDiagnostic( Diagnostic.Create( WPF0035ClrPropertyUseSetValueInSetter.Descriptor, setCall.GetLocation(), context.ContainingSymbol.Name)); } if (ClrProperty.TryGetRegisterField(propertyDeclaration, context.SemanticModel, context.CancellationToken, out var fieldOrProperty)) { if (DependencyProperty.TryGetRegisteredName(fieldOrProperty, context.SemanticModel, context.CancellationToken, out var registeredName) && registeredName != property.Name) { context.ReportDiagnostic( Diagnostic.Create( WPF0003ClrPropertyShouldMatchRegisteredName.Descriptor, propertyDeclaration.Identifier.GetLocation(), ImmutableDictionary <string, string> .Empty.Add("ExpectedName", registeredName), property.Name, registeredName)); } if (DependencyProperty.TryGetRegisteredType(fieldOrProperty, context.SemanticModel, context.CancellationToken, out var registeredType) && !registeredType.Equals(property.Type)) { context.ReportDiagnostic( Diagnostic.Create( WPF0012ClrPropertyShouldMatchRegisteredType.Descriptor, propertyDeclaration.Type.GetLocation(), ImmutableDictionary <string, string> .Empty.Add(nameof(TypeSyntax), registeredType.ToMinimalDisplayString(context.SemanticModel, context.Node.SpanStart)), property, registeredType)); } } } }
private static void Handle(SyntaxNodeAnalysisContext context) { if (!context.IsExcludedFromAnalysis() && context.Node is MethodDeclarationSyntax methodDeclaration && context.ContainingSymbol is IMethodSymbol { IsStatic : true } method&& method.Parameters.TryElementAt(0, out var element) && element.Type.IsAssignableTo(KnownSymbols.DependencyObject, context.Compilation)) { if (ClrMethod.IsAttachedGet(methodDeclaration, context.SemanticModel, context.CancellationToken, out var getValueCall, out var backing)) { if (DependencyProperty.TryGetRegisteredName(backing, context.SemanticModel, context.CancellationToken, out _, out var registeredName)) { if (!method.Name.IsParts("Get", registeredName)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0004ClrMethodShouldMatchRegisteredName, methodDeclaration.Identifier.GetLocation(), ImmutableDictionary <string, string> .Empty.Add("ExpectedName", "Get" + registeredName), method.Name, "Get" + registeredName)); } if (method.DeclaredAccessibility.IsEither(Accessibility.Protected, Accessibility.Internal, Accessibility.Public)) { var summaryFormat = "<summary>Helper for getting <see cref=\"{backing}\"/> from <paramref name=\"{element}\"/>.</summary>"; var paramFormat = "<param name=\"{element}\"><see cref=\"{element.type}\"/> to read <see cref=\"{backing}\"/> from.</param>"; var returnsFormat = "<returns>{registered_name} property value.</returns>"; if (methodDeclaration.TryGetDocumentationComment(out var comment)) { if (comment.VerifySummary(summaryFormat, backing.Symbol.Name, element.Name) is { } summaryError) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0061DocumentClrMethod, summaryError.Location, ImmutableDictionary <string, string> .Empty.Add(nameof(DocComment), summaryError.Text))); } if (comment.VerifyParameter(paramFormat, element, element.ToCrefType(), backing.Symbol.Name) is { } paramError) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0061DocumentClrMethod, paramError.Location, ImmutableDictionary <string, string> .Empty.Add(nameof(DocComment), paramError.Text))); } if (comment.VerifyReturns(returnsFormat, registeredName) is { } returnsError) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0061DocumentClrMethod, returnsError.Location, ImmutableDictionary <string, string> .Empty.Add(nameof(DocComment), returnsError.Text))); } } else { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0061DocumentClrMethod, methodDeclaration.Identifier.GetLocation(), ImmutableDictionary <string, string> .Empty.Add( nameof(DocComment), $"/// {DocComment.Format(summaryFormat, backing.Symbol.Name, element.Name)}\n" + $"/// {DocComment.Format(paramFormat, element.Name, element.ToCrefType(), backing.Name)}\n" + $"/// {DocComment.Format(returnsFormat, registeredName)}\n"))); } } } if (DependencyProperty.TryGetRegisteredType(backing, context.SemanticModel, context.CancellationToken, out var registeredType) && !Equals(method.ReturnType, registeredType)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0013ClrMethodMustMatchRegisteredType, methodDeclaration.ReturnType.GetLocation(), "Return type", registeredType)); } if (Gu.Roslyn.AnalyzerExtensions.Attribute.TryFind(methodDeclaration, KnownSymbols.AttachedPropertyBrowsableForTypeAttribute, context.SemanticModel, context.CancellationToken, out var attribute)) { if (attribute.TrySingleArgument(out var argument) && argument.Expression is TypeOfExpressionSyntax typeOf && TypeOf.TryGetType(typeOf, method.ContainingType, context.SemanticModel, context.CancellationToken, out var argumentType) && !argumentType.IsAssignableTo(element.Type, context.Compilation)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0034AttachedPropertyBrowsableForTypeAttributeArgument, argument.GetLocation(), element.Type.ToMinimalDisplayString( context.SemanticModel, argument.SpanStart))); } } else { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0033UseAttachedPropertyBrowsableForTypeAttribute, methodDeclaration.Identifier.GetLocation(), element.Type.ToMinimalDisplayString(context.SemanticModel, methodDeclaration.SpanStart))); } if (methodDeclaration.Body is { } body&& TryGetSideEffect(body, getValueCall, out var sideEffect)) { context.ReportDiagnostic(Diagnostic.Create(Descriptors.WPF0042AvoidSideEffectsInClrAccessors, sideEffect.GetLocation())); } }
private static void Handle(SyntaxNodeAnalysisContext context) { if (!context.IsExcludedFromAnalysis() && context.Node is MemberDeclarationSyntax memberDeclaration) { if (BackingFieldOrProperty.TryCreateForDependencyProperty(context.ContainingSymbol, out var backing)) { if (DependencyProperty.TryGetRegisteredName(backing, context.SemanticModel, context.CancellationToken, out _, out var registeredName)) { if (backing.Type == KnownSymbols.DependencyProperty && !backing.Name.IsParts(registeredName, "Property")) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0001BackingFieldShouldMatchRegisteredName, BackingFieldOrProperty.FindIdentifier(memberDeclaration).GetLocation(), ImmutableDictionary <string, string> .Empty.Add("ExpectedName", registeredName + "Property"), backing.Name, registeredName)); } if (backing.Type == KnownSymbols.DependencyPropertyKey && !backing.Name.IsParts(registeredName, "PropertyKey")) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0002BackingFieldShouldMatchRegisteredName, BackingFieldOrProperty.FindIdentifier(memberDeclaration).GetLocation(), ImmutableDictionary <string, string> .Empty.Add("ExpectedName", registeredName + "PropertyKey"), backing.Name, registeredName)); } if (context.ContainingSymbol.ContainingType.TryFindProperty(registeredName, out _) && context.ContainingSymbol.DeclaredAccessibility.IsEither(Accessibility.Protected, Accessibility.Internal, Accessibility.Public)) { var summaryFormat = "<summary>Identifies the <see cref=\"{backing}\"/> dependency property.</summary>"; if (memberDeclaration.TryGetDocumentationComment(out var comment)) { if (comment.VerifySummary(summaryFormat, registeredName) is { } summaryError) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0060DocumentDependencyPropertyBackingMember, summaryError.Location, ImmutableDictionary <string, string> .Empty.Add(nameof(DocComment), summaryError.Text))); } } else { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0060DocumentDependencyPropertyBackingMember, backing.Symbol.Locations[0], ImmutableDictionary <string, string> .Empty.Add( nameof(DocComment), $"/// {DocComment.Format(summaryFormat, registeredName)}"))); } } if (DependencyProperty.TryGetRegisteredType(backing, context.SemanticModel, context.CancellationToken, out var type) && type.Is(KnownSymbols.Style) && !TryFindStyleTypedPropertyAttribute(memberDeclaration, registeredName, context.SemanticModel, context.CancellationToken) && backing.FieldOrProperty.Symbol.DeclaredAccessibility.IsEither(Accessibility.Public, Accessibility.Internal)) { context.ReportDiagnostic( Diagnostic.Create( Descriptors.WPF0176StyleTypedPropertyMissing, BackingFieldOrProperty.FindIdentifier(memberDeclaration).GetLocation(), ImmutableDictionary <string, string> .Empty.Add( nameof(AttributeListSyntax), $"[StyleTypedProperty(Property = {(context.ContainingSymbol.ContainingType.TryFindProperty(registeredName, out _) ? $"nameof({registeredName})" : $"\"{registeredName}\"")}, StyleTargetType = typeof(TYPE))]"),
private static void Handle(SyntaxNodeAnalysisContext context) { if (!context.IsExcludedFromAnalysis() && context.Node is MemberDeclarationSyntax memberDeclaration) { if (BackingFieldOrProperty.TryCreateForDependencyProperty(context.ContainingSymbol, out var backingMember)) { if (DependencyProperty.TryGetRegisteredName(backingMember, context.SemanticModel, context.CancellationToken, out var registeredName)) { if (backingMember.Type == KnownSymbol.DependencyProperty && !backingMember.Name.IsParts(registeredName, "Property")) { context.ReportDiagnostic( Diagnostic.Create( WPF0001BackingFieldShouldMatchRegisteredName.Descriptor, BackingFieldOrProperty.FindIdentifier(memberDeclaration).GetLocation(), ImmutableDictionary <string, string> .Empty.Add("ExpectedName", registeredName + "Property"), backingMember.Name, registeredName)); } if (backingMember.Type == KnownSymbol.DependencyPropertyKey && !backingMember.Name.IsParts(registeredName, "PropertyKey")) { context.ReportDiagnostic( Diagnostic.Create( WPF0002BackingFieldShouldMatchRegisteredName.Descriptor, BackingFieldOrProperty.FindIdentifier(memberDeclaration).GetLocation(), ImmutableDictionary <string, string> .Empty.Add("ExpectedName", registeredName + "PropertyKey"), backingMember.Name, registeredName)); } if (context.ContainingSymbol.DeclaredAccessibility.IsEither( Accessibility.Protected, Accessibility.Internal, Accessibility.Public) && context.ContainingSymbol.ContainingType.TryFindProperty(registeredName, out _) && !HasStandardText(memberDeclaration, registeredName, out var comment)) { context.ReportDiagnostic( Diagnostic.Create( WPF0060DocumentDependencyPropertyBackingMember.Descriptor, comment == null ? BackingFieldOrProperty.FindIdentifier(memberDeclaration).GetLocation() : comment.GetLocation())); } } if (context.Node is FieldDeclarationSyntax fieldDeclaration && DependencyProperty.TryGetDependencyPropertyKeyField( backingMember, context.SemanticModel, context.CancellationToken, out var keyField) && Equals(backingMember.ContainingType, keyField.ContainingType) && keyField.TryGetSyntaxReference(out var reference)) { var keyNode = reference.GetSyntax(context.CancellationToken); if (ReferenceEquals(fieldDeclaration.SyntaxTree, keyNode.SyntaxTree) && fieldDeclaration.SpanStart < keyNode.SpanStart) { context.ReportDiagnostic( Diagnostic.Create( WPF0031FieldOrder.Descriptor, fieldDeclaration.GetLocation(), keyField.Name, backingMember.Name)); } } } if (BackingFieldOrProperty.TryCreateCandidate(context.ContainingSymbol, out var candidate) && DependencyProperty.TryGetRegisterInvocationRecursive(candidate, context.SemanticModel, context.CancellationToken, out _, out _) && !candidate.FieldOrProperty.IsStaticReadOnly()) { context.ReportDiagnostic( Diagnostic.Create( WPF0030BackingFieldShouldBeStaticReadonly.Descriptor, BackingFieldOrProperty.FindIdentifier(memberDeclaration).GetLocation(), candidate.Name, candidate.Type.Name)); } } }
internal static bool TryGetRegisteredName(ObjectCreationExpressionSyntax objectCreation, SemanticModel semanticModel, CancellationToken cancellationToken, out string registeredName) { registeredName = null; return(TryGetConstructor(objectCreation, semanticModel, cancellationToken, out _) && DependencyProperty.TryGetRegisteredName(objectCreation?.FirstAncestorOrSelf <InvocationExpressionSyntax>(), semanticModel, cancellationToken, out registeredName)); }