tree-sitter-analyzer 0.7.0__py3-none-any.whl → 0.8.1__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.
- tree_sitter_analyzer/__init__.py +132 -132
- tree_sitter_analyzer/__main__.py +11 -11
- tree_sitter_analyzer/api.py +533 -533
- tree_sitter_analyzer/cli/__init__.py +39 -39
- tree_sitter_analyzer/cli/__main__.py +12 -12
- tree_sitter_analyzer/cli/commands/__init__.py +26 -26
- tree_sitter_analyzer/cli/commands/advanced_command.py +88 -88
- tree_sitter_analyzer/cli/commands/base_command.py +178 -160
- tree_sitter_analyzer/cli/commands/default_command.py +18 -18
- tree_sitter_analyzer/cli/commands/partial_read_command.py +141 -141
- tree_sitter_analyzer/cli/commands/query_command.py +88 -81
- tree_sitter_analyzer/cli/commands/structure_command.py +138 -138
- tree_sitter_analyzer/cli/commands/summary_command.py +101 -101
- tree_sitter_analyzer/cli/commands/table_command.py +235 -235
- tree_sitter_analyzer/cli/info_commands.py +121 -121
- tree_sitter_analyzer/cli_main.py +303 -297
- tree_sitter_analyzer/core/__init__.py +15 -15
- tree_sitter_analyzer/core/analysis_engine.py +580 -555
- tree_sitter_analyzer/core/cache_service.py +320 -320
- tree_sitter_analyzer/core/engine.py +566 -566
- tree_sitter_analyzer/core/parser.py +293 -293
- tree_sitter_analyzer/encoding_utils.py +459 -459
- tree_sitter_analyzer/exceptions.py +406 -337
- tree_sitter_analyzer/file_handler.py +210 -210
- tree_sitter_analyzer/formatters/__init__.py +1 -1
- tree_sitter_analyzer/formatters/base_formatter.py +167 -167
- tree_sitter_analyzer/formatters/formatter_factory.py +78 -78
- tree_sitter_analyzer/interfaces/__init__.py +9 -9
- tree_sitter_analyzer/interfaces/cli.py +528 -528
- tree_sitter_analyzer/interfaces/cli_adapter.py +343 -343
- tree_sitter_analyzer/interfaces/mcp_adapter.py +206 -206
- tree_sitter_analyzer/interfaces/mcp_server.py +425 -405
- tree_sitter_analyzer/languages/__init__.py +10 -10
- tree_sitter_analyzer/languages/javascript_plugin.py +446 -446
- tree_sitter_analyzer/languages/python_plugin.py +755 -755
- tree_sitter_analyzer/mcp/__init__.py +31 -31
- tree_sitter_analyzer/mcp/resources/__init__.py +44 -44
- tree_sitter_analyzer/mcp/resources/code_file_resource.py +209 -209
- tree_sitter_analyzer/mcp/server.py +408 -333
- tree_sitter_analyzer/mcp/tools/__init__.py +30 -30
- tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +673 -654
- tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py +247 -247
- tree_sitter_analyzer/mcp/tools/base_tool.py +54 -54
- tree_sitter_analyzer/mcp/tools/read_partial_tool.py +308 -300
- tree_sitter_analyzer/mcp/tools/table_format_tool.py +379 -362
- tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py +559 -543
- tree_sitter_analyzer/mcp/utils/__init__.py +107 -107
- tree_sitter_analyzer/mcp/utils/error_handler.py +549 -549
- tree_sitter_analyzer/output_manager.py +253 -253
- tree_sitter_analyzer/plugins/__init__.py +280 -280
- tree_sitter_analyzer/plugins/base.py +529 -529
- tree_sitter_analyzer/plugins/manager.py +379 -379
- tree_sitter_analyzer/project_detector.py +317 -0
- tree_sitter_analyzer/queries/__init__.py +26 -26
- tree_sitter_analyzer/queries/java.py +391 -391
- tree_sitter_analyzer/queries/javascript.py +148 -148
- tree_sitter_analyzer/queries/python.py +285 -285
- tree_sitter_analyzer/queries/typescript.py +229 -229
- tree_sitter_analyzer/query_loader.py +257 -257
- tree_sitter_analyzer/security/__init__.py +22 -0
- tree_sitter_analyzer/security/boundary_manager.py +237 -0
- tree_sitter_analyzer/security/regex_checker.py +292 -0
- tree_sitter_analyzer/security/validator.py +241 -0
- tree_sitter_analyzer/table_formatter.py +652 -589
- tree_sitter_analyzer/utils.py +277 -277
- {tree_sitter_analyzer-0.7.0.dist-info → tree_sitter_analyzer-0.8.1.dist-info}/METADATA +27 -1
- tree_sitter_analyzer-0.8.1.dist-info/RECORD +77 -0
- tree_sitter_analyzer-0.7.0.dist-info/RECORD +0 -72
- {tree_sitter_analyzer-0.7.0.dist-info → tree_sitter_analyzer-0.8.1.dist-info}/WHEEL +0 -0
- {tree_sitter_analyzer-0.7.0.dist-info → tree_sitter_analyzer-0.8.1.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,317 @@
|
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Project Root Detection
|
|
4
|
+
|
|
5
|
+
Intelligent detection of project root directories based on common project markers.
|
|
6
|
+
"""
|
|
7
|
+
|
|
8
|
+
import os
|
|
9
|
+
from pathlib import Path
|
|
10
|
+
from typing import Optional, List, Tuple
|
|
11
|
+
import logging
|
|
12
|
+
|
|
13
|
+
logger = logging.getLogger(__name__)
|
|
14
|
+
|
|
15
|
+
# Common project root indicators (in priority order)
|
|
16
|
+
PROJECT_MARKERS = [
|
|
17
|
+
# Version control
|
|
18
|
+
'.git',
|
|
19
|
+
'.hg',
|
|
20
|
+
'.svn',
|
|
21
|
+
|
|
22
|
+
# Python projects
|
|
23
|
+
'pyproject.toml',
|
|
24
|
+
'setup.py',
|
|
25
|
+
'setup.cfg',
|
|
26
|
+
'requirements.txt',
|
|
27
|
+
'Pipfile',
|
|
28
|
+
'poetry.lock',
|
|
29
|
+
'conda.yaml',
|
|
30
|
+
'environment.yml',
|
|
31
|
+
|
|
32
|
+
# JavaScript/Node.js projects
|
|
33
|
+
'package.json',
|
|
34
|
+
'package-lock.json',
|
|
35
|
+
'yarn.lock',
|
|
36
|
+
'node_modules',
|
|
37
|
+
|
|
38
|
+
# Java projects
|
|
39
|
+
'pom.xml',
|
|
40
|
+
'build.gradle',
|
|
41
|
+
'build.gradle.kts',
|
|
42
|
+
'gradlew',
|
|
43
|
+
'mvnw',
|
|
44
|
+
|
|
45
|
+
# C/C++ projects
|
|
46
|
+
'CMakeLists.txt',
|
|
47
|
+
'Makefile',
|
|
48
|
+
'configure.ac',
|
|
49
|
+
'configure.in',
|
|
50
|
+
|
|
51
|
+
# Rust projects
|
|
52
|
+
'Cargo.toml',
|
|
53
|
+
'Cargo.lock',
|
|
54
|
+
|
|
55
|
+
# Go projects
|
|
56
|
+
'go.mod',
|
|
57
|
+
'go.sum',
|
|
58
|
+
|
|
59
|
+
# .NET projects
|
|
60
|
+
'*.sln',
|
|
61
|
+
'*.csproj',
|
|
62
|
+
'*.vbproj',
|
|
63
|
+
'*.fsproj',
|
|
64
|
+
|
|
65
|
+
# Other common markers
|
|
66
|
+
'README.md',
|
|
67
|
+
'README.rst',
|
|
68
|
+
'README.txt',
|
|
69
|
+
'LICENSE',
|
|
70
|
+
'CHANGELOG.md',
|
|
71
|
+
'.gitignore',
|
|
72
|
+
'.dockerignore',
|
|
73
|
+
'Dockerfile',
|
|
74
|
+
'docker-compose.yml',
|
|
75
|
+
'.editorconfig',
|
|
76
|
+
]
|
|
77
|
+
|
|
78
|
+
|
|
79
|
+
class ProjectRootDetector:
|
|
80
|
+
"""Intelligent project root directory detection."""
|
|
81
|
+
|
|
82
|
+
def __init__(self, max_depth: int = 10):
|
|
83
|
+
"""
|
|
84
|
+
Initialize project root detector.
|
|
85
|
+
|
|
86
|
+
Args:
|
|
87
|
+
max_depth: Maximum directory levels to traverse upward
|
|
88
|
+
"""
|
|
89
|
+
self.max_depth = max_depth
|
|
90
|
+
|
|
91
|
+
def detect_from_file(self, file_path: str) -> Optional[str]:
|
|
92
|
+
"""
|
|
93
|
+
Detect project root from a file path.
|
|
94
|
+
|
|
95
|
+
Args:
|
|
96
|
+
file_path: Path to a file within the project
|
|
97
|
+
|
|
98
|
+
Returns:
|
|
99
|
+
Project root directory path, or None if not detected
|
|
100
|
+
"""
|
|
101
|
+
if not file_path:
|
|
102
|
+
return None
|
|
103
|
+
|
|
104
|
+
try:
|
|
105
|
+
# Convert to absolute path and get directory
|
|
106
|
+
abs_path = os.path.abspath(file_path)
|
|
107
|
+
if os.path.isfile(abs_path):
|
|
108
|
+
start_dir = os.path.dirname(abs_path)
|
|
109
|
+
else:
|
|
110
|
+
start_dir = abs_path
|
|
111
|
+
|
|
112
|
+
return self._traverse_upward(start_dir)
|
|
113
|
+
|
|
114
|
+
except Exception as e:
|
|
115
|
+
logger.warning(f"Error detecting project root from {file_path}: {e}")
|
|
116
|
+
return None
|
|
117
|
+
|
|
118
|
+
def detect_from_cwd(self) -> Optional[str]:
|
|
119
|
+
"""
|
|
120
|
+
Detect project root from current working directory.
|
|
121
|
+
|
|
122
|
+
Returns:
|
|
123
|
+
Project root directory path, or None if not detected
|
|
124
|
+
"""
|
|
125
|
+
try:
|
|
126
|
+
return self._traverse_upward(os.getcwd())
|
|
127
|
+
except Exception as e:
|
|
128
|
+
logger.warning(f"Error detecting project root from cwd: {e}")
|
|
129
|
+
return None
|
|
130
|
+
|
|
131
|
+
def _traverse_upward(self, start_dir: str) -> Optional[str]:
|
|
132
|
+
"""
|
|
133
|
+
Traverse upward from start directory looking for project markers.
|
|
134
|
+
|
|
135
|
+
Args:
|
|
136
|
+
start_dir: Directory to start traversal from
|
|
137
|
+
|
|
138
|
+
Returns:
|
|
139
|
+
Project root directory path, or None if not found
|
|
140
|
+
"""
|
|
141
|
+
current_dir = os.path.abspath(start_dir)
|
|
142
|
+
candidates = []
|
|
143
|
+
|
|
144
|
+
for depth in range(self.max_depth):
|
|
145
|
+
# Check for project markers in current directory
|
|
146
|
+
markers_found = self._find_markers_in_dir(current_dir)
|
|
147
|
+
|
|
148
|
+
if markers_found:
|
|
149
|
+
# Calculate score based on marker priority and count
|
|
150
|
+
score = self._calculate_score(markers_found)
|
|
151
|
+
candidates.append((current_dir, score, markers_found))
|
|
152
|
+
|
|
153
|
+
# If we find high-priority markers, we can stop early
|
|
154
|
+
if any(marker in ['.git', 'pyproject.toml', 'package.json', 'pom.xml', 'Cargo.toml', 'go.mod']
|
|
155
|
+
for marker in markers_found):
|
|
156
|
+
logger.debug(f"Found high-priority project root: {current_dir} (markers: {markers_found})")
|
|
157
|
+
return current_dir
|
|
158
|
+
|
|
159
|
+
# Move up one directory
|
|
160
|
+
parent_dir = os.path.dirname(current_dir)
|
|
161
|
+
if parent_dir == current_dir: # Reached filesystem root
|
|
162
|
+
break
|
|
163
|
+
current_dir = parent_dir
|
|
164
|
+
|
|
165
|
+
# Return the best candidate if any found
|
|
166
|
+
if candidates:
|
|
167
|
+
# Sort by score (descending) and return the best
|
|
168
|
+
candidates.sort(key=lambda x: x[1], reverse=True)
|
|
169
|
+
best_candidate = candidates[0]
|
|
170
|
+
logger.debug(f"Selected project root: {best_candidate[0]} (score: {best_candidate[1]}, markers: {best_candidate[2]})")
|
|
171
|
+
return best_candidate[0]
|
|
172
|
+
|
|
173
|
+
logger.debug(f"No project root detected from {start_dir}")
|
|
174
|
+
return None
|
|
175
|
+
|
|
176
|
+
def _find_markers_in_dir(self, directory: str) -> List[str]:
|
|
177
|
+
"""
|
|
178
|
+
Find project markers in a directory.
|
|
179
|
+
|
|
180
|
+
Args:
|
|
181
|
+
directory: Directory to search in
|
|
182
|
+
|
|
183
|
+
Returns:
|
|
184
|
+
List of found marker names
|
|
185
|
+
"""
|
|
186
|
+
found_markers = []
|
|
187
|
+
|
|
188
|
+
try:
|
|
189
|
+
dir_contents = os.listdir(directory)
|
|
190
|
+
|
|
191
|
+
for marker in PROJECT_MARKERS:
|
|
192
|
+
if '*' in marker:
|
|
193
|
+
# Handle glob patterns
|
|
194
|
+
import glob
|
|
195
|
+
pattern = os.path.join(directory, marker)
|
|
196
|
+
if glob.glob(pattern):
|
|
197
|
+
found_markers.append(marker)
|
|
198
|
+
else:
|
|
199
|
+
# Handle exact matches
|
|
200
|
+
if marker in dir_contents:
|
|
201
|
+
found_markers.append(marker)
|
|
202
|
+
|
|
203
|
+
except (OSError, PermissionError) as e:
|
|
204
|
+
logger.debug(f"Cannot access directory {directory}: {e}")
|
|
205
|
+
|
|
206
|
+
return found_markers
|
|
207
|
+
|
|
208
|
+
def _calculate_score(self, markers: List[str]) -> int:
|
|
209
|
+
"""
|
|
210
|
+
Calculate a score for project root candidates based on markers found.
|
|
211
|
+
|
|
212
|
+
Args:
|
|
213
|
+
markers: List of found markers
|
|
214
|
+
|
|
215
|
+
Returns:
|
|
216
|
+
Score (higher is better)
|
|
217
|
+
"""
|
|
218
|
+
score = 0
|
|
219
|
+
|
|
220
|
+
# High-priority markers
|
|
221
|
+
high_priority = ['.git', 'pyproject.toml', 'package.json', 'pom.xml', 'Cargo.toml', 'go.mod']
|
|
222
|
+
medium_priority = ['setup.py', 'requirements.txt', 'CMakeLists.txt', 'Makefile']
|
|
223
|
+
|
|
224
|
+
for marker in markers:
|
|
225
|
+
if marker in high_priority:
|
|
226
|
+
score += 100
|
|
227
|
+
elif marker in medium_priority:
|
|
228
|
+
score += 50
|
|
229
|
+
else:
|
|
230
|
+
score += 10
|
|
231
|
+
|
|
232
|
+
# Bonus for multiple markers
|
|
233
|
+
if len(markers) > 1:
|
|
234
|
+
score += len(markers) * 5
|
|
235
|
+
|
|
236
|
+
return score
|
|
237
|
+
|
|
238
|
+
def get_fallback_root(self, file_path: str) -> str:
|
|
239
|
+
"""
|
|
240
|
+
Get fallback project root when detection fails.
|
|
241
|
+
|
|
242
|
+
Args:
|
|
243
|
+
file_path: Original file path
|
|
244
|
+
|
|
245
|
+
Returns:
|
|
246
|
+
Fallback directory (file's directory or cwd)
|
|
247
|
+
"""
|
|
248
|
+
try:
|
|
249
|
+
if file_path and os.path.exists(file_path):
|
|
250
|
+
if os.path.isfile(file_path):
|
|
251
|
+
return os.path.dirname(os.path.abspath(file_path))
|
|
252
|
+
else:
|
|
253
|
+
return os.path.abspath(file_path)
|
|
254
|
+
else:
|
|
255
|
+
return os.getcwd()
|
|
256
|
+
except Exception:
|
|
257
|
+
return os.getcwd()
|
|
258
|
+
|
|
259
|
+
|
|
260
|
+
def detect_project_root(file_path: Optional[str] = None,
|
|
261
|
+
explicit_root: Optional[str] = None) -> str:
|
|
262
|
+
"""
|
|
263
|
+
Unified project root detection with priority handling.
|
|
264
|
+
|
|
265
|
+
Priority order:
|
|
266
|
+
1. explicit_root parameter (highest priority)
|
|
267
|
+
2. Auto-detection from file_path
|
|
268
|
+
3. Auto-detection from current working directory
|
|
269
|
+
4. Fallback to file directory or cwd
|
|
270
|
+
|
|
271
|
+
Args:
|
|
272
|
+
file_path: Path to a file within the project
|
|
273
|
+
explicit_root: Explicitly specified project root
|
|
274
|
+
|
|
275
|
+
Returns:
|
|
276
|
+
Project root directory path
|
|
277
|
+
"""
|
|
278
|
+
detector = ProjectRootDetector()
|
|
279
|
+
|
|
280
|
+
# Priority 1: Explicit root
|
|
281
|
+
if explicit_root:
|
|
282
|
+
if os.path.exists(explicit_root) and os.path.isdir(explicit_root):
|
|
283
|
+
logger.info(f"Using explicit project root: {explicit_root}")
|
|
284
|
+
return os.path.abspath(explicit_root)
|
|
285
|
+
else:
|
|
286
|
+
logger.warning(f"Explicit project root does not exist: {explicit_root}")
|
|
287
|
+
|
|
288
|
+
# Priority 2: Auto-detection from file path
|
|
289
|
+
if file_path:
|
|
290
|
+
detected_root = detector.detect_from_file(file_path)
|
|
291
|
+
if detected_root:
|
|
292
|
+
logger.info(f"Auto-detected project root from file: {detected_root}")
|
|
293
|
+
return detected_root
|
|
294
|
+
|
|
295
|
+
# Priority 3: Auto-detection from cwd
|
|
296
|
+
detected_root = detector.detect_from_cwd()
|
|
297
|
+
if detected_root:
|
|
298
|
+
logger.info(f"Auto-detected project root from cwd: {detected_root}")
|
|
299
|
+
return detected_root
|
|
300
|
+
|
|
301
|
+
# Priority 4: Fallback
|
|
302
|
+
fallback_root = detector.get_fallback_root(file_path)
|
|
303
|
+
logger.info(f"Using fallback project root: {fallback_root}")
|
|
304
|
+
return fallback_root
|
|
305
|
+
|
|
306
|
+
|
|
307
|
+
if __name__ == "__main__":
|
|
308
|
+
# Test the detector
|
|
309
|
+
import sys
|
|
310
|
+
|
|
311
|
+
if len(sys.argv) > 1:
|
|
312
|
+
test_path = sys.argv[1]
|
|
313
|
+
result = detect_project_root(test_path)
|
|
314
|
+
print(f"Project root for '{test_path}': {result}")
|
|
315
|
+
else:
|
|
316
|
+
result = detect_project_root()
|
|
317
|
+
print(f"Project root from cwd: {result}")
|
|
@@ -1,26 +1,26 @@
|
|
|
1
|
-
#!/usr/bin/env python3
|
|
2
|
-
"""
|
|
3
|
-
Language-specific Tree-sitter queries package.
|
|
4
|
-
|
|
5
|
-
This package provides Tree-sitter queries for various programming languages.
|
|
6
|
-
Each language has its own module with predefined queries for common code elements.
|
|
7
|
-
|
|
8
|
-
Supported languages:
|
|
9
|
-
- Java
|
|
10
|
-
- JavaScript
|
|
11
|
-
- Python
|
|
12
|
-
- TypeScript
|
|
13
|
-
|
|
14
|
-
Usage:
|
|
15
|
-
from tree_sitter_analyzer.queries import get_query, list_queries
|
|
16
|
-
|
|
17
|
-
# Get a specific query
|
|
18
|
-
query = get_query('java', 'classes')
|
|
19
|
-
|
|
20
|
-
# List all queries for a language
|
|
21
|
-
queries = list_queries('python')
|
|
22
|
-
"""
|
|
23
|
-
|
|
24
|
-
from ..query_loader import get_query, is_language_supported, list_queries, query_loader
|
|
25
|
-
|
|
26
|
-
__all__ = ["get_query", "list_queries", "is_language_supported", "query_loader"]
|
|
1
|
+
#!/usr/bin/env python3
|
|
2
|
+
"""
|
|
3
|
+
Language-specific Tree-sitter queries package.
|
|
4
|
+
|
|
5
|
+
This package provides Tree-sitter queries for various programming languages.
|
|
6
|
+
Each language has its own module with predefined queries for common code elements.
|
|
7
|
+
|
|
8
|
+
Supported languages:
|
|
9
|
+
- Java
|
|
10
|
+
- JavaScript
|
|
11
|
+
- Python
|
|
12
|
+
- TypeScript
|
|
13
|
+
|
|
14
|
+
Usage:
|
|
15
|
+
from tree_sitter_analyzer.queries import get_query, list_queries
|
|
16
|
+
|
|
17
|
+
# Get a specific query
|
|
18
|
+
query = get_query('java', 'classes')
|
|
19
|
+
|
|
20
|
+
# List all queries for a language
|
|
21
|
+
queries = list_queries('python')
|
|
22
|
+
"""
|
|
23
|
+
|
|
24
|
+
from ..query_loader import get_query, is_language_supported, list_queries, query_loader
|
|
25
|
+
|
|
26
|
+
__all__ = ["get_query", "list_queries", "is_language_supported", "query_loader"]
|