tree-sitter-analyzer 0.1.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.

Files changed (78) hide show
  1. tree_sitter_analyzer/__init__.py +121 -0
  2. tree_sitter_analyzer/__main__.py +12 -0
  3. tree_sitter_analyzer/api.py +539 -0
  4. tree_sitter_analyzer/cli/__init__.py +39 -0
  5. tree_sitter_analyzer/cli/__main__.py +13 -0
  6. tree_sitter_analyzer/cli/commands/__init__.py +27 -0
  7. tree_sitter_analyzer/cli/commands/advanced_command.py +88 -0
  8. tree_sitter_analyzer/cli/commands/base_command.py +155 -0
  9. tree_sitter_analyzer/cli/commands/default_command.py +19 -0
  10. tree_sitter_analyzer/cli/commands/partial_read_command.py +133 -0
  11. tree_sitter_analyzer/cli/commands/query_command.py +82 -0
  12. tree_sitter_analyzer/cli/commands/structure_command.py +121 -0
  13. tree_sitter_analyzer/cli/commands/summary_command.py +93 -0
  14. tree_sitter_analyzer/cli/commands/table_command.py +233 -0
  15. tree_sitter_analyzer/cli/info_commands.py +121 -0
  16. tree_sitter_analyzer/cli_main.py +276 -0
  17. tree_sitter_analyzer/core/__init__.py +20 -0
  18. tree_sitter_analyzer/core/analysis_engine.py +574 -0
  19. tree_sitter_analyzer/core/cache_service.py +330 -0
  20. tree_sitter_analyzer/core/engine.py +560 -0
  21. tree_sitter_analyzer/core/parser.py +288 -0
  22. tree_sitter_analyzer/core/query.py +502 -0
  23. tree_sitter_analyzer/encoding_utils.py +460 -0
  24. tree_sitter_analyzer/exceptions.py +340 -0
  25. tree_sitter_analyzer/file_handler.py +222 -0
  26. tree_sitter_analyzer/formatters/__init__.py +1 -0
  27. tree_sitter_analyzer/formatters/base_formatter.py +168 -0
  28. tree_sitter_analyzer/formatters/formatter_factory.py +74 -0
  29. tree_sitter_analyzer/formatters/java_formatter.py +270 -0
  30. tree_sitter_analyzer/formatters/python_formatter.py +235 -0
  31. tree_sitter_analyzer/interfaces/__init__.py +10 -0
  32. tree_sitter_analyzer/interfaces/cli.py +557 -0
  33. tree_sitter_analyzer/interfaces/cli_adapter.py +319 -0
  34. tree_sitter_analyzer/interfaces/mcp_adapter.py +170 -0
  35. tree_sitter_analyzer/interfaces/mcp_server.py +416 -0
  36. tree_sitter_analyzer/java_analyzer.py +219 -0
  37. tree_sitter_analyzer/language_detector.py +400 -0
  38. tree_sitter_analyzer/language_loader.py +228 -0
  39. tree_sitter_analyzer/languages/__init__.py +11 -0
  40. tree_sitter_analyzer/languages/java_plugin.py +1113 -0
  41. tree_sitter_analyzer/languages/python_plugin.py +712 -0
  42. tree_sitter_analyzer/mcp/__init__.py +32 -0
  43. tree_sitter_analyzer/mcp/resources/__init__.py +47 -0
  44. tree_sitter_analyzer/mcp/resources/code_file_resource.py +213 -0
  45. tree_sitter_analyzer/mcp/resources/project_stats_resource.py +550 -0
  46. tree_sitter_analyzer/mcp/server.py +319 -0
  47. tree_sitter_analyzer/mcp/tools/__init__.py +36 -0
  48. tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +558 -0
  49. tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py +245 -0
  50. tree_sitter_analyzer/mcp/tools/base_tool.py +55 -0
  51. tree_sitter_analyzer/mcp/tools/get_positions_tool.py +448 -0
  52. tree_sitter_analyzer/mcp/tools/read_partial_tool.py +302 -0
  53. tree_sitter_analyzer/mcp/tools/table_format_tool.py +359 -0
  54. tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py +476 -0
  55. tree_sitter_analyzer/mcp/utils/__init__.py +106 -0
  56. tree_sitter_analyzer/mcp/utils/error_handler.py +549 -0
  57. tree_sitter_analyzer/models.py +481 -0
  58. tree_sitter_analyzer/output_manager.py +264 -0
  59. tree_sitter_analyzer/plugins/__init__.py +334 -0
  60. tree_sitter_analyzer/plugins/base.py +446 -0
  61. tree_sitter_analyzer/plugins/java_plugin.py +625 -0
  62. tree_sitter_analyzer/plugins/javascript_plugin.py +439 -0
  63. tree_sitter_analyzer/plugins/manager.py +355 -0
  64. tree_sitter_analyzer/plugins/plugin_loader.py +83 -0
  65. tree_sitter_analyzer/plugins/python_plugin.py +598 -0
  66. tree_sitter_analyzer/plugins/registry.py +366 -0
  67. tree_sitter_analyzer/queries/__init__.py +27 -0
  68. tree_sitter_analyzer/queries/java.py +394 -0
  69. tree_sitter_analyzer/queries/javascript.py +149 -0
  70. tree_sitter_analyzer/queries/python.py +286 -0
  71. tree_sitter_analyzer/queries/typescript.py +230 -0
  72. tree_sitter_analyzer/query_loader.py +260 -0
  73. tree_sitter_analyzer/table_formatter.py +448 -0
  74. tree_sitter_analyzer/utils.py +201 -0
  75. tree_sitter_analyzer-0.1.0.dist-info/METADATA +581 -0
  76. tree_sitter_analyzer-0.1.0.dist-info/RECORD +78 -0
  77. tree_sitter_analyzer-0.1.0.dist-info/WHEEL +4 -0
  78. tree_sitter_analyzer-0.1.0.dist-info/entry_points.txt +8 -0
@@ -0,0 +1,121 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Tree-sitter Multi-Language Code Analyzer
5
+
6
+ A comprehensive Python library for analyzing code across multiple programming languages
7
+ using Tree-sitter. Features a plugin-based architecture for extensible language support.
8
+
9
+ Architecture:
10
+ - Core Engine: UniversalCodeAnalyzer, LanguageDetector, QueryLoader
11
+ - Plugin System: Extensible language-specific analyzers and extractors
12
+ - Data Models: Generic and language-specific code element representations
13
+ """
14
+
15
+ __version__ = "0.0.1"
16
+ __author__ = "aisheng.yu"
17
+ __email__ = "aimasteracc@gmail.com"
18
+
19
+ # Legacy imports for backward compatibility
20
+
21
+ # Core Engine - 一時的に直接インポート
22
+ from .language_detector import LanguageDetector
23
+ from .query_loader import QueryLoader, get_query_loader
24
+ from .language_loader import get_loader
25
+ from .core.analysis_engine import UnifiedAnalysisEngine as UniversalCodeAnalyzer
26
+
27
+ from .encoding_utils import (
28
+ EncodingManager,
29
+ detect_encoding,
30
+ extract_text_slice,
31
+ read_file_safe,
32
+ safe_decode,
33
+ safe_encode,
34
+ write_file_safe,
35
+ )
36
+ # from .java_advanced_analyzer import AdvancedAnalyzer # Removed - migrated to plugin system
37
+ from .java_analyzer import CodeAnalyzer
38
+
39
+ # Data Models (Java-specific for backward compatibility)
40
+ # Data Models (Generic)
41
+ from .models import (
42
+ AnalysisResult,
43
+ Class,
44
+ CodeElement,
45
+ Function,
46
+ Import,
47
+ JavaAnnotation,
48
+ JavaClass,
49
+ JavaField,
50
+ JavaImport,
51
+ JavaMethod,
52
+ JavaPackage,
53
+ Variable,
54
+ )
55
+ from .output_manager import (
56
+ OutputManager,
57
+ get_output_manager,
58
+ output_data,
59
+ output_error,
60
+ output_info,
61
+ output_warning,
62
+ set_output_mode,
63
+ )
64
+
65
+ # Plugin System
66
+ from .plugins import ElementExtractor, LanguagePlugin, plugin_registry
67
+
68
+ # Import new utility modules
69
+ from .utils import (
70
+ QuietMode,
71
+ log_debug,
72
+ log_error,
73
+ log_info,
74
+ log_performance,
75
+ log_warning,
76
+ safe_print,
77
+ )
78
+
79
+ __all__ = [
80
+ # Core Models (optimized)
81
+ "JavaAnnotation",
82
+ "JavaClass",
83
+ "JavaImport",
84
+ "JavaMethod",
85
+ "JavaField",
86
+ "JavaPackage",
87
+ "AnalysisResult",
88
+ # Core Components (optimized)
89
+ # "AdvancedAnalyzer", # Removed - migrated to plugin system
90
+ "get_loader",
91
+ "get_query_loader",
92
+ # New Utilities
93
+ "log_info",
94
+ "log_warning",
95
+ "log_error",
96
+ "log_debug",
97
+ "QuietMode",
98
+ "safe_print",
99
+ "log_performance",
100
+ # Output Management
101
+ "OutputManager",
102
+ "set_output_mode",
103
+ "get_output_manager",
104
+ "output_info",
105
+ "output_warning",
106
+ "output_error",
107
+ "output_data",
108
+ # Legacy Components (backward compatibility)
109
+ "CodeAnalyzer",
110
+ "UniversalCodeAnalyzer",
111
+ # Version
112
+ "__version__",
113
+ # Encoding utilities
114
+ "EncodingManager",
115
+ "safe_encode",
116
+ "safe_decode",
117
+ "detect_encoding",
118
+ "read_file_safe",
119
+ "write_file_safe",
120
+ "extract_text_slice",
121
+ ]
@@ -0,0 +1,12 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Tree-sitter Analyzer パッケージのメインエントリーポイント
5
+
6
+ このファイルにより、`python -m tree_sitter_analyzer` でパッケージを実行できます。
7
+ """
8
+
9
+ from .cli_main import main
10
+
11
+ if __name__ == "__main__":
12
+ main()
@@ -0,0 +1,539 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Tree-sitter Analyzer API
5
+
6
+ Public API facade that provides a stable, high-level interface to the
7
+ tree-sitter analyzer framework. This is the main entry point for both
8
+ CLI and MCP interfaces.
9
+ """
10
+
11
+ from pathlib import Path
12
+ from typing import Any, Dict, List, Optional, Union
13
+ import logging
14
+
15
+ from .core.engine import AnalysisEngine
16
+ from .utils import log_error, log_info, log_warning
17
+
18
+ logger = logging.getLogger(__name__)
19
+
20
+ # Global engine instance (singleton pattern)
21
+ _engine: Optional[AnalysisEngine] = None
22
+
23
+
24
+ def get_engine() -> AnalysisEngine:
25
+ """
26
+ Get the global analysis engine instance.
27
+
28
+ Returns:
29
+ AnalysisEngine instance
30
+ """
31
+ global _engine
32
+ if _engine is None:
33
+ _engine = AnalysisEngine()
34
+ return _engine
35
+
36
+
37
+ def analyze_file(
38
+ file_path: Union[str, Path],
39
+ language: Optional[str] = None,
40
+ queries: Optional[List[str]] = None,
41
+ include_elements: bool = True,
42
+ include_details: bool = False, # Add for backward compatibility
43
+ include_queries: bool = True,
44
+ include_complexity: bool = False # Add for backward compatibility
45
+ ) -> Dict[str, Any]:
46
+ """
47
+ Analyze a source code file.
48
+
49
+ This is the main high-level function for file analysis. It handles
50
+ language detection, parsing, query execution, and element extraction.
51
+
52
+ Args:
53
+ file_path: Path to the source file to analyze
54
+ language: Programming language (auto-detected if not specified)
55
+ queries: List of query names to execute (all available if not specified)
56
+ include_elements: Whether to extract code elements
57
+ include_queries: Whether to execute queries
58
+ include_complexity: Whether to include complexity metrics (backward compatibility)
59
+
60
+ Returns:
61
+ Analysis results dictionary containing:
62
+ - success: Whether the analysis was successful
63
+ - file_info: Basic file information
64
+ - language_info: Detected/specified language information
65
+ - ast_info: Abstract syntax tree information
66
+ - query_results: Results from executed queries (if include_queries=True)
67
+ - elements: Extracted code elements (if include_elements=True)
68
+ - error: Error message (if success=False)
69
+ """
70
+ try:
71
+ engine = get_engine()
72
+
73
+ # Perform the analysis
74
+ analysis_result = engine.analyze_file(file_path, language)
75
+
76
+ # Convert AnalysisResult to expected API format
77
+ result = {
78
+ "success": analysis_result.success,
79
+ "file_info": {
80
+ "path": str(file_path),
81
+ "exists": Path(file_path).exists(),
82
+ "size": Path(file_path).stat().st_size if Path(file_path).exists() else 0
83
+ },
84
+ "language_info": {
85
+ "language": analysis_result.language,
86
+ "detected": language is None # True if language was auto-detected
87
+ },
88
+ "ast_info": {
89
+ "node_count": analysis_result.node_count,
90
+ "line_count": analysis_result.line_count
91
+ }
92
+ }
93
+
94
+ # Add elements if requested and available
95
+ if include_elements and hasattr(analysis_result, 'elements'):
96
+ result["elements"] = [
97
+ {
98
+ "name": elem.name,
99
+ "type": type(elem).__name__.lower(),
100
+ "start_line": elem.start_line,
101
+ "end_line": elem.end_line,
102
+ "raw_text": elem.raw_text,
103
+ "language": elem.language
104
+ }
105
+ for elem in analysis_result.elements
106
+ ]
107
+
108
+ # Add query results if requested and available
109
+ if include_queries and hasattr(analysis_result, 'query_results'):
110
+ result["query_results"] = analysis_result.query_results
111
+
112
+ # Add error message if analysis failed
113
+ if not analysis_result.success and analysis_result.error_message:
114
+ result["error"] = analysis_result.error_message
115
+
116
+ # Filter results based on options
117
+ if not include_elements and "elements" in result:
118
+ del result["elements"]
119
+
120
+ if not include_queries and "query_results" in result:
121
+ del result["query_results"]
122
+
123
+ return result
124
+
125
+ except FileNotFoundError as e:
126
+ # Re-raise FileNotFoundError for tests that expect it
127
+ raise e
128
+ except Exception as e:
129
+ log_error(f"API analyze_file failed: {e}")
130
+ return {
131
+ "success": False,
132
+ "error": str(e),
133
+ "file_info": {"path": str(file_path), "exists": Path(file_path).exists()}
134
+ }
135
+
136
+
137
+ def analyze_code(
138
+ source_code: str,
139
+ language: str,
140
+ queries: Optional[List[str]] = None,
141
+ include_elements: bool = True,
142
+ include_queries: bool = True
143
+ ) -> Dict[str, Any]:
144
+ """
145
+ Analyze source code directly (without file).
146
+
147
+ Args:
148
+ source_code: Source code string to analyze
149
+ language: Programming language
150
+ queries: List of query names to execute (all available if not specified)
151
+ include_elements: Whether to extract code elements
152
+ include_queries: Whether to execute queries
153
+
154
+ Returns:
155
+ Analysis results dictionary
156
+ """
157
+ try:
158
+ engine = get_engine()
159
+
160
+ # Perform the analysis
161
+ analysis_result = engine.analyze_code(source_code, language)
162
+
163
+ # Convert AnalysisResult to expected API format
164
+ result = {
165
+ "success": analysis_result.success,
166
+ "language_info": {
167
+ "language": analysis_result.language,
168
+ "detected": False # Language was explicitly provided
169
+ },
170
+ "ast_info": {
171
+ "node_count": analysis_result.node_count,
172
+ "line_count": analysis_result.line_count
173
+ }
174
+ }
175
+
176
+ # Add elements if requested and available
177
+ if include_elements and hasattr(analysis_result, 'elements'):
178
+ result["elements"] = [
179
+ {
180
+ "name": elem.name,
181
+ "type": type(elem).__name__.lower(),
182
+ "start_line": elem.start_line,
183
+ "end_line": elem.end_line,
184
+ "raw_text": elem.raw_text,
185
+ "language": elem.language
186
+ }
187
+ for elem in analysis_result.elements
188
+ ]
189
+
190
+ # Add query results if requested and available
191
+ if include_queries and hasattr(analysis_result, 'query_results'):
192
+ result["query_results"] = analysis_result.query_results
193
+
194
+ # Add error message if analysis failed
195
+ if not analysis_result.success and analysis_result.error_message:
196
+ result["error"] = analysis_result.error_message
197
+
198
+ # Filter results based on options
199
+ if not include_elements and "elements" in result:
200
+ del result["elements"]
201
+
202
+ if not include_queries and "query_results" in result:
203
+ del result["query_results"]
204
+
205
+ return result
206
+
207
+ except Exception as e:
208
+ log_error(f"API analyze_code failed: {e}")
209
+ return {
210
+ "success": False,
211
+ "error": str(e)
212
+ }
213
+
214
+
215
+ def get_supported_languages() -> List[str]:
216
+ """
217
+ Get list of all supported programming languages.
218
+
219
+ Returns:
220
+ List of supported language names
221
+ """
222
+ try:
223
+ engine = get_engine()
224
+ return engine.get_supported_languages()
225
+ except Exception as e:
226
+ log_error(f"Failed to get supported languages: {e}")
227
+ return []
228
+
229
+
230
+ def get_available_queries(language: str) -> List[str]:
231
+ """
232
+ Get available queries for a specific language.
233
+
234
+ Args:
235
+ language: Programming language name
236
+
237
+ Returns:
238
+ List of available query names
239
+ """
240
+ try:
241
+ engine = get_engine()
242
+ # Try to get plugin and its supported queries
243
+ plugin = engine._get_language_plugin(language)
244
+ if plugin and hasattr(plugin, 'get_supported_queries'):
245
+ return plugin.get_supported_queries()
246
+ else:
247
+ # Return default queries
248
+ return ['class', 'method', 'field']
249
+ except Exception as e:
250
+ log_error(f"Failed to get available queries for {language}: {e}")
251
+ return []
252
+
253
+
254
+ def is_language_supported(language: str) -> bool:
255
+ """
256
+ Check if a programming language is supported.
257
+
258
+ Args:
259
+ language: Programming language name
260
+
261
+ Returns:
262
+ True if the language is supported
263
+ """
264
+ try:
265
+ supported_languages = get_supported_languages()
266
+ return language.lower() in [lang.lower() for lang in supported_languages]
267
+ except Exception as e:
268
+ log_error(f"Failed to check language support for {language}: {e}")
269
+ return False
270
+
271
+
272
+ def detect_language(file_path: Union[str, Path]) -> Optional[str]:
273
+ """
274
+ Detect programming language from file path.
275
+
276
+ Args:
277
+ file_path: Path to the file
278
+
279
+ Returns:
280
+ Detected language name or None
281
+ """
282
+ try:
283
+ engine = get_engine()
284
+ # Use language_detector instead of language_registry
285
+ return engine.language_detector.detect_from_extension(str(file_path))
286
+ except Exception as e:
287
+ log_error(f"Failed to detect language for {file_path}: {e}")
288
+ return None
289
+
290
+
291
+ def get_file_extensions(language: str) -> List[str]:
292
+ """
293
+ Get file extensions for a specific language.
294
+
295
+ Args:
296
+ language: Programming language name
297
+
298
+ Returns:
299
+ List of file extensions
300
+ """
301
+ try:
302
+ engine = get_engine()
303
+ # Use language_detector to get extensions
304
+ if hasattr(engine.language_detector, 'get_extensions_for_language'):
305
+ return engine.language_detector.get_extensions_for_language(language)
306
+ else:
307
+ # Fallback: return common extensions
308
+ extension_map = {
309
+ 'java': ['.java'],
310
+ 'python': ['.py'],
311
+ 'javascript': ['.js'],
312
+ 'typescript': ['.ts'],
313
+ 'c': ['.c'],
314
+ 'cpp': ['.cpp', '.cxx', '.cc'],
315
+ 'go': ['.go'],
316
+ 'rust': ['.rs']
317
+ }
318
+ return extension_map.get(language.lower(), [])
319
+ except Exception as e:
320
+ log_error(f"Failed to get extensions for {language}: {e}")
321
+ return []
322
+
323
+
324
+ def validate_file(file_path: Union[str, Path]) -> Dict[str, Any]:
325
+ """
326
+ Validate a source code file without full analysis.
327
+
328
+ Args:
329
+ file_path: Path to the file to validate
330
+
331
+ Returns:
332
+ Validation results dictionary
333
+ """
334
+ file_path = Path(file_path)
335
+
336
+ result = {
337
+ "valid": False,
338
+ "exists": file_path.exists(),
339
+ "readable": False,
340
+ "language": None,
341
+ "supported": False,
342
+ "size": 0,
343
+ "errors": []
344
+ }
345
+
346
+ try:
347
+ # Check if file exists
348
+ if not file_path.exists():
349
+ result["errors"].append("File does not exist")
350
+ return result
351
+
352
+ # Check if file is readable
353
+ try:
354
+ with open(file_path, 'r', encoding='utf-8') as f:
355
+ content = f.read(100) # Read first 100 chars to test
356
+ result["readable"] = True
357
+ result["size"] = file_path.stat().st_size
358
+ except Exception as e:
359
+ result["errors"].append(f"File is not readable: {e}")
360
+ return result
361
+
362
+ # Detect language
363
+ language = detect_language(file_path)
364
+ result["language"] = language
365
+
366
+ if language:
367
+ result["supported"] = is_language_supported(language)
368
+ if not result["supported"]:
369
+ result["errors"].append(f"Language '{language}' is not supported")
370
+ else:
371
+ result["errors"].append("Could not detect programming language")
372
+
373
+ # If we got this far with no errors, the file is valid
374
+ result["valid"] = len(result["errors"]) == 0
375
+
376
+ except Exception as e:
377
+ result["errors"].append(f"Validation failed: {e}")
378
+
379
+ return result
380
+
381
+
382
+ def get_framework_info() -> Dict[str, Any]:
383
+ """
384
+ Get information about the framework and its capabilities.
385
+
386
+ Returns:
387
+ Framework information dictionary
388
+ """
389
+ try:
390
+ engine = get_engine()
391
+
392
+ return {
393
+ "name": "tree-sitter-analyzer",
394
+ "version": "2.0.0", # New architecture version
395
+ "supported_languages": engine.get_supported_languages(),
396
+ "total_languages": len(engine.get_supported_languages()),
397
+ "plugin_info": {
398
+ "manager_available": engine.plugin_manager is not None,
399
+ "loaded_plugins": len(engine.plugin_manager.get_supported_languages()) if engine.plugin_manager else 0
400
+ },
401
+ "core_components": [
402
+ "AnalysisEngine",
403
+ "Parser",
404
+ "QueryExecutor",
405
+ "PluginManager",
406
+ "LanguageDetector"
407
+ ]
408
+ }
409
+ except Exception as e:
410
+ log_error(f"Failed to get framework info: {e}")
411
+ return {
412
+ "name": "tree-sitter-analyzer",
413
+ "version": "2.0.0",
414
+ "error": str(e)
415
+ }
416
+
417
+
418
+ def execute_query(
419
+ file_path: Union[str, Path],
420
+ query_name: str,
421
+ language: Optional[str] = None
422
+ ) -> Dict[str, Any]:
423
+ """
424
+ Execute a specific query against a file.
425
+
426
+ Args:
427
+ file_path: Path to the source file
428
+ query_name: Name of the query to execute
429
+ language: Programming language (auto-detected if not specified)
430
+
431
+ Returns:
432
+ Query execution results
433
+ """
434
+ try:
435
+ # Analyze with only the specified query
436
+ result = analyze_file(
437
+ file_path,
438
+ language=language,
439
+ queries=[query_name],
440
+ include_elements=False,
441
+ include_queries=True
442
+ )
443
+
444
+ if result["success"] and "query_results" in result:
445
+ query_results = result["query_results"].get(query_name, [])
446
+ return {
447
+ "success": True,
448
+ "query_name": query_name,
449
+ "results": query_results,
450
+ "count": len(query_results),
451
+ "language": result.get("language_info", {}).get("language"),
452
+ "file_path": str(file_path)
453
+ }
454
+ else:
455
+ return {
456
+ "success": False,
457
+ "query_name": query_name,
458
+ "error": result.get("error", "Unknown error"),
459
+ "file_path": str(file_path)
460
+ }
461
+
462
+ except Exception as e:
463
+ log_error(f"Query execution failed: {e}")
464
+ return {
465
+ "success": False,
466
+ "query_name": query_name,
467
+ "error": str(e),
468
+ "file_path": str(file_path)
469
+ }
470
+
471
+
472
+ def extract_elements(
473
+ file_path: Union[str, Path],
474
+ language: Optional[str] = None,
475
+ element_types: Optional[List[str]] = None
476
+ ) -> Dict[str, Any]:
477
+ """
478
+ Extract code elements from a file.
479
+
480
+ Args:
481
+ file_path: Path to the source file
482
+ language: Programming language (auto-detected if not specified)
483
+ element_types: Types of elements to extract (all if not specified)
484
+
485
+ Returns:
486
+ Element extraction results
487
+ """
488
+ try:
489
+ # Analyze with only element extraction
490
+ result = analyze_file(
491
+ file_path,
492
+ language=language,
493
+ include_elements=True,
494
+ include_queries=False
495
+ )
496
+
497
+ if result["success"] and "elements" in result:
498
+ elements = result["elements"]
499
+
500
+ # Filter by element types if specified
501
+ if element_types:
502
+ filtered_elements = []
503
+ for element in elements:
504
+ if any(etype.lower() in element.get("type", "").lower() for etype in element_types):
505
+ filtered_elements.append(element)
506
+ elements = filtered_elements
507
+
508
+ return {
509
+ "success": True,
510
+ "elements": elements,
511
+ "count": len(elements),
512
+ "language": result.get("language_info", {}).get("language"),
513
+ "file_path": str(file_path)
514
+ }
515
+ else:
516
+ return {
517
+ "success": False,
518
+ "error": result.get("error", "Unknown error"),
519
+ "file_path": str(file_path)
520
+ }
521
+
522
+ except Exception as e:
523
+ log_error(f"Element extraction failed: {e}")
524
+ return {
525
+ "success": False,
526
+ "error": str(e),
527
+ "file_path": str(file_path)
528
+ }
529
+
530
+
531
+ # Convenience functions for backward compatibility
532
+ def analyze(file_path: Union[str, Path], **kwargs) -> Dict[str, Any]:
533
+ """Convenience function that aliases to analyze_file."""
534
+ return analyze_file(file_path, **kwargs)
535
+
536
+
537
+ def get_languages() -> List[str]:
538
+ """Convenience function that aliases to get_supported_languages."""
539
+ return get_supported_languages()
@@ -0,0 +1,39 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ CLI Package
5
+
6
+ Command-line interface components using the Command Pattern.
7
+ """
8
+
9
+ from .info_commands import (
10
+ DescribeQueryCommand,
11
+ InfoCommand,
12
+ ListQueriesCommand,
13
+ ShowExtensionsCommand,
14
+ ShowLanguagesCommand,
15
+ )
16
+
17
+ # Modern framework imports
18
+ try:
19
+ from ..core.analysis_engine import get_analysis_engine
20
+ from ..query_loader import QueryLoader
21
+ from ..cli_main import main
22
+ query_loader = QueryLoader()
23
+ except ImportError:
24
+ # Minimal fallback for import safety
25
+ get_analysis_engine = None
26
+ main = None
27
+ query_loader = None
28
+
29
+ __all__ = [
30
+ "InfoCommand",
31
+ "ListQueriesCommand",
32
+ "DescribeQueryCommand",
33
+ "ShowLanguagesCommand",
34
+ "ShowExtensionsCommand",
35
+ # Core framework exports
36
+ "query_loader",
37
+ "get_analysis_engine",
38
+ "main",
39
+ ]