tree-sitter-analyzer 1.9.1__py3-none-any.whl → 1.9.3__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 (62) hide show
  1. tree_sitter_analyzer/__init__.py +1 -1
  2. tree_sitter_analyzer/api.py +10 -6
  3. tree_sitter_analyzer/cli/argument_validator.py +1 -1
  4. tree_sitter_analyzer/cli/commands/advanced_command.py +3 -6
  5. tree_sitter_analyzer/cli/commands/query_command.py +3 -1
  6. tree_sitter_analyzer/cli/commands/table_command.py +3 -3
  7. tree_sitter_analyzer/constants.py +5 -3
  8. tree_sitter_analyzer/core/analysis_engine.py +1 -1
  9. tree_sitter_analyzer/core/cache_service.py +1 -1
  10. tree_sitter_analyzer/core/engine.py +1 -1
  11. tree_sitter_analyzer/core/query.py +0 -2
  12. tree_sitter_analyzer/exceptions.py +1 -1
  13. tree_sitter_analyzer/file_handler.py +6 -6
  14. tree_sitter_analyzer/formatters/base_formatter.py +1 -1
  15. tree_sitter_analyzer/formatters/html_formatter.py +24 -14
  16. tree_sitter_analyzer/formatters/javascript_formatter.py +28 -21
  17. tree_sitter_analyzer/formatters/language_formatter_factory.py +7 -4
  18. tree_sitter_analyzer/formatters/markdown_formatter.py +4 -4
  19. tree_sitter_analyzer/formatters/python_formatter.py +4 -4
  20. tree_sitter_analyzer/formatters/typescript_formatter.py +1 -1
  21. tree_sitter_analyzer/interfaces/mcp_adapter.py +4 -2
  22. tree_sitter_analyzer/interfaces/mcp_server.py +10 -10
  23. tree_sitter_analyzer/language_detector.py +30 -5
  24. tree_sitter_analyzer/language_loader.py +46 -26
  25. tree_sitter_analyzer/languages/css_plugin.py +6 -6
  26. tree_sitter_analyzer/languages/html_plugin.py +12 -8
  27. tree_sitter_analyzer/languages/java_plugin.py +307 -520
  28. tree_sitter_analyzer/languages/javascript_plugin.py +22 -78
  29. tree_sitter_analyzer/languages/markdown_plugin.py +277 -297
  30. tree_sitter_analyzer/languages/python_plugin.py +47 -85
  31. tree_sitter_analyzer/languages/typescript_plugin.py +48 -123
  32. tree_sitter_analyzer/mcp/resources/project_stats_resource.py +14 -8
  33. tree_sitter_analyzer/mcp/server.py +38 -23
  34. tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +10 -7
  35. tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py +51 -7
  36. tree_sitter_analyzer/mcp/tools/fd_rg_utils.py +15 -2
  37. tree_sitter_analyzer/mcp/tools/find_and_grep_tool.py +8 -6
  38. tree_sitter_analyzer/mcp/tools/list_files_tool.py +6 -6
  39. tree_sitter_analyzer/mcp/tools/search_content_tool.py +48 -19
  40. tree_sitter_analyzer/mcp/tools/table_format_tool.py +13 -8
  41. tree_sitter_analyzer/mcp/utils/file_output_manager.py +8 -3
  42. tree_sitter_analyzer/mcp/utils/gitignore_detector.py +24 -12
  43. tree_sitter_analyzer/mcp/utils/path_resolver.py +2 -2
  44. tree_sitter_analyzer/models.py +16 -0
  45. tree_sitter_analyzer/mypy_current_errors.txt +2 -0
  46. tree_sitter_analyzer/plugins/base.py +66 -0
  47. tree_sitter_analyzer/queries/java.py +1 -1
  48. tree_sitter_analyzer/queries/javascript.py +3 -8
  49. tree_sitter_analyzer/queries/markdown.py +1 -1
  50. tree_sitter_analyzer/queries/python.py +2 -2
  51. tree_sitter_analyzer/security/boundary_manager.py +2 -5
  52. tree_sitter_analyzer/security/regex_checker.py +2 -2
  53. tree_sitter_analyzer/security/validator.py +5 -1
  54. tree_sitter_analyzer/table_formatter.py +4 -4
  55. tree_sitter_analyzer/utils/__init__.py +27 -116
  56. tree_sitter_analyzer/{utils.py → utils/logging.py} +2 -2
  57. tree_sitter_analyzer/utils/tree_sitter_compat.py +2 -2
  58. {tree_sitter_analyzer-1.9.1.dist-info → tree_sitter_analyzer-1.9.3.dist-info}/METADATA +70 -30
  59. tree_sitter_analyzer-1.9.3.dist-info/RECORD +110 -0
  60. tree_sitter_analyzer-1.9.1.dist-info/RECORD +0 -109
  61. {tree_sitter_analyzer-1.9.1.dist-info → tree_sitter_analyzer-1.9.3.dist-info}/WHEEL +0 -0
  62. {tree_sitter_analyzer-1.9.1.dist-info → tree_sitter_analyzer-1.9.3.dist-info}/entry_points.txt +0 -0
@@ -321,9 +321,6 @@ class LanguageDetector:
321
321
  if not language or language.strip() == "":
322
322
  return "unknown"
323
323
  return language
324
- else:
325
- # Fallback for unexpected result format
326
- return "unknown"
327
324
 
328
325
  def is_supported(self, language: str) -> bool:
329
326
  """
@@ -335,7 +332,21 @@ class LanguageDetector:
335
332
  Returns:
336
333
  Support status
337
334
  """
338
- return language in self.SUPPORTED_LANGUAGES
335
+ # First check the static list for basic support
336
+ if language in self.SUPPORTED_LANGUAGES:
337
+ return True
338
+
339
+ # Also check if we have a plugin for this language
340
+ try:
341
+ from .plugins.manager import PluginManager
342
+
343
+ plugin_manager = PluginManager()
344
+ plugin_manager.load_plugins() # Ensure plugins are loaded
345
+ supported_languages = plugin_manager.get_supported_languages()
346
+ return language in supported_languages
347
+ except Exception:
348
+ # Fallback to static list if plugin manager fails
349
+ return language in self.SUPPORTED_LANGUAGES
339
350
 
340
351
  def get_supported_extensions(self) -> list[str]:
341
352
  """
@@ -509,4 +520,18 @@ def is_language_supported(language: str) -> bool:
509
520
  Returns:
510
521
  Support status
511
522
  """
512
- return detector.is_supported(language)
523
+ # First check the static list for basic support
524
+ if detector.is_supported(language):
525
+ return True
526
+
527
+ # Also check if we have a plugin for this language
528
+ try:
529
+ from .plugins.manager import PluginManager
530
+
531
+ plugin_manager = PluginManager()
532
+ plugin_manager.load_plugins() # Ensure plugins are loaded
533
+ supported_languages = plugin_manager.get_supported_languages()
534
+ return language in supported_languages
535
+ except Exception:
536
+ # Fallback to static list if plugin manager fails
537
+ return detector.is_supported(language)
@@ -92,7 +92,7 @@ class LanguageLoader:
92
92
  self._unavailable_languages.add(language)
93
93
  return False
94
94
 
95
- def load_language(self, language: str) -> Optional["Language"]:
95
+ def load_language(self, language: str) -> Any | None:
96
96
  """Load and return a tree-sitter Language object for the specified language"""
97
97
  if not TREE_SITTER_AVAILABLE:
98
98
  log_warning("Tree-sitter is not available")
@@ -131,16 +131,27 @@ class LanguageLoader:
131
131
  else:
132
132
  return None
133
133
 
134
- # Language オブジェクト作成(互換性対応)
134
+ # Language オブジェクト作成(新しいAPI対応)
135
135
  caps_or_lang = language_func()
136
- try:
137
- tree_sitter_language = tree_sitter.Language(caps_or_lang)
138
- except Exception:
139
- # 一部のパッケージは既に Language オブジェクトを返すため、そのまま使用
140
- tree_sitter_language = caps_or_lang # type: ignore[assignment]
141
136
 
142
- self._loaded_languages[language] = tree_sitter_language # type: ignore[assignment]
143
- return tree_sitter_language # type: ignore[return-value]
137
+ # 新しいtree-sitter APIでは、language_func()が直接Languageオブジェクトを返す
138
+ # 古いAPIではPyCapsuleを返すため、適切に処理する
139
+ if hasattr(caps_or_lang, "__class__") and "Language" in str(
140
+ type(caps_or_lang)
141
+ ):
142
+ # 既にLanguageオブジェクトの場合はそのまま使用
143
+ tree_sitter_language = caps_or_lang
144
+ else:
145
+ # PyCapsuleの場合は、Languageオブジェクトを作成
146
+ try:
147
+ # Use modern tree-sitter API - PyCapsule should be passed to Language constructor
148
+ tree_sitter_language = tree_sitter.Language(caps_or_lang)
149
+ except Exception as e:
150
+ log_warning(f"Failed to create Language object for {language}: {e}")
151
+ return None
152
+
153
+ self._loaded_languages[language] = tree_sitter_language
154
+ return tree_sitter_language
144
155
 
145
156
  except (ImportError, AttributeError, Exception) as e:
146
157
  log_warning(f"Failed to load language '{language}': {e}")
@@ -162,23 +173,32 @@ class LanguageLoader:
162
173
  return None
163
174
 
164
175
  try:
165
- # Prefer constructor with language for environments that require it
166
- try:
167
- parser = tree_sitter.Parser(tree_sitter_language)
168
- except Exception:
169
- # Fallback to no-arg constructor with setter for newer APIs
170
- parser = tree_sitter.Parser()
171
- if hasattr(parser, "set_language"):
172
- parser.set_language(tree_sitter_language)
173
- elif hasattr(parser, "language"):
174
- try:
175
- parser.language = tree_sitter_language
176
- except Exception as inner_e: # noqa: F841
177
- raise
178
- else:
179
- raise RuntimeError(
180
- "Unsupported Parser API: no way to set language"
181
- ) from None
176
+ # Create parser and set language properly
177
+ parser = tree_sitter.Parser()
178
+
179
+ # Ensure we have a proper Language object
180
+ if not hasattr(tree_sitter_language, "__class__") or "Language" not in str(
181
+ type(tree_sitter_language)
182
+ ):
183
+ log_warning(
184
+ f"Invalid language object for {language}: {type(tree_sitter_language)}"
185
+ )
186
+ return None
187
+
188
+ # Set language using the preferred method
189
+ if hasattr(parser, "set_language"):
190
+ parser.set_language(tree_sitter_language)
191
+ elif hasattr(parser, "language"):
192
+ parser.language = tree_sitter_language
193
+ else:
194
+ # Try constructor approach as last resort
195
+ try:
196
+ parser = tree_sitter.Parser(tree_sitter_language)
197
+ except Exception as e:
198
+ log_warning(
199
+ f"Failed to create parser with language constructor for {language}: {e}"
200
+ )
201
+ return None
182
202
 
183
203
  # Cache and return
184
204
  self._parser_cache[language] = parser
@@ -25,7 +25,7 @@ logger = logging.getLogger(__name__)
25
25
  class CssElementExtractor(ElementExtractor):
26
26
  """CSS-specific element extractor using tree-sitter-css"""
27
27
 
28
- def __init__(self):
28
+ def __init__(self) -> None:
29
29
  self.property_categories = {
30
30
  # CSS プロパティの分類システム
31
31
  "layout": [
@@ -100,7 +100,7 @@ class CssElementExtractor(ElementExtractor):
100
100
  self, tree: "tree_sitter.Tree", source_code: str
101
101
  ) -> list[StyleElement]:
102
102
  """Extract CSS rules using tree-sitter-css parser"""
103
- elements = []
103
+ elements: list[StyleElement] = []
104
104
 
105
105
  try:
106
106
  if hasattr(tree, "root_node"):
@@ -176,9 +176,9 @@ class CssElementExtractor(ElementExtractor):
176
176
  # Create StyleElement
177
177
  element = StyleElement(
178
178
  name=name,
179
- start_line=node.start_point[0] + 1
180
- if hasattr(node, "start_point")
181
- else 0,
179
+ start_line=(
180
+ node.start_point[0] + 1 if hasattr(node, "start_point") else 0
181
+ ),
182
182
  end_line=node.end_point[0] + 1 if hasattr(node, "end_point") else 0,
183
183
  raw_text=raw_text,
184
184
  language="css",
@@ -296,7 +296,7 @@ class CssElementExtractor(ElementExtractor):
296
296
  category_scores[category] += 1
297
297
 
298
298
  # Return category with highest score
299
- best_category = max(category_scores, key=category_scores.get)
299
+ best_category = max(category_scores, key=lambda k: category_scores[k])
300
300
  return best_category if category_scores[best_category] > 0 else "other"
301
301
 
302
302
  def _extract_node_text(self, node: "tree_sitter.Node", source_code: str) -> str:
@@ -25,7 +25,7 @@ logger = logging.getLogger(__name__)
25
25
  class HtmlElementExtractor(ElementExtractor):
26
26
  """HTML-specific element extractor using tree-sitter-html"""
27
27
 
28
- def __init__(self):
28
+ def __init__(self) -> None:
29
29
  self.element_categories = {
30
30
  # HTML要素の分類システム
31
31
  "structure": [
@@ -124,7 +124,7 @@ class HtmlElementExtractor(ElementExtractor):
124
124
  self, tree: "tree_sitter.Tree", source_code: str
125
125
  ) -> list[MarkupElement]:
126
126
  """Extract HTML elements using tree-sitter-html parser"""
127
- elements = []
127
+ elements: list[MarkupElement] = []
128
128
 
129
129
  try:
130
130
  if hasattr(tree, "root_node"):
@@ -167,18 +167,22 @@ class HtmlElementExtractor(ElementExtractor):
167
167
 
168
168
  def _is_html_element_node(self, node_type: str) -> bool:
169
169
  """Check if a node type represents an HTML element in tree-sitter-html grammar"""
170
+ # Only process top-level element nodes to avoid duplication
171
+ # tree-sitter-html structure: element contains start_tag/end_tag
172
+ # Processing only 'element' avoids counting start_tag separately
170
173
  html_element_types = [
171
174
  "element",
172
- "start_tag",
173
175
  "self_closing_tag",
174
176
  "script_element",
175
177
  "style_element",
176
- "void_element",
177
178
  ]
178
179
  return node_type in html_element_types
179
180
 
180
181
  def _create_markup_element(
181
- self, node: "tree_sitter.Node", source_code: str, parent: MarkupElement | None
182
+ self,
183
+ node: "tree_sitter.Node",
184
+ source_code: str,
185
+ parent: MarkupElement | None,
182
186
  ) -> MarkupElement | None:
183
187
  """Create MarkupElement from tree-sitter node using tree-sitter-html grammar"""
184
188
  try:
@@ -199,9 +203,9 @@ class HtmlElementExtractor(ElementExtractor):
199
203
  # Create MarkupElement
200
204
  element = MarkupElement(
201
205
  name=tag_name,
202
- start_line=node.start_point[0] + 1
203
- if hasattr(node, "start_point")
204
- else 0,
206
+ start_line=(
207
+ node.start_point[0] + 1 if hasattr(node, "start_point") else 0
208
+ ),
205
209
  end_line=node.end_point[0] + 1 if hasattr(node, "end_point") else 0,
206
210
  raw_text=raw_text,
207
211
  language="html",