tree-sitter-analyzer 1.8.4__py3-none-any.whl → 1.9.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 (64) hide show
  1. tree_sitter_analyzer/__init__.py +1 -1
  2. tree_sitter_analyzer/api.py +4 -4
  3. tree_sitter_analyzer/cli/argument_validator.py +29 -17
  4. tree_sitter_analyzer/cli/commands/advanced_command.py +7 -5
  5. tree_sitter_analyzer/cli/commands/structure_command.py +7 -5
  6. tree_sitter_analyzer/cli/commands/summary_command.py +10 -6
  7. tree_sitter_analyzer/cli/commands/table_command.py +8 -7
  8. tree_sitter_analyzer/cli/info_commands.py +1 -1
  9. tree_sitter_analyzer/cli_main.py +3 -2
  10. tree_sitter_analyzer/core/analysis_engine.py +5 -5
  11. tree_sitter_analyzer/core/cache_service.py +3 -1
  12. tree_sitter_analyzer/core/query.py +17 -5
  13. tree_sitter_analyzer/core/query_service.py +1 -1
  14. tree_sitter_analyzer/encoding_utils.py +3 -3
  15. tree_sitter_analyzer/exceptions.py +61 -50
  16. tree_sitter_analyzer/file_handler.py +3 -0
  17. tree_sitter_analyzer/formatters/base_formatter.py +10 -5
  18. tree_sitter_analyzer/formatters/formatter_registry.py +83 -68
  19. tree_sitter_analyzer/formatters/html_formatter.py +90 -54
  20. tree_sitter_analyzer/formatters/javascript_formatter.py +21 -16
  21. tree_sitter_analyzer/formatters/language_formatter_factory.py +7 -6
  22. tree_sitter_analyzer/formatters/markdown_formatter.py +247 -124
  23. tree_sitter_analyzer/formatters/python_formatter.py +61 -38
  24. tree_sitter_analyzer/formatters/typescript_formatter.py +113 -45
  25. tree_sitter_analyzer/interfaces/mcp_server.py +2 -2
  26. tree_sitter_analyzer/language_detector.py +6 -6
  27. tree_sitter_analyzer/language_loader.py +3 -1
  28. tree_sitter_analyzer/languages/css_plugin.py +120 -61
  29. tree_sitter_analyzer/languages/html_plugin.py +159 -62
  30. tree_sitter_analyzer/languages/java_plugin.py +42 -34
  31. tree_sitter_analyzer/languages/javascript_plugin.py +59 -30
  32. tree_sitter_analyzer/languages/markdown_plugin.py +402 -368
  33. tree_sitter_analyzer/languages/python_plugin.py +111 -64
  34. tree_sitter_analyzer/languages/typescript_plugin.py +241 -132
  35. tree_sitter_analyzer/mcp/server.py +22 -18
  36. tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +13 -8
  37. tree_sitter_analyzer/mcp/tools/base_tool.py +2 -2
  38. tree_sitter_analyzer/mcp/tools/fd_rg_utils.py +232 -26
  39. tree_sitter_analyzer/mcp/tools/find_and_grep_tool.py +31 -23
  40. tree_sitter_analyzer/mcp/tools/list_files_tool.py +21 -19
  41. tree_sitter_analyzer/mcp/tools/query_tool.py +17 -18
  42. tree_sitter_analyzer/mcp/tools/read_partial_tool.py +30 -31
  43. tree_sitter_analyzer/mcp/tools/search_content_tool.py +131 -77
  44. tree_sitter_analyzer/mcp/tools/table_format_tool.py +29 -16
  45. tree_sitter_analyzer/mcp/utils/file_output_factory.py +64 -51
  46. tree_sitter_analyzer/mcp/utils/file_output_manager.py +34 -24
  47. tree_sitter_analyzer/mcp/utils/gitignore_detector.py +8 -4
  48. tree_sitter_analyzer/models.py +7 -5
  49. tree_sitter_analyzer/plugins/base.py +9 -7
  50. tree_sitter_analyzer/plugins/manager.py +1 -0
  51. tree_sitter_analyzer/queries/css.py +2 -21
  52. tree_sitter_analyzer/queries/html.py +2 -15
  53. tree_sitter_analyzer/queries/markdown.py +30 -41
  54. tree_sitter_analyzer/queries/python.py +20 -5
  55. tree_sitter_analyzer/query_loader.py +5 -5
  56. tree_sitter_analyzer/security/validator.py +114 -86
  57. tree_sitter_analyzer/utils/__init__.py +58 -28
  58. tree_sitter_analyzer/utils/tree_sitter_compat.py +72 -65
  59. tree_sitter_analyzer/utils.py +26 -15
  60. {tree_sitter_analyzer-1.8.4.dist-info → tree_sitter_analyzer-1.9.0.dist-info}/METADATA +1 -1
  61. tree_sitter_analyzer-1.9.0.dist-info/RECORD +109 -0
  62. tree_sitter_analyzer-1.8.4.dist-info/RECORD +0 -109
  63. {tree_sitter_analyzer-1.8.4.dist-info → tree_sitter_analyzer-1.9.0.dist-info}/WHEEL +0 -0
  64. {tree_sitter_analyzer-1.8.4.dist-info → tree_sitter_analyzer-1.9.0.dist-info}/entry_points.txt +0 -0
@@ -8,7 +8,7 @@ selector parsing, and property analysis.
8
8
  """
9
9
 
10
10
  import logging
11
- from typing import TYPE_CHECKING, Any
11
+ from typing import TYPE_CHECKING
12
12
 
13
13
  from ..models import AnalysisResult, StyleElement
14
14
  from ..plugins.base import ElementExtractor, LanguagePlugin
@@ -28,15 +28,56 @@ class CssElementExtractor(ElementExtractor):
28
28
  def __init__(self):
29
29
  self.property_categories = {
30
30
  # CSS プロパティの分類システム
31
- "layout": ["display", "position", "float", "clear", "overflow", "visibility", "z-index"],
32
- "box_model": ["width", "height", "margin", "padding", "border", "box-sizing"],
33
- "typography": ["font", "color", "text", "line-height", "letter-spacing", "word-spacing"],
34
- "background": ["background", "background-color", "background-image", "background-position", "background-size"],
35
- "flexbox": ["flex", "justify-content", "align-items", "align-content", "flex-direction", "flex-wrap"],
31
+ "layout": [
32
+ "display",
33
+ "position",
34
+ "float",
35
+ "clear",
36
+ "overflow",
37
+ "visibility",
38
+ "z-index",
39
+ ],
40
+ "box_model": [
41
+ "width",
42
+ "height",
43
+ "margin",
44
+ "padding",
45
+ "border",
46
+ "box-sizing",
47
+ ],
48
+ "typography": [
49
+ "font",
50
+ "color",
51
+ "text",
52
+ "line-height",
53
+ "letter-spacing",
54
+ "word-spacing",
55
+ ],
56
+ "background": [
57
+ "background",
58
+ "background-color",
59
+ "background-image",
60
+ "background-position",
61
+ "background-size",
62
+ ],
63
+ "flexbox": [
64
+ "flex",
65
+ "justify-content",
66
+ "align-items",
67
+ "align-content",
68
+ "flex-direction",
69
+ "flex-wrap",
70
+ ],
36
71
  "grid": ["grid", "grid-template", "grid-area", "grid-column", "grid-row"],
37
72
  "animation": ["animation", "transition", "transform", "keyframes"],
38
- "responsive": ["media", "min-width", "max-width", "min-height", "max-height"],
39
- "other": []
73
+ "responsive": [
74
+ "media",
75
+ "min-width",
76
+ "max-width",
77
+ "min-height",
78
+ "max-height",
79
+ ],
80
+ "other": [],
40
81
  }
41
82
 
42
83
  def extract_functions(self, tree: "tree_sitter.Tree", source_code: str) -> list:
@@ -55,10 +96,12 @@ class CssElementExtractor(ElementExtractor):
55
96
  """CSS doesn't have imports in the traditional sense, return empty list"""
56
97
  return []
57
98
 
58
- def extract_css_rules(self, tree: "tree_sitter.Tree", source_code: str) -> list[StyleElement]:
99
+ def extract_css_rules(
100
+ self, tree: "tree_sitter.Tree", source_code: str
101
+ ) -> list[StyleElement]:
59
102
  """Extract CSS rules using tree-sitter-css parser"""
60
103
  elements = []
61
-
104
+
62
105
  try:
63
106
  if hasattr(tree, "root_node"):
64
107
  self._traverse_for_css_rules(tree.root_node, elements, source_code)
@@ -68,10 +111,7 @@ class CssElementExtractor(ElementExtractor):
68
111
  return elements
69
112
 
70
113
  def _traverse_for_css_rules(
71
- self,
72
- node: "tree_sitter.Node",
73
- elements: list[StyleElement],
74
- source_code: str
114
+ self, node: "tree_sitter.Node", elements: list[StyleElement], source_code: str
75
115
  ) -> None:
76
116
  """Traverse tree to find CSS rules using tree-sitter-css grammar"""
77
117
  if hasattr(node, "type") and self._is_css_rule_node(node.type):
@@ -99,14 +139,12 @@ class CssElementExtractor(ElementExtractor):
99
139
  "font_face_statement",
100
140
  "page_statement",
101
141
  "charset_statement",
102
- "namespace_statement"
142
+ "namespace_statement",
103
143
  ]
104
144
  return node_type in css_rule_types
105
145
 
106
146
  def _create_style_element(
107
- self,
108
- node: "tree_sitter.Node",
109
- source_code: str
147
+ self, node: "tree_sitter.Node", source_code: str
110
148
  ) -> StyleElement | None:
111
149
  """Create StyleElement from tree-sitter node using tree-sitter-css grammar"""
112
150
  try:
@@ -116,7 +154,12 @@ class CssElementExtractor(ElementExtractor):
116
154
  properties = self._extract_properties(node, source_code)
117
155
  element_class = self._classify_rule(properties)
118
156
  name = selector or "unknown_rule"
119
- elif node.type in ["at_rule", "media_statement", "import_statement", "keyframes_statement"]:
157
+ elif node.type in [
158
+ "at_rule",
159
+ "media_statement",
160
+ "import_statement",
161
+ "keyframes_statement",
162
+ ]:
120
163
  selector = self._extract_at_rule_name(node, source_code)
121
164
  properties = {}
122
165
  element_class = "at_rule"
@@ -133,13 +176,15 @@ class CssElementExtractor(ElementExtractor):
133
176
  # Create StyleElement
134
177
  element = StyleElement(
135
178
  name=name,
136
- start_line=node.start_point[0] + 1 if hasattr(node, "start_point") else 0,
179
+ start_line=node.start_point[0] + 1
180
+ if hasattr(node, "start_point")
181
+ else 0,
137
182
  end_line=node.end_point[0] + 1 if hasattr(node, "end_point") else 0,
138
183
  raw_text=raw_text,
139
184
  language="css",
140
185
  selector=selector,
141
186
  properties=properties,
142
- element_class=element_class
187
+ element_class=element_class,
143
188
  )
144
189
 
145
190
  return element
@@ -155,28 +200,35 @@ class CssElementExtractor(ElementExtractor):
155
200
  for child in node.children:
156
201
  if hasattr(child, "type") and child.type == "selectors":
157
202
  return self._extract_node_text(child, source_code).strip()
158
-
203
+
159
204
  # Fallback: extract from beginning of node text
160
205
  node_text = self._extract_node_text(node, source_code)
161
206
  if "{" in node_text:
162
207
  return node_text.split("{")[0].strip()
163
-
208
+
164
209
  return "unknown"
165
210
  except Exception:
166
211
  return "unknown"
167
212
 
168
- def _extract_properties(self, node: "tree_sitter.Node", source_code: str) -> dict[str, str]:
213
+ def _extract_properties(
214
+ self, node: "tree_sitter.Node", source_code: str
215
+ ) -> dict[str, str]:
169
216
  """Extract properties from CSS rule_set node using tree-sitter-css grammar"""
170
217
  properties = {}
171
-
218
+
172
219
  try:
173
220
  if hasattr(node, "children"):
174
221
  for child in node.children:
175
222
  if hasattr(child, "type") and child.type == "block":
176
223
  # Look for declarations within the block
177
224
  for grandchild in child.children:
178
- if hasattr(grandchild, "type") and grandchild.type == "declaration":
179
- prop_name, prop_value = self._parse_declaration(grandchild, source_code)
225
+ if (
226
+ hasattr(grandchild, "type")
227
+ and grandchild.type == "declaration"
228
+ ):
229
+ prop_name, prop_value = self._parse_declaration(
230
+ grandchild, source_code
231
+ )
180
232
  if prop_name:
181
233
  properties[prop_name] = prop_value
182
234
  except Exception as e:
@@ -184,20 +236,26 @@ class CssElementExtractor(ElementExtractor):
184
236
 
185
237
  return properties
186
238
 
187
- def _parse_declaration(self, decl_node: "tree_sitter.Node", source_code: str) -> tuple[str, str]:
239
+ def _parse_declaration(
240
+ self, decl_node: "tree_sitter.Node", source_code: str
241
+ ) -> tuple[str, str]:
188
242
  """Parse individual CSS declaration using tree-sitter-css grammar"""
189
243
  try:
190
244
  prop_name = ""
191
245
  prop_value = ""
192
-
246
+
193
247
  if hasattr(decl_node, "children"):
194
248
  for child in decl_node.children:
195
249
  if hasattr(child, "type"):
196
250
  if child.type == "property_name":
197
- prop_name = self._extract_node_text(child, source_code).strip()
251
+ prop_name = self._extract_node_text(
252
+ child, source_code
253
+ ).strip()
198
254
  elif child.type in ["value", "values"]:
199
- prop_value = self._extract_node_text(child, source_code).strip()
200
-
255
+ prop_value = self._extract_node_text(
256
+ child, source_code
257
+ ).strip()
258
+
201
259
  # Fallback to simple parsing
202
260
  if not prop_name:
203
261
  decl_text = self._extract_node_text(decl_node, source_code)
@@ -205,7 +263,7 @@ class CssElementExtractor(ElementExtractor):
205
263
  parts = decl_text.split(":", 1)
206
264
  prop_name = parts[0].strip()
207
265
  prop_value = parts[1].strip().rstrip(";")
208
-
266
+
209
267
  return prop_name, prop_value
210
268
  except Exception:
211
269
  return "", ""
@@ -227,16 +285,16 @@ class CssElementExtractor(ElementExtractor):
227
285
  """Classify CSS rule based on properties"""
228
286
  if not properties:
229
287
  return "other"
230
-
288
+
231
289
  # Count properties in each category
232
- category_scores = {category: 0 for category in self.property_categories}
233
-
290
+ category_scores = dict.fromkeys(self.property_categories, 0)
291
+
234
292
  for prop_name in properties.keys():
235
293
  prop_name_lower = prop_name.lower()
236
294
  for category, props in self.property_categories.items():
237
295
  if any(prop in prop_name_lower for prop in props):
238
296
  category_scores[category] += 1
239
-
297
+
240
298
  # Return category with highest score
241
299
  best_category = max(category_scores, key=category_scores.get)
242
300
  return best_category if category_scores[best_category] > 0 else "other"
@@ -272,13 +330,16 @@ class CssPlugin(LanguagePlugin):
272
330
  def get_queries(self) -> dict[str, str]:
273
331
  """Return CSS-specific tree-sitter queries"""
274
332
  from ..queries.css import CSS_QUERIES
333
+
275
334
  return CSS_QUERIES
276
335
 
277
- def execute_query_strategy(self, query_key: str | None, language: str) -> str | None:
336
+ def execute_query_strategy(
337
+ self, query_key: str | None, language: str
338
+ ) -> str | None:
278
339
  """Execute query strategy for CSS"""
279
340
  if language != "css":
280
341
  return None
281
-
342
+
282
343
  queries = self.get_queries()
283
344
  return queries.get(query_key) if query_key else None
284
345
 
@@ -294,44 +355,40 @@ class CssPlugin(LanguagePlugin):
294
355
  "animation": ["rule_set"],
295
356
  "responsive": ["media_statement"],
296
357
  "at_rules": ["at_rule"],
297
- "other": ["rule_set"]
358
+ "other": ["rule_set"],
298
359
  }
299
360
 
300
361
  async def analyze_file(
301
362
  self, file_path: str, request: "AnalysisRequest"
302
363
  ) -> "AnalysisResult":
303
364
  """Analyze CSS file using tree-sitter-css parser"""
304
- from ..core.analysis_engine import UnifiedAnalysisEngine
305
365
  from ..encoding_utils import read_file_safe
306
366
 
307
367
  try:
308
368
  # Read file content
309
369
  content, encoding = read_file_safe(file_path)
310
-
311
- # Create analysis engine
312
- engine = UnifiedAnalysisEngine()
313
-
370
+
314
371
  # Use tree-sitter-css for parsing
315
372
  try:
316
- import tree_sitter_css as ts_css
317
373
  import tree_sitter
318
-
374
+ import tree_sitter_css as ts_css
375
+
319
376
  # Get CSS language
320
377
  CSS_LANGUAGE = tree_sitter.Language(ts_css.language())
321
-
378
+
322
379
  # Create parser
323
380
  parser = tree_sitter.Parser()
324
381
  parser.language = CSS_LANGUAGE
325
-
382
+
326
383
  # Parse the CSS content
327
- tree = parser.parse(content.encode('utf-8'))
328
-
384
+ tree = parser.parse(content.encode("utf-8"))
385
+
329
386
  # Extract elements using the extractor
330
387
  extractor = self.create_extractor()
331
388
  elements = extractor.extract_css_rules(tree, content)
332
-
389
+
333
390
  log_info(f"Extracted {len(elements)} CSS rules from {file_path}")
334
-
391
+
335
392
  return AnalysisResult(
336
393
  file_path=file_path,
337
394
  language="css",
@@ -341,15 +398,17 @@ class CssPlugin(LanguagePlugin):
341
398
  query_results={},
342
399
  source_code=content,
343
400
  success=True,
344
- error_message=None
401
+ error_message=None,
345
402
  )
346
-
403
+
347
404
  except ImportError:
348
- log_error("tree-sitter-css not available, falling back to basic parsing")
405
+ log_error(
406
+ "tree-sitter-css not available, falling back to basic parsing"
407
+ )
349
408
  # Fallback to basic parsing
350
409
  lines = content.splitlines()
351
410
  line_count = len(lines)
352
-
411
+
353
412
  # Create basic StyleElement for the CSS document
354
413
  css_element = StyleElement(
355
414
  name="css",
@@ -359,7 +418,7 @@ class CssPlugin(LanguagePlugin):
359
418
  language="css",
360
419
  selector="*",
361
420
  properties={},
362
- element_class="other"
421
+ element_class="other",
363
422
  )
364
423
  elements = [css_element]
365
424
 
@@ -372,7 +431,7 @@ class CssPlugin(LanguagePlugin):
372
431
  query_results={},
373
432
  source_code=content,
374
433
  success=True,
375
- error_message=None
434
+ error_message=None,
376
435
  )
377
436
 
378
437
  except Exception as e:
@@ -386,5 +445,5 @@ class CssPlugin(LanguagePlugin):
386
445
  query_results={},
387
446
  source_code="",
388
447
  success=False,
389
- error_message=str(e)
390
- )
448
+ error_message=str(e),
449
+ )