/// <summary>
        /// Returns the candidate callees after resolving the specified invocation.
        /// </summary>
        /// <param name="invocation">InvocationExpressionSyntax</param>
        /// <param name="node">IDataFlowNode</param>
        /// <returns>Set of candidate callees</returns>
        private static HashSet <MethodDeclarationSyntax> ResolveCandidateMethodsAtCallSite(
            InvocationExpressionSyntax invocation, IDataFlowNode node)
        {
            var candidateCallees           = new HashSet <MethodDeclarationSyntax>();
            var candidateMethodDeclaration = MethodSummaryResolver.ResolveMethodDeclaration(
                invocation, node) as MethodDeclarationSyntax;

            if (candidateMethodDeclaration == null)
            {
                return(candidateCallees);
            }

            if (candidateMethodDeclaration.Modifiers.Any(SyntaxKind.AbstractKeyword) ||
                candidateMethodDeclaration.Modifiers.Any(SyntaxKind.VirtualKeyword) ||
                candidateMethodDeclaration.Modifiers.Any(SyntaxKind.OverrideKeyword))
            {
                HashSet <MethodDeclarationSyntax> overriders = null;
                if (!MethodSummaryResolver.TryGetCandidateMethodOverriders(out overriders,
                                                                           invocation, node))
                {
                    return(candidateCallees);
                }

                candidateCallees.UnionWith(overriders);
            }

            if (candidateCallees.Count == 0)
            {
                candidateCallees.Add(candidateMethodDeclaration);
            }

            return(candidateCallees);
        }
        /// <summary>
        /// Returns all cached method summaries for the specified call.
        /// </summary>
        /// <param name="call">ExpressionSyntax</param>
        /// <param name="node">IDataFlowNode</param>
        /// <returns>MethodSummarys</returns>
        private static ISet <MethodSummary> ResolveMethodSummaries(ExpressionSyntax call, IDataFlowNode node)
        {
            var summaries = new HashSet <MethodSummary>();

            var invocation  = call as InvocationExpressionSyntax;
            var objCreation = call as ObjectCreationExpressionSyntax;
            var callSymbol  = node.Summary.SemanticModel.GetSymbolInfo(call).Symbol;

            if (callSymbol == null ||
                (invocation == null && objCreation == null))
            {
                return(summaries);
            }

            if (node.MethodSummaryCache.ContainsKey(callSymbol))
            {
                summaries.UnionWith(node.MethodSummaryCache[callSymbol]);
            }
            else if (invocation != null)
            {
                var parameterTypes = MethodSummaryResolver.GetCandidateParameterTypes(
                    invocation.ArgumentList, node);
                var candidateCalleeDeclarations = MethodSummaryResolver.
                                                  ResolveCandidateMethodsAtCallSite(invocation, node);
                foreach (var candidateCalleeDeclaration in candidateCalleeDeclarations)
                {
                    var calleeSummary = MethodSummary.Create(node.Summary.AnalysisContext,
                                                             candidateCalleeDeclaration, parameterTypes);
                    if (calleeSummary != null)
                    {
                        summaries.Add(calleeSummary);
                    }
                }
            }
            else
            {
                var parameterTypes = MethodSummaryResolver.GetCandidateParameterTypes(
                    objCreation.ArgumentList, node);
                var constructor = MethodSummaryResolver.ResolveMethodDeclaration(
                    objCreation, node) as ConstructorDeclarationSyntax;
                if (constructor != null)
                {
                    var calleeSummary = MethodSummary.Create(node.Summary.AnalysisContext,
                                                             constructor, parameterTypes);
                    if (calleeSummary != null)
                    {
                        summaries.Add(calleeSummary);
                    }
                }
            }

            return(summaries);
        }
 /// <summary>
 /// Returns all cached method summaries for the specified object creation.
 /// </summary>
 /// <param name="objCreation">ObjectCreationExpressionSyntax</param>
 /// <param name="node">IDataFlowNode</param>
 /// <returns>MethodSummarys</returns>
 internal static ISet <MethodSummary> ResolveMethodSummaries(
     ObjectCreationExpressionSyntax objCreation, IDataFlowNode node)
 {
     return(MethodSummaryResolver.ResolveMethodSummaries(objCreation as ExpressionSyntax, node));
 }
 /// <summary>
 /// Returns all cached method summaries for the specified invocation.
 /// </summary>
 /// <param name="invocation">InvocationExpressionSyntax</param>
 /// <param name="node">IDataFlowNode</param>
 /// <returns>MethodSummarys</returns>
 internal static ISet <MethodSummary> ResolveMethodSummaries(
     InvocationExpressionSyntax invocation, IDataFlowNode node)
 {
     return(MethodSummaryResolver.ResolveMethodSummaries(invocation as ExpressionSyntax, node));
 }
        /// <summary>
        /// Tries to get the list of candidate methods that can
        /// override the specified virtual call.
        /// </summary>
        /// <param name="overriders">List of overrider methods</param>
        /// <param name="virtualCall">Virtual call</param>
        /// <param name="node">IDataFlowNode</param>
        /// <returns>Boolean</returns>
        private static bool TryGetCandidateMethodOverriders(out HashSet <MethodDeclarationSyntax> overriders,
                                                            InvocationExpressionSyntax virtualCall, IDataFlowNode node)
        {
            overriders = new HashSet <MethodDeclarationSyntax>();

            ISymbol          calleeSymbol = null;
            SimpleNameSyntax callee       = null;
            bool             isThis       = false;

            if (virtualCall.Expression is MemberAccessExpressionSyntax)
            {
                var expr       = virtualCall.Expression as MemberAccessExpressionSyntax;
                var identifier = expr.Expression.DescendantNodesAndSelf().
                                 OfType <IdentifierNameSyntax>().Last();
                calleeSymbol = node.Summary.SemanticModel.GetSymbolInfo(identifier).Symbol;

                if (expr.Expression is ThisExpressionSyntax)
                {
                    callee = expr.Name;
                    isThis = true;
                }
            }
            else
            {
                callee = virtualCall.Expression as IdentifierNameSyntax;
                isThis = true;
            }

            if (isThis)
            {
                var typeDeclaration = node.Summary.Method.FirstAncestorOrSelf <TypeDeclarationSyntax>();
                if (typeDeclaration != null)
                {
                    foreach (var method in typeDeclaration.Members.OfType <MethodDeclarationSyntax>())
                    {
                        if (method.Identifier.ToString().Equals(callee.Identifier.ToString()))
                        {
                            overriders.Add(method);
                            return(true);
                        }
                    }
                }

                return(false);
            }

            var calleeDefinitions = node.DataFlowInfo.ResolveOutputAliases(calleeSymbol);
            var calleeTypes       = calleeDefinitions.SelectMany(def => def.CandidateTypes);

            if (!calleeTypes.Any())
            {
                return(false);
            }

            foreach (var calleeType in calleeTypes)
            {
                MethodDeclarationSyntax method = null;
                if (MethodSummaryResolver.TryGetMethodDeclarationFromType(
                        out method, calleeType, virtualCall, node))
                {
                    overriders.Add(method);
                }
            }

            return(true);
        }
Example #6
0
        /// <summary>
        /// Analyzes the data-flow in the method call.
        /// </summary>
        /// <param name="call">ExpressionSyntax</param>
        /// <param name="node">IDataFlowNode</param>
        /// <param name="returnSymbols">Return symbols</param>
        /// <param name="returnTypes">Return types</param>
        private void AnalyzeMethodCall(ExpressionSyntax call, IDataFlowNode node,
                                       out ISet <ISymbol> returnSymbols, out ISet <ITypeSymbol> returnTypes)
        {
            returnSymbols = new HashSet <ISymbol>();
            returnTypes   = new HashSet <ITypeSymbol>();

            var callSymbol = this.SemanticModel.GetSymbolInfo(call).Symbol;

            if (callSymbol == null)
            {
                return;
            }

            var invocation  = call as InvocationExpressionSyntax;
            var objCreation = call as ObjectCreationExpressionSyntax;

            ISet <MethodSummary> candidateCalleeSummaries;

            if (invocation != null)
            {
                candidateCalleeSummaries = MethodSummaryResolver.ResolveMethodSummaries(invocation, node);
            }
            else
            {
                candidateCalleeSummaries = MethodSummaryResolver.ResolveMethodSummaries(objCreation, node);
            }

            ArgumentListSyntax argumentList;

            if (invocation != null)
            {
                argumentList = invocation.ArgumentList;
            }
            else
            {
                argumentList = objCreation.ArgumentList;
            }

            this.ResolveGivesUpOwnershipInCall(callSymbol, argumentList, node);

            foreach (var candidateCalleeSummary in candidateCalleeSummaries)
            {
                this.MapCalleeSummaryToCallSymbol(candidateCalleeSummary, callSymbol, node);
                this.ResolveGivesUpOwnershipInCall(callSymbol, candidateCalleeSummary,
                                                   argumentList, node);
                this.ResolveSideEffectsInCall(call, candidateCalleeSummary, node);

                if (invocation != null)
                {
                    returnSymbols.UnionWith(candidateCalleeSummary.GetResolvedReturnSymbols(
                                                invocation, this.SemanticModel));
                }

                returnTypes.UnionWith(candidateCalleeSummary.SideEffectsInfo.ReturnTypes);
            }

            if (objCreation != null)
            {
                returnTypes.Add(this.SemanticModel.GetTypeInfo(call).Type);
            }

            if (invocation != null)
            {
                this.ResolveSideEffectsInExpression(invocation.Expression, node);
            }
        }