tree-sitter-analyzer 1.0.0__py3-none-any.whl → 1.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 (29) hide show
  1. tree_sitter_analyzer/__init__.py +132 -132
  2. tree_sitter_analyzer/api.py +542 -542
  3. tree_sitter_analyzer/cli/commands/base_command.py +181 -181
  4. tree_sitter_analyzer/cli/commands/partial_read_command.py +139 -139
  5. tree_sitter_analyzer/cli/info_commands.py +124 -124
  6. tree_sitter_analyzer/cli_main.py +327 -327
  7. tree_sitter_analyzer/core/analysis_engine.py +584 -584
  8. tree_sitter_analyzer/core/query_service.py +162 -162
  9. tree_sitter_analyzer/file_handler.py +212 -212
  10. tree_sitter_analyzer/formatters/base_formatter.py +169 -169
  11. tree_sitter_analyzer/interfaces/cli.py +535 -535
  12. tree_sitter_analyzer/mcp/__init__.py +1 -1
  13. tree_sitter_analyzer/mcp/resources/__init__.py +1 -1
  14. tree_sitter_analyzer/mcp/resources/project_stats_resource.py +16 -5
  15. tree_sitter_analyzer/mcp/server.py +655 -655
  16. tree_sitter_analyzer/mcp/tools/__init__.py +30 -30
  17. tree_sitter_analyzer/mcp/utils/__init__.py +2 -2
  18. tree_sitter_analyzer/mcp/utils/error_handler.py +569 -569
  19. tree_sitter_analyzer/mcp/utils/path_resolver.py +414 -414
  20. tree_sitter_analyzer/output_manager.py +257 -257
  21. tree_sitter_analyzer/project_detector.py +330 -330
  22. tree_sitter_analyzer/security/boundary_manager.py +260 -260
  23. tree_sitter_analyzer/security/validator.py +257 -257
  24. tree_sitter_analyzer/table_formatter.py +710 -710
  25. tree_sitter_analyzer/utils.py +335 -335
  26. {tree_sitter_analyzer-1.0.0.dist-info → tree_sitter_analyzer-1.1.0.dist-info}/METADATA +11 -11
  27. {tree_sitter_analyzer-1.0.0.dist-info → tree_sitter_analyzer-1.1.0.dist-info}/RECORD +29 -29
  28. {tree_sitter_analyzer-1.0.0.dist-info → tree_sitter_analyzer-1.1.0.dist-info}/WHEEL +0 -0
  29. {tree_sitter_analyzer-1.0.0.dist-info → tree_sitter_analyzer-1.1.0.dist-info}/entry_points.txt +0 -0
@@ -1,162 +1,162 @@
1
- #!/usr/bin/env python3
2
- """
3
- Query Service
4
-
5
- Unified query service for both CLI and MCP interfaces to avoid code duplication.
6
- Provides core tree-sitter query functionality including predefined and custom queries.
7
- """
8
-
9
- import logging
10
- from typing import Any
11
-
12
- from ..encoding_utils import read_file_safe
13
- from ..query_loader import query_loader
14
- from .parser import Parser
15
- from .query_filter import QueryFilter
16
-
17
- logger = logging.getLogger(__name__)
18
-
19
-
20
- class QueryService:
21
- """Unified query service providing tree-sitter query functionality"""
22
-
23
- def __init__(self, project_root: str | None = None) -> None:
24
- """Initialize the query service"""
25
- self.project_root = project_root
26
- self.parser = Parser()
27
- self.filter = QueryFilter()
28
-
29
- async def execute_query(
30
- self,
31
- file_path: str,
32
- language: str,
33
- query_key: str | None = None,
34
- query_string: str | None = None,
35
- filter_expression: str | None = None,
36
- ) -> list[dict[str, Any]] | None:
37
- """
38
- Execute a query
39
-
40
- Args:
41
- file_path: Path to the file to analyze
42
- language: Programming language
43
- query_key: Predefined query key (e.g., 'methods', 'class')
44
- query_string: Custom query string (e.g., '(method_declaration) @method')
45
- filter_expression: Filter expression (e.g., 'name=main', 'name=~get*,public=true')
46
-
47
- Returns:
48
- List of query results, each containing capture_name, node_type, start_line, end_line, content
49
-
50
- Raises:
51
- ValueError: If neither query_key nor query_string is provided
52
- FileNotFoundError: If file doesn't exist
53
- Exception: If query execution fails
54
- """
55
- if not query_key and not query_string:
56
- raise ValueError("Must provide either query_key or query_string")
57
-
58
- if query_key and query_string:
59
- raise ValueError("Cannot provide both query_key and query_string")
60
-
61
- try:
62
- # Read file content
63
- content, encoding = read_file_safe(file_path)
64
-
65
- # Parse file
66
- parse_result = self.parser.parse_code(content, language, file_path)
67
- if not parse_result or not parse_result.tree:
68
- raise Exception("Failed to parse file")
69
-
70
- tree = parse_result.tree
71
- language_obj = tree.language if hasattr(tree, "language") else None
72
- if not language_obj:
73
- raise Exception(f"Language object not available for {language}")
74
-
75
- # Get query string
76
- if query_key:
77
- query_string = query_loader.get_query(language, query_key)
78
- if not query_string:
79
- raise ValueError(
80
- f"Query '{query_key}' not found for language '{language}'"
81
- )
82
-
83
- # Execute tree-sitter query
84
- ts_query = language_obj.query(query_string)
85
- captures = ts_query.captures(tree.root_node)
86
-
87
- # Process capture results
88
- results = []
89
- if isinstance(captures, dict):
90
- # New tree-sitter API returns dictionary
91
- for capture_name, nodes in captures.items():
92
- for node in nodes:
93
- results.append(self._create_result_dict(node, capture_name))
94
- else:
95
- # Old tree-sitter API returns list of tuples
96
- for capture in captures:
97
- if isinstance(capture, tuple) and len(capture) == 2:
98
- node, name = capture
99
- results.append(self._create_result_dict(node, name))
100
-
101
- # Apply filters
102
- if filter_expression and results:
103
- results = self.filter.filter_results(results, filter_expression)
104
-
105
- return results
106
-
107
- except Exception as e:
108
- logger.error(f"Query execution failed: {e}")
109
- raise
110
-
111
- def _create_result_dict(self, node: Any, capture_name: str) -> dict[str, Any]:
112
- """
113
- Create result dictionary from tree-sitter node
114
-
115
- Args:
116
- node: tree-sitter node
117
- capture_name: capture name
118
-
119
- Returns:
120
- Result dictionary
121
- """
122
- return {
123
- "capture_name": capture_name,
124
- "node_type": node.type if hasattr(node, "type") else "unknown",
125
- "start_line": (
126
- node.start_point[0] + 1 if hasattr(node, "start_point") else 0
127
- ),
128
- "end_line": node.end_point[0] + 1 if hasattr(node, "end_point") else 0,
129
- "content": (
130
- node.text.decode("utf-8", errors="replace")
131
- if hasattr(node, "text") and node.text
132
- else ""
133
- ),
134
- }
135
-
136
- def get_available_queries(self, language: str) -> list[str]:
137
- """
138
- Get available query keys for specified language
139
-
140
- Args:
141
- language: Programming language
142
-
143
- Returns:
144
- List of available query keys
145
- """
146
- return query_loader.list_queries(language)
147
-
148
- def get_query_description(self, language: str, query_key: str) -> str | None:
149
- """
150
- Get description for query key
151
-
152
- Args:
153
- language: Programming language
154
- query_key: Query key
155
-
156
- Returns:
157
- Query description, or None if not found
158
- """
159
- try:
160
- return query_loader.get_query_description(language, query_key)
161
- except Exception:
162
- return None
1
+ #!/usr/bin/env python3
2
+ """
3
+ Query Service
4
+
5
+ Unified query service for both CLI and MCP interfaces to avoid code duplication.
6
+ Provides core tree-sitter query functionality including predefined and custom queries.
7
+ """
8
+
9
+ import logging
10
+ from typing import Any
11
+
12
+ from ..encoding_utils import read_file_safe
13
+ from ..query_loader import query_loader
14
+ from .parser import Parser
15
+ from .query_filter import QueryFilter
16
+
17
+ logger = logging.getLogger(__name__)
18
+
19
+
20
+ class QueryService:
21
+ """Unified query service providing tree-sitter query functionality"""
22
+
23
+ def __init__(self, project_root: str | None = None) -> None:
24
+ """Initialize the query service"""
25
+ self.project_root = project_root
26
+ self.parser = Parser()
27
+ self.filter = QueryFilter()
28
+
29
+ async def execute_query(
30
+ self,
31
+ file_path: str,
32
+ language: str,
33
+ query_key: str | None = None,
34
+ query_string: str | None = None,
35
+ filter_expression: str | None = None,
36
+ ) -> list[dict[str, Any]] | None:
37
+ """
38
+ Execute a query
39
+
40
+ Args:
41
+ file_path: Path to the file to analyze
42
+ language: Programming language
43
+ query_key: Predefined query key (e.g., 'methods', 'class')
44
+ query_string: Custom query string (e.g., '(method_declaration) @method')
45
+ filter_expression: Filter expression (e.g., 'name=main', 'name=~get*,public=true')
46
+
47
+ Returns:
48
+ List of query results, each containing capture_name, node_type, start_line, end_line, content
49
+
50
+ Raises:
51
+ ValueError: If neither query_key nor query_string is provided
52
+ FileNotFoundError: If file doesn't exist
53
+ Exception: If query execution fails
54
+ """
55
+ if not query_key and not query_string:
56
+ raise ValueError("Must provide either query_key or query_string")
57
+
58
+ if query_key and query_string:
59
+ raise ValueError("Cannot provide both query_key and query_string")
60
+
61
+ try:
62
+ # Read file content
63
+ content, encoding = read_file_safe(file_path)
64
+
65
+ # Parse file
66
+ parse_result = self.parser.parse_code(content, language, file_path)
67
+ if not parse_result or not parse_result.tree:
68
+ raise Exception("Failed to parse file")
69
+
70
+ tree = parse_result.tree
71
+ language_obj = tree.language if hasattr(tree, "language") else None
72
+ if not language_obj:
73
+ raise Exception(f"Language object not available for {language}")
74
+
75
+ # Get query string
76
+ if query_key:
77
+ query_string = query_loader.get_query(language, query_key)
78
+ if not query_string:
79
+ raise ValueError(
80
+ f"Query '{query_key}' not found for language '{language}'"
81
+ )
82
+
83
+ # Execute tree-sitter query
84
+ ts_query = language_obj.query(query_string)
85
+ captures = ts_query.captures(tree.root_node)
86
+
87
+ # Process capture results
88
+ results = []
89
+ if isinstance(captures, dict):
90
+ # New tree-sitter API returns dictionary
91
+ for capture_name, nodes in captures.items():
92
+ for node in nodes:
93
+ results.append(self._create_result_dict(node, capture_name))
94
+ else:
95
+ # Old tree-sitter API returns list of tuples
96
+ for capture in captures:
97
+ if isinstance(capture, tuple) and len(capture) == 2:
98
+ node, name = capture
99
+ results.append(self._create_result_dict(node, name))
100
+
101
+ # Apply filters
102
+ if filter_expression and results:
103
+ results = self.filter.filter_results(results, filter_expression)
104
+
105
+ return results
106
+
107
+ except Exception as e:
108
+ logger.error(f"Query execution failed: {e}")
109
+ raise
110
+
111
+ def _create_result_dict(self, node: Any, capture_name: str) -> dict[str, Any]:
112
+ """
113
+ Create result dictionary from tree-sitter node
114
+
115
+ Args:
116
+ node: tree-sitter node
117
+ capture_name: capture name
118
+
119
+ Returns:
120
+ Result dictionary
121
+ """
122
+ return {
123
+ "capture_name": capture_name,
124
+ "node_type": node.type if hasattr(node, "type") else "unknown",
125
+ "start_line": (
126
+ node.start_point[0] + 1 if hasattr(node, "start_point") else 0
127
+ ),
128
+ "end_line": node.end_point[0] + 1 if hasattr(node, "end_point") else 0,
129
+ "content": (
130
+ node.text.decode("utf-8", errors="replace")
131
+ if hasattr(node, "text") and node.text
132
+ else ""
133
+ ),
134
+ }
135
+
136
+ def get_available_queries(self, language: str) -> list[str]:
137
+ """
138
+ Get available query keys for specified language
139
+
140
+ Args:
141
+ language: Programming language
142
+
143
+ Returns:
144
+ List of available query keys
145
+ """
146
+ return query_loader.list_queries(language)
147
+
148
+ def get_query_description(self, language: str, query_key: str) -> str | None:
149
+ """
150
+ Get description for query key
151
+
152
+ Args:
153
+ language: Programming language
154
+ query_key: Query key
155
+
156
+ Returns:
157
+ Query description, or None if not found
158
+ """
159
+ try:
160
+ return query_loader.get_query_description(language, query_key)
161
+ except Exception:
162
+ return None