Пример #1
0
        private static void HandleAssignment(SyntaxNodeAnalysisContext context)
        {
            if (context.IsExcludedFromAnalysis())
            {
                return;
            }

            var assignment = (AssignmentExpressionSyntax)context.Node;

            if (Disposable.IsCreation(assignment.Right, context.SemanticModel, context.CancellationToken)
                .IsEither(Result.No, Result.Unknown))
            {
                return;
            }

            if (Disposable.IsAssignedWithCreated(assignment.Left, context.SemanticModel, context.CancellationToken, out ISymbol assignedSymbol)
                .IsEither(Result.No, Result.Unknown))
            {
                return;
            }

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

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

            context.ReportDiagnostic(Diagnostic.Create(Descriptor, assignment.GetLocation()));
        }
Пример #2
0
        private static void Handle(SyntaxNodeAnalysisContext context)
        {
            if (!context.IsExcludedFromAnalysis() &&
                context.Node is ArgumentSyntax {
                Parent : ArgumentListSyntax {
                    Parent : InvocationExpressionSyntax invocation
                }
            } argument&&
                argument.RefOrOutKeyword.IsEither(SyntaxKind.RefKeyword, SyntaxKind.OutKeyword) &&
                IsCreation(argument, context.SemanticModel, context.CancellationToken) &&
                context.SemanticModel.TryGetSymbol(argument.Expression, context.CancellationToken, out var symbol))
            {
                if (symbol.Kind == SymbolKind.Discard ||
                    (LocalOrParameter.TryCreate(symbol, out var localOrParameter) &&
                     Disposable.ShouldDispose(localOrParameter, context.SemanticModel, context.CancellationToken)))
                {
                    context.ReportDiagnostic(Diagnostic.Create(Descriptors.IDISP001DisposeCreated, argument.GetLocation()));
                }

                if (Disposable.IsAssignedWithCreated(symbol, invocation, context.SemanticModel, context.CancellationToken).IsEither(Result.Yes, Result.AssumeYes) &&
                    !Disposable.IsDisposedBefore(symbol, invocation, context.SemanticModel, context.CancellationToken))
                {
                    context.ReportDiagnostic(Diagnostic.Create(Descriptors.IDISP003DisposeBeforeReassigning, argument.GetLocation()));
                }
            }
        }
        private static void HandleField(SyntaxNodeAnalysisContext context)
        {
            if (context.IsExcludedFromAnalysis())
            {
                return;
            }

            var field = (IFieldSymbol)context.ContainingSymbol;

            if (field.IsStatic || field.IsConst)
            {
                return;
            }

            if (field.DeclaredAccessibility != Accessibility.Private &&
                !field.IsReadOnly)
            {
                if (Disposable.IsAssignedWithCreated(field, context.SemanticModel, context.CancellationToken).IsEither(Result.Yes, Result.Maybe))
                {
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, context.Node.GetLocation()));
                }
            }
            else if (Disposable.IsAssignedWithCreatedAndInjected(field, context.SemanticModel, context.CancellationToken))
            {
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, context.Node.GetLocation()));
            }
        }
        private static void Handle(SyntaxNodeAnalysisContext context)
        {
            if (!context.IsExcludedFromAnalysis() &&
                context.Node is ArgumentSyntax argument &&
                argument.Parent is ArgumentListSyntax argumentList &&
                argumentList.Parent is InvocationExpressionSyntax invocation &&
                argument.RefOrOutKeyword.IsEither(SyntaxKind.RefKeyword, SyntaxKind.OutKeyword) &&
                context.SemanticModel.TryGetSymbol(invocation, context.CancellationToken, out var method) &&
                method.TrySingleDeclaration(context.CancellationToken, out BaseMethodDeclarationSyntax declaration) &&
                method.TryFindParameter(argument, out var parameter) &&
                Disposable.IsPotentiallyAssignableFrom(parameter.Type, context.Compilation))
            {
                if (Disposable.IsCreation(argument, context.SemanticModel, context.CancellationToken).IsEither(Result.Yes, Result.AssumeYes) &&
                    !Disposable.IsAddedToFieldOrProperty(parameter, declaration, context.SemanticModel, context.CancellationToken) &&
                    context.SemanticModel.TryGetSymbol(argument.Expression, context.CancellationToken, out ISymbol symbol))
                {
                    if (LocalOrParameter.TryCreate(symbol, out var localOrParameter) &&
                        Disposable.ShouldDispose(localOrParameter, argument.Expression, context.SemanticModel, context.CancellationToken))
                    {
                        context.ReportDiagnostic(Diagnostic.Create(IDISP001DisposeCreated.Descriptor, argument.GetLocation()));
                    }

                    if (Disposable.IsAssignedWithCreated(symbol, invocation, context.SemanticModel, context.CancellationToken).IsEither(Result.Yes, Result.AssumeYes) &&
                        !Disposable.IsDisposedBefore(symbol, invocation, context.SemanticModel, context.CancellationToken))
                    {
                        context.ReportDiagnostic(Diagnostic.Create(IDISP003DisposeBeforeReassigning.Descriptor, argument.GetLocation()));
                    }
                }
            }
        }
Пример #5
0
        private static void HandleArgument(SyntaxNodeAnalysisContext context)
        {
            if (context.IsExcludedFromAnalysis())
            {
                return;
            }

            var argument = (ArgumentSyntax)context.Node;

            if (argument.RefOrOutKeyword.IsKind(SyntaxKind.None))
            {
                return;
            }

            var invocation = argument.FirstAncestor <InvocationExpressionSyntax>();

            if (invocation == null)
            {
                return;
            }

            var method = context.SemanticModel.GetSymbolSafe(invocation, context.CancellationToken);

            if (method == null ||
                method.DeclaringSyntaxReferences.Length == 0)
            {
                return;
            }

            if (Disposable.IsCreation(argument, context.SemanticModel, context.CancellationToken)
                .IsEither(Result.No, Result.Unknown))
            {
                return;
            }

            var symbol = context.SemanticModel.GetSymbolSafe(argument.Expression, context.CancellationToken);

            if (Disposable.IsAssignedWithCreated(symbol, argument.FirstAncestor <InvocationExpressionSyntax>(), context.SemanticModel, context.CancellationToken)
                .IsEither(Result.No, Result.Unknown))
            {
                return;
            }

            if (IsDisposedBefore(symbol, argument.Expression, context.SemanticModel, context.CancellationToken))
            {
                return;
            }

            context.ReportDiagnostic(Diagnostic.Create(Descriptor, argument.GetLocation()));
        }
        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.TryGetSetAccessorDeclaration(out AccessorDeclarationSyntax setter) &&
                setter.Body != null)
            {
                // Handle the backing field
                return;
            }

            if (property.SetMethod != null &&
                property.SetMethod.DeclaredAccessibility != Accessibility.Private)
            {
                if (Disposable.IsAssignedWithCreated(property, context.SemanticModel, context.CancellationToken)
                    .IsEither(Result.Yes, Result.Maybe))
                {
                    context.ReportDiagnostic(Diagnostic.Create(Descriptor, context.Node.GetLocation()));
                }
            }
            else if (Disposable.IsAssignedWithCreatedAndInjected(property, context.SemanticModel, context.CancellationToken))
            {
                context.ReportDiagnostic(Diagnostic.Create(Descriptor, context.Node.GetLocation()));
            }
        }
Пример #7
0
        private static bool TryCreateDisposeStatement(AssignmentExpressionSyntax assignment, SemanticModel semanticModel, CancellationToken cancellationToken, out StatementSyntax result)
        {
            result = null;
            if (!(assignment.Parent is StatementSyntax && assignment.Parent.Parent is BlockSyntax))
            {
                return(false);
            }

            if (Disposable.IsAssignedWithCreated(assignment.Left, semanticModel, cancellationToken, out var assignedSymbol)
                .IsEither(Result.No, Result.Unknown))
            {
                return(false);
            }

            var prefix = (assignedSymbol is IPropertySymbol || assignedSymbol is IFieldSymbol) &&
                         !assignment.UsesUnderscore(semanticModel, cancellationToken)
                             ? "this."
                             : string.Empty;

            if (!Disposable.IsAssignableTo(MemberType(assignedSymbol)))
            {
                result = SyntaxFactory.ParseStatement($"({prefix}{assignment.Left} as System.IDisposable)?.Dispose();")
                         .WithLeadingTrivia(SyntaxFactory.ElasticMarker)
                         .WithTrailingTrivia(SyntaxFactory.ElasticMarker)
                         .WithSimplifiedNames();
                return(true);
            }

            if (IsAlwaysAssigned(assignedSymbol))
            {
                result = SyntaxFactory.ParseStatement($"{prefix}{assignedSymbol.Name}.Dispose();")
                         .WithLeadingTrivia(SyntaxFactory.ElasticMarker)
                         .WithTrailingTrivia(SyntaxFactory.ElasticMarker);
                return(true);
            }

            result = SyntaxFactory.ParseStatement($"{prefix}{assignedSymbol.Name}?.Dispose();")
                     .WithLeadingTrivia(SyntaxFactory.ElasticMarker)
                     .WithTrailingTrivia(SyntaxFactory.ElasticMarker);
            return(true);
        }