private static bool ShouldCallBase(IMethodSymbol method, MethodDeclarationSyntax methodDeclaration, SyntaxNodeAnalysisContext context)
        {
            if (method.Parameters.TrySingle(out var parameter) &&
                parameter.Type == KnownSymbol.Boolean &&
                method.IsOverride &&
                method.OverriddenMethod is IMethodSymbol overridden &&
                !DisposeMethod.TryFindBaseCall(methodDeclaration, context.SemanticModel, context.CancellationToken, out _))
            {
                if (overridden.DeclaringSyntaxReferences.Length == 0)
                {
                    return(true);
                }
                else
                {
                    using (var disposeWalker = DisposeWalker.Borrow(overridden, context.SemanticModel, context.CancellationToken))
                    {
                        foreach (var disposeCall in disposeWalker)
                        {
                            if (DisposeCall.TryGetDisposed(disposeCall, context.SemanticModel, context.CancellationToken, out var disposed) &&
                                FieldOrProperty.TryCreate(disposed, out var fieldOrProperty) &&
                                !DisposableMember.IsDisposed(fieldOrProperty, method, context.SemanticModel, context.CancellationToken))
                            {
                                return(true);
                            }
                        }
                    }
                }
            }

            return(false);
        }
Esempio n. 2
0
        internal static bool HasMutableInstanceMembers(ITypeSymbol type)
        {
            if (type == null)
            {
                return(false);
            }

            while (type != null &&
                   type != KnownSymbols.Object)
            {
                foreach (var member in type.GetMembers())
                {
                    if (FieldOrProperty.TryCreate(member, out var fieldOrProperty) &&
                        !fieldOrProperty.IsStatic)
                    {
                        switch (member)
                        {
                        case IFieldSymbol field when !field.IsConst && !field.IsReadOnly:
                        case IPropertySymbol property when property.SetMethod != null:
                            return(true);
                        }

                        if (fieldOrProperty.Type.Is(KnownSymbols.IEnumerable) &&
                            fieldOrProperty.Type.TryFindFirstMethod("Add", out _))
                        {
                            return(true);
                        }
                    }
                }

                type = type.BaseType;
            }

            return(false);
        }
Esempio n. 3
0
        internal static bool TryGetDefaultFieldsOrProperties(ITypeSymbol type, Compilation compilation, out IReadOnlyList <FieldOrProperty> defaults)
        {
            List <FieldOrProperty> temp = null;

            foreach (var member in type.GetMembers())
            {
                if (member.IsStatic &&
                    (member.DeclaredAccessibility == Accessibility.Public ||
                     member.DeclaredAccessibility == Accessibility.Internal))
                {
                    if (FieldOrProperty.TryCreate(member, out var fieldOrProperty) &&
                        (fieldOrProperty.Type.IsAssignableTo(KnownSymbol.IValueConverter, compilation) ||
                         fieldOrProperty.Type.IsAssignableTo(KnownSymbol.IMultiValueConverter, compilation)))
                    {
                        if (temp == null)
                        {
                            temp = new List <FieldOrProperty>();
                        }

                        temp.Add(fieldOrProperty);
                    }
                }
            }

            defaults = temp;
            return(defaults != null);
        }
        private static bool IsRelayReturn(MemberAccessExpressionSyntax memberAccess, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (memberAccess == null ||
                !memberAccess.IsKind(SyntaxKind.SimpleMemberAccessExpression) ||
                memberAccess.Expression is InstanceExpressionSyntax ||
                memberAccess.Expression == null)
            {
                return(false);
            }

            if (semanticModel.TryGetSymbol(memberAccess.Expression, cancellationToken, out ISymbol member) &&
                FieldOrProperty.TryCreate(member, out FieldOrProperty fieldOrProperty) &&
                memberAccess.TryFirstAncestor <TypeDeclarationSyntax>(out var typeDeclaration) &&
                !IsInjected(fieldOrProperty, typeDeclaration, semanticModel, cancellationToken))
            {
                return(false);
            }

            if (memberAccess.Expression is IdentifierNameSyntax &&
                memberAccess.Name is IdentifierNameSyntax)
            {
                return(true);
            }

            if (memberAccess.Expression is MemberAccessExpressionSyntax &&
                memberAccess.Name is IdentifierNameSyntax)
            {
                return(true);
            }

            return(false);
        }
        private static void HandleProperty(SyntaxNodeAnalysisContext context)
        {
            if (context.IsExcludedFromAnalysis())
            {
                return;
            }

            var property = (IPropertySymbol)context.ContainingSymbol;

            if (property.IsStatic ||
                property.IsIndexer)
            {
                return;
            }

            var propertyDeclaration = (PropertyDeclarationSyntax)context.Node;

            if (propertyDeclaration.ExpressionBody != null)
            {
                return;
            }

            if (propertyDeclaration.TryGetSetter(out var setter) &&
                setter.Body != null)
            {
                // Handle the backing field
                return;
            }

            if (FieldOrProperty.TryCreate(property, out var fieldOrProperty) &&
                Disposable.IsPotentiallyAssignableFrom(property.Type, context.Compilation))
            {
                HandleFieldOrProperty(context, fieldOrProperty);
            }
        }
Esempio n. 6
0
 private static bool TryGetBackingMember(ObjectCreationExpressionSyntax objectCreation, SyntaxNodeAnalysisContext context, out FieldOrProperty fieldOrProperty, [NotNullWhen(true)] out MemberDeclarationSyntax?memberDeclaration)
 {
     fieldOrProperty   = default;
     memberDeclaration = null;
     return(objectCreation.Parent switch
     {
         EqualsValueClauseSyntax _ => objectCreation.TryFirstAncestor(out memberDeclaration) &&
         FieldOrProperty.TryCreate(context.ContainingSymbol, out fieldOrProperty),
         ArrowExpressionClauseSyntax _ => objectCreation.TryFirstAncestor(out memberDeclaration) &&
         context.ContainingSymbol is IMethodSymbol {
             AssociatedSymbol : { } associatedSymbol
         } &&
 private static void HandleField(SyntaxNodeAnalysisContext context)
 {
     if (!context.IsExcludedFromAnalysis() &&
         context.ContainingSymbol is IFieldSymbol field &&
         !field.IsStatic &&
         !field.IsConst &&
         FieldOrProperty.TryCreate(field, out var fieldOrProperty) &&
         Disposable.IsPotentiallyAssignableFrom(field.Type, context.Compilation))
     {
         HandleFieldOrProperty(context, fieldOrProperty);
     }
 }
        private static void Handle(SyntaxNodeAnalysisContext context)
        {
            if (!context.IsExcludedFromAnalysis() &&
                context.Node is ObjectCreationExpressionSyntax {
                ArgumentList : { } argumentList
            } objectCreation&&
                objectCreation.Type == KnownSymbols.ComponentResourceKey &&
                context.SemanticModel.TryGetSymbol(objectCreation, KnownSymbols.ComponentResourceKey, context.CancellationToken, out var constructor) &&
                FieldOrProperty.TryCreate(context.ContainingSymbol, out var fieldOrProperty))
            {
                if (constructor.Parameters.Length == 0)
                {
                    var containingTypeString = context.ContainingSymbol.ContainingType.ToMinimalDisplayString(context.SemanticModel, objectCreation.SpanStart);
                    var argumentListText     = $"typeof({containingTypeString}), nameof({fieldOrProperty.Name})";
                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            Descriptors.WPF0140UseContainingTypeComponentResourceKey,
                            argumentList.GetLocation(),
                            ImmutableDictionary <string, string> .Empty.Add(nameof(ArgumentListSyntax), argumentListText),
                            argumentListText));
                }
                else
                {
                    if (constructor.TryFindParameter("typeInTargetAssembly", out var parameter) &&
                        objectCreation.TryFindArgument(parameter, out var arg) &&
                        arg.TryGetTypeofValue(context.SemanticModel, context.CancellationToken, out var type) &&
                        !type.Equals(context.ContainingSymbol.ContainingType))
                    {
                        context.ReportDiagnostic(
                            Diagnostic.Create(
                                Descriptors.WPF0140UseContainingTypeComponentResourceKey,
                                arg.GetLocation(),
                                context.ContainingSymbol.ContainingType.ToMinimalDisplayString(context.SemanticModel, objectCreation.SpanStart)));
                    }

                    if (constructor.TryFindParameter("resourceId", out parameter) &&
                        objectCreation.TryFindArgument(parameter, out arg) &&
                        context.SemanticModel.TryGetConstantValue(arg.Expression, context.CancellationToken, out string?name) &&
                        name != fieldOrProperty.Name)
                    {
                        var keyText = $"nameof({fieldOrProperty.Name})";
                        context.ReportDiagnostic(
                            Diagnostic.Create(
                                Descriptors.WPF0141UseContainingMemberComponentResourceKey,
                                arg.GetLocation(),
                                ImmutableDictionary <string, string> .Empty.Add(nameof(ArgumentSyntax), keyText),
                                keyText));
                    }
                }
            }
        }
Esempio n. 9
0
        protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context)
        {
            var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken)
                             .ConfigureAwait(false);

            var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken)
                                .ConfigureAwait(false);

            foreach (var diagnostic in context.Diagnostics)
            {
                if (TryGetMemberAccess(out var member) &&
                    semanticModel.TryGetSymbol(member, context.CancellationToken, out ISymbol? memberSymbol) &&
                    FieldOrProperty.TryCreate(memberSymbol, out var fieldOrProperty) &&
                    member.FirstAncestor <ClassDeclarationSyntax>() is { } classDeclaration&&
                    InitializeAndCleanup.IsAssignedInInitialize(fieldOrProperty, classDeclaration, semanticModel, context.CancellationToken, out var assignment, out var initialize) &&
                    assignment is { Left: { } left })
Esempio n. 10
0
        private static bool TryGetMemberType(MemberAccessExpressionSyntax memberAccess, SemanticModel semanticModel, CancellationToken cancellationToken, out INamedTypeSymbol result)
        {
            if (semanticModel.TryGetSymbol(memberAccess, cancellationToken, out var symbol) &&
                FieldOrProperty.TryCreate(symbol, out var fieldOrProperty) &&
                fieldOrProperty.Type.IsReferenceType)
            {
                if (TryFindAssignedType(symbol, semanticModel, cancellationToken, out result))
                {
                    return(true);
                }

                result = fieldOrProperty.Type as INamedTypeSymbol;
                return(result != null);
            }

            result = null;
            return(false);
        }
Esempio n. 11
0
        private static bool TryGetBackingMember(ObjectCreationExpressionSyntax objectCreation, SyntaxNodeAnalysisContext context, out FieldOrProperty fieldOrProperty, out MemberDeclarationSyntax memberDeclaration)
        {
            fieldOrProperty   = default(FieldOrProperty);
            memberDeclaration = null;
            switch (objectCreation.Parent)
            {
            case EqualsValueClauseSyntax _:
                return(objectCreation.TryFirstAncestor(out memberDeclaration) &&
                       FieldOrProperty.TryCreate(context.ContainingSymbol, out fieldOrProperty));

            case ArrowExpressionClauseSyntax _:
                return(objectCreation.TryFirstAncestor(out memberDeclaration) &&
                       context.ContainingSymbol is IMethodSymbol getter &&
                       FieldOrProperty.TryCreate(getter.AssociatedSymbol, out fieldOrProperty));
            }

            return(false);
        }
Esempio n. 12
0
        internal static bool IsNop(ExpressionSyntax candidate, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (semanticModel.TryGetSymbol(candidate, cancellationToken, out ISymbol symbol) &&
                FieldOrProperty.TryCreate(symbol, out var fieldOrProperty) &&
                fieldOrProperty.IsStatic &&
                IsAssignableFrom(fieldOrProperty.Type, semanticModel.Compilation))
            {
                if (fieldOrProperty.Type == KnownSymbol.Task ||
                    symbol == KnownSymbol.RxDisposable.Empty)
                {
                    return(true);
                }

                using (var walker = ReturnValueWalker.Borrow(candidate, ReturnValueSearch.Recursive, semanticModel, cancellationToken))
                {
                    if (walker.Count > 0)
                    {
                        return(walker.TrySingle(out var value) &&
                               semanticModel.TryGetType(value, cancellationToken, out var type) &&
                               IsNop(type));
                    }
                }

                using (var walker = AssignedValueWalker.Borrow(symbol, semanticModel, cancellationToken))
                {
                    return(walker.TrySingle(out var value) &&
                           semanticModel.TryGetType(value, cancellationToken, out var type) &&
                           IsNop(type));
                }
            }

            return(false);

            bool IsNop(ITypeSymbol type)
            {
                return(type.IsSealed &&
                       type.BaseType == KnownSymbol.Object &&
                       type.TryFindSingleMethod("Dispose", out var disposeMethod) &&
                       disposeMethod.Parameters.Length == 0 &&
                       disposeMethod.TrySingleDeclaration(cancellationToken, out MethodDeclarationSyntax declaration) &&
                       declaration.Body is BlockSyntax body &&
                       body.Statements.Count == 0);
            }
        }
Esempio n. 13
0
        private static bool IsInjectable(INamedTypeSymbol type)
        {
            if (type?.ContainingNamespace == null ||
                type.IsValueType ||
                type.IsStatic ||
                type.IsAbstract ||
                type.DeclaringSyntaxReferences.Length == 0)
            {
                return(false);
            }

            if (type.Constructors.TrySingle(x => !x.IsStatic, out var ctor))
            {
                if (ctor.Parameters.TryFirst(x => !IsInjectable(x.Type as INamedTypeSymbol), out _))
                {
                    return(false);
                }

                return(true);
            }

            return(type.TryFindSingleMember <ISymbol>(x => IsMatch(x), out _));

            bool IsMatch(ISymbol candidate)
            {
                if (candidate.IsStatic)
                {
                    if (FieldOrProperty.TryCreate(candidate, out var fieldOrProperty))
                    {
                        return(Equals(fieldOrProperty.Type, type));
                    }

                    if (candidate is IMethodSymbol method &&
                        method.MethodKind == MethodKind.Ordinary &&
                        Equals(method.ReturnType, type))
                    {
                        return(true);
                    }
                }

                return(false);
            }
        }
Esempio n. 14
0
        private static void Handle(SyntaxNodeAnalysisContext context)
        {
            if (!context.IsExcludedFromAnalysis() &&
                context.Node is MemberDeclarationSyntax memberDeclaration &&
                FieldOrProperty.TryCreate(context.ContainingSymbol, out var fieldOrProperty) &&
                fieldOrProperty.Type == KnownSymbol.RoutedEvent)
            {
                if (RoutedEvent.TryGetRegisteredName(fieldOrProperty, context.SemanticModel, context.CancellationToken, out var registeredName) &&
                    !fieldOrProperty.Name.IsParts(registeredName, "Event"))
                {
                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            WPF0100BackingFieldShouldMatchRegisteredName.Descriptor,
                            FindIdentifier(context.Node).GetLocation(),
                            ImmutableDictionary <string, string> .Empty.Add("ExpectedName", registeredName + "Event"),
                            fieldOrProperty.Name,
                            registeredName));
                }

                if (RoutedEvent.TryGetRegisteredType(fieldOrProperty, context.SemanticModel, context.CancellationToken, out var typeArg, out var registeredOwnerType) &&
                    !Equals(registeredOwnerType, context.ContainingSymbol.ContainingType))
                {
                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            WPF0101RegisterContainingTypeAsOwner.Descriptor,
                            typeArg.GetLocation(),
                            fieldOrProperty.ContainingType.Name,
                            registeredName));
                }

                if (!fieldOrProperty.IsStaticReadOnly())
                {
                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            WPF0107BackingMemberShouldBeStaticReadonly.Descriptor,
                            BackingFieldOrProperty.FindIdentifier(memberDeclaration).GetLocation()));
                }
            }
        }
Esempio n. 15
0
        private static bool IsInitializedWithUninitialized(ExpressionSyntax value, SyntaxNodeAnalysisContext context, out FieldOrProperty other)
        {
            using (var walker = Walker.Borrow(value, context.SemanticModel, context.CancellationToken))
            {
                foreach (var identifierName in walker.IdentifierNames)
                {
                    if (!IsNameOf(identifierName) &&
                        context.SemanticModel.TryGetSymbol(identifierName, context.CancellationToken, out ISymbol symbol) &&
                        FieldOrProperty.TryCreate(symbol, out other) &&
                        other.IsStatic &&
                        other.ContainingType == context.ContainingSymbol.ContainingType &&
                        symbol.TrySingleDeclaration(context.CancellationToken, out MemberDeclarationSyntax otherDeclaration) &&
                        otherDeclaration.SpanStart > context.Node.SpanStart &&
                        IsInitialized(otherDeclaration))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        /// <inheritdoc/>
        public override async Task RegisterCodeFixesAsync(CodeFixContext context)
        {
            var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken)
                             .ConfigureAwait(false);

            var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken)
                                .ConfigureAwait(false);

            foreach (var diagnostic in context.Diagnostics)
            {
                var node   = syntaxRoot.FindNode(diagnostic.Location.SourceSpan);
                var member = node as MemberDeclarationSyntax ??
                             (SyntaxNode)(node as AssignmentExpressionSyntax)?.Left;
                if (semanticModel.TryGetSymbol(member, context.CancellationToken, out ISymbol memberSymbol) &&
                    FieldOrProperty.TryCreate(memberSymbol, out var fieldOrProperty) &&
                    TestFixture.IsAssignedInSetUp(fieldOrProperty, member.FirstAncestor <ClassDeclarationSyntax>(), semanticModel, context.CancellationToken, out var setupAttribute))
                {
                    if (TestFixture.TryGetTearDownMethod(setupAttribute, semanticModel, context.CancellationToken, out var tearDownMethodDeclaration))
                    {
                        context.RegisterDocumentEditorFix(
                            $"Dispose member in {tearDownMethodDeclaration.Identifier.ValueText}.",
                            (editor, cancellationToken) => DisposeInTearDownMethod(editor, memberSymbol, tearDownMethodDeclaration, cancellationToken),
                            diagnostic);
                    }
                    else if (setupAttribute.TryFirstAncestor <MethodDeclarationSyntax>(out var setupMethod))
                    {
                        var tearDownType = semanticModel.GetTypeInfoSafe(setupAttribute, context.CancellationToken)
                                           .Type == KnownSymbol.NUnitSetUpAttribute
                            ? KnownSymbol.NUnitTearDownAttribute
                            : KnownSymbol.NUnitOneTimeTearDownAttribute;

                        context.RegisterDocumentEditorFix(
                            $"Create {tearDownType.Type} method and dispose member.",
                            (editor, cancellationToken) => CreateTearDownMethod(editor, memberSymbol, setupMethod, tearDownType, cancellationToken),
                            diagnostic);
                    }
                }
            }
        }
Esempio n. 17
0
        public override void ReportSuppressions(SuppressionAnalysisContext context)
        {
            foreach (var diagnostic in context.ReportedDiagnostics)
            {
                var root = diagnostic.Location.SourceTree.GetRoot(context.CancellationToken);
                if (root.FindNode(diagnostic.Location.SourceSpan) is { } node&&
                    node.TryFirstAncestorOrSelf(out IdentifierNameSyntax? identifierName) &&
                    context.GetSemanticModel(identifierName.SyntaxTree) is { } semanticModel)
                {
                    if (semanticModel.TryGetSymbol(identifierName, context.CancellationToken, out var symbol) &&
                        FieldOrProperty.TryCreate(symbol, out var fieldOrProperty) &&
                        fieldOrProperty.Type == KnownSymbols.DependencyPropertyKey)
                    {
                        context.ReportSuppression(Suppression.Create(Descriptor, diagnostic));
                    }

                    if (identifierName.Parent is MethodDeclarationSyntax method &&
                        ClrMethod.IsAttachedSet(method, semanticModel, context.CancellationToken, out _, out _))
                    {
                        context.ReportSuppression(Suppression.Create(Descriptor, diagnostic));
                    }
                }
            }
        }
        protected override async Task RegisterCodeFixesAsync(DocumentEditorCodeFixContext context)
        {
            var syntaxRoot = await context.Document.GetSyntaxRootAsync(context.CancellationToken)
                             .ConfigureAwait(false);

            var semanticModel = await context.Document.GetSemanticModelAsync(context.CancellationToken)
                                .ConfigureAwait(false);

            foreach (var diagnostic in context.Diagnostics)
            {
                if (syntaxRoot.TryFindNode <MemberDeclarationSyntax>(diagnostic, out var member) &&
                    semanticModel.TryGetSymbol(member, context.CancellationToken, out ISymbol? symbol) &&
                    FieldOrProperty.TryCreate(symbol, out var disposable))
                {
                    if (diagnostic.AdditionalLocations.TrySingle(out var additionalLocation) &&
                        syntaxRoot.TryFindNodeOrAncestor(additionalLocation, out MethodDeclarationSyntax? method))
                    {
                        switch (method)
                        {
                        case { Identifier: { ValueText : "DisposeAsync" } }
                            when IDisposableFactory.MemberAccessContext.Create(disposable, method, semanticModel, context.CancellationToken) is
                            {
                                NotNull : { }
                            }
        private static void Handle(SyntaxNodeAnalysisContext context)
        {
            if (!context.IsExcludedFromAnalysis() &&
                context.Node is MemberDeclarationSyntax memberDeclaration &&
                FieldOrProperty.TryCreate(context.ContainingSymbol, out var fieldOrProperty) &&
                fieldOrProperty.Type == KnownSymbols.RoutedEvent)
            {
                if (RoutedEvent.TryGetRegisteredName(fieldOrProperty, context.SemanticModel, context.CancellationToken, out var nameArg, out var registeredName))
                {
                    if (!fieldOrProperty.Name.IsParts(registeredName, "Event"))
                    {
                        context.ReportDiagnostic(
                            Diagnostic.Create(
                                Descriptors.WPF0100BackingFieldShouldMatchRegisteredName,
                                FindIdentifier(context.Node).GetLocation(),
                                ImmutableDictionary <string, string> .Empty.Add("ExpectedName", registeredName + "Event"),
                                fieldOrProperty.Name,
                                registeredName));
                    }

                    if (fieldOrProperty.ContainingType.TryFindEvent(registeredName, out var eventSymbol))
                    {
                        if (nameArg.Expression is LiteralExpressionSyntax)
                        {
                            context.ReportDiagnostic(
                                Diagnostic.Create(
                                    Descriptors.WPF0150UseNameofInsteadOfLiteral,
                                    nameArg.GetLocation(),
                                    ImmutableDictionary <string, string> .Empty.Add(nameof(IdentifierNameSyntax), eventSymbol.Name),
                                    eventSymbol.Name));
                        }
                        else if (!nameArg.Expression.IsNameof())
                        {
                            context.ReportDiagnostic(
                                Diagnostic.Create(
                                    Descriptors.WPF0151UseNameofInsteadOfConstant,
                                    nameArg.GetLocation(),
                                    ImmutableDictionary <string, string> .Empty.Add(nameof(IdentifierNameSyntax), eventSymbol.Name),
                                    eventSymbol.Name));
                        }
                    }

                    if (context.ContainingSymbol.ContainingType.TryFindEvent(registeredName, out _) &&
                        context.ContainingSymbol.DeclaredAccessibility.IsEither(Accessibility.Protected, Accessibility.Internal, Accessibility.Public) &&
                        !HasStandardText(memberDeclaration, registeredName, out var comment))
                    {
                        context.ReportDiagnostic(
                            Diagnostic.Create(
                                Descriptors.WPF0108DocumentRoutedEventBackingMember,
                                comment == null
                                    ? BackingFieldOrProperty.FindIdentifier(memberDeclaration).GetLocation()
                                    : comment.GetLocation(),
                                properties: ImmutableDictionary <string, string> .Empty.Add(nameof(CrefParameterSyntax), registeredName)));
                    }
                }

                if (RoutedEvent.TryGetRegisteredType(fieldOrProperty, context.SemanticModel, context.CancellationToken, out var typeArg, out var registeredOwnerType) &&
                    !Equals(registeredOwnerType, context.ContainingSymbol.ContainingType))
                {
                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            Descriptors.WPF0101RegisterContainingTypeAsOwner,
                            typeArg.GetLocation(),
                            fieldOrProperty.ContainingType.Name,
                            registeredName));
                }

                if (!fieldOrProperty.IsStaticReadOnly())
                {
                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            Descriptors.WPF0107BackingMemberShouldBeStaticReadonly,
                            BackingFieldOrProperty.FindIdentifier(memberDeclaration).GetLocation()));
                }
            }
        }
        private static bool IsRedundantAssignment(ISymbol left, AssignmentExpressionSyntax assignment, SyntaxNodeAnalysisContext context)
        {
            if (left is IDiscardSymbol ||
                assignment.TryFirstAncestor <ObjectCreationExpressionSyntax>(out _))
            {
                return(false);
            }

            if (assignment.TryFirstAncestor <MemberDeclarationSyntax>(out var member))
            {
                if (!(member is ConstructorDeclarationSyntax) &&
                    context.SemanticModel.TryGetType(assignment.Left, context.CancellationToken, out var type) &&
                    FieldOrProperty.TryCreate(left, out _))
                {
                    if (type == KnownSymbol.Boolean ||
                        type.TypeKind == TypeKind.Enum)
                    {
                        return(false);
                    }
                }

                using (var walker = AssignmentExecutionWalker.For(left, member, Scope.Member, context.SemanticModel, context.CancellationToken))
                {
                    foreach (var candidate in walker.Assignments)
                    {
                        if (candidate == assignment)
                        {
                            continue;
                        }

                        if (!MemberPath.Equals(candidate.Left, assignment.Left))
                        {
                            continue;
                        }

                        if (candidate.IsExecutedBefore(assignment) == ExecutedBefore.Yes)
                        {
                            if (left is IParameterSymbol parameter &&
                                parameter.RefKind == RefKind.Out &&
                                assignment.TryFirstAncestor <BlockSyntax>(out var assignmentBlock) &&
                                candidate.TryFirstAncestor <BlockSyntax>(out var candidateBlock) &&
                                (candidateBlock.Contains(assignmentBlock) ||
                                 candidateBlock.Statements.Last() is ReturnStatementSyntax))
                            {
                                return(false);
                            }

                            using (var nameWalker = IdentifierNameWalker.Borrow(assignment.Right))
                            {
                                foreach (var name in nameWalker.IdentifierNames)
                                {
                                    if (left.Name == name.Identifier.ValueText &&
                                        context.SemanticModel.TryGetSymbol(
                                            name,
                                            context.CancellationToken,
                                            out ISymbol symbol) &&
                                        symbol.Equals(left))
                                    {
                                        return(false);
                                    }
                                }
                            }

                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
        private static bool IsReassignedWithCreated(AssignmentExpressionSyntax assignment, SyntaxNodeAnalysisContext context)
        {
            if (assignment.FirstAncestor <AccessorDeclarationSyntax>() is AccessorDeclarationSyntax accessor &&
                accessor.IsKind(SyntaxKind.SetAccessorDeclaration) &&
                assignment.Right is IdentifierNameSyntax assignedIdentifier &&
                assignedIdentifier.Identifier.ValueText == "value")
            {
                return(false);
            }

            if (Disposable.IsAlreadyAssignedWithCreated(assignment.Left, context.SemanticModel, context.CancellationToken, out var assignedSymbol)
                .IsEither(Result.No, Result.AssumeNo, Result.Unknown))
            {
                return(false);
            }

            if (assignedSymbol == KnownSymbol.SerialDisposable.Disposable ||
                assignedSymbol == KnownSymbol.SingleAssignmentDisposable.Disposable)
            {
                return(false);
            }

            if (Disposable.IsDisposedBefore(assignedSymbol, assignment, context.SemanticModel, context.CancellationToken))
            {
                return(false);
            }

            if (FieldOrProperty.TryCreate(assignedSymbol, out var fieldOrProperty) &&
                TestFixture.IsAssignedAndDisposedInSetupAndTearDown(fieldOrProperty, context.Node.FirstAncestor <TypeDeclarationSyntax>(), context.SemanticModel, context.CancellationToken))
            {
                return(false);
            }

            if (IsNullChecked(assignedSymbol, assignment, context.SemanticModel, context.CancellationToken))
            {
                return(false);
            }

            if (TryGetAssignedLocal(out var local) &&
                Disposable.IsDisposedAfter(local, assignment, context.SemanticModel, context.CancellationToken))
            {
                return(false);
            }

            return(true);

            bool TryGetAssignedLocal(out ILocalSymbol result)
            {
                result = null;
                if (assignment.TryFirstAncestor(out MemberDeclarationSyntax memberDeclaration))
                {
                    using (var walker = VariableDeclaratorWalker.Borrow(memberDeclaration))
                    {
                        return(walker.VariableDeclarators.TrySingle(
                                   x => context.SemanticModel.TryGetSymbol(
                                       x.Initializer?.Value, context.CancellationToken, out ISymbol symbol) &&
                                   symbol.Equals(assignedSymbol),
                                   out var match) &&
                               match.Initializer.Value.IsExecutedBefore(assignment) == ExecutedBefore.Yes &&
                               context.SemanticModel.TryGetSymbol(match, context.CancellationToken, out result));
                    }
                }

                return(false);
            }
        }
        internal static Result IsArgumentDisposedByReturnValue(ArgumentSyntax argument, SemanticModel semanticModel, CancellationToken cancellationToken, PooledSet <SyntaxNode> visited = null)
        {
            if (argument?.Parent is ArgumentListSyntax argumentList)
            {
                if (argumentList.Parent is InvocationExpressionSyntax invocation &&
                    semanticModel.GetSymbolSafe(invocation, cancellationToken) is IMethodSymbol method)
                {
                    if (method.ContainingType.DeclaringSyntaxReferences.Length == 0)
                    {
                        return(method.ReturnsVoid ||
                               !IsAssignableFrom(method.ReturnType, semanticModel.Compilation)
                            ? Result.No
                            : Result.AssumeYes);
                    }

                    if (method.TryFindParameter(argument, out var parameter))
                    {
                        return(CheckReturnValues(parameter, invocation, semanticModel, cancellationToken, visited));
                    }

                    return(Result.Unknown);
                }

                if (argumentList.Parent is ObjectCreationExpressionSyntax ||
                    argumentList.Parent is ConstructorInitializerSyntax)
                {
                    if (TryGetAssignedFieldOrProperty(argument, semanticModel, cancellationToken, out var member, out var ctor) &&
                        FieldOrProperty.TryCreate(member, out var fieldOrProperty))
                    {
                        var initializer = argument.FirstAncestorOrSelf <ConstructorInitializerSyntax>();
                        if (initializer != null)
                        {
                            if (semanticModel.GetDeclaredSymbolSafe(initializer.Parent, cancellationToken) is IMethodSymbol chainedCtor &&
                                chainedCtor.ContainingType != member.ContainingType)
                            {
                                if (DisposeMethod.TryFindFirst(chainedCtor.ContainingType, semanticModel.Compilation, Search.TopLevel, out var disposeMethod))
                                {
                                    return(DisposableMember.IsDisposed(fieldOrProperty, disposeMethod, semanticModel, cancellationToken)
                                        ? Result.Yes
                                        : Result.No);
                                }
                            }
                        }

                        return(DisposableMember.IsDisposed(fieldOrProperty, ctor.ContainingType, semanticModel, cancellationToken));
                    }

                    if (ctor == null)
                    {
                        return(Result.AssumeYes);
                    }

                    if (ctor.ContainingType.DeclaringSyntaxReferences.Length == 0)
                    {
                        return(IsAssignableFrom(ctor.ContainingType, semanticModel.Compilation) ? Result.AssumeYes : Result.No);
                    }

                    if (ctor.ContainingType.IsAssignableTo(KnownSymbol.NinjectStandardKernel, semanticModel.Compilation))
                    {
                        return(Result.Yes);
                    }

                    return(Result.No);
                }
            }

            return(Result.Unknown);
        }
Esempio n. 23
0
        internal static bool IsIgnored(ExpressionSyntax node, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (node.Parent is AnonymousFunctionExpressionSyntax ||
                node.Parent is UsingStatementSyntax ||
                node.Parent is EqualsValueClauseSyntax ||
                node.Parent is ReturnStatementSyntax ||
                node.Parent is ArrowExpressionClauseSyntax)
            {
                return(false);
            }

            if (node.Parent is StatementSyntax)
            {
                return(true);
            }

            if (node.Parent is AssignmentExpressionSyntax assignment &&
                assignment.Left is IdentifierNameSyntax left &&
                left.Identifier.ValueText == "_")
            {
                return(true);
            }

            if (node.Parent is ArgumentSyntax argument)
            {
                if (argument.Parent is ArgumentListSyntax argumentList &&
                    argumentList.Parent is InvocationExpressionSyntax invocation &&
                    semanticModel.TryGetSymbol(invocation, cancellationToken, out var method) &&
                    method.Name == "Add" &&
                    method.ContainingType.IsAssignableTo(KnownSymbol.IEnumerable, semanticModel.Compilation))
                {
                    if (method.ContainingType == KnownSymbol.CompositeDisposable)
                    {
                        return(false);
                    }

                    if (!method.ContainingType.TypeArguments.Any(x => x.IsAssignableTo(KnownSymbol.IDisposable, semanticModel.Compilation)))
                    {
                        if (MemberPath.TryFindRoot(invocation, out var identifierName) &&
                            semanticModel.TryGetSymbol(identifierName, cancellationToken, out ISymbol symbol) &&
                            FieldOrProperty.TryCreate(symbol, out var fieldOrProperty) &&
                            argument.TryFirstAncestor(out TypeDeclarationSyntax typeDeclaration) &&
                            DisposableMember.IsDisposed(fieldOrProperty, typeDeclaration, semanticModel, cancellationToken) != Result.No)
                        {
                            return(false);
                        }

                        return(true);
                    }

                    return(false);
                }

                return(IsArgumentDisposedByReturnValue(argument, semanticModel, cancellationToken).IsEither(Result.No, Result.AssumeNo) &&
                       IsArgumentAssignedToDisposable(argument, semanticModel, cancellationToken).IsEither(Result.No, Result.AssumeNo));
            }

            if (node.Parent is MemberAccessExpressionSyntax memberAccess)
            {
                if (memberAccess.Parent is InvocationExpressionSyntax invocation &&
                    DisposeCall.IsIDisposableDispose(invocation, semanticModel, cancellationToken))
                {
                    return(false);
                }

                return(IsArgumentDisposedByInvocationReturnValue(memberAccess, semanticModel, cancellationToken).IsEither(Result.No, Result.AssumeNo));
            }

            return(false);
        }
Esempio n. 24
0
        private static void Handle(SyntaxNodeAnalysisContext context)
        {
            if (!context.IsExcludedFromAnalysis() &&
                context.Node is MemberDeclarationSyntax memberDeclaration &&
                FieldOrProperty.TryCreate(context.ContainingSymbol, out var backing) &&
                backing.Type == KnownSymbols.RoutedEvent)
            {
                if (RoutedEvent.TryGetRegisteredName(backing, context.SemanticModel, context.CancellationToken, out var nameArg, out var registeredName))
                {
                    if (!backing.Name.IsParts(registeredName, "Event"))
                    {
                        context.ReportDiagnostic(
                            Diagnostic.Create(
                                Descriptors.WPF0100BackingFieldShouldMatchRegisteredName,
                                backing.Symbol.Locations[0],
                                ImmutableDictionary <string, string> .Empty.Add("ExpectedName", registeredName + "Event"),
                                backing.Name,
                                registeredName));
                    }

                    if (backing.ContainingType.TryFindEvent(registeredName, out var eventSymbol))
                    {
                        if (nameArg.Expression is LiteralExpressionSyntax)
                        {
                            context.ReportDiagnostic(
                                Diagnostic.Create(
                                    Descriptors.WPF0150UseNameofInsteadOfLiteral,
                                    nameArg.GetLocation(),
                                    ImmutableDictionary <string, string> .Empty.Add(nameof(IdentifierNameSyntax), eventSymbol.Name),
                                    eventSymbol.Name));
                        }
                        else if (!nameArg.Expression.IsNameof())
                        {
                            context.ReportDiagnostic(
                                Diagnostic.Create(
                                    Descriptors.WPF0151UseNameofInsteadOfConstant,
                                    nameArg.GetLocation(),
                                    ImmutableDictionary <string, string> .Empty.Add(nameof(IdentifierNameSyntax), eventSymbol.Name),
                                    eventSymbol.Name));
                        }
                    }

                    if (context.ContainingSymbol.ContainingType.TryFindEvent(registeredName, out _) &&
                        context.ContainingSymbol.DeclaredAccessibility.IsEither(Accessibility.Protected, Accessibility.Internal, Accessibility.Public))
                    {
                        var summaryFormat = "<summary>Identifies the <see cref=\"{registered_name}\"/> routed event.</summary>";
                        if (memberDeclaration.TryGetDocumentationComment(out var comment))
                        {
                            if (comment.VerifySummary(summaryFormat, registeredName) is { } summaryError)
                            {
                                context.ReportDiagnostic(
                                    Diagnostic.Create(
                                        Descriptors.WPF0108DocumentRoutedEventBackingMember,
                                        summaryError.Location,
                                        ImmutableDictionary <string, string> .Empty.Add(nameof(DocComment), summaryError.Text)));
                            }
                        }
                        else
                        {
                            context.ReportDiagnostic(
                                Diagnostic.Create(
                                    Descriptors.WPF0108DocumentRoutedEventBackingMember,
                                    backing.Symbol.Locations[0],
                                    ImmutableDictionary <string, string> .Empty.Add(
                                        nameof(DocComment),
                                        $"/// {DocComment.Format(summaryFormat, registeredName)}")));
                        }
                    }
                }

                if (RoutedEvent.TryGetRegisteredType(backing, context.SemanticModel, context.CancellationToken, out var typeArg, out var registeredOwnerType) &&
                    !Equals(registeredOwnerType, context.ContainingSymbol.ContainingType))
                {
                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            Descriptors.WPF0101RegisterContainingTypeAsOwner,
                            typeArg.GetLocation(),
                            backing.ContainingType.Name,
                            registeredName));
                }

                if (!backing.IsStaticReadOnly())
                {
                    context.ReportDiagnostic(
                        Diagnostic.Create(
                            Descriptors.WPF0107BackingMemberShouldBeStaticReadonly,
                            BackingFieldOrProperty.FindIdentifier(memberDeclaration).GetLocation()));
                }
            }
        }