コード例 #1
0
        public override void VisitConstructorDeclaration(ConstructorDeclarationSyntax node)
        {
            var ctor = this.semanticModel.GetDeclaredSymbolSafe(node, this.cancellationToken);

            if (SymbolComparer.Equals(this.type, ctor.ContainingType))
            {
                if (ctor.DeclaredAccessibility != Accessibility.Private)
                {
                    this.nonPrivateCtors.Add(node);
                }

                if (ctor.Parameters.Length == 0)
                {
                    this.Default = node;
                }
            }

            base.VisitConstructorDeclaration(node);
        }
コード例 #2
0
        internal static bool FirstWith(ISymbol symbol, SyntaxNode scope, Search search, SemanticModel semanticModel, CancellationToken cancellationToken, out AssignmentExpressionSyntax assignment)
        {
            assignment = null;
            if (symbol == null ||
                scope == null)
            {
                return(false);
            }

            using (var pooledAssignments = Borrow(scope, search, semanticModel, cancellationToken))
            {
                foreach (var candidate in pooledAssignments.Assignments)
                {
                    if (candidate.Right is ConditionalExpressionSyntax conditional)
                    {
                        if (SymbolComparer.Equals(symbol, semanticModel.GetSymbolSafe(conditional.WhenTrue, cancellationToken)) ||
                            SymbolComparer.Equals(symbol, semanticModel.GetSymbolSafe(conditional.WhenFalse, cancellationToken)))
                        {
                            assignment = candidate;
                            return(true);
                        }
                    }

                    var assignedSymbol = semanticModel.GetSymbolSafe(candidate.Right, cancellationToken);
                    if (SymbolComparer.Equals(symbol, assignedSymbol))
                    {
                        assignment = candidate;
                        return(true);
                    }

                    if (candidate.Right is ObjectCreationExpressionSyntax objectCreation &&
                        objectCreation.ArgumentList != null &&
                        objectCreation.ArgumentList.Arguments.TryGetFirst(x => SymbolComparer.Equals(symbol, semanticModel.GetSymbolSafe(x.Expression, cancellationToken)), out ArgumentSyntax _))
                    {
                        assignment = candidate;
                        return(true);
                    }
                }
            }

            return(false);
        }
コード例 #3
0
        public override void VisitArgument(ArgumentSyntax node)
        {
            if (this.visitedLocations.Add(node) &&
                (node.RefOrOutKeyword.IsKind(SyntaxKind.RefKeyword) ||
                 node.RefOrOutKeyword.IsKind(SyntaxKind.OutKeyword)))
            {
                var invocation = node.FirstAncestorOrSelf <InvocationExpressionSyntax>();
                var argSymbol  = this.semanticModel.GetSymbolSafe(node.Expression, this.cancellationToken);
                if (invocation != null &&
                    (SymbolComparer.Equals(this.CurrentSymbol, argSymbol) ||
                     this.refParameters.Contains(argSymbol as IParameterSymbol)))
                {
                    var method = this.semanticModel.GetSymbolSafe(invocation, this.cancellationToken);
                    if (method != null &&
                        method.DeclaringSyntaxReferences.Length > 0)
                    {
                        foreach (var reference in method.DeclaringSyntaxReferences)
                        {
                            var methodDeclaration = reference.GetSyntax(this.cancellationToken) as MethodDeclarationSyntax;
                            if (methodDeclaration.TryGetMatchingParameter(node, out ParameterSyntax parameterSyntax))
                            {
                                var parameterSymbol = this.semanticModel.GetDeclaredSymbolSafe(parameterSyntax, this.cancellationToken);
                                if (parameterSymbol != null)
                                {
                                    if (node.RefOrOutKeyword.IsKind(SyntaxKind.RefKeyword))
                                    {
                                        this.refParameters.Add(parameterSymbol).IgnoreReturnValue();
                                    }

                                    if (node.RefOrOutKeyword.IsKind(SyntaxKind.OutKeyword))
                                    {
                                        this.values.Add(node.Expression);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            base.VisitArgument(node);
        }
コード例 #4
0
        internal static bool IsDisposing(InvocationExpressionSyntax invocation, ISymbol member, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            var method = semanticModel.GetSymbolSafe(invocation, cancellationToken) as IMethodSymbol;

            if (method == null ||
                method.Parameters.Length != 0 ||
                method != KnownSymbol.IDisposable.Dispose)
            {
                return(false);
            }

            if (TryGetDisposedRootMember(invocation, semanticModel, cancellationToken, out ExpressionSyntax disposed))
            {
                if (SymbolComparer.Equals(member, semanticModel.GetSymbolSafe(disposed, cancellationToken)))
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #5
0
            internal Result IsMemberDisposed(ISymbol member)
            {
                foreach (var invocation in this.invocations)
                {
                    if (TryGetDisposedRootMember(invocation, this.SemanticModel, this.CancellationToken, out ExpressionSyntax disposed) &&
                        SymbolComparer.Equals(member, this.SemanticModel.GetSymbolSafe(disposed, this.CancellationToken)))
                    {
                        return(Result.Yes);
                    }
                }

                foreach (var name in this.identifiers)
                {
                    if (SymbolComparer.Equals(member, this.SemanticModel.GetSymbolSafe(name, this.CancellationToken)))
                    {
                        return(Result.Maybe);
                    }
                }

                return(Result.No);
            }
コード例 #6
0
        private bool TryHandleInvocation(MemberAccessExpressionSyntax invocation)
        {
            if (invocation == null)
            {
                return(false);
            }

            var method = this.semanticModel.GetSymbolSafe(invocation, this.cancellationToken);

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

            foreach (var reference in method.DeclaringSyntaxReferences)
            {
                base.Visit(reference.GetSyntax(this.cancellationToken));
            }

            for (var i = this.values.Count - 1; i >= 0; i--)
            {
                var symbol = this.semanticModel.GetSymbolSafe(this.values[i], this.cancellationToken);
                if (this.search == Search.Recursive &&
                    SymbolComparer.Equals(symbol, method))
                {
                    this.values.RemoveAt(i);
                    continue;
                }

                if (symbol is IParameterSymbol parameter &&
                    parameter.IsThis)
                {
                    this.values[i] = invocation.Expression;
                }
            }

            this.values.PurgeDuplicates();
            return(true);
        }
コード例 #7
0
        internal static bool IsDisposing(InvocationExpressionSyntax invocation, ISymbol member, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            if (invocation.Expression is MemberAccessExpressionSyntax memberAccess &&
                memberAccess.Name is IdentifierNameSyntax methodName &&
                methodName.Identifier.ValueText != "Dispose")
            {
                return(false);
            }

            if (semanticModel.GetSymbolSafe(invocation, cancellationToken) is IMethodSymbol method &&
                method.Parameters.Length == 0 &&
                method == KnownSymbol.RefCounter.Dispose &&
                TryGetDisposedRootMember(invocation, semanticModel, cancellationToken, out var disposed))
            {
                if (SymbolComparer.Equals(member, semanticModel.GetSymbolSafe(disposed, cancellationToken)))
                {
                    return(true);
                }
            }

            return(false);
        }
コード例 #8
0
        private bool TryHandlePropertyGet(ExpressionSyntax propertyGet)
        {
            if (propertyGet == null)
            {
                return(false);
            }

            var property = this.semanticModel.GetSymbolSafe(propertyGet, this.cancellationToken) as IPropertySymbol;
            var getter   = property?.GetMethod;

            if (getter == null)
            {
                return(false);
            }

            if (getter.DeclaringSyntaxReferences.Length == 0)
            {
                return(true);
            }

            foreach (var reference in getter.DeclaringSyntaxReferences)
            {
                base.Visit(reference.GetSyntax(this.cancellationToken));
            }

            for (var i = this.values.Count - 1; i >= 0; i--)
            {
                var symbol = this.semanticModel.GetSymbolSafe(this.values[i], this.cancellationToken);
                if (this.search == Search.Recursive &&
                    SymbolComparer.Equals(symbol, property))
                {
                    this.values.RemoveAt(i);
                }
            }

            this.values.PurgeDuplicates();

            return(true);
        }
コード例 #9
0
        internal static bool FirstForSymbol(ISymbol symbol, SyntaxNode scope, Search search, SemanticModel semanticModel, CancellationToken cancellationToken, out AssignmentExpressionSyntax assignment)
        {
            assignment = null;
            if (symbol == null ||
                scope == null)
            {
                return(false);
            }

            using (var pooledAssignments = Borrow(scope, search, semanticModel, cancellationToken))
            {
                foreach (var candidate in pooledAssignments.Assignments)
                {
                    var assignedSymbol = semanticModel.GetSymbolSafe(candidate.Left, cancellationToken);
                    if (SymbolComparer.Equals(symbol, assignedSymbol))
                    {
                        assignment = candidate;
                        return(true);
                    }
                }
            }

            return(false);
        }
コード例 #10
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);
        }
コード例 #11
0
        private static bool IsReturned(ILocalSymbol symbol, BlockSyntax block, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            using (var walker = ReturnValueWalker.Borrow(block, Search.TopLevel, semanticModel, cancellationToken))
            {
                foreach (var value in walker)
                {
                    var returnedSymbol = semanticModel.GetSymbolSafe(value, cancellationToken);
                    if (SymbolComparer.Equals(symbol, returnedSymbol))
                    {
                        return(true);
                    }

                    if (value is ObjectCreationExpressionSyntax objectCreation)
                    {
                        if (objectCreation.ArgumentList != null)
                        {
                            foreach (var argument in objectCreation.ArgumentList.Arguments)
                            {
                                var arg = semanticModel.GetSymbolSafe(argument.Expression, cancellationToken);
                                if (SymbolComparer.Equals(symbol, arg))
                                {
                                    return(true);
                                }
                            }
                        }

                        if (objectCreation.Initializer != null)
                        {
                            foreach (var argument in objectCreation.Initializer.Expressions)
                            {
                                var arg = semanticModel.GetSymbolSafe(argument, cancellationToken);
                                if (SymbolComparer.Equals(symbol, arg))
                                {
                                    return(true);
                                }
                            }
                        }
                    }

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

            return(false);
        }
コード例 #12
0
        private void HandleAssignedValue(SyntaxNode assignee, ExpressionSyntax value)
        {
            if (value == null)
            {
                return;
            }

            var assignedSymbol = this.semanticModel.GetSymbolSafe(assignee, this.cancellationToken) ??
                                 this.semanticModel.GetDeclaredSymbolSafe(assignee, this.cancellationToken);

            if (assignedSymbol == null)
            {
                return;
            }

            if (this.Context is ElementAccessExpressionSyntax)
            {
                switch (value)
                {
                case ArrayCreationExpressionSyntax arrayCreation:
                {
                    if (arrayCreation.Initializer == null)
                    {
                        return;
                    }

                    foreach (var item in arrayCreation.Initializer.Expressions)
                    {
                        this.values.Add(item);
                    }
                }

                break;

                case ObjectCreationExpressionSyntax objectCreation:
                {
                    if (objectCreation.Initializer == null)
                    {
                        return;
                    }

                    foreach (var item in objectCreation.Initializer.Expressions)
                    {
                        if (item is InitializerExpressionSyntax kvp)
                        {
                            if (kvp.Expressions.Count == 2)
                            {
                                this.values.Add(kvp.Expressions[1]);
                            }
                        }
                        else if (item is AssignmentExpressionSyntax assignment)
                        {
                            this.values.Add(assignment.Right);
                        }
                        else
                        {
                            this.values.Add(item);
                        }
                    }
                }

                break;

                case InitializerExpressionSyntax initializer:
                {
                    foreach (var item in initializer.Expressions)
                    {
                        this.values.Add(item);
                    }
                }

                break;

                default:
                    return;
                }

                return;
            }

            var property = assignedSymbol as IPropertySymbol;

            if (!SymbolComparer.Equals(this.CurrentSymbol, property) &&
                (this.CurrentSymbol is IFieldSymbol || this.CurrentSymbol is IPropertySymbol) &&
                property != null &&
                Property.AssignsSymbolInSetter(
                    property,
                    this.CurrentSymbol,
                    this.semanticModel,
                    this.cancellationToken))
            {
                var before = this.values.Count;
                foreach (var reference in property.DeclaringSyntaxReferences)
                {
                    var declaration = (PropertyDeclarationSyntax)reference.GetSyntax(this.cancellationToken);
                    if (declaration.TryGetSetAccessorDeclaration(out AccessorDeclarationSyntax setter))
                    {
                        this.Visit(setter);
                    }
                }

                for (var i = before; i < this.values.Count; i++)
                {
                    var parameter = this.semanticModel.GetSymbolSafe(this.values[i], this.cancellationToken) as IParameterSymbol;
                    if (Equals(parameter?.ContainingSymbol, property.SetMethod))
                    {
                        this.values[i] = value;
                    }
                }
            }
            else
            {
                if (SymbolComparer.Equals(this.CurrentSymbol, assignedSymbol) ||
                    this.refParameters.Contains(assignedSymbol as IParameterSymbol))
                {
                    this.values.Add(value);
                }
            }
        }
コード例 #13
0
        internal static void AllWith(ISymbol symbol, SyntaxNode scope, Search search, SemanticModel semanticModel, CancellationToken cancellationToken, List <AssignmentExpressionSyntax> assignments)
        {
            if (symbol == null ||
                scope == null)
            {
                return;
            }

            using (var walker = Borrow(scope, Search.TopLevel, semanticModel, cancellationToken))
            {
                foreach (var candidate in walker.Assignments)
                {
                    if (candidate.Right is ConditionalExpressionSyntax conditional)
                    {
                        if (SymbolComparer.Equals(symbol, semanticModel.GetSymbolSafe(conditional.WhenTrue, cancellationToken)) ||
                            SymbolComparer.Equals(symbol, semanticModel.GetSymbolSafe(conditional.WhenFalse, cancellationToken)))
                        {
                            assignments.Add(candidate);
                        }
                    }

                    if (candidate.Right is BinaryExpressionSyntax binary &&
                        binary.IsKind(SyntaxKind.CoalesceExpression))
                    {
                        if (SymbolComparer.Equals(symbol, semanticModel.GetSymbolSafe(binary.Left, cancellationToken)) ||
                            SymbolComparer.Equals(symbol, semanticModel.GetSymbolSafe(binary.Right, cancellationToken)))
                        {
                            assignments.Add(candidate);
                        }
                    }

                    var assignedSymbol = semanticModel.GetSymbolSafe(candidate.Right, cancellationToken);
                    if (SymbolComparer.Equals(symbol, assignedSymbol))
                    {
                        assignments.Add(candidate);
                    }

                    if (candidate.Right is ObjectCreationExpressionSyntax objectCreation &&
                        objectCreation.ArgumentList != null &&
                        objectCreation.ArgumentList.Arguments.TryFirst(x => SymbolComparer.Equals(symbol, semanticModel.GetSymbolSafe(x.Expression, cancellationToken)), out ArgumentSyntax _))
                    {
                        assignments.Add(candidate);
                    }
                }

                if (search == Search.Recursive)
                {
                    foreach (var argument in walker.arguments)
                    {
                        if (argument.Expression is IdentifierNameSyntax identifierName &&
                            identifierName.Identifier.ValueText == symbol.Name &&
                            semanticModel.GetSymbolSafe(argument.Parent?.Parent, cancellationToken) is IMethodSymbol method &&
                            method.TrySingleDeclaration(cancellationToken, out BaseMethodDeclarationSyntax methodDeclaration) &&
                            methodDeclaration.TryGetMatchingParameter(argument, out var parameter))
                        {
                            AllWith(semanticModel.GetDeclaredSymbolSafe(parameter, cancellationToken), methodDeclaration, search,
                                    semanticModel, cancellationToken, assignments);
                        }
                    }
                }
            }
        }