tree-sitter-analyzer 1.8.3__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 +83 -25
  60. {tree_sitter_analyzer-1.8.3.dist-info → tree_sitter_analyzer-1.9.0.dist-info}/METADATA +19 -5
  61. tree_sitter_analyzer-1.9.0.dist-info/RECORD +109 -0
  62. tree_sitter_analyzer-1.8.3.dist-info/RECORD +0 -109
  63. {tree_sitter_analyzer-1.8.3.dist-info → tree_sitter_analyzer-1.9.0.dist-info}/WHEEL +0 -0
  64. {tree_sitter_analyzer-1.8.3.dist-info → tree_sitter_analyzer-1.9.0.dist-info}/entry_points.txt +0 -0
@@ -7,7 +7,7 @@ Supports tree-sitter 0.20+ with query.matches() method only.
7
7
  """
8
8
 
9
9
  import logging
10
- from typing import Any, List, Tuple, Optional
10
+ from typing import Any
11
11
 
12
12
  logger = logging.getLogger(__name__)
13
13
 
@@ -15,82 +15,82 @@ logger = logging.getLogger(__name__)
15
15
  class TreeSitterQueryCompat:
16
16
  """
17
17
  Tree-sitter query execution wrapper for modern API.
18
-
18
+
19
19
  Uses only the modern tree-sitter API (query.matches()).
20
20
  """
21
-
21
+
22
22
  @staticmethod
23
23
  def execute_query(
24
- language: Any,
25
- query_string: str,
26
- root_node: Any
27
- ) -> List[Tuple[Any, str]]:
24
+ language: Any, query_string: str, root_node: Any
25
+ ) -> list[tuple[Any, str]]:
28
26
  """
29
27
  Execute a tree-sitter query using the modern API.
30
-
28
+
31
29
  Args:
32
30
  language: Tree-sitter language object
33
31
  query_string: Query string to execute
34
32
  root_node: Root node to query against
35
-
33
+
36
34
  Returns:
37
35
  List of (node, capture_name) tuples
38
-
36
+
39
37
  Raises:
40
38
  Exception: If query execution fails
41
39
  """
42
40
  try:
43
41
  import tree_sitter
42
+
44
43
  query = tree_sitter.Query(language, query_string)
45
-
44
+
46
45
  # Try newest API first (tree-sitter 0.25+) with QueryCursor
47
- if hasattr(tree_sitter, 'QueryCursor'):
46
+ if hasattr(tree_sitter, "QueryCursor"):
48
47
  logger.debug("Using newest tree-sitter API (QueryCursor)")
49
48
  return TreeSitterQueryCompat._execute_newest_api(query, root_node)
50
49
  # Try modern API (tree-sitter 0.20+)
51
- elif hasattr(query, 'matches'):
50
+ elif hasattr(query, "matches"):
52
51
  logger.debug("Using modern tree-sitter API (matches)")
53
52
  return TreeSitterQueryCompat._execute_modern_api(query, root_node)
54
53
  # Fall back to legacy API (tree-sitter < 0.20)
55
- elif hasattr(query, 'captures'):
54
+ elif hasattr(query, "captures"):
56
55
  logger.debug("Using legacy tree-sitter API (captures)")
57
56
  return TreeSitterQueryCompat._execute_legacy_api(query, root_node)
58
57
  # Try very old API with different method signature
59
58
  else:
60
59
  logger.debug("Using very old tree-sitter API (direct query)")
61
60
  return TreeSitterQueryCompat._execute_old_api(query, root_node)
62
-
61
+
63
62
  except Exception as e:
64
63
  logger.error(f"Tree-sitter query execution failed: {e}")
65
64
  # Return empty result instead of raising to prevent complete failure
66
65
  logger.debug("Returning empty result due to query execution failure")
67
66
  return []
68
-
67
+
69
68
  @staticmethod
70
- def _execute_newest_api(query: Any, root_node: Any) -> List[Tuple[Any, str]]:
69
+ def _execute_newest_api(query: Any, root_node: Any) -> list[tuple[Any, str]]:
71
70
  """Execute query using newest API (tree-sitter 0.25+) with QueryCursor"""
72
71
  captures = []
73
72
  try:
74
73
  import tree_sitter
74
+
75
75
  cursor = tree_sitter.QueryCursor(query)
76
-
76
+
77
77
  # Execute query and get matches
78
78
  matches = cursor.matches(root_node)
79
79
  # matches is a list of tuples: (pattern_index, captures_dict)
80
- for pattern_index, captures_dict in matches:
80
+ for _pattern_index, captures_dict in matches:
81
81
  # captures_dict is {capture_name: [node1, node2, ...]}
82
82
  for capture_name, nodes in captures_dict.items():
83
83
  for node in nodes:
84
84
  captures.append((node, capture_name))
85
-
85
+
86
86
  except Exception as e:
87
87
  logger.error(f"Newest API execution failed: {e}")
88
88
  # Don't raise, just return empty result
89
-
89
+
90
90
  return captures
91
-
91
+
92
92
  @staticmethod
93
- def _execute_modern_api(query: Any, root_node: Any) -> List[Tuple[Any, str]]:
93
+ def _execute_modern_api(query: Any, root_node: Any) -> list[tuple[Any, str]]:
94
94
  """Execute query using modern API (tree-sitter 0.20+)"""
95
95
  captures = []
96
96
  try:
@@ -103,9 +103,9 @@ class TreeSitterQueryCompat:
103
103
  logger.error(f"Modern API execution failed: {e}")
104
104
  raise
105
105
  return captures
106
-
106
+
107
107
  @staticmethod
108
- def _execute_legacy_api(query: Any, root_node: Any) -> List[Tuple[Any, str]]:
108
+ def _execute_legacy_api(query: Any, root_node: Any) -> list[tuple[Any, str]]:
109
109
  """Execute query using legacy API (tree-sitter < 0.20)"""
110
110
  captures = []
111
111
  try:
@@ -117,71 +117,76 @@ class TreeSitterQueryCompat:
117
117
  logger.error(f"Legacy API execution failed: {e}")
118
118
  raise
119
119
  return captures
120
-
120
+
121
121
  @staticmethod
122
- def _execute_old_api(query: Any, root_node: Any) -> List[Tuple[Any, str]]:
122
+ def _execute_old_api(query: Any, root_node: Any) -> list[tuple[Any, str]]:
123
123
  """Execute query using very old API (tree-sitter < 0.19)"""
124
124
  captures = []
125
125
  try:
126
126
  # Try different old API patterns
127
- if hasattr(query, '__call__'):
127
+ if callable(query):
128
128
  # Some very old versions had callable queries
129
129
  query_result = query(root_node)
130
130
  if isinstance(query_result, list):
131
131
  for item in query_result:
132
132
  if isinstance(item, tuple) and len(item) >= 2:
133
133
  captures.append((item[0], str(item[1])))
134
- elif hasattr(item, 'node') and hasattr(item, 'name'):
134
+ elif hasattr(item, "node") and hasattr(item, "name"):
135
135
  captures.append((item.node, item.name))
136
136
  else:
137
137
  # If no known API is available, return empty result
138
- logger.warning("No compatible tree-sitter query API found, returning empty result")
139
-
138
+ logger.warning(
139
+ "No compatible tree-sitter query API found, returning empty result"
140
+ )
141
+
140
142
  except Exception as e:
141
143
  logger.error(f"Old API execution failed: {e}")
142
144
  # Don't raise, just return empty result
143
-
145
+
144
146
  return captures
145
-
147
+
146
148
  @staticmethod
147
149
  def safe_execute_query(
148
150
  language: Any,
149
151
  query_string: str,
150
152
  root_node: Any,
151
- fallback_result: Optional[List[Tuple[Any, str]]] = None
152
- ) -> List[Tuple[Any, str]]:
153
+ fallback_result: list[tuple[Any, str]] | None = None,
154
+ ) -> list[tuple[Any, str]]:
153
155
  """
154
156
  Safely execute a query with fallback handling.
155
-
157
+
156
158
  Args:
157
159
  language: Tree-sitter language object
158
160
  query_string: Query string to execute
159
161
  root_node: Root node to query against
160
162
  fallback_result: Result to return if query fails
161
-
163
+
162
164
  Returns:
163
165
  List of (node, capture_name) tuples or fallback_result
164
166
  """
165
167
  try:
166
- return TreeSitterQueryCompat.execute_query(language, query_string, root_node)
168
+ return TreeSitterQueryCompat.execute_query(
169
+ language, query_string, root_node
170
+ )
167
171
  except Exception as e:
168
172
  logger.debug(f"Query execution failed, using fallback: {e}")
169
173
  return fallback_result or []
170
174
 
171
175
 
172
- def create_query_safely(language: Any, query_string: str) -> Optional[Any]:
176
+ def create_query_safely(language: Any, query_string: str) -> Any | None:
173
177
  """
174
178
  Safely create a tree-sitter query object.
175
-
179
+
176
180
  Args:
177
181
  language: Tree-sitter language object
178
182
  query_string: Query string
179
-
183
+
180
184
  Returns:
181
185
  Query object or None if creation fails
182
186
  """
183
187
  try:
184
188
  import tree_sitter
189
+
185
190
  return tree_sitter.Query(language, query_string)
186
191
  except Exception as e:
187
192
  logger.debug(f"Query creation failed: {e}")
@@ -191,37 +196,39 @@ def create_query_safely(language: Any, query_string: str) -> Optional[Any]:
191
196
  def get_node_text_safe(node: Any, source_code: str, encoding: str = "utf-8") -> str:
192
197
  """
193
198
  Safely extract text from a tree-sitter node.
194
-
199
+
195
200
  Args:
196
201
  node: Tree-sitter node
197
202
  source_code: Source code string
198
203
  encoding: Text encoding
199
-
204
+
200
205
  Returns:
201
206
  Node text or empty string if extraction fails
202
207
  """
203
208
  try:
204
209
  # Try byte-based extraction first
205
- if hasattr(node, 'start_byte') and hasattr(node, 'end_byte'):
210
+ if hasattr(node, "start_byte") and hasattr(node, "end_byte"):
206
211
  start_byte = node.start_byte
207
212
  end_byte = node.end_byte
208
213
  source_bytes = source_code.encode(encoding)
209
214
  if start_byte <= end_byte <= len(source_bytes):
210
- return source_bytes[start_byte:end_byte].decode(encoding, errors='replace')
211
-
215
+ return source_bytes[start_byte:end_byte].decode(
216
+ encoding, errors="replace"
217
+ )
218
+
212
219
  # Fall back to node.text if available
213
- if hasattr(node, 'text') and node.text:
220
+ if hasattr(node, "text") and node.text:
214
221
  if isinstance(node.text, bytes):
215
- return node.text.decode(encoding, errors='replace')
222
+ return node.text.decode(encoding, errors="replace")
216
223
  else:
217
224
  return str(node.text)
218
-
225
+
219
226
  # Fall back to point-based extraction
220
- if hasattr(node, 'start_point') and hasattr(node, 'end_point'):
227
+ if hasattr(node, "start_point") and hasattr(node, "end_point"):
221
228
  start_point = node.start_point
222
229
  end_point = node.end_point
223
- lines = source_code.split('\n')
224
-
230
+ lines = source_code.split("\n")
231
+
225
232
  if start_point[0] < len(lines) and end_point[0] < len(lines):
226
233
  if start_point[0] == end_point[0]:
227
234
  # Single line
@@ -242,10 +249,10 @@ def get_node_text_safe(node: Any, source_code: str, encoding: str = "utf-8") ->
242
249
  result_lines.append(line[:end_col])
243
250
  else:
244
251
  result_lines.append(line)
245
- return '\n'.join(result_lines)
246
-
252
+ return "\n".join(result_lines)
253
+
247
254
  return ""
248
-
255
+
249
256
  except Exception as e:
250
257
  logger.debug(f"Node text extraction failed: {e}")
251
258
  return ""
@@ -255,28 +262,28 @@ def log_api_info():
255
262
  """Log information about available tree-sitter APIs."""
256
263
  try:
257
264
  import tree_sitter
265
+
258
266
  logger.debug("Tree-sitter library available")
259
-
267
+
260
268
  # Check available APIs
261
269
  try:
262
270
  # Create a dummy query to test available methods
263
- dummy_lang = None
264
- dummy_query_str = "(identifier) @name"
265
-
271
+ # We can't actually test without a language, so just check the class
272
+
266
273
  # We can't actually test without a language, so just check the class
267
274
  query_class = tree_sitter.Query
268
- has_matches = 'matches' in dir(query_class)
269
- has_captures = 'captures' in dir(query_class)
270
-
275
+ has_matches = "matches" in dir(query_class)
276
+ has_captures = "captures" in dir(query_class)
277
+
271
278
  if has_matches:
272
279
  logger.debug("Tree-sitter modern API (matches) available")
273
280
  elif has_captures:
274
281
  logger.debug("Tree-sitter legacy API (captures) available")
275
282
  else:
276
283
  logger.warning("No compatible tree-sitter API found")
277
-
284
+
278
285
  except Exception as e:
279
286
  logger.debug(f"API detection failed: {e}")
280
-
287
+
281
288
  except ImportError:
282
- logger.debug("Tree-sitter library not available")
289
+ logger.debug("Tree-sitter library not available")
@@ -9,7 +9,9 @@ import atexit
9
9
  import logging
10
10
  import os
11
11
  import sys
12
+ import tempfile
12
13
  from functools import wraps
14
+ from pathlib import Path
13
15
  from typing import Any
14
16
 
15
17
 
@@ -31,7 +33,7 @@ def setup_logger(
31
33
  level = logging.ERROR
32
34
  else:
33
35
  level = logging.WARNING # Default fallback
34
-
36
+
35
37
  # Get log level from environment variable (only if set and not empty)
36
38
  env_level = os.environ.get("LOG_LEVEL", "").upper()
37
39
  if env_level and env_level in ["DEBUG", "INFO", "WARNING", "ERROR"]:
@@ -46,11 +48,17 @@ def setup_logger(
46
48
  # If env_level is empty or not recognized, use the passed level parameter
47
49
 
48
50
  logger = logging.getLogger(name)
49
-
51
+
50
52
  # Clear existing handlers if this is a test logger to ensure clean state
51
53
  if name.startswith("test_"):
52
54
  logger.handlers.clear()
53
55
 
56
+ # Initialize file logging variables at function scope
57
+ enable_file_log = (
58
+ os.environ.get("TREE_SITTER_ANALYZER_ENABLE_FILE_LOG", "").lower() == "true"
59
+ )
60
+ file_log_level = level # Default to main logger level
61
+
54
62
  if not logger.handlers: # Avoid duplicate handlers
55
63
  # Create a safe handler that writes to stderr to avoid breaking MCP stdio
56
64
  handler = SafeStreamHandler()
@@ -60,28 +68,78 @@ def setup_logger(
60
68
  handler.setFormatter(formatter)
61
69
  logger.addHandler(handler)
62
70
 
63
- # Also log to a local file for debugging when launched by clients (e.g., Cursor)
71
+ # Optional file logging for debugging when launched by clients (e.g., Cursor)
64
72
  # This helps diagnose cases where stdio is captured by the client and logs are hidden.
65
- try:
66
- file_handler = logging.FileHandler(
67
- "cursor_mcp_server.log", encoding="utf-8"
68
- )
69
- file_handler.setFormatter(formatter)
70
- logger.addHandler(file_handler)
71
- except Exception as e:
72
- # Never let logging configuration break runtime behavior; log to stderr if possible
73
- if hasattr(sys, "stderr") and hasattr(sys.stderr, "write"):
74
- try:
75
- sys.stderr.write(
76
- f"[logging_setup] file handler init skipped: {e}\n"
77
- )
78
- except Exception:
79
- ...
73
+ # Only enabled when TREE_SITTER_ANALYZER_ENABLE_FILE_LOG is set to 'true'
74
+ if enable_file_log:
75
+ try:
76
+ # Determine log directory
77
+ log_dir = os.environ.get("TREE_SITTER_ANALYZER_LOG_DIR")
78
+ if log_dir:
79
+ # Use specified directory
80
+ log_path = Path(log_dir) / "tree_sitter_analyzer.log"
81
+ # Ensure directory exists
82
+ Path(log_dir).mkdir(parents=True, exist_ok=True)
83
+ else:
84
+ # Use system temporary directory
85
+ temp_dir = tempfile.gettempdir()
86
+ log_path = Path(temp_dir) / "tree_sitter_analyzer.log"
87
+
88
+ # Determine file log level
89
+ file_log_level_str = os.environ.get(
90
+ "TREE_SITTER_ANALYZER_FILE_LOG_LEVEL", ""
91
+ ).upper()
92
+ if file_log_level_str and file_log_level_str in [
93
+ "DEBUG",
94
+ "INFO",
95
+ "WARNING",
96
+ "ERROR",
97
+ ]:
98
+ if file_log_level_str == "DEBUG":
99
+ file_log_level = logging.DEBUG
100
+ elif file_log_level_str == "INFO":
101
+ file_log_level = logging.INFO
102
+ elif file_log_level_str == "WARNING":
103
+ file_log_level = logging.WARNING
104
+ elif file_log_level_str == "ERROR":
105
+ file_log_level = logging.ERROR
106
+ else:
107
+ # Use same level as main logger
108
+ file_log_level = level
109
+
110
+ file_handler = logging.FileHandler(str(log_path), encoding="utf-8")
111
+ file_handler.setFormatter(formatter)
112
+ file_handler.setLevel(file_log_level)
113
+ logger.addHandler(file_handler)
114
+
115
+ # Log the file location for debugging purposes
116
+ if hasattr(sys, "stderr") and hasattr(sys.stderr, "write"):
117
+ try:
118
+ sys.stderr.write(
119
+ f"[logging_setup] File logging enabled: {log_path}\n"
120
+ )
121
+ except Exception:
122
+ ...
123
+
124
+ except Exception as e:
125
+ # Never let logging configuration break runtime behavior; log to stderr if possible
126
+ if hasattr(sys, "stderr") and hasattr(sys.stderr, "write"):
127
+ try:
128
+ sys.stderr.write(
129
+ f"[logging_setup] file handler init skipped: {e}\n"
130
+ )
131
+ except Exception:
132
+ ...
133
+
134
+ # Set the logger level to the minimum of main level and file log level
135
+ # This ensures that all messages that should go to any handler are processed
136
+ final_level = level
137
+ if enable_file_log:
138
+ # Use the minimum level to ensure all messages reach their intended handlers
139
+ final_level = min(level, file_log_level)
140
+
141
+ logger.setLevel(final_level)
80
142
 
81
- # Always set the level, even if handlers already exist
82
- # Ensure the level is properly set, not inherited
83
- logger.setLevel(level)
84
-
85
143
  # For test loggers, ensure they don't inherit from parent and force level
86
144
  if logger.name.startswith("test_"):
87
145
  logger.propagate = False
@@ -115,8 +173,8 @@ class SafeStreamHandler(logging.StreamHandler):
115
173
 
116
174
  # Special handling for pytest capture scenarios
117
175
  # Check if this is a pytest capture stream that might be problematic
118
- stream_name = getattr(self.stream, 'name', '')
119
- if stream_name is None or 'pytest' in str(type(self.stream)).lower():
176
+ stream_name = getattr(self.stream, "name", "")
177
+ if stream_name is None or "pytest" in str(type(self.stream)).lower():
120
178
  # For pytest streams, be extra cautious
121
179
  try:
122
180
  # Just try to emit without any pre-checks
@@ -295,7 +353,7 @@ def safe_print(message: str | None, level: str = "info", quiet: bool = False) ->
295
353
 
296
354
  # Handle None message by converting to string - always call log function even for None
297
355
  msg = str(message) if message is not None else "None"
298
-
356
+
299
357
  # Use dynamic lookup to support mocking
300
358
  level_lower = level.lower()
301
359
  if level_lower == "info":
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: tree-sitter-analyzer
3
- Version: 1.8.3
3
+ Version: 1.9.0
4
4
  Summary: AI-era enterprise-grade code analysis tool with comprehensive HTML/CSS support, dynamic plugin architecture, and MCP integration
5
5
  Project-URL: Homepage, https://github.com/aimasteracc/tree-sitter-analyzer
6
6
  Project-URL: Documentation, https://github.com/aimasteracc/tree-sitter-analyzer#readme
@@ -198,11 +198,11 @@ Description-Content-Type: text/markdown
198
198
 
199
199
  [![Python Version](https://img.shields.io/badge/python-3.10%2B-blue.svg)](https://python.org)
200
200
  [![License](https://img.shields.io/badge/license-MIT-green.svg)](LICENSE)
201
- [![Tests](https://img.shields.io/badge/tests-3361%20passed-brightgreen.svg)](#quality-assurance)
201
+ [![Tests](https://img.shields.io/badge/tests-3380%20passed-brightgreen.svg)](#quality-assurance)
202
202
  [![Coverage](https://codecov.io/gh/aimasteracc/tree-sitter-analyzer/branch/main/graph/badge.svg)](https://codecov.io/gh/aimasteracc/tree-sitter-analyzer)
203
203
  [![Quality](https://img.shields.io/badge/quality-enterprise%20grade-blue.svg)](#quality-assurance)
204
204
  [![PyPI](https://img.shields.io/pypi/v/tree-sitter-analyzer.svg)](https://pypi.org/project/tree-sitter-analyzer/)
205
- [![Version](https://img.shields.io/badge/version-1.8.3-blue.svg)](https://github.com/aimasteracc/tree-sitter-analyzer/releases)
205
+ [![Version](https://img.shields.io/badge/version-1.8.4-blue.svg)](https://github.com/aimasteracc/tree-sitter-analyzer/releases)
206
206
  [![zread](https://img.shields.io/badge/Ask_Zread-_.svg?style=flat&color=00b0aa&labelColor=000000&logo=data%3Aimage%2Fsvg%2Bxml%3Bbase64%2CPHN2ZyB3aWR0aD0iMTYiIGhlaWdodD0iMTYiIHZpZXdCb3g9IjAgMCAxNiAxNiIgZmlsbD0ibm9uZSIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIj4KPHBhdGggZD0iTTQuOTYxNTYgMS42MDAxSDIuMjQxNTZDMS44ODgxIDEuNjAwMSAxLjYwMTU2IDEuODg2NjQgMS42MDE1NiAyLjI0MDFWNC45NjAxQzEuNjAxNTYgNS4zMTM1NiAxLjg4ODEgNS42MDAxIDIuMjQxNTYgNS42MDAxSDQuOTYxNTZDNS4zMTUwMiA1LjYwMDEgNS42MDE1NiA1LjMxMzU2IDUuNjAxNTYgNC45NjAxVjIuMjQwMUM1LjYwMTU2IDEuODg2NjQgNS4zMTUwMiAxLjYwMDEgNC45NjE1NiAxLjYwMDFaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00Ljk2MTU2IDEwLjM5OTlIMi4yNDE1NkMxLjg4ODEgMTAuMzk5OSAxLjYwMTU2IDEwLjY4NjQgMS42MDE1NiAxMS4wMzk5VjEzLjc1OTlDMS42MDE1NiAxNC4xMTM0IDEuODg4MSAxNC4zOTk5IDIuMjQxNTYgMTQuMzk5OUg0Ljk2MTU2QzUuMzE1MDIgMTQuMzk5OSA1LjYwMTU2IDE0LjExMzQgNS42MDE1NiAxMy43NTk5VjExLjAzOTlDNS42MDE1NiAxMC42ODY0IDUuMzE1MDIgMTAuMzk5OSA0Ljk2MTU2IDEwLjM5OTlaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik0xMy43NTg0IDEuNjAwMUgxMS4wMzg0QzEwLjY4NSAxLjYwMDEgMTAuMzk4NCAxLjg4NjY0IDEwLjM5ODQgMi4yNDAxVjQuOTYwMUMxMC4zOTg0IDUuMzEzNTYgMTAuNjg1IDUuNjAwMSAxMS4wMzg0IDUuNjAwMUgxMy43NTg0QzE0LjExMTkgNS42MDAxIDE0LjM5ODQgNS4zMTM1NiAxNC4zOTg0IDQuOTYwMVYyLjI0MDFDMTQuMzk4NCAxLjg4NjY0IDE0LjExMTkgMS42MDAxIDEzLjc1ODQgMS42MDAxWiIgZmlsbD0iI2ZmZiIvPgo8cGF0aCBkPSJNNCAxMkwxMiA0TDQgMTJaIiBmaWxsPSIjZmZmIi8%2BCjxwYXRoIGQ9Ik00IDEyTDEyIDQiIHN0cm9rZT0iI2ZmZiIgc3Ryb2tlLXdpZHRoPSIxLjUiIHN0cm9rZS1saW5lY2FwPSJyb3VuZCIvPgo8L3N2Zz4K&logoColor=ffffff)](https://zread.ai/aimasteracc/tree-sitter-analyzer)
207
207
  [![GitHub Stars](https://img.shields.io/github/stars/aimasteracc/tree-sitter-analyzer.svg?style=social)](https://github.com/aimasteracc/tree-sitter-analyzer)
208
208
 
@@ -255,7 +255,7 @@ Tree-sitter Analyzer is an enterprise-grade code analysis tool designed for the
255
255
  | **Go** | Basic Support | Basic syntax parsing |
256
256
 
257
257
  ### 🏆 Production Ready
258
- - **3,361 Tests** - 100% pass rate, enterprise-grade quality assurance
258
+ - **3,380 Tests** - 100% pass rate, enterprise-grade quality assurance
259
259
  - **High Coverage** - Comprehensive test coverage
260
260
  - **Cross-platform Support** - Compatible with Windows, macOS, Linux
261
261
  - **Continuous Maintenance** - Active development and community support
@@ -373,6 +373,7 @@ rg --version
373
373
  - **Roo Code**: Supports MCP protocol, use the same configuration format
374
374
  - **Other MCP-compatible clients**: Use the same server configuration
375
375
 
376
+
376
377
  ---
377
378
 
378
379
  ### 3.2 💻 CLI Users (Command Line Tools)
@@ -640,6 +641,19 @@ Tree-sitter Analyzer provides a rich set of MCP tools designed for AI assistants
640
641
  | **📁 Resource Access** | Code file resources | URI code file access | File content access via URI identification |
641
642
  | | Project statistics resources | Project statistics data access | Project analysis data and statistical information |
642
643
 
644
+ ### 🆕 v1.8.4 New Feature: Configurable File Logging
645
+
646
+ Revolutionary environment variable-controlled file logging system:
647
+
648
+ - **🔧 Environment Variable Control**: Flexible file logging behavior control through environment variables
649
+ - `TREE_SITTER_ANALYZER_ENABLE_FILE_LOG`: Enable/disable file logging
650
+ - `TREE_SITTER_ANALYZER_LOG_DIR`: Custom log directory path
651
+ - `TREE_SITTER_ANALYZER_FILE_LOG_LEVEL`: Control file log level
652
+ - **🛡️ Improved Default Behavior**: File logging disabled by default to prevent user project pollution
653
+ - **📁 Smart Directory Selection**: Uses system temp directory when enabled, keeping projects clean
654
+ - **🔄 Backward Compatibility**: Maintains all existing functionality unchanged
655
+ - **📚 Complete Documentation Support**: Includes debugging guides and troubleshooting documentation
656
+
643
657
  ### 🆕 v1.8.3 New Feature: MCP Tools Design Consistency Enhancement
644
658
 
645
659
  Comprehensive MCP tools unification and design consistency improvements:
@@ -859,7 +873,7 @@ uv run python -m tree_sitter_analyzer --show-query-languages
859
873
  ## 8. 🏆 Quality Assurance
860
874
 
861
875
  ### 📊 Quality Metrics
862
- - **3,361 tests** - 100% pass rate ✅
876
+ - **3,380 tests** - 100% pass rate ✅
863
877
  - **High code coverage** - Comprehensive test suite
864
878
  - **Zero test failures** - Production ready
865
879
  - **Cross-platform support** - Windows, macOS, Linux