8000 Merge pull request #132 from codellm-devkit/source-code-option-fix · codellm-devkit/python-sdk@4a89fe1 · GitHub
[go: up one dir, main page]

Skip to content

Commit 4a89fe1

Browse files
authored
Merge pull request #132 from codellm-devkit/source-code-option-fix
Fixed handling of source code option in Java codeanalyzer
2 parents e4ea5f5 + 7074822 commit 4a89fe1

File tree

8 files changed

+351
-22
lines changed

8 files changed

+351
-22
lines changed

cldk/analysis/java/codeanalyzer/codeanalyzer.py

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,10 @@ def __init__(
6767
self.eager_analysis = eager_analysis
6868
self.analysis_level = analysis_level
6969
self.target_files = target_files
70-
self.application = self._init_codeanalyzer(analysis_level=1 if analysis_level == AnalysisLevel.symbol_table else 2)
70+
if self.source_code is None:
71+
self.application = self._init_codeanalyzer(analysis_level=1 if analysis_level == AnalysisLevel.symbol_table else 2)
72+
else:
73+
self.application = self._codeanalyzer_single_file()
7174
# Attributes related the Java code analysis...
7275
if analysis_level == AnalysisLevel.call_graph:
7376
self.call_graph: nx.DiGraph = self._generate_call_graph(using_symbol_table=False)

cldk/analysis/python/python_analysis.py

Lines changed: 0 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -30,17 +30,11 @@ class PythonAnalysis:
3030

3131
def __init__(
3232
self,
33-
eager_analysis: bool,
3433
project_dir: str | Path | None,
3534
source_code: str | None,
36-
analysis_backend_path: str | None,
37-
analysis_json_path: str | Path | None,
3835
) -> None:
3936
self.project_dir = project_dir
4037
self.source_code = source_code
41-
self.analysis_json_path = analysis_json_path
42-
self.analysis_backend_path = analysis_backend_path
43-
self.eager_analysis = eager_analysis
4438
self.analysis_backend: TreesitterPython = TreesitterPython()
4539

4640
def get_methods(self) -> List[PyMethod]:

cldk/core.py

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@
2727
from cldk.analysis.c import CAnalysis
2828
from cldk.analysis.java import JavaAnalysis
2929
from cldk.analysis.commons.treesitter import TreesitterJava
30+
from cldk.analysis.python.python_analysis import PythonAnalysis
3031
from cldk.utils.exceptions import CldkInitializationException
3132
from cldk.utils.sanitization.java import TreesitterSanitizer
3233

@@ -118,6 +119,11 @@ def analysis(
118119
target_files=target_files,
119120
eager_analysis=eager,
120121
)
122+
elif self.language == "python":
123+
return PythonAnalysis(
124+
project_dir=project_path,
125+
source_code=source_code,
126+
)
121127
elif self.language == "c":
122128
return CAnalysis(project_dir=project_path)
123129
else:

cldk/models/java/models.py

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -363,11 +363,15 @@ class JCompilationUnit(BaseModel):
363363
"""Represents a compilation unit in Java.
364364
365365
Attributes:
366+
file_path (str): The path to the source file.
367+
package_name (str): The name of the package for the comppilation unit.
366368
comments (List[JComment]): A list of comments in the compilation unit.
367369
imports (List[str]): A list of import statements in the compilation unit.
368370
type_declarations (Dict[str, JType]): A dictionary mapping type names to their corresponding JType representations.
369371
"""
370372

373+
file_path: str
374+
package_name: str
371375
comments: List[JComment]
372376
imports: List[str]
373377
type_declarations: Dict[str, JType]

tests/analysis/java/test_java_analysis.py

Lines changed: 18 additions & 0 deletions
Original file line num F438 berDiff line numberDiff line change
@@ -50,6 +50,24 @@ def test_get_symbol_table_is_not_null(test_fixture, analysis_json):
5050
)
5151
assert analysis.get_symbol_table() is not None
5252

53+
def test_get_symbol_table_source_code(java_code):
54+
"""Should return a symbol table for source analysis with expected class/method count"""
55+
56+
# Initialize the CLDK object with the project directory, language, and analysis_backend
57+
cldk = CLDK(language="java")
58+
analysis = cldk.analysis(
59+
source_code=java_code,
60+
analysis_backend_path=None,
61+
eager=True,
62+
analysis_level=AnalysisLevel.symbol_table,
63+
)
64+
65+
# assert on expected class name and method count in the symbol table
66+
expected_class_name = "com.acme.modres.WeatherServlet"
67+
assert analysis.get_symbol_table() is not None
68+
assert len(analysis.get_symbol_table().keys()) == 1
69+
assert expected_class_name in analysis.get_methods().keys()
70+
assert len(analysis.get_methods().get(expected_class_name).keys()) == 9
5371

5472
def test_get_imports(test_fixture, analysis_json):
5573
"""Should return NotImplemented for get_imports()"""

tests/analysis/python/test_python_analysis.py

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -67,7 +67,7 @@ def divide(self, a, b):
6767

6868
def test_get_methods():
6969
"""Should return all of the methods"""
70-
python_analysis = PythonAnalysis(eager_analysis=True, project_dir=None, source_code=PYTHON_CODE, analysis_backend_path=None, analysis_json_path=None)
70+
python_analysis = PythonAnalysis(project_dir=None, source_code=PYTHON_CODE)
7171

7272
all_methods = python_analysis.get_methods()
7373
assert all_methods is not None
@@ -79,7 +79,7 @@ def test_get_methods():
7979

8080
def test_get_functions():
8181
"""Should return all of the functions"""
82-
python_analysis = PythonAnalysis(eager_analysis=True, project_dir=None, source_code=PYTHON_CODE, analysis_backend_path=None, analysis_json_path=None)
82+
python_analysis = PythonAnalysis(project_dir=None, source_code=PYTHON_CODE)
8383

8484
all_functions = python_analysis.get_functions()
8585
assert all_functions is not None
@@ -91,7 +91,7 @@ def test_get_functions():
9191

9292
def test_get_all_modules(tmp_path):
9393
"""Should return all of the modules"""
94-
python_analysis = PythonAnalysis(eager_analysis=True, project_dir=tmp_path, source_code=None, analysis_backend_path=None, analysis_json_path=None)
94+
python_analysis = PythonAnalysis(project_dir=tmp_path, source_code=None)
9595

9696
# set up some temporary modules
9797
temp_file_path = os.path.join(tmp_path, "hello.py")
@@ -111,7 +111,7 @@ def test_get_all_modules(tmp_path):
111111

112112
def test_get_method_details():
113113
"""Should return the method details"""
114-
python_analysis = PythonAnalysis(eager_analysis=True, project_dir=None, source_code=PYTHON_CODE, analysis_backend_path=None, analysis_json_path=None)
114+
python_analysis = PythonAnalysis(project_dir=None, source_code=PYTHON_CODE)
115115

116116
method_details = python_analysis.get_method_details("add(self, a, b)")
117117
assert method_details is not None
@@ -121,7 +121,7 @@ def test_get_method_details():
121121

122122
def test_is_parsable():
123123
"""Should be able to parse the code"""
124-
python_analysis = PythonAnalysis(eager_analysis=True, project_dir=None, source_code=PYTHON_CODE, analysis_backend_path=None, analysis_json_path=None)
124+
python_analysis = PythonAnalysis(project_dir=None, source_code=PYTHON_CODE)
125125

126126
code = "def is_parsable(self, code: str) -> bool: return True"
127127
is_parsable = python_analysis.is_parsable(code)
@@ -134,7 +134,7 @@ def test_is_parsable():
134134

135135
def test_get_raw_ast():
136136
"""Should return the raw AST"""
137-
python_analysis = PythonAnalysis(eager_analysis=True, project_dir=None, source_code=PYTHON_CODE, analysis_backend_path=None, analysis_json_path=None)
137+
python_analysis = PythonAnalysis(project_dir=None, source_code=PYTHON_CODE)
138138

139139
raw_ast = python_analysis.get_raw_ast(PYTHON_CODE)
140140
assert raw_ast is not None
@@ -144,7 +144,7 @@ def test_get_raw_ast():
144144

145145
def test_get_imports():
146146
"""Should return all of the imports"""
147-
python_analysis = PythonAnalysis(eager_analysis=True, project_dir=None, source_code=PYTHON_CODE, analysis_backend_path=None, analysis_json_path=None)
147+
python_analysis = PythonAnalysis(project_dir=None, source_code=PYTHON_CODE)
148148

149149
all_imports = python_analysis.get_imports()
150150
assert all_imports is not None
@@ -156,7 +156,7 @@ def test_get_imports():
156156

157157
def test_get_variables():
158158
"""Should return all of the variables"""
159-
python_analysis = PythonAnalysis(eager_analysis=True, project_dir=None, source_code=PYTHON_CODE, analysis_backend_path=None, analysis_json_path=None)
159+
python_analysis = PythonAnalysis(project_dir=None, source_code=PYTHON_CODE)
160160

161161
with pytest.raises(NotImplementedError) as except_info:
162162
python_analysis.get_variables()
@@ -165,7 +165,7 @@ def test_get_variables():
165165

166166
def test_get_classes():
167167
"""Should return all of the classes"""
168-
python_analysis = PythonAnalysis(eager_analysis=True, project_dir=None, source_code=PYTHON_CODE, analysis_backend_path=None, analysis_json_path=None)
168+
python_analysis = PythonAnalysis(project_dir=None, source_code=PYTHON_CODE)
169169

170170
all_classes = python_analysis.get_classes()
171171
assert all_classes is not None
@@ -178,7 +178,7 @@ def test_get_classes():
178178

179179
def test_get_classes_by_criteria():
180180
"""Should return all of the classes that match the criteria"""
181-
python_analysis = PythonAnalysis(eager_analysis=True, project_dir=None, source_code=PYTHON_CODE, analysis_backend_path=None, analysis_json_path=None)
181+
python_analysis = PythonAnalysis(project_dir=None, source_code=PYTHON_CODE)
182182

183183
with pytest.raises(NotImplementedError) as except_info:
184184
python_analysis.get_classes_by_criteria()
@@ -187,7 +187,7 @@ def test_get_classes_by_criteria():
187187

188188
def test_get_sub_classes():
189189
"""Should return all of the subclasses"""
190-
python_analysis = PythonAnalysis(eager_analysis=True, project_dir=None, source_code=PYTHON_CODE, analysis_backend_path=None, analysis_json_path=None)
190+
python_analysis = PythonAnalysis(project_dir=None, source_code=PYTHON_CODE)
191191

192192
with pytest.raises(NotImplementedError) as except_info:
193193
python_analysis.get_sub_classes()
@@ -196,7 +196,7 @@ def test_get_sub_classe 10000 s():
196196

197197
def test_get_nested_classes():
198198
"""Should return all of the nested classes"""
199-
python_analysis = PythonAnalysis(eager_analysis=True, project_dir=None, source_code=PYTHON_CODE, analysis_backend_path=None, analysis_json_path=None)
199+
python_analysis = PythonAnalysis(project_dir=None, source_code=PYTHON_CODE)
200200

201201
with pytest.raises(NotImplementedError) as except_info:
202202
python_analysis.get_nested_classes()
@@ -205,7 +205,7 @@ def test_get_nested_classes():
205205

206206
def test_get_constructors():
207207
"""Should return all of the constructors"""
208-
python_analysis = PythonAnalysis(eager_analysis=True, project_dir=None, source_code=PYTHON_CODE, analysis_backend_path=None, analysis_json_path=None)
208+
python_analysis = PythonAnalysis(project_dir=None, source_code=PYTHON_CODE)
209209

210210
with pytest.raises(NotImplementedError) as except_info:
211211
python_analysis.get_constructors()
@@ -214,7 +214,7 @@ def test_get_constructors():
214214

215215
def test_get_methods_in_class():
216216
"""Should return all of the methods in the class"""
217-
python_analysis = PythonAnalysis(eager_analysis=True, project_dir=None, source_code=PYTHON_CODE, analysis_backend_path=None, analysis_json_path=None)
217+
python_analysis = PythonAnalysis(project_dir=None, source_code=PYTHON_CODE)
218218

219219
with pytest.raises(NotImplementedError) as except_info:
220220
python_analysis.get_methods_in_class()
@@ -223,7 +223,7 @@ def test_get_methods_in_class():
223223

224224
def test_get_fields():
225225
"""Should return all of the fields in the class"""
226-
python_analysis = PythonAnalysis(eager_analysis=True, project_dir=None, source_code=PYTHON_CODE, analysis_backend_path=None, analysis_json_path=None)
226+
python_analysis = PythonAnalysis(project_dir=None, source_code=PYTHON_CODE)
227227

228228
with pytest.raises(NotImplementedError) as except_info:
229229
python_analysis.get_fields()

tests/conftest.py

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -190,3 +190,24 @@ def test_fixture_binutils():
190190
for directory in Path(test_data_path).iterdir():
191191
if directory.exists() and directory.is_dir():
192192
shutil.rmtree(directory)
193+
194+
@pytest.fixture(scope="session", autouse=True)
195+
def java_code() -> str:
196+
"""
197+
Returns sample Java source code for analysis.
198+
199+
Yields:
200+
str : Java code to be analyzed.
201+
"""
202+
# ----------------------------------[ SETUP ]----------------------------------
203+
# Path to your pyproject.toml
204+
pyproject_path = Path(__file__).parent.parent / "pyproject.toml"
205+
206+
# Load the configuration
207+
config = toml.load(pyproject_path)
208+
209+
# Access the test data path
210+
test_data_path = config["tool"]["cldk"]["testing"]["sample-application"]
211+
javafile = Path(test_data_path).absolute() / ("WeatherServlet.java")
212+
with open(javafile) as f:
213+
return f.read()

0 commit comments

Comments
 (0)
0