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,366 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Language Registry
5
+
6
+ Manages mapping between languages, file extensions, and plugins.
7
+ Provides language detection and plugin resolution services.
8
+ """
9
+
10
+ from pathlib import Path
11
+ from typing import Dict, List, Optional, Set
12
+ import logging
13
+
14
+ from .base import LanguagePlugin
15
+ from ..utils import log_error, log_info, log_warning, log_debug
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class LanguageRegistry:
21
+ """
22
+ Registry for managing language-to-plugin mappings.
23
+
24
+ This class handles:
25
+ - Mapping languages to plugins
26
+ - Mapping file extensions to languages
27
+ - Language detection from file paths
28
+ - Plugin resolution for languages
29
+ """
30
+
31
+ def __init__(self):
32
+ """Initialize the language registry."""
33
+ self._plugins: Dict[str, LanguagePlugin] = {}
34
+ self._extension_map: Dict[str, str] = {} # extension -> language
35
+ self._language_aliases: Dict[str, str] = {} # alias -> canonical_language
36
+
37
+ # Initialize common language aliases
38
+ self._init_language_aliases()
39
+
40
+ def _init_language_aliases(self):
41
+ """Initialize common language aliases."""
42
+ self._language_aliases.update({
43
+ 'js': 'javascript',
44
+ 'ts': 'typescript',
45
+ 'py': 'python',
46
+ 'rb': 'ruby',
47
+ 'cpp': 'c++',
48
+ 'cxx': 'c++',
49
+ 'cc': 'c++',
50
+ 'c++': 'cpp', # Normalize c++ to cpp
51
+ })
52
+
53
+ def register_plugin(self, plugin: LanguagePlugin) -> bool:
54
+ """
55
+ Register a language plugin.
56
+
57
+ Args:
58
+ plugin: Plugin instance to register
59
+
60
+ Returns:
61
+ True if registration was successful
62
+ """
63
+ try:
64
+ language = plugin.get_language_name().lower()
65
+ extensions = plugin.get_file_extensions()
66
+
67
+ # Check for conflicts
68
+ if language in self._plugins:
69
+ existing_plugin = self._plugins[language]
70
+ log_warning(
71
+ f"Language '{language}' already registered by {existing_plugin.__class__.__name__}, "
72
+ f"replacing with {plugin.__class__.__name__}"
73
+ )
74
+
75
+ # Register the plugin
76
+ self._plugins[language] = plugin
77
+
78
+ # Register file extensions
79
+ for ext in extensions:
80
+ ext = ext.lower()
81
+ if not ext.startswith('.'):
82
+ ext = '.' + ext
83
+
84
+ if ext in self._extension_map:
85
+ existing_lang = self._extension_map[ext]
86
+ log_debug(f"Extension '{ext}' already mapped to '{existing_lang}', overriding with '{language}'")
87
+
88
+ self._extension_map[ext] = language
89
+
90
+ log_debug(f"Registered plugin for language '{language}' with extensions: {extensions}")
91
+ return True
92
+
93
+ except Exception as e:
94
+ log_error(f"Failed to register plugin: {e}")
95
+ return False
96
+
97
+ def get_plugin(self, language: str) -> Optional[LanguagePlugin]:
98
+ """
99
+ Get plugin for a specific language.
100
+
101
+ Args:
102
+ language: Programming language name
103
+
104
+ Returns:
105
+ Plugin instance or None if not found
106
+ """
107
+ # Normalize language name
108
+ language = self._normalize_language(language)
109
+ return self._plugins.get(language)
110
+
111
+ def detect_language_from_file(self, file_path: Path) -> Optional[str]:
112
+ """
113
+ Detect programming language from file path.
114
+
115
+ Args:
116
+ file_path: Path to the file
117
+
118
+ Returns:
119
+ Detected language name or None
120
+ """
121
+ if file_path is None:
122
+ return None
123
+
124
+ if isinstance(file_path, str):
125
+ file_path = Path(file_path)
126
+
127
+ # Get file extension
128
+ extension = file_path.suffix.lower()
129
+
130
+ # Look up in extension map
131
+ language = self._extension_map.get(extension)
132
+ if language:
133
+ return language
134
+
135
+ # Try compound extensions (e.g., .test.js, .spec.ts)
136
+ if len(file_path.suffixes) > 1:
137
+ # Try the last extension
138
+ last_ext = file_path.suffixes[-1].lower()
139
+ language = self._extension_map.get(last_ext)
140
+ if language:
141
+ return language
142
+
143
+ # Special cases based on filename patterns
144
+ filename = file_path.name.lower()
145
+
146
+ # Common configuration files
147
+ config_patterns = {
148
+ 'makefile': 'make',
149
+ 'dockerfile': 'dockerfile',
150
+ 'vagrantfile': 'ruby',
151
+ 'rakefile': 'ruby',
152
+ 'gemfile': 'ruby',
153
+ 'podfile': 'ruby',
154
+ }
155
+
156
+ for pattern, lang in config_patterns.items():
157
+ if filename == pattern or filename.startswith(pattern):
158
+ if lang in self._plugins:
159
+ return lang
160
+
161
+ log_debug(f"Could not detect language for file: {file_path}")
162
+ return None
163
+
164
+ def get_supported_languages(self) -> List[str]:
165
+ """
166
+ Get list of all supported languages.
167
+
168
+ Returns:
169
+ List of supported language names
170
+ """
171
+ return list(self._plugins.keys())
172
+
173
+ def get_supported_extensions(self) -> List[str]:
174
+ """
175
+ Get list of all supported file extensions.
176
+
177
+ Returns:
178
+ List of supported file extensions
179
+ """
180
+ return list(self._extension_map.keys())
181
+
182
+ def get_extensions_for_language(self, language: str) -> List[str]:
183
+ """
184
+ Get file extensions for a specific language.
185
+
186
+ Args:
187
+ language: Programming language name
188
+
189
+ Returns:
190
+ List of file extensions for the language
191
+ """
192
+ language = self._normalize_language(language)
193
+ plugin = self._plugins.get(language)
194
+
195
+ if plugin:
196
+ return plugin.get_file_extensions()
197
+
198
+ return []
199
+
200
+ def get_language_for_extension(self, extension: str) -> Optional[str]:
201
+ """
202
+ Get language for a specific file extension.
203
+
204
+ Args:
205
+ extension: File extension (with or without leading dot)
206
+
207
+ Returns:
208
+ Language name or None if not found
209
+ """
210
+ if not extension.startswith('.'):
211
+ extension = '.' + extension
212
+
213
+ return self._extension_map.get(extension.lower())
214
+
215
+ def is_language_supported(self, language: str) -> bool:
216
+ """
217
+ Check if a language is supported.
218
+
219
+ Args:
220
+ language: Programming language name
221
+
222
+ Returns:
223
+ True if the language is supported
224
+ """
225
+ language = self._normalize_language(language)
226
+ return language in self._plugins
227
+
228
+ def is_extension_supported(self, extension: str) -> bool:
229
+ """
230
+ Check if a file extension is supported.
231
+
232
+ Args:
233
+ extension: File extension (with or without leading dot)
234
+
235
+ Returns:
236
+ True if the extension is supported
237
+ """
238
+ if not extension.startswith('.'):
239
+ extension = '.' + extension
240
+
241
+ return extension.lower() in self._extension_map
242
+
243
+ def _normalize_language(self, language: str) -> str:
244
+ """
245
+ Normalize language name using aliases.
246
+
247
+ Args:
248
+ language: Language name to normalize
249
+
250
+ Returns:
251
+ Normalized language name
252
+ """
253
+ if language is None:
254
+ return ""
255
+ language = language.lower().strip()
256
+ return self._language_aliases.get(language, language)
257
+
258
+ def add_language_alias(self, alias: str, canonical_language: str) -> bool:
259
+ """
260
+ Add a language alias.
261
+
262
+ Args:
263
+ alias: Alias name
264
+ canonical_language: Canonical language name
265
+
266
+ Returns:
267
+ True if alias was added successfully
268
+ """
269
+ try:
270
+ alias = alias.lower().strip()
271
+ canonical_language = canonical_language.lower().strip()
272
+
273
+ if canonical_language not in self._plugins:
274
+ log_warning(f"Cannot add alias '{alias}' for unsupported language '{canonical_language}'")
275
+ return False
276
+
277
+ self._language_aliases[alias] = canonical_language
278
+ log_debug(f"Added language alias: '{alias}' -> '{canonical_language}'")
279
+ return True
280
+
281
+ except Exception as e:
282
+ log_error(f"Failed to add language alias: {e}")
283
+ return False
284
+
285
+ def get_registry_info(self) -> Dict[str, any]:
286
+ """
287
+ Get comprehensive information about the registry.
288
+
289
+ "plugin_count": len(self._plugins),
290
+ Returns:
291
+ Dictionary containing registry information
292
+ """
293
+ return {
294
+ "plugin_count": len(self._plugins),
295
+ "supported_languages": len(self._plugins),
296
+ "supported_extensions": len(self._extension_map),
297
+ "language_aliases": len(self._language_aliases),
298
+ "languages": list(self._plugins.keys()),
299
+ "extensions": list(self._extension_map.keys()),
300
+ "aliases": dict(self._language_aliases),
301
+ "extension_mapping": dict(self._extension_map)
302
+ }
303
+
304
+ def find_plugins_for_file(self, file_path: Path) -> List[LanguagePlugin]:
305
+ """
306
+ Find all possible plugins for a file (useful for ambiguous cases).
307
+
308
+ Args:
309
+ file_path: Path to the file
310
+
311
+ Returns:
312
+ List of possible plugins
313
+ """
314
+ plugins = []
315
+
316
+ # Primary detection
317
+ language = self.detect_language_from_file(file_path)
318
+ if language:
319
+ plugin = self.get_plugin(language)
320
+ if plugin:
321
+ plugins.append(plugin)
322
+
323
+ # Check if any plugins explicitly support this file
324
+ for plugin in self._plugins.values():
325
+ if hasattr(plugin, 'is_applicable') and plugin.is_applicable(str(file_path)):
326
+ if plugin not in plugins:
327
+ plugins.append(plugin)
328
+
329
+ return plugins
330
+
331
+ def clear(self):
332
+ """Clear all registered plugins and mappings."""
333
+ self._plugins.clear()
334
+ self._extension_map.clear()
335
+ # Keep language aliases as they're static
336
+ log_debug("Cleared language registry")
337
+
338
+ def unregister_plugin(self, language: str) -> bool:
339
+ """
340
+ Unregister a plugin for a specific language.
341
+
342
+ Args:
343
+ language: Programming language name
344
+
345
+ Returns:
346
+ True if unregistration was successful
347
+ """
348
+ language = self._normalize_language(language)
349
+
350
+ if language not in self._plugins:
351
+ return False
352
+
353
+ # Remove the plugin
354
+ plugin = self._plugins.pop(language)
355
+
356
+ # Remove associated extensions
357
+ extensions_to_remove = []
358
+ for ext, lang in self._extension_map.items():
359
+ if lang == language:
360
+ extensions_to_remove.append(ext)
361
+
362
+ for ext in extensions_to_remove:
363
+ del self._extension_map[ext]
364
+
365
+ log_debug(f"Unregistered plugin for language '{language}'")
366
+ return True
@@ -0,0 +1,27 @@
1
+ #!/usr/bin/env python3
2
+ # -*- coding: utf-8 -*-
3
+ """
4
+ Language-specific Tree-sitter queries package.
5
+
6
+ This package provides Tree-sitter queries for various programming languages.
7
+ Each language has its own module with predefined queries for common code elements.
8
+
9
+ Supported languages:
10
+ - Java
11
+ - JavaScript
12
+ - Python
13
+ - TypeScript
14
+
15
+ Usage:
16
+ from tree_sitter_analyzer.queries import get_query, list_queries
17
+
18
+ # Get a specific query
19
+ query = get_query('java', 'classes')
20
+
21
+ # List all queries for a language
22
+ queries = list_queries('python')
23
+ """
24
+
25
+ from ..query_loader import get_query, is_language_supported, list_queries, query_loader
26
+
27
+ __all__ = ["get_query", "list_queries", "is_language_supported", "query_loader"]