/// <summary> /// Get topologically sorted methods in call graph /// </summary> /// <param name="methods"></param> /// <param name="cgm"></param> /// <returns>Bottom-up ordering of the methods, which is later used to propagate method description.</returns> public static List<MethodDefinition> GetBottomUpSortedMethodsFromCallGraph(IEnumerable<MethodDefinition> methods, CGManager cgm) { if (Constants.ShowLog) { Console.WriteLine("***Getting ordered (bottom-up) methods in call graph..."); } HashSet<Tuple<MethodDefinition, MethodDefinition>> callerToCalleeEdges = GetCallerToCalleeEdges(methods, cgm); TopoSortCallGraph tscg = new TopoSortCallGraph(); foreach (MethodDefinition m in methods) { tscg.addMethod(m); } foreach (Tuple<MethodDefinition, MethodDefinition> edge in callerToCalleeEdges) { tscg.addCallerToCalleeEdge(edge.Item1, edge.Item2); } List<MethodDefinition> sortedMethodsBottomToTop = tscg.topoSort(); return sortedMethodsBottomToTop; }
/// <summary> /// Get all edges in call graph /// </summary> /// <param name="methods"></param> /// <param name="cgm"></param> /// <returns></returns> private static HashSet<Tuple<MethodDefinition, MethodDefinition>> GetCallerToCalleeEdges(IEnumerable<MethodDefinition> methods, CGManager cgm) { HashSet<Tuple<MethodDefinition, MethodDefinition>> callerToCalleeEdges = new HashSet<Tuple<MethodDefinition, MethodDefinition>>(); foreach (MethodDefinition callee in methods) { List<List<MethodDefinition>> paths = cgm.FindCallerList(callee); foreach (List<MethodDefinition> path in paths) // path[0]--> this callee, path[1]--> this callee's immediate caller, path[2]--> that caller's immediate caller ... { if (path.Count() == 1) // along this path, no caller { continue; } else { MethodDefinition immediate_caller = path[1]; callerToCalleeEdges.Add(Tuple.Create(immediate_caller, callee)); } } } return callerToCalleeEdges; }
/// <summary> /// Step 2 of DBScribeHibernate. /// Build call graph for the target project. /// Also, topologically sorted the methods in the call graph, for later bottom-up method description propagation. /// </summary> public void Step2_1_GenerateCallGraph() { // Get methods from SrcML.net //Console.Out.WriteLine("Invoke call graph generator "); string dataDir = @"TESTNAIVE_1.0"; string localProj = TargetProjPath + "\\" + ProjName; using (var project = new DataProject<CompleteWorkingSet>(dataDir, localProj, Constants.SrcmlLoc)) { string unknownLogPath = Path.Combine(project.StoragePath, "unknown.log"); DateTime start = DateTime.Now, end; using (var unknownLog = new StreamWriter(unknownLogPath)) { project.UnknownLog = unknownLog; project.UpdateAsync().Wait(); } end = DateTime.Now; project.WorkingSet.TryObtainReadLock(5000, out globalNamespace); try { // return IEnumerable<MethodDefinition> type methods = globalNamespace.GetDescendants<MethodDefinition>(); num_of_methods = globalNamespace.GetDescendants<MethodDefinition>().Count(); Console.WriteLine("# of methods = " + num_of_methods); cgm = new CGManager(); cgm.BuildCallGraph(methods); bottomUpSortedMethods = InvokeCGManager.GetBottomUpSortedMethodsFromCallGraph(methods, cgm); } finally { project.WorkingSet.ReleaseReadLock(); } } }