Esempio n. 1
0
        internal static bool IsDisposedAfter(ISymbol local, ExpressionSyntax location, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (location.FirstAncestorOrSelf <MemberDeclarationSyntax>() is MemberDeclarationSyntax scope)
            {
                using (var walker = InvocationWalker.Borrow(scope))
                {
                    foreach (var invocation in walker.Invocations)
                    {
                        if (location.IsExecutedBefore(invocation).IsEither(ExecutedBefore.Maybe, ExecutedBefore.Yes) &&
                            DisposeCall.IsDisposing(invocation, local, semanticModel, cancellationToken))
                        {
                            return(true);
                        }
                    }
                }

                using (var walker = UsingStatementWalker.Borrow(scope))
                {
                    foreach (var usingStatement in walker.UsingStatements)
                    {
                        if (location.IsExecutedBefore(usingStatement) == ExecutedBefore.Yes &&
                            usingStatement.Expression is IdentifierNameSyntax identifierName &&
                            identifierName.Identifier.ValueText == local.Name)
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
Esempio n. 2
0
        internal Result IsMemberDisposed(ISymbol member)
        {
            foreach (var invocation in this.invocations)
            {
                if (DisposeCall.IsDisposing(invocation, member, this.SemanticModel, this.CancellationToken))
                {
                    return(Result.Yes);
                }
            }

            if (member is IPropertySymbol property &&
                property.OverriddenProperty is IPropertySymbol overridden)
            {
                return(this.IsMemberDisposed(overridden));
            }

            foreach (var name in this.identifiers)
            {
                if (member.Name == name.Identifier.ValueText &&
                    this.SemanticModel.TryGetSymbol(name, this.CancellationToken, out ISymbol candidate) &&
                    member.Equals(candidate))
                {
                    return(Result.AssumeYes);
                }
            }

            return(Result.No);
        }
        internal static bool IsDisposed(FieldOrProperty member, MethodDeclarationSyntax disposeMethod, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            using var walker = DisposeWalker.Borrow(disposeMethod, semanticModel, cancellationToken);
            if (Disposable.IsAssignableFrom(member.Type, semanticModel.Compilation))
            {
                foreach (var candidate in walker.Invocations)
                {
                    if (DisposeCall.IsDisposing(candidate, member.Symbol, semanticModel, cancellationToken))
                    {
                        return(true);
                    }
                }
            }

            foreach (var candidate in walker.Identifiers)
            {
                if (candidate.Identifier.Text == member.Name &&
                    semanticModel.TryGetSymbol(candidate, cancellationToken, out var candidateSymbol) &&
                    candidateSymbol.OriginalDefinition.Equals(member.Symbol))
                {
                    return(true);
                }
            }

            return(false);
        }
Esempio n. 4
0
        internal static bool IsDisposed(FieldOrProperty member, IMethodSymbol disposeMethod, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (disposeMethod == null)
            {
                return(false);
            }

            using (var walker = DisposeWalker.Borrow(disposeMethod, semanticModel, cancellationToken))
            {
                foreach (var invocation in walker)
                {
                    if (DisposeCall.IsDisposing(invocation, member.Symbol, semanticModel, cancellationToken))
                    {
                        return(true);
                    }
                }
            }

            return(false);
        }
        internal static bool IsDisposedBefore(ISymbol symbol, ExpressionSyntax expression, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (TryGetScope(expression, out var block))
            {
                using var walker = InvocationWalker.Borrow(block);
                foreach (var invocation in walker.Invocations)
                {
                    if (invocation.IsExecutedBefore(expression) == ExecutedBefore.No)
                    {
                        continue;
                    }

                    if (DisposeCall.IsDisposing(invocation, symbol, semanticModel, cancellationToken) &&
                        !IsReassignedAfter(block, invocation))
                    {
                        return(true);
                    }
                }
            }

            if (expression is AssignmentExpressionSyntax {
                Left : { } left
            } &&
Esempio n. 6
0
        internal static bool IsDisposedBefore(ISymbol symbol, ExpressionSyntax expression, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (TryGetScope(expression, out var block))
            {
                using (var walker = InvocationWalker.Borrow(block))
                {
                    foreach (var invocation in walker.Invocations)
                    {
                        if (invocation.IsExecutedBefore(expression) == ExecutedBefore.No)
                        {
                            continue;
                        }

                        if (DisposeCall.IsDisposing(invocation, symbol, semanticModel, cancellationToken) &&
                            !IsReassignedAfter(block, invocation))
                        {
                            return(true);
                        }
                    }
                }
            }

            if (expression is AssignmentExpressionSyntax assignmentExpression &&
                semanticModel.GetSymbolSafe(assignmentExpression.Left, cancellationToken) is IPropertySymbol property &&
                property.TryGetSetter(cancellationToken, out var setter))
            {
                using (var pooled = InvocationWalker.Borrow(setter))
                {
                    foreach (var invocation in pooled.Invocations)
                    {
                        if ((DisposeCall.IsDisposing(invocation, symbol, semanticModel, cancellationToken) ||
                             DisposeCall.IsDisposing(invocation, property, semanticModel, cancellationToken)) &&
                            !IsReassignedAfter(setter, invocation))
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);

            bool TryGetScope(SyntaxNode node, out BlockSyntax result)
            {
                result = null;
                if (node.FirstAncestor <AnonymousFunctionExpressionSyntax>() is AnonymousFunctionExpressionSyntax lambda)
                {
                    result = lambda.Body as BlockSyntax;
                }
                else if (node.FirstAncestor <AccessorDeclarationSyntax>() is AccessorDeclarationSyntax accessor)
                {
                    result = accessor.Body;
                }
                else if (node.FirstAncestor <BaseMethodDeclarationSyntax>() is BaseMethodDeclarationSyntax method)
                {
                    result = method.Body;
                }

                return(result != null);
            }

            bool IsReassignedAfter(SyntaxNode scope, InvocationExpressionSyntax disposeCall)
            {
                using (var walker = MutationWalker.Borrow(scope, Scope.Member, semanticModel, cancellationToken))
                {
                    foreach (var mutation in walker.All())
                    {
                        if (mutation.TryFirstAncestor(out StatementSyntax statement) &&
                            disposeCall.IsExecutedBefore(statement) == ExecutedBefore.Yes &&
                            statement.IsExecutedBefore(expression) == ExecutedBefore.Yes)
                        {
                            return(true);
                        }
                    }
                }

                return(false);
            }
        }
Esempio n. 7
0
        internal static bool IsReturned(ISymbol symbol, SyntaxNode scope, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            using (var walker = ReturnValueWalker.Borrow(scope, ReturnValueSearch.TopLevel, semanticModel, cancellationToken))
            {
                foreach (var value in walker)
                {
                    var candidate = value;
                    switch (candidate)
                    {
                    case CastExpressionSyntax castExpression:
                        candidate = castExpression.Expression;
                        break;

                    case BinaryExpressionSyntax binary when binary.IsKind(SyntaxKind.AsExpression):
                        candidate = binary.Left;

                        break;
                    }

                    if (candidate is ObjectCreationExpressionSyntax objectCreation)
                    {
                        if (objectCreation.ArgumentList != null)
                        {
                            foreach (var argument in objectCreation.ArgumentList.Arguments)
                            {
                                if (semanticModel.TryGetSymbol(argument.Expression, cancellationToken, out ISymbol argumentSymbol) &&
                                    symbol.Equals(argumentSymbol))
                                {
                                    return(true);
                                }
                            }
                        }

                        if (objectCreation.Initializer != null)
                        {
                            foreach (var expression in objectCreation.Initializer.Expressions)
                            {
                                if (semanticModel.TryGetSymbol(expression, cancellationToken, out ISymbol expressionSymbol) &&
                                    symbol.Equals(expressionSymbol))
                                {
                                    return(true);
                                }
                            }
                        }
                    }

                    if (semanticModel.TryGetSymbol(candidate, cancellationToken, out ISymbol returnedSymbol) &&
                        symbol.Equals(returnedSymbol))
                    {
                        return(true);
                    }

                    if (candidate is InvocationExpressionSyntax invocation)
                    {
                        if (returnedSymbol == KnownSymbol.RxDisposable.Create &&
                            invocation.ArgumentList != null &&
                            invocation.ArgumentList.Arguments.TrySingle(out var argument) &&
                            argument.Expression is ParenthesizedLambdaExpressionSyntax lambda)
                        {
                            var body = lambda.Body;
                            using (var pooledInvocations = InvocationWalker.Borrow(body))
                            {
                                foreach (var disposeCandidate in pooledInvocations.Invocations)
                                {
                                    if (DisposeCall.IsDisposing(disposeCandidate, symbol, semanticModel, cancellationToken))
                                    {
                                        return(true);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(false);
        }