Beispiel #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);
        }
Beispiel #2
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 var 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);
        }
        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);
        }
            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);
            }
        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);
        }
        private bool TryHandleInvocation(InvocationExpressionSyntax 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 (invocation.TryGetArgumentValue(symbol as IParameterSymbol, this.cancellationToken, out ExpressionSyntax arg))
                {
                    this.values[i] = arg;
                }
            }

            this.values.PurgeDuplicates();
            return(true);
        }
Beispiel #7
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 = Create(scope, search, semanticModel, cancellationToken))
            {
                foreach (var candidate in pooledAssignments.Item.Assignments)
                {
                    var assignedSymbol = semanticModel.GetSymbolSafe(candidate.Left, cancellationToken);
                    if (SymbolComparer.Equals(symbol, assignedSymbol))
                    {
                        assignment = candidate;
                        return(true);
                    }
                }
            }

            return(false);
        }
        public override void VisitInvocationExpression(InvocationExpressionSyntax node)
        {
            if (this.semanticModel.GetSymbolSafe(node, this.cancellationToken) is IMethodSymbol method)
            {
                base.VisitInvocationExpression(node);
                if (this.context is ElementAccessExpressionSyntax &&
                    node.Expression is MemberAccessExpressionSyntax memberAccess &&
                    method.Name == "Add" &&
                    SymbolComparer.Equals(this.CurrentSymbol, this.semanticModel.GetSymbolSafe(memberAccess.Expression, this.cancellationToken)))
                {
                    if (method.ContainingType.Is(KnownSymbol.IDictionary) &&
                        node.ArgumentList?.Arguments.Count == 2)
                    {
                        this.values.Add(node.ArgumentList.Arguments[1].Expression);
                    }
                    else if (node.ArgumentList?.Arguments.Count == 1)
                    {
                        this.values.Add(node.ArgumentList.Arguments[0].Expression);
                    }
                }

                this.HandleInvoke(method, node.ArgumentList);
            }
        }
Beispiel #9
0
        private void HandleAssignedValue(SyntaxNode assignee, ExpressionSyntax value)
        {
            if (value == null)
            {
                return;
            }

            if (assignee is VariableDeclaratorSyntax declarator &&
                declarator.Identifier.ValueText != this.CurrentSymbol.Name)
            {
                return;
            }

            if (this.CurrentSymbol.IsEither <ILocalSymbol, IParameterSymbol>() &&
                assignee is MemberAccessExpressionSyntax)
            {
                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 assignedSymbol = this.semanticModel.GetSymbolSafe(assignee, this.cancellationToken) ??
                                 this.semanticModel.GetDeclaredSymbolSafe(assignee, this.cancellationToken);

            if (assignedSymbol == null)
            {
                return;
            }

            if (this.CurrentSymbol.IsEither <IFieldSymbol, IPropertySymbol>() &&
                assignedSymbol is IPropertySymbol property &&
                !SymbolComparer.Equals(this.CurrentSymbol, property) &&
                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.TryGetSetter(out var 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;
                    }
                }
            }
Beispiel #10
0
        private static bool IsReturned(ILocalSymbol symbol, BlockSyntax block, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            using (var pooled = ReturnValueWalker.Create(block, Search.TopLevel, semanticModel, cancellationToken))
            {
                foreach (var value in pooled.Item)
                {
                    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))
                        {
                            var body = (argument.Expression as ParenthesizedLambdaExpressionSyntax)?.Body;
                            using (var pooledInvocations = InvocationWalker.Create(body))
                            {
                                foreach (var candidate in pooledInvocations.Item.Invocations)
                                {
                                    if (Disposable.IsDisposing(candidate, symbol, semanticModel, cancellationToken))
                                    {
                                        return(true);
                                    }
                                }
                            }
                        }
                    }
                }
            }

            return(false);
        }
Beispiel #11
0
        private static bool IsMatch(ISymbol symbol, ExpressionSyntax expression, SemanticModel semanticModel, CancellationToken cancellationToken)
        {
            switch (expression)
            {
            case ConditionalExpressionSyntax conditional:
                return(IsMatch(symbol, conditional.WhenTrue, semanticModel, cancellationToken) ||
                       IsMatch(symbol, conditional.WhenFalse, semanticModel, cancellationToken));

            case BinaryExpressionSyntax binary when binary.IsKind(SyntaxKind.CoalesceExpression):
                return(IsMatch(symbol, binary.Left, semanticModel, cancellationToken) ||
                       IsMatch(symbol, binary.Right, semanticModel, cancellationToken));

            case BinaryExpressionSyntax binary when binary.IsKind(SyntaxKind.AsExpression):
                return(IsMatch(symbol, binary.Left, semanticModel, cancellationToken));

            case CastExpressionSyntax cast:
                return(IsMatch(symbol, cast.Expression, semanticModel, cancellationToken));

            case ObjectCreationExpressionSyntax objectCreation when objectCreation.ArgumentList != null && objectCreation.ArgumentList.Arguments.TryFirst(x => SymbolComparer.Equals(symbol, semanticModel.GetSymbolSafe(x.Expression, cancellationToken)), out ArgumentSyntax _):
                return(true);

            default:
                if (symbol.IsEither <ILocalSymbol, IParameterSymbol>())
                {
                    return(expression is IdentifierNameSyntax identifierName &&
                           identifierName.Identifier.ValueText == symbol.Name &&
                           SymbolComparer.Equals(symbol, semanticModel.GetSymbolSafe(expression, cancellationToken)));
                }

                return(SymbolComparer.Equals(symbol, semanticModel.GetSymbolSafe(expression, cancellationToken)));
            }
        }
        internal void HandleInvoke(IMethodSymbol method, ArgumentListSyntax argumentList)
        {
            if (method != null &&
                (method.Parameters.TryFirst(x => x.RefKind != RefKind.None, out _) ||
                 this.CurrentSymbol.ContainingType.Is(method.ContainingType)))
            {
                if (TryGetWalker(out var walker))
                {
                    foreach (var value in walker.values)
                    {
                        this.values.Add(GetArgumentValue(value));
                    }

                    foreach (var outValue in walker.outValues)
                    {
                        this.values.Add(GetArgumentValue(outValue));
                    }
                }
            }

            bool TryGetWalker(out AssignedValueWalker result)
            {
                result = null;
                if (TryGetKey(out var key))
                {
                    if (this.memberWalkers.TryGetValue(key, out result))
                    {
                        return(false);
                    }

                    if (method.TrySingleDeclaration(this.cancellationToken, out var declaration))
                    {
                        result = Borrow(() => new AssignedValueWalker());
                        this.memberWalkers.Add(key, result);
                        result.CurrentSymbol        = this.CurrentSymbol;
                        result.semanticModel        = this.semanticModel;
                        result.cancellationToken    = this.cancellationToken;
                        result.context              = this.context.FirstAncestorOrSelf <ConstructorDeclarationSyntax>() != null ? this.context : declaration;
                        result.memberWalkers.Parent = this.memberWalkers;
                        if (argumentList != null)
                        {
                            foreach (var argument in argumentList.Arguments)
                            {
                                if (argument.RefOrOutKeyword.IsKind(SyntaxKind.RefKeyword) &&
                                    TryGetMatchingParameter(argument, out var parameter))
                                {
                                    result.refParameters.Add(parameter);
                                }
                                else if (argument.RefOrOutKeyword.IsKind(SyntaxKind.OutKeyword) &&
                                         TryGetMatchingParameter(argument, out parameter))
                                {
                                    result.outParameters.Add(parameter);
                                }
                            }
                        }

                        result.Visit(declaration);
                    }
                }

                return(result != null);

                bool TryGetMatchingParameter(ArgumentSyntax argument, out IParameterSymbol parameter)
                {
                    parameter = null;
                    if (this.semanticModel.GetSymbolSafe(argument.Expression, this.cancellationToken) is ISymbol symbol)
                    {
                        if (SymbolComparer.Equals(this.CurrentSymbol, symbol) ||
                            this.refParameters.Contains(symbol as IParameterSymbol) ||
                            this.outParameters.Contains(symbol as IParameterSymbol))
                        {
                            return(method.TryGetMatchingParameter(argument, out parameter));
                        }
                    }

                    return(false);
                }

                bool TryGetKey(out SyntaxNode node)
                {
                    if (argumentList != null)
                    {
                        node = argumentList;
                        return(true);
                    }

                    return(method.TrySingleDeclaration(this.cancellationToken, out node));
                }
            }

            ExpressionSyntax GetArgumentValue(ExpressionSyntax value)
            {
                if (value is IdentifierNameSyntax identifierName &&
                    method.Parameters.TryFirst(x => x.Name == identifierName.Identifier.ValueText, out var parameter))
                {
                    if (argumentList.TryGetMatchingArgument(parameter, out var argument))
                    {
                        return(argument.Expression);
                    }

                    if (parameter.HasExplicitDefaultValue &&
                        parameter.TrySingleDeclaration(this.cancellationToken, out var parameterDeclaration))
                    {
                        return(parameterDeclaration.Default?.Value);
                    }
                }

                return(value);
            }
        }