tree-sitter-analyzer 0.6.2__py3-none-any.whl → 0.8.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 (69) hide show
  1. tree_sitter_analyzer/__init__.py +132 -132
  2. tree_sitter_analyzer/__main__.py +11 -11
  3. tree_sitter_analyzer/api.py +533 -533
  4. tree_sitter_analyzer/cli/__init__.py +39 -39
  5. tree_sitter_analyzer/cli/__main__.py +12 -12
  6. tree_sitter_analyzer/cli/commands/__init__.py +26 -26
  7. tree_sitter_analyzer/cli/commands/advanced_command.py +88 -88
  8. tree_sitter_analyzer/cli/commands/base_command.py +160 -160
  9. tree_sitter_analyzer/cli/commands/default_command.py +18 -18
  10. tree_sitter_analyzer/cli/commands/partial_read_command.py +141 -141
  11. tree_sitter_analyzer/cli/commands/query_command.py +81 -81
  12. tree_sitter_analyzer/cli/commands/structure_command.py +138 -138
  13. tree_sitter_analyzer/cli/commands/summary_command.py +101 -101
  14. tree_sitter_analyzer/cli/commands/table_command.py +235 -235
  15. tree_sitter_analyzer/cli/info_commands.py +121 -121
  16. tree_sitter_analyzer/cli_main.py +297 -297
  17. tree_sitter_analyzer/core/__init__.py +15 -15
  18. tree_sitter_analyzer/core/analysis_engine.py +555 -555
  19. tree_sitter_analyzer/core/cache_service.py +320 -320
  20. tree_sitter_analyzer/core/engine.py +566 -566
  21. tree_sitter_analyzer/core/parser.py +293 -293
  22. tree_sitter_analyzer/encoding_utils.py +459 -459
  23. tree_sitter_analyzer/exceptions.py +406 -337
  24. tree_sitter_analyzer/file_handler.py +210 -210
  25. tree_sitter_analyzer/formatters/__init__.py +1 -1
  26. tree_sitter_analyzer/formatters/base_formatter.py +167 -167
  27. tree_sitter_analyzer/formatters/formatter_factory.py +78 -78
  28. tree_sitter_analyzer/interfaces/__init__.py +9 -9
  29. tree_sitter_analyzer/interfaces/cli.py +528 -528
  30. tree_sitter_analyzer/interfaces/cli_adapter.py +343 -343
  31. tree_sitter_analyzer/interfaces/mcp_adapter.py +206 -206
  32. tree_sitter_analyzer/interfaces/mcp_server.py +425 -405
  33. tree_sitter_analyzer/languages/__init__.py +10 -10
  34. tree_sitter_analyzer/languages/javascript_plugin.py +446 -446
  35. tree_sitter_analyzer/languages/python_plugin.py +755 -755
  36. tree_sitter_analyzer/mcp/__init__.py +31 -31
  37. tree_sitter_analyzer/mcp/resources/__init__.py +44 -44
  38. tree_sitter_analyzer/mcp/resources/code_file_resource.py +209 -209
  39. tree_sitter_analyzer/mcp/server.py +346 -333
  40. tree_sitter_analyzer/mcp/tools/__init__.py +30 -30
  41. tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +654 -654
  42. tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py +247 -247
  43. tree_sitter_analyzer/mcp/tools/base_tool.py +54 -54
  44. tree_sitter_analyzer/mcp/tools/read_partial_tool.py +300 -300
  45. tree_sitter_analyzer/mcp/tools/table_format_tool.py +362 -362
  46. tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py +543 -543
  47. tree_sitter_analyzer/mcp/utils/__init__.py +107 -107
  48. tree_sitter_analyzer/mcp/utils/error_handler.py +549 -549
  49. tree_sitter_analyzer/output_manager.py +253 -253
  50. tree_sitter_analyzer/plugins/__init__.py +280 -280
  51. tree_sitter_analyzer/plugins/base.py +529 -529
  52. tree_sitter_analyzer/plugins/manager.py +379 -379
  53. tree_sitter_analyzer/queries/__init__.py +26 -26
  54. tree_sitter_analyzer/queries/java.py +391 -391
  55. tree_sitter_analyzer/queries/javascript.py +148 -148
  56. tree_sitter_analyzer/queries/python.py +285 -285
  57. tree_sitter_analyzer/queries/typescript.py +229 -229
  58. tree_sitter_analyzer/query_loader.py +257 -257
  59. tree_sitter_analyzer/security/__init__.py +22 -0
  60. tree_sitter_analyzer/security/boundary_manager.py +237 -0
  61. tree_sitter_analyzer/security/regex_checker.py +292 -0
  62. tree_sitter_analyzer/security/validator.py +224 -0
  63. tree_sitter_analyzer/table_formatter.py +652 -473
  64. tree_sitter_analyzer/utils.py +277 -277
  65. {tree_sitter_analyzer-0.6.2.dist-info → tree_sitter_analyzer-0.8.0.dist-info}/METADATA +4 -1
  66. tree_sitter_analyzer-0.8.0.dist-info/RECORD +76 -0
  67. tree_sitter_analyzer-0.6.2.dist-info/RECORD +0 -72
  68. {tree_sitter_analyzer-0.6.2.dist-info → tree_sitter_analyzer-0.8.0.dist-info}/WHEEL +0 -0
  69. {tree_sitter_analyzer-0.6.2.dist-info → tree_sitter_analyzer-0.8.0.dist-info}/entry_points.txt +0 -0
@@ -1,18 +1,18 @@
1
- #!/usr/bin/env python3
2
- """
3
- Default Command
4
-
5
- Handles default analysis when no specific command is specified.
6
- """
7
-
8
- from ...output_manager import output_error
9
- from .base_command import BaseCommand
10
-
11
-
12
- class DefaultCommand(BaseCommand):
13
- """Default command that shows error when no specific command is given."""
14
-
15
- async def execute_async(self, language: str) -> int:
16
- """Execute default command - show error for missing options."""
17
- output_error("ERROR: Please specify a query or --advanced option")
18
- return 1
1
+ #!/usr/bin/env python3
2
+ """
3
+ Default Command
4
+
5
+ Handles default analysis when no specific command is specified.
6
+ """
7
+
8
+ from ...output_manager import output_error
9
+ from .base_command import BaseCommand
10
+
11
+
12
+ class DefaultCommand(BaseCommand):
13
+ """Default command that shows error when no specific command is given."""
14
+
15
+ async def execute_async(self, language: str) -> int:
16
+ """Execute default command - show error for missing options."""
17
+ output_error("ERROR: Please specify a query or --advanced option")
18
+ return 1
@@ -1,141 +1,141 @@
1
- #!/usr/bin/env python3
2
- """
3
- Partial Read Command
4
-
5
- Handles partial file reading functionality, extracting specified line ranges.
6
- """
7
-
8
- from typing import TYPE_CHECKING, Any
9
-
10
- from ...file_handler import read_file_partial
11
- from ...output_manager import output_data, output_json, output_section
12
- from .base_command import BaseCommand
13
-
14
- if TYPE_CHECKING:
15
- pass
16
-
17
-
18
- class PartialReadCommand(BaseCommand):
19
- """Command for reading partial file content by line range."""
20
-
21
- def __init__(self, args: Any) -> None:
22
- """Initialize with arguments but skip base class analysis engine setup."""
23
- self.args = args
24
- # Don't call super().__init__() to avoid unnecessary analysis engine setup
25
-
26
- def validate_file(self) -> bool:
27
- """Validate input file exists and is accessible."""
28
- if not hasattr(self.args, "file_path") or not self.args.file_path:
29
- from ...output_manager import output_error
30
-
31
- output_error("ERROR: File path not specified.")
32
- return False
33
-
34
- import os
35
-
36
- if not os.path.exists(self.args.file_path):
37
- from ...output_manager import output_error
38
-
39
- output_error(f"ERROR: File not found: {self.args.file_path}")
40
- return False
41
-
42
- return True
43
-
44
- def execute(self) -> int:
45
- """
46
- Execute partial read command.
47
-
48
- Returns:
49
- int: Exit code (0 for success, 1 for failure)
50
- """
51
- # Validate inputs
52
- if not self.validate_file():
53
- return 1
54
-
55
- # Validate partial read arguments
56
- if not self.args.start_line:
57
- from ...output_manager import output_error
58
-
59
- output_error("ERROR: --start-line is required")
60
- return 1
61
-
62
- if self.args.start_line < 1:
63
- from ...output_manager import output_error
64
-
65
- output_error("ERROR: --start-line must be 1 or greater")
66
- return 1
67
-
68
- if self.args.end_line and self.args.end_line < self.args.start_line:
69
- from ...output_manager import output_error
70
-
71
- output_error(
72
- "ERROR: --end-line must be greater than or equal to --start-line"
73
- )
74
- return 1
75
-
76
- # Read partial content
77
- try:
78
- partial_content = read_file_partial(
79
- self.args.file_path,
80
- start_line=self.args.start_line,
81
- end_line=getattr(self.args, "end_line", None),
82
- start_column=getattr(self.args, "start_column", None),
83
- end_column=getattr(self.args, "end_column", None),
84
- )
85
-
86
- if partial_content is None:
87
- from ...output_manager import output_error
88
-
89
- output_error("ERROR: Failed to read file partially")
90
- return 1
91
-
92
- # Output the result
93
- self._output_partial_content(partial_content)
94
- return 0
95
-
96
- except Exception as e:
97
- from ...output_manager import output_error
98
-
99
- output_error(f"ERROR: Failed to read file partially: {e}")
100
- return 1
101
-
102
- def _output_partial_content(self, content: str) -> None:
103
- """Output the partial content in the specified format."""
104
- # Build result data
105
- result_data = {
106
- "file_path": self.args.file_path,
107
- "range": {
108
- "start_line": self.args.start_line,
109
- "end_line": getattr(self.args, "end_line", None),
110
- "start_column": getattr(self.args, "start_column", None),
111
- "end_column": getattr(self.args, "end_column", None),
112
- },
113
- "content": content,
114
- "content_length": len(content),
115
- }
116
-
117
- # Build range info for header
118
- range_info = f"Line {self.args.start_line}"
119
- if hasattr(self.args, "end_line") and self.args.end_line:
120
- range_info += f"-{self.args.end_line}"
121
-
122
- # Output format selection
123
- output_format = getattr(self.args, "output_format", "text")
124
-
125
- if output_format == "json":
126
- # Pure JSON output
127
- output_json(result_data)
128
- else:
129
- # Human-readable format with header
130
- output_section("Partial Read Result")
131
- output_data(f"File: {self.args.file_path}")
132
- output_data(f"Range: {range_info}")
133
- output_data(f"Characters read: {len(content)}")
134
- output_data("") # Empty line for separation
135
-
136
- # Output the actual content
137
- print(content, end="") # Use print to avoid extra formatting
138
-
139
- async def execute_async(self, language: str) -> int:
140
- """Not used for partial read command."""
141
- return self.execute()
1
+ #!/usr/bin/env python3
2
+ """
3
+ Partial Read Command
4
+
5
+ Handles partial file reading functionality, extracting specified line ranges.
6
+ """
7
+
8
+ from typing import TYPE_CHECKING, Any
9
+
10
+ from ...file_handler import read_file_partial
11
+ from ...output_manager import output_data, output_json, output_section
12
+ from .base_command import BaseCommand
13
+
14
+ if TYPE_CHECKING:
15
+ pass
16
+
17
+
18
+ class PartialReadCommand(BaseCommand):
19
+ """Command for reading partial file content by line range."""
20
+
21
+ def __init__(self, args: Any) -> None:
22
+ """Initialize with arguments but skip base class analysis engine setup."""
23
+ self.args = args
24
+ # Don't call super().__init__() to avoid unnecessary analysis engine setup
25
+
26
+ def validate_file(self) -> bool:
27
+ """Validate input file exists and is accessible."""
28
+ if not hasattr(self.args, "file_path") or not self.args.file_path:
29
+ from ...output_manager import output_error
30
+
31
+ output_error("ERROR: File path not specified.")
32
+ return False
33
+
34
+ import os
35
+
36
+ if not os.path.exists(self.args.file_path):
37
+ from ...output_manager import output_error
38
+
39
+ output_error(f"ERROR: File not found: {self.args.file_path}")
40
+ return False
41
+
42
+ return True
43
+
44
+ def execute(self) -> int:
45
+ """
46
+ Execute partial read command.
47
+
48
+ Returns:
49
+ int: Exit code (0 for success, 1 for failure)
50
+ """
51
+ # Validate inputs
52
+ if not self.validate_file():
53
+ return 1
54
+
55
+ # Validate partial read arguments
56
+ if not self.args.start_line:
57
+ from ...output_manager import output_error
58
+
59
+ output_error("ERROR: --start-line is required")
60
+ return 1
61
+
62
+ if self.args.start_line < 1:
63
+ from ...output_manager import output_error
64
+
65
+ output_error("ERROR: --start-line must be 1 or greater")
66
+ return 1
67
+
68
+ if self.args.end_line and self.args.end_line < self.args.start_line:
69
+ from ...output_manager import output_error
70
+
71
+ output_error(
72
+ "ERROR: --end-line must be greater than or equal to --start-line"
73
+ )
74
+ return 1
75
+
76
+ # Read partial content
77
+ try:
78
+ partial_content = read_file_partial(
79
+ self.args.file_path,
80
+ start_line=self.args.start_line,
81
+ end_line=getattr(self.args, "end_line", None),
82
+ start_column=getattr(self.args, "start_column", None),
83
+ end_column=getattr(self.args, "end_column", None),
84
+ )
85
+
86
+ if partial_content is None:
87
+ from ...output_manager import output_error
88
+
89
+ output_error("ERROR: Failed to read file partially")
90
+ return 1
91
+
92
+ # Output the result
93
+ self._output_partial_content(partial_content)
94
+ return 0
95
+
96
+ except Exception as e:
97
+ from ...output_manager import output_error
98
+
99
+ output_error(f"ERROR: Failed to read file partially: {e}")
100
+ return 1
101
+
102
+ def _output_partial_content(self, content: str) -> None:
103
+ """Output the partial content in the specified format."""
104
+ # Build result data
105
+ result_data = {
106
+ "file_path": self.args.file_path,
107
+ "range": {
108
+ "start_line": self.args.start_line,
109
+ "end_line": getattr(self.args, "end_line", None),
110
+ "start_column": getattr(self.args, "start_column", None),
111
+ "end_column": getattr(self.args, "end_column", None),
112
+ },
113
+ "content": content,
114
+ "content_length": len(content),
115
+ }
116
+
117
+ # Build range info for header
118
+ range_info = f"Line {self.args.start_line}"
119
+ if hasattr(self.args, "end_line") and self.args.end_line:
120
+ range_info += f"-{self.args.end_line}"
121
+
122
+ # Output format selection
123
+ output_format = getattr(self.args, "output_format", "text")
124
+
125
+ if output_format == "json":
126
+ # Pure JSON output
127
+ output_json(result_data)
128
+ else:
129
+ # Human-readable format with header
130
+ output_section("Partial Read Result")
131
+ output_data(f"File: {self.args.file_path}")
132
+ output_data(f"Range: {range_info}")
133
+ output_data(f"Characters read: {len(content)}")
134
+ output_data("") # Empty line for separation
135
+
136
+ # Output the actual content
137
+ print(content, end="") # Use print to avoid extra formatting
138
+
139
+ async def execute_async(self, language: str) -> int:
140
+ """Not used for partial read command."""
141
+ return self.execute()
@@ -1,81 +1,81 @@
1
- #!/usr/bin/env python3
2
- """
3
- Query Command
4
-
5
- Handles query execution functionality.
6
- """
7
-
8
- from ...output_manager import output_data, output_error, output_info, output_json
9
- from ...query_loader import query_loader
10
- from .base_command import BaseCommand
11
-
12
-
13
- class QueryCommand(BaseCommand):
14
- """Command for executing queries."""
15
-
16
- async def execute_async(self, language: str) -> int:
17
- # Get the query to execute
18
- query_to_execute = None
19
-
20
- if hasattr(self.args, "query_key") and self.args.query_key:
21
- try:
22
- query_to_execute = query_loader.get_query(language, self.args.query_key)
23
- if query_to_execute is None:
24
- output_error(
25
- f"ERROR: Query '{self.args.query_key}' not found for language '{language}'"
26
- )
27
- return 1
28
- except ValueError as e:
29
- output_error(f"ERROR: {e}")
30
- return 1
31
- elif hasattr(self.args, "query_string") and self.args.query_string:
32
- query_to_execute = self.args.query_string
33
-
34
- if not query_to_execute:
35
- output_error("ERROR: No query specified.")
36
- return 1
37
-
38
- # Perform analysis
39
- analysis_result = await self.analyze_file(language)
40
- if not analysis_result:
41
- return 1
42
-
43
- # Process query results
44
- results = []
45
- if hasattr(analysis_result, "query_results") and analysis_result.query_results:
46
- results = analysis_result.query_results.get("captures", [])
47
- else:
48
- # Create basic results from elements
49
- if hasattr(analysis_result, "elements") and analysis_result.elements:
50
- for element in analysis_result.elements:
51
- results.append(
52
- {
53
- "capture_name": getattr(
54
- element, "__class__", type(element)
55
- ).__name__.lower(),
56
- "node_type": getattr(
57
- element, "__class__", type(element)
58
- ).__name__,
59
- "start_line": getattr(element, "start_line", 0),
60
- "end_line": getattr(element, "end_line", 0),
61
- "content": getattr(element, "name", str(element)),
62
- }
63
- )
64
-
65
- # Output results
66
- if results:
67
- if self.args.output_format == "json":
68
- output_json(results)
69
- else:
70
- for i, query_result in enumerate(results, 1):
71
- output_data(
72
- f"\n{i}. {query_result['capture_name']} ({query_result['node_type']})"
73
- )
74
- output_data(
75
- f" Position: Line {query_result['start_line']}-{query_result['end_line']}"
76
- )
77
- output_data(f" Content:\n{query_result['content']}")
78
- else:
79
- output_info("\nINFO: No results found matching the query.")
80
-
81
- return 0
1
+ #!/usr/bin/env python3
2
+ """
3
+ Query Command
4
+
5
+ Handles query execution functionality.
6
+ """
7
+
8
+ from ...output_manager import output_data, output_error, output_info, output_json
9
+ from ...query_loader import query_loader
10
+ from .base_command import BaseCommand
11
+
12
+
13
+ class QueryCommand(BaseCommand):
14
+ """Command for executing queries."""
15
+
16
+ async def execute_async(self, language: str) -> int:
17
+ # Get the query to execute
18
+ query_to_execute = None
19
+
20
+ if hasattr(self.args, "query_key") and self.args.query_key:
21
+ try:
22
+ query_to_execute = query_loader.get_query(language, self.args.query_key)
23
+ if query_to_execute is None:
24
+ output_error(
25
+ f"ERROR: Query '{self.args.query_key}' not found for language '{language}'"
26
+ )
27
+ return 1
28
+ except ValueError as e:
29
+ output_error(f"ERROR: {e}")
30
+ return 1
31
+ elif hasattr(self.args, "query_string") and self.args.query_string:
32
+ query_to_execute = self.args.query_string
33
+
34
+ if not query_to_execute:
35
+ output_error("ERROR: No query specified.")
36
+ return 1
37
+
38
+ # Perform analysis
39
+ analysis_result = await self.analyze_file(language)
40
+ if not analysis_result:
41
+ return 1
42
+
43
+ # Process query results
44
+ results = []
45
+ if hasattr(analysis_result, "query_results") and analysis_result.query_results:
46
+ results = analysis_result.query_results.get("captures", [])
47
+ else:
48
+ # Create basic results from elements
49
+ if hasattr(analysis_result, "elements") and analysis_result.elements:
50
+ for element in analysis_result.elements:
51
+ results.append(
52
+ {
53
+ "capture_name": getattr(
54
+ element, "__class__", type(element)
55
+ ).__name__.lower(),
56
+ "node_type": getattr(
57
+ element, "__class__", type(element)
58
+ ).__name__,
59
+ "start_line": getattr(element, "start_line", 0),
60
+ "end_line": getattr(element, "end_line", 0),
61
+ "content": getattr(element, "name", str(element)),
62
+ }
63
+ )
64
+
65
+ # Output results
66
+ if results:
67
+ if self.args.output_format == "json":
68
+ output_json(results)
69
+ else:
70
+ for i, query_result in enumerate(results, 1):
71
+ output_data(
72
+ f"\n{i}. {query_result['capture_name']} ({query_result['node_type']})"
73
+ )
74
+ output_data(
75
+ f" Position: Line {query_result['start_line']}-{query_result['end_line']}"
76
+ )
77
+ output_data(f" Content:\n{query_result['content']}")
78
+ else:
79
+ output_info("\nINFO: No results found matching the query.")
80
+
81
+ return 0