Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
58 changes: 30 additions & 28 deletions cldk/analysis/java/codeanalyzer/codeanalyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -729,20 +729,21 @@ def __raw_call_graph_using_symbol_table_target_method(self, target_class_name: s
source_class = ""
callee_signature = ""
if call_site.callee_signature != "":
pattern = r"\b(?:[a-zA-Z_][\w\.]*\.)+([a-zA-Z_][\w]*)\b|<[^>]*>"

# Find the part within the parentheses
start = call_site.callee_signature.find("(") + 1
end = call_site.callee_signature.rfind(")")

# Extract the elements inside the parentheses
elements = call_site.callee_signature[start:end].split(",")

# Apply the regex to each element
simplified_elements = [re.sub(pattern, r"\1", element.strip()) for element in elements]

# Reconstruct the string with simplified elements
callee_signature = f"{call_site.callee_signature[:start]}{', '.join(simplified_elements)}{call_site.callee_signature[end:]}"
# pattern = r"\b(?:[a-zA-Z_][\w\.]*\.)+([a-zA-Z_][\w]*)\b|<[^>]*>"
#
# # Find the part within the parentheses
# start = call_site.callee_signature.find("(") + 1
# end = call_site.callee_signature.rfind(")")
#
# # Extract the elements inside the parentheses
# elements = call_site.callee_signature[start:end].split(",")
#
# # Apply the regex to each element
# simplified_elements = [re.sub(pattern, r"\1", element.strip()) for element in elements]
#
# # Reconstruct the string with simplified elements
# callee_signature = f"{call_site.callee_signature[:start]}{', '.join(simplified_elements)}{call_site.callee_signature[end:]}"
callee_signature = call_site.callee_signature

if call_site.receiver_type != "":
# call to any class
Expand Down Expand Up @@ -796,20 +797,21 @@ def __raw_call_graph_using_symbol_table(self, qualified_class_name: str, method_
# Currently the callee signature returns the fully qualified type, whereas
# the key for JCallable does not. The below logic converts the fully qualified signature
# to the desider format. Only limitation is the nested generic type.
pattern = r"\b(?:[a-zA-Z_][\w\.]*\.)+([a-zA-Z_][\w]*)\b|<[^>]*>"

# Find the part within the parentheses
start = call_site.callee_signature.find("(") + 1
end = call_site.callee_signature.rfind(")")

# Extract the elements inside the parentheses
elements = call_site.callee_signature[start:end].split(",")

# Apply the regex to each element
simplified_elements = [re.sub(pattern, r"\1", element.strip()) for element in elements]

# Reconstruct the string with simplified elements
callee_signature = f"{call_site.callee_signature[:start]}{', '.join(simplified_elements)}{call_site.callee_signature[end:]}"
# pattern = r"\b(?:[a-zA-Z_][\w\.]*\.)+([a-zA-Z_][\w]*)\b|<[^>]*>"
#
# # Find the part within the parentheses
# start = call_site.callee_signature.find("(") + 1
# end = call_site.callee_signature.rfind(")")
#
# # Extract the elements inside the parentheses
# elements = call_site.callee_signature[start:end].split(",")
#
# # Apply the regex to each element
# simplified_elements = [re.sub(pattern, r"\1", element.strip()) for element in elements]
#
# # Reconstruct the string with simplified elements
# callee_signature = f"{call_site.callee_signature[:start]}{', '.join(simplified_elements)}{call_site.callee_signature[end:]}"
callee_signature = call_site.callee_signature

if call_site.receiver_type != "":
# call to any class
Expand Down
Binary file not shown.
2 changes: 2 additions & 0 deletions cldk/models/java/models.py
Original file line number Diff line number Diff line change
Expand Up @@ -158,6 +158,7 @@ class JCallSite(BaseModel):
receiver_expr (str): Expression for the receiver of the method call.
receiver_type (str): Name of type declaring the called method.
argument_types (List[str]): Types of actual parameters for the call.
argument_expr (List[str]): Actual parameter expressions for the call.
return_type (str): Return type of the method call (resolved type of the method call expression; empty string if expression is unresolved).
callee_signature (str): Signature of the callee.
is_static_call (bool): Flag indicating whether the call is a static call.
Expand All @@ -179,6 +180,7 @@ class JCallSite(BaseModel):
receiver_expr: str = ""
receiver_type: str
argument_types: List[str]
argument_expr: List[str]
return_type: str = ""
callee_signature: str = ""
is_static_call: bool | None = None
Expand Down
14 changes: 7 additions & 7 deletions tests/analysis/java/test_java_analysis.py
Original file line number Diff line number Diff line change
Expand Up @@ -370,7 +370,7 @@ def test_get_callers(test_fixture, analysis_json):
)

# Test using call graph
callers = java_analysis.get_callers("com.ibm.websphere.samples.daytrader.util.Log", "log(String)", False)
callers = java_analysis.get_callers("com.ibm.websphere.samples.daytrader.util.Log", "log(java.lang.String)", False)
assert callers is not None
assert isinstance(callers, Dict)
assert "caller_details" in callers
Expand All @@ -383,7 +383,7 @@ def test_get_callers(test_fixture, analysis_json):
# Uncomment this next test section when fixed

# Test using symbol table
callers = java_analysis.get_callers("com.ibm.websphere.samples.daytrader.util.Log", "log(String)", True)
callers = java_analysis.get_callers("com.ibm.websphere.samples.daytrader.util.Log", "log(java.lang.String)", True)
assert callers is not None
assert isinstance(callers, Dict)
assert "caller_details" in callers
Expand Down Expand Up @@ -415,14 +415,14 @@ def test_get_callees(test_fixture, analysis_json):
)

# Test with a class that has no callees
callees = java_analysis.get_callees("com.ibm.websphere.samples.daytrader.util.Log", "log(String)", False)
callees = java_analysis.get_callees("com.ibm.websphere.samples.daytrader.util.Log", "log(java.lang.String)", False)
assert callees is not None
assert isinstance(callees, Dict)
assert "callee_details" in callees
assert len(callees["callee_details"]) == 0

# Test with a class that has callees
callees = java_analysis.get_callees("com.ibm.websphere.samples.daytrader.web.websocket.ActionMessage", "doDecoding(String)", False)
callees = java_analysis.get_callees("com.ibm.websphere.samples.daytrader.web.websocket.ActionMessage", "doDecoding(java.lang.String)", False)
assert callees is not None
assert isinstance(callees, Dict)
assert "callee_details" in callees
Expand All @@ -435,7 +435,7 @@ def test_get_callees(test_fixture, analysis_json):
# Uncomment this next test section when fixed

# # Test using symbol table
callees = java_analysis.get_callees("com.ibm.websphere.samples.daytrader.web.websocket.ActionMessage", "doDecoding(String)", True)
callees = java_analysis.get_callees("com.ibm.websphere.samples.daytrader.web.websocket.ActionMessage", "doDecoding(java.lang.String)", True)
assert callees is not None
assert isinstance(callees, Dict)
assert "callee_details" in callees
Expand Down Expand Up @@ -572,7 +572,7 @@ def test_get_method(test_fixture, analysis_json):
eager_analysis=False,
)

the_method = java_analysis.get_method("com.ibm.websphere.samples.daytrader.util.Log", "trace(String)")
the_method = java_analysis.get_method("com.ibm.websphere.samples.daytrader.util.Log", "trace(java.lang.String)")
assert the_method is not None
assert isinstance(the_method, JCallable)
assert the_method.declaration == "public static void trace(String message)"
Expand All @@ -594,7 +594,7 @@ def test_get_method_parameters(test_fixture, analysis_json):
eager_analysis=False,
)

the_method_parameters = java_analysis.get_method_parameters("com.ibm.websphere.samples.daytrader.util.Log", "trace(String)")
the_method_parameters = java_analysis.get_method_parameters("com.ibm.websphere.samples.daytrader.util.Log", "trace(java.lang.String)")
assert the_method_parameters is not None
assert isinstance(the_method_parameters, List)
assert len(the_method_parameters) == 1
Expand Down
12 changes: 6 additions & 6 deletions tests/analysis/java/test_jcodeanalyzer.py
Original file line number Diff line number Diff line change
Expand Up @@ -342,7 +342,7 @@ def test_get_all_callers(test_fixture, analysis_json):
)

# Call without using symbol table
all_callers = code_analyzer.get_all_callers("com.ibm.websphere.samples.daytrader.util.Log", "log(String)", False)
all_callers = code_analyzer.get_all_callers("com.ibm.websphere.samples.daytrader.util.Log", "log(java.lang.String)", False)
assert all_callers is not None
assert isinstance(all_callers, Dict)
assert len(all_callers) > 0
Expand All @@ -355,7 +355,7 @@ def test_get_all_callers(test_fixture, analysis_json):

# TODO: This currently doesn't work. Code has bad call as seen in this error message:
# TypeError: TreesitterJava.get_calling_lines() missing 1 required positional argument: 'is_target_method_a_constructor'
all_callers = code_analyzer.get_all_callers("com.ibm.websphere.samples.daytrader.util.Log", "log(String)", True)
all_callers = code_analyzer.get_all_callers("com.ibm.websphere.samples.daytrader.util.Log", "log(java.lang.String)", True)
assert all_callers is not None
assert isinstance(all_callers, Dict)
assert "caller_details" in all_callers
Expand All @@ -378,7 +378,7 @@ def test_get_all_callees(test_fixture, analysis_json):
)

# Call without using symbol table
all_callees = code_analyzer.get_all_callees("com.ibm.websphere.samples.daytrader.util.Log", "printCollection(String, Collection)", False)
all_callees = code_analyzer.get_all_callees("com.ibm.websphere.samples.daytrader.util.Log", "printCollection(java.lang.String, java.util.Collection)", False)
assert all_callees is not None
assert isinstance(all_callees, Dict)
assert "callee_details" in all_callees
Expand All @@ -388,7 +388,7 @@ def test_get_all_callees(test_fixture, analysis_json):

# TODO: Throws the following exception
# TypeError: TreesitterJava.get_calling_lines() missing 1 required positional argument: 'is_target_method_a_constructor'
all_callees = code_analyzer.get_all_callees("com.ibm.websphere.samples.daytrader.util.Log", "printCollection(String, Collection)", True)
all_callees = code_analyzer.get_all_callees("com.ibm.websphere.samples.daytrader.util.Log", "printCollection(java.lang.String, java.util.Collection)", True)
assert all_callees is not None
assert isinstance(all_callees, Dict)
assert "callee_details" in all_callees
Expand Down Expand Up @@ -458,7 +458,7 @@ def test_get_method(test_fixture, analysis_json):
target_files=None,
)

method = code_analyzer.get_method("com.ibm.websphere.samples.daytrader.impl.direct.TradeDirect", "publishQuotePriceChange(QuoteDataBean, BigDecimal, BigDecimal, double)")
method = code_analyzer.get_method("com.ibm.websphere.samples.daytrader.impl.direct.TradeDirect", "publishQuotePriceChange(com.ibm.websphere.samples.daytrader.entities.QuoteDataBean, java.math.BigDecimal, java.math.BigDecimal, double)")
assert method is not None
assert isinstance(method, JCallable)

Expand Down Expand Up @@ -730,7 +730,7 @@ def test_get_class_call_graph(test_fixture, analysis_json):

# Call with method signature
class_call_graph = code_analyzer.get_class_call_graph(
"com.ibm.websphere.samples.daytrader.impl.direct.TradeDirect", "createHolding(Connection, int, String, double, BigDecimal)"
"com.ibm.websphere.samples.daytrader.impl.direct.TradeDirect", "createHolding(java.sql.Connection, int, java.lang.String, double, java.math.BigDecimal)"
)
assert class_call_graph is not None
assert isinstance(class_call_graph, List)
Expand Down
Loading