@@ -65,9 +65,13 @@ def __init__(
6565 self .use_graalvm_binary = use_graalvm_binary
6666 self .eager_analysis = eager_analysis
6767 self .analysis_level = analysis_level
68+ self .application = self ._init_codeanalyzer (analysis_level = 1 if analysis_level == 'symbol_table' else 2 )
6869 # Attributes related the Java code analysis...
69- self .call_graph : DiGraph | None = None
70- self .application = None
70+ if analysis_level == 'symbol_table' :
71+ self .call_graph : DiGraph | None = None
72+ else :
73+ self .call_graph : DiGraph = self ._generate_call_graph (using_symbol_table = False )
74+
7175
7276 @staticmethod
7377 def _download_or_update_code_analyzer (filepath : Path ) -> str :
@@ -164,7 +168,7 @@ def _get_codeanalyzer_exec(self) -> List[str]:
164168 codeanalyzer_exec = shlex .split (codeanalyzer_bin_path .__str__ ())
165169 else :
166170 if self .analysis_backend_path :
167- analysis_backend_path = Path (analysis_backend_path )
171+ analysis_backend_path = Path (self . analysis_backend_path )
168172 logger .info (f"Using codeanalyzer.jar from { analysis_backend_path } " )
169173 codeanalyzer_exec = shlex .split (f"java -jar { analysis_backend_path / 'codeanalyzer.jar' } " )
170174 else :
@@ -715,43 +719,19 @@ def get_class_call_graph(self, qualified_class_name: str, method_name: str | Non
715719 """
716720 # If the method name is not provided, we'll get the call graph for the entire class.
717721
718- # TODO: Implement class call graph generation @rahlk
719-
720- _class : JType = self .get_class (qualified_class_name )
721-
722- edge_list = []
723- for method_signature , callable in _class .callable_declarations .items ():
724- for callsite in callable .callsites :
725- edge_list .append (((callable .signature , qualified_class_name ),))
726-
727- class_call_graph = nx .DiGraph ()
728-
729- edge_list = [
730- (
731- (jge .source .method .signature , jge .source .klass ),
732- (jge .target .method .signature , jge .target .klass ),
733- {
734- "type" : jge .type ,
735- "weight" : jge .weight ,
736- "calling_lines" : tsu .get_calling_lines (jge .source .method .code , jge .target .method .signature ),
737- },
738- )
739- for jge in sdg
740- if jge .type == "CONTROL_DEP" or jge .type == "CALL_DEP"
741- ]
742-
743- for jge in sdg :
744- class_call_graph .add_node (
745- (jge .source .method .signature , jge .source .klass ),
746- method_detail = jge .source ,
747- )
748- class_call_graph .add_node (
749- (jge .target .method .signature , jge .target .klass ),
750- method_detail = jge .target ,
751- )
752- class_call_graph .add_edges_from (edge_list )
753-
754- NotImplementedError ("Class call graph generation is not implemented yet." )
722+ if method_name is None :
723+ filter_criteria = {node for node in self .call_graph .nodes if node [1 ] == qualified_class_name }
724+ else :
725+ filter_criteria = {node for node in self .call_graph .nodes if
726+ tuple (node ) == (method_name , qualified_class_name )}
727+
728+ graph_edges : List [Tuple [JMethodDetail , JMethodDetail ]] = list ()
729+ for edge in self .call_graph .edges (nbunch = filter_criteria ):
730+ source : JMethodDetail = self .call_graph .nodes [edge [0 ]]["method_detail" ]
731+ target : JMethodDetail = self .call_graph .nodes [edge [1 ]]["method_detail" ]
732+ graph_edges .append ((source , target ))
733+
734+ return graph_edges
755735
756736 def get_all_entry_point_methods (self ) -> Dict [str , Dict [str , JCallable ]]:
757737 """
0 commit comments