@@ -51,15 +51,14 @@ class JCodeanalyzer:
51
51
"""
52
52
53
53
def __init__ (
54
- self ,
55
- project_dir : Union [str , Path ],
56
- source_code : str | None ,
57
- analysis_backend_path : Union [str , Path , None ],
58
- analysis_json_path : Union [str , Path , None ],
59
- analysis_level : str ,
60
- use_graalvm_binary : bool ,
61
- eager_analysis : bool ,
62
- target_files : List [str ] | None
54
+ self ,
55
+ project_dir : Union [str , Path ],
56
+ source_code : str | None ,
57
+ analysis_backend_path : Union [str , Path , None ],
58
+ analysis_json_path : Union [str , Path , None ],
59
+ analysis_level : str ,
60
+ use_graalvm_binary : bool ,
61
+ eager_analysis : bool ,
63
62
) -> None :
64
63
self .project_dir = project_dir
65
64
self .source_code = source_code
@@ -68,7 +67,6 @@ def __init__(
68
67
self .use_graalvm_binary = use_graalvm_binary
69
68
self .eager_analysis = eager_analysis
70
69
self .analysis_level = analysis_level
71
- self .target_files = target_files
72
70
self .application = self ._init_codeanalyzer (
73
71
analysis_level = 1 if analysis_level == AnalysisLevel .symbol_table else 2 )
74
72
# Attributes related the Java code analysis...
@@ -173,7 +171,7 @@ def _get_codeanalyzer_exec(self) -> List[str]:
173
171
resources .files ("cldk.analysis.java.codeanalyzer.bin" ) / "codeanalyzer" ) as codeanalyzer_bin_path :
174
172
codeanalyzer_exec = shlex .split (codeanalyzer_bin_path .__str__ ())
175
173
else :
176
-
174
+
177
175
if self .analysis_backend_path :
178
176
analysis_backend_path = Path (self .analysis_backend_path )
179
177
logger .info (f"Using codeanalyzer.jar from { analysis_backend_path } " )
@@ -200,19 +198,11 @@ def _init_codeanalyzer(self, analysis_level=1) -> JApplication:
200
198
"""
201
199
202
200
codeanalyzer_exec = self ._get_codeanalyzer_exec ()
203
- codeanalyzer_args = ''
201
+
204
202
if self .analysis_json_path is None :
205
203
logger .info ("Reading analysis from the pipe." )
206
- # If target file is provided, the input is merged into a single string and passed to codeanalyzer
207
- if self .target_files :
208
- target_file_options = ' -t ' .join ([s .strip () for s in self .target_files ])
209
- codeanalyzer_args = codeanalyzer_exec + shlex .split (
210
- f"-i { Path (self .project_dir )} --analysis-level={ analysis_level } -t { target_file_options } "
211
- )
212
- else :
213
- codeanalyzer_args = codeanalyzer_exec + shlex .split (
214
- f"-i { Path (self .project_dir )} --analysis-level={ analysis_level } "
215
- )
204
+ codeanalyzer_args = codeanalyzer_exec + shlex .split (
205
+ f"-i { Path (self .project_dir )} --analysis-level={ analysis_level } " )
216
206
try :
217
207
logger .info (f"Running codeanalyzer: { ' ' .join (codeanalyzer_args )} " )
218
208
console_out : CompletedProcess [str ] = subprocess .run (
@@ -226,29 +216,15 @@ def _init_codeanalyzer(self, analysis_level=1) -> JApplication:
226
216
raise CodeanalyzerExecutionException (str (e )) from e
227
217
228
218
else :
229
- # Check if the code analyzer needs to be run
230
- is_run_code_analyzer = False
231
219
analysis_json_path_file = Path (self .analysis_json_path ).joinpath ("analysis.json" )
232
- # If target file is provided, the input is merged into a single string and passed to codeanalyzer
233
- if self .target_files :
234
- target_file_options = ' -t ' .join ([s .strip () for s in self .target_files ])
220
+ if not analysis_json_path_file .exists () or self .eager_analysis :
221
+ # If the analysis file does not exist, we'll run the analysis. Alternately, if the eager_analysis
222
+ # flag is set, we'll run the analysis every time the object is created. This will happen regradless
223
+ # of the existence of the analysis file.
224
+ # Create the executable command for codeanalyzer.
235
225
codeanalyzer_args = codeanalyzer_exec + shlex .split (
236
- f"-i { Path (self .project_dir )} --analysis-level={ analysis_level } "
237
- f" -o { self .analysis_json_path } -t { target_file_options } "
238
- )
239
- is_run_code_analyzer = True
240
- else :
241
- if not analysis_json_path_file .exists () or self .eager_analysis :
242
- # If the analysis file does not exist, we'll run the analysis. Alternately, if the eager_analysis
243
- # flag is set, we'll run the analysis every time the object is created. This will happen regradless
244
- # of the existence of the analysis file.
245
- # Create the executable command for codeanalyzer.
246
- codeanalyzer_args = codeanalyzer_exec + shlex .split (
247
- f"-i { Path (self .project_dir )} --analysis-level={ analysis_level } -o { self .analysis_json_path } "
248
- )
249
- is_run_code_analyzer = True
250
-
251
- if is_run_code_analyzer :
226
+ f"-i { Path (self .project_dir )} --analysis-level={ analysis_level } -o { self .analysis_json_path } " )
227
+
252
228
try :
253
229
logger .info (f"Running codeanalyzer subprocess with args { codeanalyzer_args } " )
254
230
subprocess .run (
@@ -262,6 +238,7 @@ def _init_codeanalyzer(self, analysis_level=1) -> JApplication:
262
238
263
239
except Exception as e :
264
240
raise CodeanalyzerExecutionException (str (e )) from e
241
+
265
242
with open (analysis_json_path_file ) as f :
266
243
data = json .load (f )
267
244
return JApplication (** data )
@@ -275,6 +252,7 @@ def _codeanalyzer_single_file(self):
275
252
JApplication
276
253
The application view of the Java code with the analysis results.
277
254
"""
255
+ # self.source_code: str = re.sub(r"[\r\n\t\f\v]+", lambda x: " " if x.group() in "\t\f\v" else " ", self.source_code)
278
256
codeanalyzer_exec = self ._get_codeanalyzer_exec ()
279
257
codeanalyzer_args = ["--source-analysis" , self .source_code ]
280
258
codeanalyzer_cmd = codeanalyzer_exec + codeanalyzer_args
@@ -430,8 +408,9 @@ def get_all_callers(self, target_class_name: str, target_method_signature: str,
430
408
caller_detail_dict = {}
431
409
call_graph = None
432
410
if using_symbol_table :
433
- call_graph = self .__raw_call_graph_using_symbol_table_target_method (target_class_name = target_class_name ,
434
- target_method_signature = target_method_signature )
411
+ call_graph = self .__call_graph_using_symbol_table (qualified_class_name = target_class_name ,
412
+ method_signature = target_method_signature ,
413
+ is_target_method = True )
435
414
else :
436
415
call_graph = self .call_graph
437
416
if (target_method_signature , target_class_name ) not in call_graph .nodes ():
@@ -768,7 +747,7 @@ def get_class_call_graph_using_symbol_table(self, qualified_class_name: str,
768
747
769
748
def __call_graph_using_symbol_table (self ,
770
749
qualified_class_name : str ,
771
- method_signature : str , is_target_method : bool = False )-> DiGraph :
750
+ method_signature : str , is_target_method : bool = False ) -> DiGraph :
772
751
"""
773
752
Generate call graph using symbol table
774
753
Args:
@@ -782,10 +761,11 @@ def __call_graph_using_symbol_table(self,
782
761
cg = nx .DiGraph ()
783
762
sdg = None
784
763
if is_target_method :
785
- sdg = None
764
+ sdg = self .__raw_call_graph_using_symbol_table_target_method (target_class_name = qualified_class_name ,
765
+ target_method_signature = method_signature )
786
766
else :
787
767
sdg = self .__raw_call_graph_using_symbol_table (qualified_class_name = qualified_class_name ,
788
- method_signature = method_signature )
768
+ method_signature = method_signature )
789
769
tsu = JavaSitter ()
790
770
edge_list = [
791
771
(
@@ -812,8 +792,8 @@ def __call_graph_using_symbol_table(self,
812
792
return cg
813
793
814
794
def __raw_call_graph_using_symbol_table_target_method (self ,
815
- target_class_name : str ,
816
- target_method_signature : str ,
795
+ target_class_name : str ,
796
+ target_method_signature : str ,
817
797
cg = None ) -> list [JGraphEdgesST ]:
818
798
"""
819
799
Generates call graph using symbol table information given the target method and target class
@@ -832,7 +812,7 @@ def __raw_call_graph_using_symbol_table_target_method(self,
832
812
for class_name in self .get_all_classes ():
833
813
for method in self .get_all_methods_in_class (qualified_class_name = class_name ):
834
814
method_details = self .get_method (qualified_class_name = class_name ,
835
- method_signature = method )
815
+ method_signature = method )
836
816
for call_site in method_details .call_sites :
837
817
source_method_details = None
838
818
source_class = ''
@@ -856,9 +836,9 @@ def __raw_call_graph_using_symbol_table_target_method(self,
856
836
if call_site .receiver_type != "" :
857
837
# call to any class
858
838
if self .get_class (qualified_class_name = call_site .receiver_type ):
859
- if callee_signature == target_method_signature and call_site .receiver_type == target_class_name :
839
+ if callee_signature == target_method_signature and call_site .receiver_type == target_class_name :
860
840
source_method_details = self .get_method (method_signature = method ,
861
- qualified_class_name = class_name )
841
+ qualified_class_name = class_name )
862
842
source_class = class_name
863
843
else :
864
844
# check if any method exists with the signature in the class even if the receiver type is blank
0 commit comments