private static IEnumerable <SuspectSet> FindCallersCallingAtLeastNSameMethods(CallerAndMembersUsed[] callersSuspect, HashSet <PairOfMethodCallers> pairsOfCallersAlreadyTreated, int N)
        {
            Debug.Assert(callersSuspect != null);
            Debug.Assert(callersSuspect.Length >= 2);
            Debug.Assert(pairsOfCallersAlreadyTreated != null);

            var suspectSetsWith2Callers = new List <SuspectSet>();


            MembersUsedIntersectionComputer <CallerAndMembersUsed> .Go(callersSuspect, N,
                                                                       // This lambda is called to know if a pair of CallerAndMembersUsed should be treated or not.
                                                                       (callerI, callerJ) => {
                var pair = new PairOfMethodCallers(callerI.MethodCaller, callerJ.MethodCaller);
                // Avoid treating a pair of method callers already reated!
                if (pairsOfCallersAlreadyTreated.Contains(pair))
                {
                    return(false);
                }
                pairsOfCallersAlreadyTreated.Add(pair);
                return(true);
            },

                                                                       // This lambda is called when a merge should occurs.
                                                                       (callerI, callerJ, methodCalledsIntersection, fieldsReadIntersection, fieldsAssignedIntersection) => {
                // Merge suspectSetI and suspectSetJ
                var suspectSet = new SuspectSet(new List <IMethod> {
                    callerI.MethodCaller, callerJ.MethodCaller
                }, methodCalledsIntersection, fieldsReadIntersection, fieldsAssignedIntersection);
                suspectSetsWith2Callers.Add(suspectSet);
                return(false); // <-- This provoques continue current loop
            });


            return(suspectSetsWith2Callers);
        }
Ejemplo n.º 2
0
        //
        // Inputed suspectSets that shares a common caller, all have 2 callers.
        //
        private static IEnumerable <SuspectSet> MergeSuspectSetsSharingACommonCaller(IList <SuspectSet> suspectSetsSharingACommonCaller, int N)
        {
            Debug.Assert(suspectSetsSharingACommonCaller != null);
            if (suspectSetsSharingACommonCaller.Count == 1)
            {
                return(suspectSetsSharingACommonCaller);
            }

            var suspectSetsMergedFinal = new List <SuspectSet>();

            // suspectSetsMergedCurrent  => i.e merged during the current iteration
            List <SuspectSet> suspectSetsMergedCurrent;

            // suspectSetsMergedPrevious => i.e merged during previous iteration
            SuspectSet[] suspectSetsMergedPrevious = suspectSetsSharingACommonCaller.ToArray();

            //
            // Iteratively merge suspectSets when possible, until no more suspectSets can be merged.
            //
            do
            {
                suspectSetsMergedCurrent = new List <SuspectSet>();

                // Optimization: use a hashset to have a constant time remove.
                var suspectSetsNotMergeableAnymore = suspectSetsMergedPrevious.ToHashSet();


                //
                // Try to merge suspectSets merged during the previous iteration.
                //
                MembersUsedIntersectionComputer <SuspectSet> .Go(suspectSetsMergedPrevious, N,

                                                                 // Always see if a pair of SuspectSet can be merged
                                                                 (callerI, callerJ) => true,

                                                                 // This lambda is called when a merge should occurs.
                                                                 (suspectSetI, suspectSetJ, methodCalledsIntersection, fieldsReadIntersection, fieldsAssignedIntersection) => {
                    // Merge suspectSetI and suspectSetJ
                    var callersUnion = suspectSetI.MethodsCaller.Union(suspectSetJ.MethodsCaller).ToArray();
                    suspectSetsMergedCurrent.Add(new SuspectSet(callersUnion, methodCalledsIntersection, fieldsReadIntersection, fieldsAssignedIntersection));
                    suspectSetsNotMergeableAnymore.Remove(suspectSetI);
                    suspectSetsNotMergeableAnymore.Remove(suspectSetJ);
                    return(true); // <-- This provoques break current loop
                });

                suspectSetsMergedPrevious = suspectSetsMergedCurrent.ToArray();
                suspectSetsMergedFinal.AddRange(suspectSetsNotMergeableAnymore);
            } while (suspectSetsMergedCurrent.Count > 0);
            return(suspectSetsMergedFinal);
        }