Esempio n. 1
0
        /// <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);
                }
            }
        }
Esempio n. 2
0
 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))]"),
Esempio n. 4
0
 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));
 }
Esempio n. 5
0
        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()));
                }
            }
        }
Esempio n. 6
0
        /// <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);
                    }
                }
            }
        }
Esempio n. 7
0
        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()));
                    }
                }
Esempio n. 8
0
        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))]"),
Esempio n. 11
0
        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));
                }
            }
        }
Esempio n. 12
0
 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));
 }