tree-sitter-analyzer 0.3.0__py3-none-any.whl → 0.4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of tree-sitter-analyzer might be problematic. Click here for more details.
- tree_sitter_analyzer/__init__.py +4 -3
- tree_sitter_analyzer/api.py +4 -2
- tree_sitter_analyzer/cli/__init__.py +3 -3
- tree_sitter_analyzer/cli/commands/advanced_command.py +1 -1
- tree_sitter_analyzer/cli/commands/base_command.py +1 -1
- tree_sitter_analyzer/cli/commands/partial_read_command.py +2 -2
- tree_sitter_analyzer/cli/commands/summary_command.py +2 -2
- tree_sitter_analyzer/cli/commands/table_command.py +11 -8
- tree_sitter_analyzer/cli_main.py +2 -1
- tree_sitter_analyzer/core/analysis_engine.py +33 -69
- tree_sitter_analyzer/core/engine.py +6 -4
- tree_sitter_analyzer/core/parser.py +1 -1
- tree_sitter_analyzer/core/query.py +16 -8
- tree_sitter_analyzer/encoding_utils.py +0 -2
- tree_sitter_analyzer/exceptions.py +23 -23
- tree_sitter_analyzer/file_handler.py +4 -11
- tree_sitter_analyzer/formatters/java_formatter.py +8 -4
- tree_sitter_analyzer/formatters/python_formatter.py +8 -4
- tree_sitter_analyzer/interfaces/cli.py +1 -1
- tree_sitter_analyzer/interfaces/cli_adapter.py +30 -9
- tree_sitter_analyzer/interfaces/mcp_adapter.py +43 -17
- tree_sitter_analyzer/interfaces/mcp_server.py +9 -9
- tree_sitter_analyzer/java_analyzer.py +20 -51
- tree_sitter_analyzer/language_loader.py +2 -2
- tree_sitter_analyzer/languages/java_plugin.py +86 -41
- tree_sitter_analyzer/{plugins → languages}/javascript_plugin.py +3 -3
- tree_sitter_analyzer/languages/python_plugin.py +16 -6
- tree_sitter_analyzer/mcp/resources/code_file_resource.py +0 -3
- tree_sitter_analyzer/mcp/resources/project_stats_resource.py +0 -5
- tree_sitter_analyzer/mcp/server.py +4 -4
- tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +63 -30
- tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py +9 -4
- tree_sitter_analyzer/mcp/tools/table_format_tool.py +2 -2
- tree_sitter_analyzer/mcp/utils/__init__.py +10 -8
- tree_sitter_analyzer/models.py +1 -1
- tree_sitter_analyzer/output_manager.py +4 -10
- tree_sitter_analyzer/plugins/__init__.py +9 -62
- tree_sitter_analyzer/plugins/base.py +20 -1
- tree_sitter_analyzer/plugins/manager.py +29 -12
- tree_sitter_analyzer/query_loader.py +4 -1
- tree_sitter_analyzer/table_formatter.py +4 -1
- tree_sitter_analyzer/utils.py +6 -6
- {tree_sitter_analyzer-0.3.0.dist-info → tree_sitter_analyzer-0.4.0.dist-info}/METADATA +3 -3
- tree_sitter_analyzer-0.4.0.dist-info/RECORD +73 -0
- {tree_sitter_analyzer-0.3.0.dist-info → tree_sitter_analyzer-0.4.0.dist-info}/entry_points.txt +2 -1
- tree_sitter_analyzer/plugins/java_plugin.py +0 -608
- tree_sitter_analyzer/plugins/plugin_loader.py +0 -85
- tree_sitter_analyzer/plugins/python_plugin.py +0 -606
- tree_sitter_analyzer/plugins/registry.py +0 -374
- tree_sitter_analyzer-0.3.0.dist-info/RECORD +0 -77
- {tree_sitter_analyzer-0.3.0.dist-info → tree_sitter_analyzer-0.4.0.dist-info}/WHEEL +0 -0
|
@@ -1,608 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Java Language Plugin
|
|
4
|
-
|
|
5
|
-
Provides Java-specific parsing and element extraction functionality.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from typing import TYPE_CHECKING, Optional
|
|
9
|
-
|
|
10
|
-
if TYPE_CHECKING:
|
|
11
|
-
import tree_sitter
|
|
12
|
-
|
|
13
|
-
from ..core.analysis_engine import AnalysisRequest
|
|
14
|
-
from ..models import AnalysisResult
|
|
15
|
-
|
|
16
|
-
from ..language_loader import loader
|
|
17
|
-
from ..models import Class, Function, Import, JavaAnnotation, Variable
|
|
18
|
-
from ..utils import log_error, log_warning
|
|
19
|
-
from . import ElementExtractor, LanguagePlugin
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class JavaElementExtractor(ElementExtractor):
|
|
23
|
-
"""Advanced Java-specific element extractor with comprehensive analysis"""
|
|
24
|
-
|
|
25
|
-
def __init__(self) -> None:
|
|
26
|
-
# 分析コンテキスト
|
|
27
|
-
self.current_package: str = ""
|
|
28
|
-
self.current_file: str = ""
|
|
29
|
-
self.source_code: str = ""
|
|
30
|
-
self.imports: list[str] = []
|
|
31
|
-
|
|
32
|
-
def extract_functions(
|
|
33
|
-
self, tree: "tree_sitter.Tree", source_code: str
|
|
34
|
-
) -> list[Function]:
|
|
35
|
-
"""Extract Java method definitions with comprehensive analysis"""
|
|
36
|
-
self.source_code = source_code
|
|
37
|
-
functions: list[Function] = []
|
|
38
|
-
|
|
39
|
-
# 複数のメソッドパターンを検索
|
|
40
|
-
method_queries = [
|
|
41
|
-
# 通常のメソッド宣言
|
|
42
|
-
"""
|
|
43
|
-
(method_declaration
|
|
44
|
-
(modifiers)? @method.modifiers
|
|
45
|
-
type: (_)? @method.return_type
|
|
46
|
-
name: (identifier) @method.name
|
|
47
|
-
parameters: (formal_parameters) @method.params
|
|
48
|
-
(throws)? @method.throws
|
|
49
|
-
body: (block)? @method.body) @method.declaration
|
|
50
|
-
""",
|
|
51
|
-
# コンストラクタ
|
|
52
|
-
"""
|
|
53
|
-
(constructor_declaration
|
|
54
|
-
(modifiers)? @constructor.modifiers
|
|
55
|
-
name: (identifier) @constructor.name
|
|
56
|
-
parameters: (formal_parameters) @constructor.params
|
|
57
|
-
(throws)? @constructor.throws
|
|
58
|
-
body: (constructor_body) @constructor.body) @constructor.declaration
|
|
59
|
-
""",
|
|
60
|
-
]
|
|
61
|
-
|
|
62
|
-
try:
|
|
63
|
-
language = tree.language if hasattr(tree, "language") else None
|
|
64
|
-
if language:
|
|
65
|
-
for query_string in method_queries:
|
|
66
|
-
query = language.query(query_string)
|
|
67
|
-
captures = query.captures(tree.root_node)
|
|
68
|
-
|
|
69
|
-
if isinstance(captures, dict):
|
|
70
|
-
# メソッド宣言を処理
|
|
71
|
-
method_nodes = captures.get("method.declaration", [])
|
|
72
|
-
for node in method_nodes:
|
|
73
|
-
function = self._extract_detailed_method_info(
|
|
74
|
-
node, source_code, False
|
|
75
|
-
)
|
|
76
|
-
if function:
|
|
77
|
-
functions.append(function)
|
|
78
|
-
|
|
79
|
-
# コンストラクタを処理
|
|
80
|
-
constructor_nodes = captures.get("constructor.declaration", [])
|
|
81
|
-
for node in constructor_nodes:
|
|
82
|
-
function = self._extract_detailed_method_info(
|
|
83
|
-
node, source_code, True
|
|
84
|
-
)
|
|
85
|
-
if function:
|
|
86
|
-
functions.append(function)
|
|
87
|
-
|
|
88
|
-
except Exception as e:
|
|
89
|
-
log_warning(f"Could not extract Java methods: {e}")
|
|
90
|
-
|
|
91
|
-
return functions
|
|
92
|
-
|
|
93
|
-
def extract_classes(
|
|
94
|
-
self, tree: "tree_sitter.Tree", source_code: str
|
|
95
|
-
) -> list[Class]:
|
|
96
|
-
"""Extract Java class definitions with comprehensive analysis"""
|
|
97
|
-
self.source_code = source_code
|
|
98
|
-
classes: list[Class] = []
|
|
99
|
-
|
|
100
|
-
# 複数のクラスタイプを検索
|
|
101
|
-
class_queries = [
|
|
102
|
-
# 通常のクラス
|
|
103
|
-
"""
|
|
104
|
-
(class_declaration
|
|
105
|
-
(modifiers)? @class.modifiers
|
|
106
|
-
name: (identifier) @class.name
|
|
107
|
-
(superclass)? @class.superclass
|
|
108
|
-
(super_interfaces)? @class.interfaces
|
|
109
|
-
body: (class_body) @class.body) @class.declaration
|
|
110
|
-
""",
|
|
111
|
-
# インターフェース
|
|
112
|
-
"""
|
|
113
|
-
(interface_declaration
|
|
114
|
-
(modifiers)? @interface.modifiers
|
|
115
|
-
name: (identifier) @interface.name
|
|
116
|
-
(extends_interfaces)? @interface.extends
|
|
117
|
-
body: (interface_body) @interface.body) @interface.declaration
|
|
118
|
-
""",
|
|
119
|
-
# 列挙型
|
|
120
|
-
"""
|
|
121
|
-
(enum_declaration
|
|
122
|
-
(modifiers)? @enum.modifiers
|
|
123
|
-
name: (identifier) @enum.name
|
|
124
|
-
(super_interfaces)? @enum.interfaces
|
|
125
|
-
body: (enum_body) @enum.body) @enum.declaration
|
|
126
|
-
""",
|
|
127
|
-
# アノテーション型
|
|
128
|
-
"""
|
|
129
|
-
(annotation_type_declaration
|
|
130
|
-
(modifiers)? @annotation.modifiers
|
|
131
|
-
name: (identifier) @annotation.name
|
|
132
|
-
body: (annotation_type_body) @annotation.body) @annotation.declaration
|
|
133
|
-
""",
|
|
134
|
-
]
|
|
135
|
-
|
|
136
|
-
try:
|
|
137
|
-
language = tree.language if hasattr(tree, "language") else None
|
|
138
|
-
if language:
|
|
139
|
-
for query_string in class_queries:
|
|
140
|
-
query = language.query(query_string)
|
|
141
|
-
captures = query.captures(tree.root_node)
|
|
142
|
-
|
|
143
|
-
if isinstance(captures, dict):
|
|
144
|
-
# 各タイプのクラスを処理
|
|
145
|
-
for key, nodes in captures.items():
|
|
146
|
-
if key.endswith(".declaration"):
|
|
147
|
-
class_type = key.split(".")[0]
|
|
148
|
-
for node in nodes:
|
|
149
|
-
cls = self._extract_detailed_class_info(
|
|
150
|
-
node, source_code, class_type
|
|
151
|
-
)
|
|
152
|
-
if cls:
|
|
153
|
-
classes.append(cls)
|
|
154
|
-
|
|
155
|
-
except Exception as e:
|
|
156
|
-
log_warning(f"Could not extract Java classes: {e}")
|
|
157
|
-
|
|
158
|
-
return classes
|
|
159
|
-
|
|
160
|
-
def extract_variables(
|
|
161
|
-
self, tree: "tree_sitter.Tree", source_code: str
|
|
162
|
-
) -> list[Variable]:
|
|
163
|
-
"""Extract Java field and variable definitions"""
|
|
164
|
-
variables: list[Variable] = []
|
|
165
|
-
|
|
166
|
-
# Field declarations
|
|
167
|
-
query_string = """
|
|
168
|
-
(field_declaration
|
|
169
|
-
type: (_) @field.type
|
|
170
|
-
declarator: (variable_declarator
|
|
171
|
-
name: (identifier) @field.name)) @field.declaration
|
|
172
|
-
"""
|
|
173
|
-
|
|
174
|
-
try:
|
|
175
|
-
language = tree.language if hasattr(tree, "language") else None
|
|
176
|
-
if language:
|
|
177
|
-
query = language.query(query_string)
|
|
178
|
-
captures = query.captures(tree.root_node)
|
|
179
|
-
|
|
180
|
-
if isinstance(captures, dict):
|
|
181
|
-
field_nodes = captures.get("field.declaration", [])
|
|
182
|
-
for node in field_nodes:
|
|
183
|
-
variable = self._extract_field_info(node, source_code)
|
|
184
|
-
if variable:
|
|
185
|
-
variables.append(variable)
|
|
186
|
-
|
|
187
|
-
except Exception as e:
|
|
188
|
-
log_warning(f"Could not extract Java fields: {e}")
|
|
189
|
-
|
|
190
|
-
return variables
|
|
191
|
-
|
|
192
|
-
def extract_imports(
|
|
193
|
-
self, tree: "tree_sitter.Tree", source_code: str
|
|
194
|
-
) -> list[Import]:
|
|
195
|
-
"""Extract Java import statements"""
|
|
196
|
-
imports: list[Import] = []
|
|
197
|
-
|
|
198
|
-
query_string = """
|
|
199
|
-
(import_declaration
|
|
200
|
-
(scoped_identifier) @import.name) @import.declaration
|
|
201
|
-
"""
|
|
202
|
-
|
|
203
|
-
try:
|
|
204
|
-
language = tree.language if hasattr(tree, "language") else None
|
|
205
|
-
if language:
|
|
206
|
-
query = language.query(query_string)
|
|
207
|
-
captures = query.captures(tree.root_node)
|
|
208
|
-
|
|
209
|
-
if isinstance(captures, dict):
|
|
210
|
-
import_nodes = captures.get("import.declaration", [])
|
|
211
|
-
for node in import_nodes:
|
|
212
|
-
imp = self._extract_import_info(node, source_code)
|
|
213
|
-
if imp:
|
|
214
|
-
imports.append(imp)
|
|
215
|
-
|
|
216
|
-
except Exception as e:
|
|
217
|
-
log_warning(f"Could not extract Java imports: {e}")
|
|
218
|
-
|
|
219
|
-
return imports
|
|
220
|
-
|
|
221
|
-
def _extract_detailed_method_info(
|
|
222
|
-
self, node: "tree_sitter.Node", source_code: str, is_constructor: bool = False
|
|
223
|
-
) -> Function | None:
|
|
224
|
-
"""Extract comprehensive method information from AST node"""
|
|
225
|
-
try:
|
|
226
|
-
# 基本情報の抽出
|
|
227
|
-
name = self._extract_name_from_node(node, source_code)
|
|
228
|
-
if not name:
|
|
229
|
-
return None
|
|
230
|
-
|
|
231
|
-
# 詳細情報の抽出
|
|
232
|
-
return_type = (
|
|
233
|
-
self._extract_return_type_from_node(node, source_code)
|
|
234
|
-
if not is_constructor
|
|
235
|
-
else "void"
|
|
236
|
-
)
|
|
237
|
-
parameters = self._extract_parameters_from_node(node, source_code)
|
|
238
|
-
modifiers = self._extract_modifiers_from_node(node, source_code)
|
|
239
|
-
# annotations = self._extract_annotations_from_node(node, source_code) # Not used currently
|
|
240
|
-
# throws = self._extract_throws_from_node(node, source_code) # Not used currently
|
|
241
|
-
|
|
242
|
-
# 可視性の判定
|
|
243
|
-
# visibility = "public"
|
|
244
|
-
# if "private" in modifiers:
|
|
245
|
-
# visibility = "private"
|
|
246
|
-
# elif "protected" in modifiers:
|
|
247
|
-
# visibility = "protected" # Not used currently
|
|
248
|
-
# elif "public" not in modifiers and len(modifiers) > 0:
|
|
249
|
-
# visibility = "package" # Not used currently
|
|
250
|
-
|
|
251
|
-
# メソッドボディの抽出
|
|
252
|
-
# body = self._extract_method_body(node, source_code) # Not used currently
|
|
253
|
-
# signature = self._generate_method_signature(
|
|
254
|
-
# name, return_type, parameters, modifiers
|
|
255
|
-
# ) # Not used currently
|
|
256
|
-
|
|
257
|
-
# 複雑度の簡易計算
|
|
258
|
-
# complexity_score = self._calculate_complexity(body) # Not used currently
|
|
259
|
-
|
|
260
|
-
# Function型として返すため、基本的なFunction型を作成
|
|
261
|
-
return Function(
|
|
262
|
-
name=name,
|
|
263
|
-
start_line=node.start_point[0] + 1,
|
|
264
|
-
end_line=node.end_point[0] + 1,
|
|
265
|
-
raw_text=source_code[node.start_byte : node.end_byte],
|
|
266
|
-
language="java",
|
|
267
|
-
parameters=parameters,
|
|
268
|
-
return_type=return_type,
|
|
269
|
-
modifiers=modifiers,
|
|
270
|
-
is_static="static" in modifiers,
|
|
271
|
-
is_private="private" in modifiers,
|
|
272
|
-
is_public="public" in modifiers,
|
|
273
|
-
)
|
|
274
|
-
|
|
275
|
-
except Exception as e:
|
|
276
|
-
log_warning(f"Could not extract detailed method info: {e}")
|
|
277
|
-
return None
|
|
278
|
-
|
|
279
|
-
def _extract_name_from_node(
|
|
280
|
-
self, node: "tree_sitter.Node", source_code: str
|
|
281
|
-
) -> str | None:
|
|
282
|
-
"""Extract name from AST node"""
|
|
283
|
-
for child in node.children:
|
|
284
|
-
if child.type == "identifier":
|
|
285
|
-
return source_code[child.start_byte : child.end_byte]
|
|
286
|
-
return None
|
|
287
|
-
|
|
288
|
-
def _extract_return_type_from_node(
|
|
289
|
-
self, node: "tree_sitter.Node", source_code: str
|
|
290
|
-
) -> str:
|
|
291
|
-
"""Extract return type from method node"""
|
|
292
|
-
for child in node.children:
|
|
293
|
-
if child.type in [
|
|
294
|
-
"type_identifier",
|
|
295
|
-
"generic_type",
|
|
296
|
-
"array_type",
|
|
297
|
-
"primitive_type",
|
|
298
|
-
]:
|
|
299
|
-
return source_code[child.start_byte : child.end_byte]
|
|
300
|
-
return "void"
|
|
301
|
-
|
|
302
|
-
def _extract_parameters_from_node(
|
|
303
|
-
self, node: "tree_sitter.Node", source_code: str
|
|
304
|
-
) -> list[str]:
|
|
305
|
-
"""Extract parameters from method node"""
|
|
306
|
-
parameters: list[str] = []
|
|
307
|
-
for child in node.children:
|
|
308
|
-
if child.type == "formal_parameters":
|
|
309
|
-
for param_child in child.children:
|
|
310
|
-
if param_child.type == "formal_parameter":
|
|
311
|
-
param_text = source_code[
|
|
312
|
-
param_child.start_byte : param_child.end_byte
|
|
313
|
-
]
|
|
314
|
-
parameters.append(param_text)
|
|
315
|
-
return parameters
|
|
316
|
-
|
|
317
|
-
def _extract_modifiers_from_node(
|
|
318
|
-
self, node: "tree_sitter.Node", source_code: str
|
|
319
|
-
) -> list[str]:
|
|
320
|
-
"""Extract modifiers from node"""
|
|
321
|
-
modifiers: list[str] = []
|
|
322
|
-
for child in node.children:
|
|
323
|
-
if child.type == "modifiers":
|
|
324
|
-
modifier_text = source_code[child.start_byte : child.end_byte]
|
|
325
|
-
# 簡単な分割で各修飾子を抽出
|
|
326
|
-
for modifier in modifier_text.split():
|
|
327
|
-
if modifier in [
|
|
328
|
-
"public",
|
|
329
|
-
"private",
|
|
330
|
-
"protected",
|
|
331
|
-
"static",
|
|
332
|
-
"final",
|
|
333
|
-
"abstract",
|
|
334
|
-
"synchronized",
|
|
335
|
-
]:
|
|
336
|
-
modifiers.append(modifier)
|
|
337
|
-
return modifiers
|
|
338
|
-
|
|
339
|
-
def _extract_annotations_from_node(
|
|
340
|
-
self, node: "tree_sitter.Node", source_code: str
|
|
341
|
-
) -> list[JavaAnnotation]:
|
|
342
|
-
"""Extract annotations from node (simplified)"""
|
|
343
|
-
annotations: list[JavaAnnotation] = []
|
|
344
|
-
# より詳細な実装が必要だが、今回は簡略化
|
|
345
|
-
return annotations
|
|
346
|
-
|
|
347
|
-
def _extract_throws_from_node(
|
|
348
|
-
self, node: "tree_sitter.Node", source_code: str
|
|
349
|
-
) -> list[str]:
|
|
350
|
-
"""Extract throws clause from method node"""
|
|
351
|
-
throws: list[str] = []
|
|
352
|
-
for child in node.children:
|
|
353
|
-
if child.type == "throws":
|
|
354
|
-
throws_text = source_code[child.start_byte : child.end_byte]
|
|
355
|
-
# "throws" キーワードを除去して例外タイプを抽出
|
|
356
|
-
if throws_text.startswith("throws"):
|
|
357
|
-
exceptions = throws_text[6:].strip()
|
|
358
|
-
throws.extend([ex.strip() for ex in exceptions.split(",")])
|
|
359
|
-
return throws
|
|
360
|
-
|
|
361
|
-
def _extract_method_body(self, node: "tree_sitter.Node", source_code: str) -> str:
|
|
362
|
-
"""Extract method body"""
|
|
363
|
-
for child in node.children:
|
|
364
|
-
if child.type in ["block", "constructor_body"]:
|
|
365
|
-
return source_code[child.start_byte : child.end_byte]
|
|
366
|
-
return ""
|
|
367
|
-
|
|
368
|
-
def _generate_method_signature(
|
|
369
|
-
self, name: str, return_type: str, parameters: list[str], modifiers: list[str]
|
|
370
|
-
) -> str:
|
|
371
|
-
"""Generate method signature"""
|
|
372
|
-
modifier_str = " ".join(modifiers) + " " if modifiers else ""
|
|
373
|
-
param_str = ", ".join(parameters) if parameters else ""
|
|
374
|
-
return f"{modifier_str}{return_type} {name}({param_str})"
|
|
375
|
-
|
|
376
|
-
def _calculate_complexity(self, body: str) -> int:
|
|
377
|
-
"""Calculate cyclomatic complexity (simplified)"""
|
|
378
|
-
complexity = 1 # Base complexity
|
|
379
|
-
keywords = ["if", "else", "for", "while", "switch", "case", "catch", "&&", "||"]
|
|
380
|
-
for keyword in keywords:
|
|
381
|
-
complexity += body.count(keyword)
|
|
382
|
-
return complexity
|
|
383
|
-
|
|
384
|
-
def _extract_detailed_class_info(
|
|
385
|
-
self, node: "tree_sitter.Node", source_code: str, class_type: str = "class"
|
|
386
|
-
) -> Class | None:
|
|
387
|
-
"""Extract comprehensive class information from AST node"""
|
|
388
|
-
try:
|
|
389
|
-
# 基本情報の抽出
|
|
390
|
-
name = self._extract_name_from_node(node, source_code)
|
|
391
|
-
if not name:
|
|
392
|
-
return None
|
|
393
|
-
|
|
394
|
-
# 詳細情報の抽出
|
|
395
|
-
modifiers = self._extract_modifiers_from_node(node, source_code)
|
|
396
|
-
# annotations = self._extract_annotations_from_node(node, source_code) # Not used currently
|
|
397
|
-
superclass = self._extract_superclass_from_node(node, source_code)
|
|
398
|
-
interfaces = self._extract_interfaces_from_node(node, source_code)
|
|
399
|
-
|
|
400
|
-
# 完全修飾名の生成
|
|
401
|
-
full_qualified_name = (
|
|
402
|
-
f"{self.current_package}.{name}" if self.current_package else name
|
|
403
|
-
)
|
|
404
|
-
|
|
405
|
-
# 可視性の判定
|
|
406
|
-
# visibility = "public"
|
|
407
|
-
# if "private" in modifiers:
|
|
408
|
-
# visibility = "private"
|
|
409
|
-
# elif "protected" in modifiers:
|
|
410
|
-
# visibility = "protected" # Not used currently
|
|
411
|
-
# elif "public" not in modifiers and len(modifiers) > 0:
|
|
412
|
-
# visibility = "package" # Not used currently
|
|
413
|
-
|
|
414
|
-
# ネストクラスかどうかの判定(簡略化)
|
|
415
|
-
# is_nested = "." in self.current_package if self.current_package else False # Not used currently
|
|
416
|
-
|
|
417
|
-
# Class型として返すため、基本的なClass型を作成
|
|
418
|
-
return Class(
|
|
419
|
-
name=name,
|
|
420
|
-
start_line=node.start_point[0] + 1,
|
|
421
|
-
end_line=node.end_point[0] + 1,
|
|
422
|
-
raw_text=source_code[node.start_byte : node.end_byte],
|
|
423
|
-
language="java",
|
|
424
|
-
class_type=class_type,
|
|
425
|
-
full_qualified_name=full_qualified_name,
|
|
426
|
-
package_name=self.current_package,
|
|
427
|
-
superclass=superclass,
|
|
428
|
-
interfaces=interfaces,
|
|
429
|
-
modifiers=modifiers,
|
|
430
|
-
)
|
|
431
|
-
|
|
432
|
-
except Exception as e:
|
|
433
|
-
log_warning(f"Could not extract detailed class info: {e}")
|
|
434
|
-
return None
|
|
435
|
-
|
|
436
|
-
def _extract_superclass_from_node(
|
|
437
|
-
self, node: "tree_sitter.Node", source_code: str
|
|
438
|
-
) -> str | None:
|
|
439
|
-
"""Extract superclass from class node"""
|
|
440
|
-
for child in node.children:
|
|
441
|
-
if child.type == "superclass":
|
|
442
|
-
for subchild in child.children:
|
|
443
|
-
if subchild.type == "type_identifier":
|
|
444
|
-
return source_code[subchild.start_byte : subchild.end_byte]
|
|
445
|
-
return None
|
|
446
|
-
|
|
447
|
-
def _extract_interfaces_from_node(
|
|
448
|
-
self, node: "tree_sitter.Node", source_code: str
|
|
449
|
-
) -> list[str]:
|
|
450
|
-
"""Extract implemented interfaces from class node"""
|
|
451
|
-
interfaces: list[str] = []
|
|
452
|
-
for child in node.children:
|
|
453
|
-
if child.type in ["super_interfaces", "extends_interfaces"]:
|
|
454
|
-
for subchild in child.children:
|
|
455
|
-
if subchild.type == "type_identifier":
|
|
456
|
-
interfaces.append(
|
|
457
|
-
source_code[subchild.start_byte : subchild.end_byte]
|
|
458
|
-
)
|
|
459
|
-
return interfaces
|
|
460
|
-
|
|
461
|
-
def _extract_field_info(
|
|
462
|
-
self, node: "tree_sitter.Node", source_code: str
|
|
463
|
-
) -> Variable | None:
|
|
464
|
-
"""Extract detailed field information from AST node"""
|
|
465
|
-
try:
|
|
466
|
-
# Check if node has required attributes
|
|
467
|
-
if (
|
|
468
|
-
not hasattr(node, "start_byte")
|
|
469
|
-
or not hasattr(node, "end_byte")
|
|
470
|
-
or not hasattr(node, "start_point")
|
|
471
|
-
or not hasattr(node, "end_point")
|
|
472
|
-
or node.start_byte is None
|
|
473
|
-
or node.end_byte is None
|
|
474
|
-
or node.start_point is None
|
|
475
|
-
or node.end_point is None
|
|
476
|
-
):
|
|
477
|
-
return None
|
|
478
|
-
|
|
479
|
-
# Simple field extraction
|
|
480
|
-
field_text = source_code[node.start_byte : node.end_byte]
|
|
481
|
-
|
|
482
|
-
# Variable型として返すため、基本的なVariable型を作成
|
|
483
|
-
return Variable(
|
|
484
|
-
name="field", # Would need more sophisticated parsing
|
|
485
|
-
start_line=node.start_point[0] + 1,
|
|
486
|
-
end_line=node.end_point[0] + 1,
|
|
487
|
-
raw_text=field_text,
|
|
488
|
-
language="java",
|
|
489
|
-
)
|
|
490
|
-
|
|
491
|
-
except Exception as e:
|
|
492
|
-
log_warning(f"Could not extract field info: {e}")
|
|
493
|
-
return None
|
|
494
|
-
|
|
495
|
-
def _extract_import_info(
|
|
496
|
-
self, node: "tree_sitter.Node", source_code: str
|
|
497
|
-
) -> Import | None:
|
|
498
|
-
"""Extract detailed import information from AST node"""
|
|
499
|
-
try:
|
|
500
|
-
# Check if node has required attributes
|
|
501
|
-
if (
|
|
502
|
-
not hasattr(node, "start_byte")
|
|
503
|
-
or not hasattr(node, "end_byte")
|
|
504
|
-
or not hasattr(node, "start_point")
|
|
505
|
-
or not hasattr(node, "end_point")
|
|
506
|
-
or node.start_byte is None
|
|
507
|
-
or node.end_byte is None
|
|
508
|
-
or node.start_point is None
|
|
509
|
-
or node.end_point is None
|
|
510
|
-
):
|
|
511
|
-
return None
|
|
512
|
-
|
|
513
|
-
import_text = source_code[node.start_byte : node.end_byte]
|
|
514
|
-
|
|
515
|
-
# Import型として返すため、基本的なImport型を作成
|
|
516
|
-
return Import(
|
|
517
|
-
name="import", # Would need more sophisticated parsing
|
|
518
|
-
start_line=node.start_point[0] + 1,
|
|
519
|
-
end_line=node.end_point[0] + 1,
|
|
520
|
-
raw_text=import_text,
|
|
521
|
-
language="java",
|
|
522
|
-
module_name=import_text,
|
|
523
|
-
)
|
|
524
|
-
|
|
525
|
-
except Exception as e:
|
|
526
|
-
log_warning(f"Could not extract import info: {e}")
|
|
527
|
-
return None
|
|
528
|
-
|
|
529
|
-
|
|
530
|
-
class JavaPlugin(LanguagePlugin):
|
|
531
|
-
"""Java language plugin"""
|
|
532
|
-
|
|
533
|
-
def __init__(self) -> None:
|
|
534
|
-
self._extractor = JavaElementExtractor()
|
|
535
|
-
self._language: tree_sitter.Language | None = None
|
|
536
|
-
|
|
537
|
-
@property
|
|
538
|
-
def language_name(self) -> str:
|
|
539
|
-
return "java"
|
|
540
|
-
|
|
541
|
-
@property
|
|
542
|
-
def file_extensions(self) -> list[str]:
|
|
543
|
-
return [".java", ".jsp", ".jspx"]
|
|
544
|
-
|
|
545
|
-
def get_language_name(self) -> str:
|
|
546
|
-
"""Return the name of the programming language this plugin supports"""
|
|
547
|
-
return "java"
|
|
548
|
-
|
|
549
|
-
def get_file_extensions(self) -> list[str]:
|
|
550
|
-
"""Return list of file extensions this plugin supports"""
|
|
551
|
-
return [".java", ".jsp", ".jspx"]
|
|
552
|
-
|
|
553
|
-
def create_extractor(self) -> ElementExtractor:
|
|
554
|
-
"""Create and return an element extractor for this language"""
|
|
555
|
-
return JavaElementExtractor()
|
|
556
|
-
|
|
557
|
-
def get_extractor(self) -> ElementExtractor:
|
|
558
|
-
return self._extractor
|
|
559
|
-
|
|
560
|
-
def get_tree_sitter_language(self) -> Optional["tree_sitter.Language"]:
|
|
561
|
-
"""Load and return Java tree-sitter language"""
|
|
562
|
-
if self._language is None:
|
|
563
|
-
self._language = loader.load_language("java")
|
|
564
|
-
return self._language
|
|
565
|
-
|
|
566
|
-
async def analyze_file(
|
|
567
|
-
self, file_path: str, request: "AnalysisRequest"
|
|
568
|
-
) -> "AnalysisResult":
|
|
569
|
-
"""
|
|
570
|
-
Javaファイルを解析してAnalysisResultを返す
|
|
571
|
-
|
|
572
|
-
Args:
|
|
573
|
-
file_path: 解析対象ファイルのパス
|
|
574
|
-
request: 解析リクエスト
|
|
575
|
-
|
|
576
|
-
Returns:
|
|
577
|
-
解析結果
|
|
578
|
-
"""
|
|
579
|
-
from ..core.analysis_engine import AnalysisRequest, get_analysis_engine
|
|
580
|
-
from ..models import AnalysisResult
|
|
581
|
-
|
|
582
|
-
try:
|
|
583
|
-
# Use UnifiedAnalysisEngine for file analysis
|
|
584
|
-
analyzer = get_analysis_engine()
|
|
585
|
-
|
|
586
|
-
# Create analysis request and analyze file
|
|
587
|
-
request = AnalysisRequest(
|
|
588
|
-
file_path=file_path,
|
|
589
|
-
language="java",
|
|
590
|
-
include_complexity=True,
|
|
591
|
-
include_details=True,
|
|
592
|
-
)
|
|
593
|
-
result = await analyzer.analyze(request)
|
|
594
|
-
|
|
595
|
-
if not result or not result.success:
|
|
596
|
-
return AnalysisResult(
|
|
597
|
-
file_path=file_path,
|
|
598
|
-
success=False,
|
|
599
|
-
error_message=f"Failed to analyze Java file: {file_path}",
|
|
600
|
-
)
|
|
601
|
-
|
|
602
|
-
return result
|
|
603
|
-
|
|
604
|
-
except Exception as e:
|
|
605
|
-
log_error(f"Error analyzing Java file {file_path}: {e}")
|
|
606
|
-
return AnalysisResult(
|
|
607
|
-
file_path=file_path, success=False, error_message=str(e)
|
|
608
|
-
)
|
|
@@ -1,85 +0,0 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Plugin Loader for Tree-sitter Analyzer
|
|
4
|
-
|
|
5
|
-
Automatically loads and registers all available language plugins.
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
from typing import TYPE_CHECKING
|
|
9
|
-
|
|
10
|
-
from ..utils import log_debug, log_error, log_info
|
|
11
|
-
from . import plugin_registry
|
|
12
|
-
|
|
13
|
-
if TYPE_CHECKING:
|
|
14
|
-
from .base import LanguagePlugin
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def load_all_plugins() -> list[str]:
|
|
18
|
-
"""Load and register all available language plugins"""
|
|
19
|
-
loaded_plugins = []
|
|
20
|
-
|
|
21
|
-
try:
|
|
22
|
-
# Import and register Java plugin
|
|
23
|
-
from .java_plugin import JavaPlugin
|
|
24
|
-
|
|
25
|
-
java_plugin = JavaPlugin()
|
|
26
|
-
plugin_registry.register_plugin(java_plugin)
|
|
27
|
-
loaded_plugins.append("java")
|
|
28
|
-
log_debug("Loaded Java plugin")
|
|
29
|
-
except Exception as e:
|
|
30
|
-
log_error(f"Failed to load Java plugin: {e}")
|
|
31
|
-
|
|
32
|
-
try:
|
|
33
|
-
# Import and register JavaScript plugin
|
|
34
|
-
from .javascript_plugin import JavaScriptPlugin
|
|
35
|
-
|
|
36
|
-
js_plugin = JavaScriptPlugin()
|
|
37
|
-
plugin_registry.register_plugin(js_plugin)
|
|
38
|
-
loaded_plugins.append("javascript")
|
|
39
|
-
log_debug("Loaded JavaScript plugin")
|
|
40
|
-
except Exception as e:
|
|
41
|
-
log_error(f"Failed to load JavaScript plugin: {e}")
|
|
42
|
-
|
|
43
|
-
try:
|
|
44
|
-
# Import and register Python plugin
|
|
45
|
-
from .python_plugin import PythonPlugin
|
|
46
|
-
|
|
47
|
-
python_plugin = PythonPlugin()
|
|
48
|
-
plugin_registry.register_plugin(python_plugin)
|
|
49
|
-
loaded_plugins.append("python")
|
|
50
|
-
log_debug("Loaded Python plugin")
|
|
51
|
-
except Exception as e:
|
|
52
|
-
log_error(f"Failed to load Python plugin: {e}")
|
|
53
|
-
|
|
54
|
-
if loaded_plugins:
|
|
55
|
-
log_info(
|
|
56
|
-
f"Successfully loaded {len(loaded_plugins)} language plugins: {', '.join(loaded_plugins)}"
|
|
57
|
-
)
|
|
58
|
-
else:
|
|
59
|
-
log_error("No language plugins were loaded successfully")
|
|
60
|
-
|
|
61
|
-
return loaded_plugins
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
def get_supported_languages() -> list[str]:
|
|
65
|
-
"""Get list of all supported languages"""
|
|
66
|
-
return plugin_registry.list_supported_languages()
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
def get_supported_extensions() -> list[str]:
|
|
70
|
-
"""Get list of all supported file extensions"""
|
|
71
|
-
return plugin_registry.list_supported_extensions()
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
def get_plugin_for_file(file_path: str) -> "LanguagePlugin | None":
|
|
75
|
-
"""Get appropriate plugin for a file"""
|
|
76
|
-
return plugin_registry.get_plugin_for_file(file_path)
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
def get_plugin_by_language(language: str) -> "LanguagePlugin | None":
|
|
80
|
-
"""Get plugin by language name"""
|
|
81
|
-
return plugin_registry.get_plugin(language)
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
# Auto-load plugins when module is imported
|
|
85
|
-
_loaded_plugins = load_all_plugins()
|