private static bool IsAddedToFieldOrProperty(ILocalSymbol symbol, BlockSyntax block, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            using (var pooledInvocations = InvocationWalker.Borrow(block))
            {
                foreach (var invocation in pooledInvocations.Invocations)
                {
                    var method = semanticModel.GetSymbolSafe(invocation, cancellationToken) as IMethodSymbol;
                    if (method?.Name == "Add")
                    {
                        using (var nameWalker = IdentifierNameWalker.Borrow(invocation.ArgumentList))
                        {
                            foreach (var identifierName in nameWalker.IdentifierNames)
                            {
                                var argSymbol = semanticModel.GetSymbolSafe(identifierName, cancellationToken);
                                if (symbol.Equals(argSymbol))
                                {
                                    return(true);
                                }
                            }
                        }
                    }
                }
            }

            return(false);
        }
Exemple #2
0
        internal static bool IsMemberDisposed(ISymbol member, IMethodSymbol disposeMethod, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (member == null ||
                disposeMethod == null)
            {
                return(false);
            }

            foreach (var reference in disposeMethod.DeclaringSyntaxReferences)
            {
                var node = reference.GetSyntax(cancellationToken) as MethodDeclarationSyntax;
                using (var pooled = DisposeWalker.Borrow(disposeMethod, semanticModel, cancellationToken))
                {
                    foreach (var invocation in pooled)
                    {
                        if (IsDisposing(invocation, member, semanticModel, cancellationToken))
                        {
                            return(true);
                        }
                    }
                }

                using (var walker = IdentifierNameWalker.Borrow(node))
                {
                    foreach (var identifier in walker.IdentifierNames)
                    {
                        var memberAccess = identifier.Parent as MemberAccessExpressionSyntax;
                        if (memberAccess?.Expression is BaseExpressionSyntax)
                        {
                            var baseMethod = semanticModel.GetSymbolSafe(identifier, cancellationToken) as IMethodSymbol;
                            if (baseMethod?.Name == "Dispose")
                            {
                                if (IsMemberDisposed(member, baseMethod, semanticModel, cancellationToken))
                                {
                                    return(true);
                                }
                            }
                        }

                        if (identifier.Identifier.ValueText != member.Name)
                        {
                            continue;
                        }

                        var symbol = semanticModel.GetSymbolSafe(identifier, cancellationToken);
                        if (member.Equals(symbol) || (member as IPropertySymbol)?.OverriddenProperty?.Equals(symbol) == true)
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
Exemple #3
0
        private static bool IsDisposedBefore(ISymbol symbol, ExpressionSyntax assignment, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            using (var pooled = InvocationWalker.Create(assignment.FirstAncestorOrSelf <MemberDeclarationSyntax>()))
            {
                foreach (var invocation in pooled.Item.Invocations)
                {
                    if (invocation.IsBeforeInScope(assignment) != Result.Yes)
                    {
                        continue;
                    }

                    var invokedSymbol = semanticModel.GetSymbolSafe(invocation, cancellationToken);
                    if (invokedSymbol?.Name != "Dispose")
                    {
                        continue;
                    }

                    var statement = invocation.FirstAncestorOrSelf <StatementSyntax>();
                    if (statement != null)
                    {
                        using (var pooledNames = IdentifierNameWalker.Create(statement))
                        {
                            foreach (var identifierName in pooledNames.Item.IdentifierNames)
                            {
                                var otherSymbol = semanticModel.GetSymbolSafe(identifierName, cancellationToken);
                                if (symbol.Equals(otherSymbol))
                                {
                                    return(true);
                                }
                            }
                        }
                    }
                }
            }

            return(false);
        }
Exemple #4
0
        internal static bool IsDisposedBefore(ISymbol symbol, ExpressionSyntax assignment, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            bool IsDisposing(InvocationExpressionSyntax invocation, ISymbol current)
            {
                if (invocation.TryGetInvokedMethodName(out var name) &&
                    name != "Dispose")
                {
                    return(false);
                }

                var invokedSymbol = semanticModel.GetSymbolSafe(invocation, cancellationToken);

                if (invokedSymbol?.Name != "Dispose")
                {
                    return(false);
                }

                var statement = invocation.FirstAncestorOrSelf <StatementSyntax>();

                if (statement != null)
                {
                    using (var names = IdentifierNameWalker.Borrow(statement))
                    {
                        foreach (var identifierName in names.IdentifierNames)
                        {
                            if (identifierName.Identifier.ValueText == current.Name &&
                                SymbolComparer.Equals(current, semanticModel.GetSymbolSafe(identifierName, cancellationToken)))
                            {
                                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);
            }

            if (TryGetScope(assignment, out var block))
            {
                using (var walker = InvocationWalker.Borrow(block))
                {
                    foreach (var invocation in walker.Invocations)
                    {
                        if (invocation.IsBeforeInScope(assignment) != Result.Yes)
                        {
                            continue;
                        }

                        if (IsDisposing(invocation, symbol))
                        {
                            return(true);
                        }
                    }
                }
            }

            if (assignment 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 (IsDisposing(invocation, symbol) ||
                            IsDisposing(invocation, property))
                        {
                            return(true);
                        }
                    }
                }
            }

            return(false);
        }
        private static bool IsUsedAfter(ILocalSymbol local, InvocationExpressionSyntax invocation, SyntaxNodeAnalysisContext context, out IReadOnlyList <Location> locations)
        {
            if (local.TrySingleDeclaration(context.CancellationToken, out var declaration) &&
                declaration.TryFirstAncestor(out BlockSyntax block))
            {
                List <Location> temp = null;
                using (var walker = IdentifierNameWalker.Borrow(block))
                {
                    foreach (var identifierName in walker.IdentifierNames)
                    {
                        if (identifierName.Identifier.ValueText == local.Name &&
                            invocation.IsExecutedBefore(identifierName) == ExecutedBefore.Yes &&
                            context.SemanticModel.TryGetSymbol(identifierName, context.CancellationToken, out ILocalSymbol candidate) &&
                            local.Equals(candidate) &&
                            !IsAssigned(identifierName) &&
                            !IsReassigned(identifierName))
                        {
                            if (temp == null)
                            {
                                temp = new List <Location>();
                            }

                            temp.Add(identifierName.GetLocation());
                        }
                    }

                    locations = temp;
                    return(locations != null);
                }
            }

            locations = null;
            return(false);

            bool IsAssigned(IdentifierNameSyntax identifier)
            {
                switch (identifier.Parent)
                {
                case AssignmentExpressionSyntax assignment:
                    return(assignment.Left == identifier);

                case ArgumentSyntax argument when argument.RefOrOutKeyword.IsKind(SyntaxKind.OutKeyword):
                    return(true);
                }

                return(false);
            }

            bool IsReassigned(ExpressionSyntax location)
            {
                using (var walker = MutationWalker.For(local, context.SemanticModel, context.CancellationToken))
                {
                    foreach (var mutation in walker.All())
                    {
                        if (mutation.TryFirstAncestorOrSelf(out ExpressionSyntax expression) &&
                            invocation.IsExecutedBefore(expression) != ExecutedBefore.No &&
                            expression.IsExecutedBefore(location) != ExecutedBefore.No)
                        {
                            return(true);
                        }
                    }
                }

                return(false);
            }
        }