tree-sitter-analyzer 1.9.17.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.
Files changed (149) hide show
  1. tree_sitter_analyzer/__init__.py +132 -0
  2. tree_sitter_analyzer/__main__.py +11 -0
  3. tree_sitter_analyzer/api.py +853 -0
  4. tree_sitter_analyzer/cli/__init__.py +39 -0
  5. tree_sitter_analyzer/cli/__main__.py +12 -0
  6. tree_sitter_analyzer/cli/argument_validator.py +89 -0
  7. tree_sitter_analyzer/cli/commands/__init__.py +26 -0
  8. tree_sitter_analyzer/cli/commands/advanced_command.py +226 -0
  9. tree_sitter_analyzer/cli/commands/base_command.py +181 -0
  10. tree_sitter_analyzer/cli/commands/default_command.py +18 -0
  11. tree_sitter_analyzer/cli/commands/find_and_grep_cli.py +188 -0
  12. tree_sitter_analyzer/cli/commands/list_files_cli.py +133 -0
  13. tree_sitter_analyzer/cli/commands/partial_read_command.py +139 -0
  14. tree_sitter_analyzer/cli/commands/query_command.py +109 -0
  15. tree_sitter_analyzer/cli/commands/search_content_cli.py +161 -0
  16. tree_sitter_analyzer/cli/commands/structure_command.py +156 -0
  17. tree_sitter_analyzer/cli/commands/summary_command.py +116 -0
  18. tree_sitter_analyzer/cli/commands/table_command.py +414 -0
  19. tree_sitter_analyzer/cli/info_commands.py +124 -0
  20. tree_sitter_analyzer/cli_main.py +472 -0
  21. tree_sitter_analyzer/constants.py +85 -0
  22. tree_sitter_analyzer/core/__init__.py +15 -0
  23. tree_sitter_analyzer/core/analysis_engine.py +580 -0
  24. tree_sitter_analyzer/core/cache_service.py +333 -0
  25. tree_sitter_analyzer/core/engine.py +585 -0
  26. tree_sitter_analyzer/core/parser.py +293 -0
  27. tree_sitter_analyzer/core/query.py +605 -0
  28. tree_sitter_analyzer/core/query_filter.py +200 -0
  29. tree_sitter_analyzer/core/query_service.py +340 -0
  30. tree_sitter_analyzer/encoding_utils.py +530 -0
  31. tree_sitter_analyzer/exceptions.py +747 -0
  32. tree_sitter_analyzer/file_handler.py +246 -0
  33. tree_sitter_analyzer/formatters/__init__.py +1 -0
  34. tree_sitter_analyzer/formatters/base_formatter.py +201 -0
  35. tree_sitter_analyzer/formatters/csharp_formatter.py +367 -0
  36. tree_sitter_analyzer/formatters/formatter_config.py +197 -0
  37. tree_sitter_analyzer/formatters/formatter_factory.py +84 -0
  38. tree_sitter_analyzer/formatters/formatter_registry.py +377 -0
  39. tree_sitter_analyzer/formatters/formatter_selector.py +96 -0
  40. tree_sitter_analyzer/formatters/go_formatter.py +368 -0
  41. tree_sitter_analyzer/formatters/html_formatter.py +498 -0
  42. tree_sitter_analyzer/formatters/java_formatter.py +423 -0
  43. tree_sitter_analyzer/formatters/javascript_formatter.py +611 -0
  44. tree_sitter_analyzer/formatters/kotlin_formatter.py +268 -0
  45. tree_sitter_analyzer/formatters/language_formatter_factory.py +123 -0
  46. tree_sitter_analyzer/formatters/legacy_formatter_adapters.py +228 -0
  47. tree_sitter_analyzer/formatters/markdown_formatter.py +725 -0
  48. tree_sitter_analyzer/formatters/php_formatter.py +301 -0
  49. tree_sitter_analyzer/formatters/python_formatter.py +830 -0
  50. tree_sitter_analyzer/formatters/ruby_formatter.py +278 -0
  51. tree_sitter_analyzer/formatters/rust_formatter.py +233 -0
  52. tree_sitter_analyzer/formatters/sql_formatter_wrapper.py +689 -0
  53. tree_sitter_analyzer/formatters/sql_formatters.py +536 -0
  54. tree_sitter_analyzer/formatters/typescript_formatter.py +543 -0
  55. tree_sitter_analyzer/formatters/yaml_formatter.py +462 -0
  56. tree_sitter_analyzer/interfaces/__init__.py +9 -0
  57. tree_sitter_analyzer/interfaces/cli.py +535 -0
  58. tree_sitter_analyzer/interfaces/cli_adapter.py +359 -0
  59. tree_sitter_analyzer/interfaces/mcp_adapter.py +224 -0
  60. tree_sitter_analyzer/interfaces/mcp_server.py +428 -0
  61. tree_sitter_analyzer/language_detector.py +553 -0
  62. tree_sitter_analyzer/language_loader.py +271 -0
  63. tree_sitter_analyzer/languages/__init__.py +10 -0
  64. tree_sitter_analyzer/languages/csharp_plugin.py +1076 -0
  65. tree_sitter_analyzer/languages/css_plugin.py +449 -0
  66. tree_sitter_analyzer/languages/go_plugin.py +836 -0
  67. tree_sitter_analyzer/languages/html_plugin.py +496 -0
  68. tree_sitter_analyzer/languages/java_plugin.py +1299 -0
  69. tree_sitter_analyzer/languages/javascript_plugin.py +1622 -0
  70. tree_sitter_analyzer/languages/kotlin_plugin.py +656 -0
  71. tree_sitter_analyzer/languages/markdown_plugin.py +1928 -0
  72. tree_sitter_analyzer/languages/php_plugin.py +862 -0
  73. tree_sitter_analyzer/languages/python_plugin.py +1636 -0
  74. tree_sitter_analyzer/languages/ruby_plugin.py +757 -0
  75. tree_sitter_analyzer/languages/rust_plugin.py +673 -0
  76. tree_sitter_analyzer/languages/sql_plugin.py +2444 -0
  77. tree_sitter_analyzer/languages/typescript_plugin.py +1892 -0
  78. tree_sitter_analyzer/languages/yaml_plugin.py +695 -0
  79. tree_sitter_analyzer/legacy_table_formatter.py +860 -0
  80. tree_sitter_analyzer/mcp/__init__.py +34 -0
  81. tree_sitter_analyzer/mcp/resources/__init__.py +43 -0
  82. tree_sitter_analyzer/mcp/resources/code_file_resource.py +208 -0
  83. tree_sitter_analyzer/mcp/resources/project_stats_resource.py +586 -0
  84. tree_sitter_analyzer/mcp/server.py +869 -0
  85. tree_sitter_analyzer/mcp/tools/__init__.py +28 -0
  86. tree_sitter_analyzer/mcp/tools/analyze_scale_tool.py +779 -0
  87. tree_sitter_analyzer/mcp/tools/analyze_scale_tool_cli_compatible.py +291 -0
  88. tree_sitter_analyzer/mcp/tools/base_tool.py +139 -0
  89. tree_sitter_analyzer/mcp/tools/fd_rg_utils.py +816 -0
  90. tree_sitter_analyzer/mcp/tools/find_and_grep_tool.py +686 -0
  91. tree_sitter_analyzer/mcp/tools/list_files_tool.py +413 -0
  92. tree_sitter_analyzer/mcp/tools/output_format_validator.py +148 -0
  93. tree_sitter_analyzer/mcp/tools/query_tool.py +443 -0
  94. tree_sitter_analyzer/mcp/tools/read_partial_tool.py +464 -0
  95. tree_sitter_analyzer/mcp/tools/search_content_tool.py +836 -0
  96. tree_sitter_analyzer/mcp/tools/table_format_tool.py +572 -0
  97. tree_sitter_analyzer/mcp/tools/universal_analyze_tool.py +653 -0
  98. tree_sitter_analyzer/mcp/utils/__init__.py +113 -0
  99. tree_sitter_analyzer/mcp/utils/error_handler.py +569 -0
  100. tree_sitter_analyzer/mcp/utils/file_output_factory.py +217 -0
  101. tree_sitter_analyzer/mcp/utils/file_output_manager.py +322 -0
  102. tree_sitter_analyzer/mcp/utils/gitignore_detector.py +358 -0
  103. tree_sitter_analyzer/mcp/utils/path_resolver.py +414 -0
  104. tree_sitter_analyzer/mcp/utils/search_cache.py +343 -0
  105. tree_sitter_analyzer/models.py +840 -0
  106. tree_sitter_analyzer/mypy_current_errors.txt +2 -0
  107. tree_sitter_analyzer/output_manager.py +255 -0
  108. tree_sitter_analyzer/platform_compat/__init__.py +3 -0
  109. tree_sitter_analyzer/platform_compat/adapter.py +324 -0
  110. tree_sitter_analyzer/platform_compat/compare.py +224 -0
  111. tree_sitter_analyzer/platform_compat/detector.py +67 -0
  112. tree_sitter_analyzer/platform_compat/fixtures.py +228 -0
  113. tree_sitter_analyzer/platform_compat/profiles.py +217 -0
  114. tree_sitter_analyzer/platform_compat/record.py +55 -0
  115. tree_sitter_analyzer/platform_compat/recorder.py +155 -0
  116. tree_sitter_analyzer/platform_compat/report.py +92 -0
  117. tree_sitter_analyzer/plugins/__init__.py +280 -0
  118. tree_sitter_analyzer/plugins/base.py +647 -0
  119. tree_sitter_analyzer/plugins/manager.py +384 -0
  120. tree_sitter_analyzer/project_detector.py +328 -0
  121. tree_sitter_analyzer/queries/__init__.py +27 -0
  122. tree_sitter_analyzer/queries/csharp.py +216 -0
  123. tree_sitter_analyzer/queries/css.py +615 -0
  124. tree_sitter_analyzer/queries/go.py +275 -0
  125. tree_sitter_analyzer/queries/html.py +543 -0
  126. tree_sitter_analyzer/queries/java.py +402 -0
  127. tree_sitter_analyzer/queries/javascript.py +724 -0
  128. tree_sitter_analyzer/queries/kotlin.py +192 -0
  129. tree_sitter_analyzer/queries/markdown.py +258 -0
  130. tree_sitter_analyzer/queries/php.py +95 -0
  131. tree_sitter_analyzer/queries/python.py +859 -0
  132. tree_sitter_analyzer/queries/ruby.py +92 -0
  133. tree_sitter_analyzer/queries/rust.py +223 -0
  134. tree_sitter_analyzer/queries/sql.py +555 -0
  135. tree_sitter_analyzer/queries/typescript.py +871 -0
  136. tree_sitter_analyzer/queries/yaml.py +236 -0
  137. tree_sitter_analyzer/query_loader.py +272 -0
  138. tree_sitter_analyzer/security/__init__.py +22 -0
  139. tree_sitter_analyzer/security/boundary_manager.py +277 -0
  140. tree_sitter_analyzer/security/regex_checker.py +297 -0
  141. tree_sitter_analyzer/security/validator.py +599 -0
  142. tree_sitter_analyzer/table_formatter.py +782 -0
  143. tree_sitter_analyzer/utils/__init__.py +53 -0
  144. tree_sitter_analyzer/utils/logging.py +433 -0
  145. tree_sitter_analyzer/utils/tree_sitter_compat.py +289 -0
  146. tree_sitter_analyzer-1.9.17.1.dist-info/METADATA +485 -0
  147. tree_sitter_analyzer-1.9.17.1.dist-info/RECORD +149 -0
  148. tree_sitter_analyzer-1.9.17.1.dist-info/WHEEL +4 -0
  149. tree_sitter_analyzer-1.9.17.1.dist-info/entry_points.txt +25 -0
@@ -0,0 +1,236 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ YAML Language Queries
4
+
5
+ Comprehensive Tree-sitter queries for YAML language constructs.
6
+ Covers documents, mappings, sequences, scalars, anchors, aliases, and comments.
7
+ """
8
+
9
+ # YAML-specific query library
10
+ YAML_QUERIES: dict[str, str] = {
11
+ # --- Document Structure ---
12
+ "document": """
13
+ (document) @document
14
+ """,
15
+ "stream": """
16
+ (stream) @stream
17
+ """,
18
+ # --- Block Style Mappings ---
19
+ "block_mapping": """
20
+ (block_mapping) @block_mapping
21
+ """,
22
+ "block_mapping_pair": """
23
+ (block_mapping_pair) @block_mapping_pair
24
+ """,
25
+ "block_node": """
26
+ (block_node) @block_node
27
+ """,
28
+ # --- Block Style Sequences ---
29
+ "block_sequence": """
30
+ (block_sequence) @block_sequence
31
+ """,
32
+ "block_sequence_item": """
33
+ (block_sequence_item) @block_sequence_item
34
+ """,
35
+ # --- Flow Style Mappings ---
36
+ "flow_mapping": """
37
+ (flow_mapping) @flow_mapping
38
+ """,
39
+ "flow_pair": """
40
+ (flow_pair) @flow_pair
41
+ """,
42
+ "flow_node": """
43
+ (flow_node) @flow_node
44
+ """,
45
+ # --- Flow Style Sequences ---
46
+ "flow_sequence": """
47
+ (flow_sequence) @flow_sequence
48
+ """,
49
+ # --- Scalars ---
50
+ "plain_scalar": """
51
+ (plain_scalar) @plain_scalar
52
+ """,
53
+ "double_quote_scalar": """
54
+ (double_quote_scalar) @double_quote_scalar
55
+ """,
56
+ "single_quote_scalar": """
57
+ (single_quote_scalar) @single_quote_scalar
58
+ """,
59
+ "block_scalar": """
60
+ (block_scalar) @block_scalar
61
+ """,
62
+ "string_scalar": """
63
+ (string_scalar) @string_scalar
64
+ """,
65
+ "integer_scalar": """
66
+ (integer_scalar) @integer_scalar
67
+ """,
68
+ "float_scalar": """
69
+ (float_scalar) @float_scalar
70
+ """,
71
+ "boolean_scalar": """
72
+ (boolean_scalar) @boolean_scalar
73
+ """,
74
+ "null_scalar": """
75
+ (null_scalar) @null_scalar
76
+ """,
77
+ # --- Anchors and Aliases ---
78
+ "anchor": """
79
+ (anchor) @anchor
80
+ """,
81
+ "alias": """
82
+ (alias) @alias
83
+ """,
84
+ # --- Tags ---
85
+ "tag": """
86
+ (tag) @tag
87
+ """,
88
+ # --- Comments ---
89
+ "comment": """
90
+ (comment) @comment
91
+ """,
92
+ # --- Keys ---
93
+ "key": """
94
+ (block_mapping_pair
95
+ key: (_) @key)
96
+ """,
97
+ "flow_key": """
98
+ (flow_pair
99
+ key: (_) @flow_key)
100
+ """,
101
+ # --- Values ---
102
+ "value": """
103
+ (block_mapping_pair
104
+ value: (_) @value)
105
+ """,
106
+ "flow_value": """
107
+ (flow_pair
108
+ value: (_) @flow_value)
109
+ """,
110
+ # --- All Mappings (Block + Flow) ---
111
+ "all_mappings": """
112
+ [
113
+ (block_mapping)
114
+ (flow_mapping)
115
+ ] @mapping
116
+ """,
117
+ # --- All Sequences (Block + Flow) ---
118
+ "all_sequences": """
119
+ [
120
+ (block_sequence)
121
+ (flow_sequence)
122
+ ] @sequence
123
+ """,
124
+ # --- All Scalars ---
125
+ "all_scalars": """
126
+ [
127
+ (plain_scalar)
128
+ (double_quote_scalar)
129
+ (single_quote_scalar)
130
+ (block_scalar)
131
+ ] @scalar
132
+ """,
133
+ }
134
+
135
+ # Query descriptions
136
+ YAML_QUERY_DESCRIPTIONS: dict[str, str] = {
137
+ "document": "Search YAML documents",
138
+ "stream": "Search YAML streams",
139
+ "block_mapping": "Search block-style mappings",
140
+ "block_mapping_pair": "Search block-style key-value pairs",
141
+ "block_node": "Search block nodes",
142
+ "block_sequence": "Search block-style sequences",
143
+ "block_sequence_item": "Search block-style sequence items",
144
+ "flow_mapping": "Search flow-style mappings",
145
+ "flow_pair": "Search flow-style key-value pairs",
146
+ "flow_node": "Search flow nodes",
147
+ "flow_sequence": "Search flow-style sequences",
148
+ "plain_scalar": "Search plain scalars",
149
+ "double_quote_scalar": "Search double-quoted scalars",
150
+ "single_quote_scalar": "Search single-quoted scalars",
151
+ "block_scalar": "Search block scalars (literal/folded)",
152
+ "string_scalar": "Search string scalars",
153
+ "integer_scalar": "Search integer scalars",
154
+ "float_scalar": "Search float scalars",
155
+ "boolean_scalar": "Search boolean scalars",
156
+ "null_scalar": "Search null scalars",
157
+ "anchor": "Search anchors (&name)",
158
+ "alias": "Search aliases (*name)",
159
+ "tag": "Search tags (!tag)",
160
+ "comment": "Search comments",
161
+ "key": "Search mapping keys",
162
+ "flow_key": "Search flow mapping keys",
163
+ "value": "Search mapping values",
164
+ "flow_value": "Search flow mapping values",
165
+ "all_mappings": "Search all mappings (block and flow)",
166
+ "all_sequences": "Search all sequences (block and flow)",
167
+ "all_scalars": "Search all scalars",
168
+ }
169
+
170
+ # Convert to ALL_QUERIES format for dynamic loader compatibility
171
+ ALL_QUERIES: dict[str, dict[str, str]] = {}
172
+ for query_name, query_string in YAML_QUERIES.items():
173
+ description = YAML_QUERY_DESCRIPTIONS.get(query_name, "No description")
174
+ ALL_QUERIES[query_name] = {"query": query_string, "description": description}
175
+
176
+
177
+ def get_yaml_query(name: str) -> str:
178
+ """
179
+ Get the specified YAML query.
180
+
181
+ Args:
182
+ name: Query name
183
+
184
+ Returns:
185
+ Query string
186
+
187
+ Raises:
188
+ ValueError: When query is not found
189
+ """
190
+ if name not in YAML_QUERIES:
191
+ available = list(YAML_QUERIES.keys())
192
+ raise ValueError(f"YAML query '{name}' does not exist. Available: {available}")
193
+
194
+ return YAML_QUERIES[name]
195
+
196
+
197
+ def get_yaml_query_description(name: str) -> str:
198
+ """
199
+ Get the description of the specified YAML query.
200
+
201
+ Args:
202
+ name: Query name
203
+
204
+ Returns:
205
+ Query description
206
+ """
207
+ return YAML_QUERY_DESCRIPTIONS.get(name, "No description")
208
+
209
+
210
+ def get_query(name: str) -> str:
211
+ """Get a specific query by name."""
212
+ if name in ALL_QUERIES:
213
+ return ALL_QUERIES[name]["query"]
214
+ raise ValueError(
215
+ f"Query '{name}' not found. Available queries: {list(ALL_QUERIES.keys())}"
216
+ )
217
+
218
+
219
+ def get_all_queries() -> dict[str, dict[str, str]]:
220
+ """Get all available queries."""
221
+ return ALL_QUERIES
222
+
223
+
224
+ def list_queries() -> list[str]:
225
+ """List all available query names."""
226
+ return list(ALL_QUERIES.keys())
227
+
228
+
229
+ def get_available_yaml_queries() -> list[str]:
230
+ """
231
+ Get list of available YAML queries.
232
+
233
+ Returns:
234
+ List of query names
235
+ """
236
+ return list(YAML_QUERIES.keys())
@@ -0,0 +1,272 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Dynamic query loader for language-specific Tree-sitter queries.
4
+ Optimized with enhanced caching and lazy loading for better performance.
5
+ """
6
+
7
+ import importlib
8
+
9
+ from .utils import log_error
10
+
11
+
12
+ class QueryLoader:
13
+ """Load and manage language-specific Tree-sitter queries with optimizations."""
14
+
15
+ # --- Predefined Queries (from query_library.py) ---
16
+ _PREDEFINED_QUERIES: dict[str, dict[str, str]] = {
17
+ "java": {
18
+ "class": "(class_declaration) @class",
19
+ "interface": "(interface_declaration) @interface",
20
+ "method": "(method_declaration) @method",
21
+ "constructor": "(constructor_declaration) @constructor",
22
+ "field": "(field_declaration) @field",
23
+ "import": "(import_declaration) @import",
24
+ "package": "(package_declaration) @package",
25
+ "annotation": "(annotation) @annotation",
26
+ "method_name": "(method_declaration name: (identifier) @method.name)",
27
+ "class_name": "(class_declaration name: (identifier) @class.name)",
28
+ "method_invocations": "(method_invocation name: (identifier) @invocation.name)",
29
+ "class_with_body": "(class_declaration name: (identifier) @class.name body: (class_body) @class.body)",
30
+ "method_with_body": "(method_declaration name: (identifier) @method.name body: (block) @method.body)",
31
+ }
32
+ # Add other languages here if needed
33
+ }
34
+
35
+ _QUERY_DESCRIPTIONS: dict[str, str] = {
36
+ "class": "Extract class declarations",
37
+ "interface": "Extract interface declarations",
38
+ "method": "Extract method declarations",
39
+ "constructor": "Extract constructor declarations",
40
+ "field": "Extract field declarations",
41
+ "import": "Extract import statements",
42
+ "package": "Extract package declarations",
43
+ "annotation": "Extract annotations",
44
+ "method_name": "Extract method names only",
45
+ "class_name": "Extract class names only",
46
+ "method_invocations": "Extract method invocations",
47
+ "class_with_body": "Extract class declarations with body",
48
+ "method_with_body": "Extract method declarations with body",
49
+ }
50
+
51
+ def __init__(self) -> None:
52
+ self._loaded_queries: dict[str, dict] = {}
53
+ self._query_modules: dict[str, object] = {}
54
+ self._failed_languages: set[str] = set() # 読み込み失敗した言語をキャッシュ
55
+
56
+ def load_language_queries(self, language: str) -> dict:
57
+ """Load queries for a specific language with optimized caching."""
58
+ # Handle None or empty language - return empty dict without warning
59
+ if not language or language == "None" or language.strip() == "":
60
+ return {}
61
+
62
+ # Normalize language name
63
+ language = language.strip().lower()
64
+
65
+ if language in self._failed_languages:
66
+ return {}
67
+
68
+ if language in self._loaded_queries:
69
+ return self._loaded_queries[language]
70
+
71
+ # Start with predefined queries
72
+ queries = self._PREDEFINED_QUERIES.get(language, {}).copy()
73
+
74
+ try:
75
+ module_name = f"tree_sitter_analyzer.queries.{language}"
76
+ module = importlib.import_module(module_name)
77
+
78
+ if hasattr(module, "get_all_queries"):
79
+ queries.update(module.get_all_queries())
80
+ elif hasattr(module, "ALL_QUERIES"):
81
+ queries.update(module.ALL_QUERIES)
82
+ else:
83
+ for attr_name in dir(module):
84
+ if not attr_name.startswith("_"):
85
+ attr_value = getattr(module, attr_name)
86
+ if isinstance(attr_value, str):
87
+ queries[attr_name] = attr_value
88
+ elif isinstance(attr_value, dict):
89
+ # Merge dict queries into the main queries dict
90
+ queries.update(attr_value)
91
+
92
+ self._loaded_queries[language] = queries
93
+ self._query_modules[language] = module
94
+ return queries
95
+
96
+ except ImportError:
97
+ # Silently handle missing query modules - no warnings needed
98
+ self._loaded_queries[language] = queries
99
+ return queries
100
+ except Exception as e:
101
+ log_error(f"Error loading dynamic queries for '{language}': {e}")
102
+ self._failed_languages.add(language)
103
+ self._loaded_queries[language] = {} # Reset on error
104
+ return {}
105
+
106
+ def get_query(self, language: str, query_name: str) -> str | None:
107
+ """Get a specific query for a language with optimized lookup."""
108
+ # Handle invalid language early
109
+ if not language or language == "None" or language.strip() == "":
110
+ return None
111
+
112
+ queries = self.load_language_queries(language)
113
+
114
+ if query_name in queries:
115
+ query_info = queries[query_name]
116
+ if isinstance(query_info, dict) and "query" in query_info:
117
+ return str(query_info["query"])
118
+ elif isinstance(query_info, str):
119
+ return query_info
120
+
121
+ return None
122
+
123
+ def get_query_description(self, language: str, query_name: str) -> str | None:
124
+ """Get description for a specific query."""
125
+ # Check predefined descriptions first
126
+ if query_name in self._QUERY_DESCRIPTIONS:
127
+ return self._QUERY_DESCRIPTIONS[query_name]
128
+
129
+ queries = self.load_language_queries(language)
130
+ if query_name in queries:
131
+ query_info = queries[query_name]
132
+ if isinstance(query_info, dict) and "description" in query_info:
133
+ return str(query_info["description"])
134
+ return f"Query '{query_name}' for {language}"
135
+
136
+ return None
137
+
138
+ def list_queries_for_language(self, language: str) -> list[str]:
139
+ """List all available queries for a language."""
140
+ # Handle invalid language early
141
+ if not language or language == "None" or language.strip() == "":
142
+ return []
143
+
144
+ queries = self.load_language_queries(language)
145
+ return list(queries.keys())
146
+
147
+ def list_queries(self, language: str) -> list[str]:
148
+ """List all available queries for a language.
149
+
150
+ Args:
151
+ language: The programming language to list queries for
152
+
153
+ Returns:
154
+ List of query names available for the specified language
155
+ """
156
+ return self.list_queries_for_language(language)
157
+
158
+ def list_supported_languages(self) -> list[str]:
159
+ """List all languages that have query modules available."""
160
+ languages = []
161
+
162
+ # 既知の言語をチェック
163
+ known_languages = [
164
+ "java",
165
+ "javascript",
166
+ "typescript",
167
+ "python",
168
+ "sql",
169
+ "c",
170
+ "cpp",
171
+ "rust",
172
+ "go",
173
+ "markdown",
174
+ ]
175
+
176
+ for language in known_languages:
177
+ if language not in self._failed_languages:
178
+ try:
179
+ module_name = f"tree_sitter_analyzer.queries.{language}"
180
+ importlib.import_module(module_name)
181
+ languages.append(language)
182
+ except ImportError:
183
+ self._failed_languages.add(language)
184
+
185
+ return languages
186
+
187
+ def get_common_queries(self) -> list[str]:
188
+ """Get commonly used queries across languages."""
189
+ # Return a flat list of common query names
190
+ return ["functions", "classes", "variables", "imports"]
191
+
192
+ def get_all_queries_for_language(self, language: str) -> dict[str, tuple[str, str]]:
193
+ """Get all query information for a language including metadata.
194
+
195
+ Returns:
196
+ Dictionary mapping query names to (query_string, description) tuples
197
+ """
198
+ queries = self.load_language_queries(language)
199
+ result = {}
200
+
201
+ for name, query_info in queries.items():
202
+ if isinstance(query_info, dict):
203
+ query_string = query_info.get("query", "")
204
+ description = query_info.get(
205
+ "description", f"Query '{name}' for {language}"
206
+ )
207
+ result[name] = (query_string, description)
208
+ elif isinstance(query_info, str):
209
+ result[name] = (query_info, f"Query '{name}' for {language}")
210
+
211
+ return result
212
+
213
+ def refresh_cache(self) -> None:
214
+ """Refresh the query cache."""
215
+ self._loaded_queries.clear()
216
+ self._query_modules.clear()
217
+ self._failed_languages.clear()
218
+ # Cache was removed for memory efficiency
219
+
220
+ def is_language_supported(self, language: str) -> bool:
221
+ """Check if a language has query support."""
222
+ if language in self._failed_languages:
223
+ return False
224
+ return language in self.list_supported_languages()
225
+
226
+ def preload_languages(self, languages: list[str]) -> dict[str, bool]:
227
+ """Preload queries for multiple languages efficiently."""
228
+ results = {}
229
+ for language in languages:
230
+ try:
231
+ queries = self.load_language_queries(language)
232
+ results[language] = len(queries) > 0
233
+ except Exception:
234
+ results[language] = False
235
+ return results
236
+
237
+
238
+ # グローバルインスタンス(シングルトンパターン)
239
+ _query_loader_instance = None
240
+
241
+
242
+ def get_query_loader() -> QueryLoader:
243
+ """Get singleton query loader instance."""
244
+ global _query_loader_instance
245
+ if _query_loader_instance is None:
246
+ _query_loader_instance = QueryLoader()
247
+ return _query_loader_instance
248
+
249
+
250
+ # 後方互換性のため
251
+ query_loader = get_query_loader()
252
+
253
+
254
+ # 便利関数(最適化済み)
255
+ def get_query(language: str, query_name: str) -> str | None:
256
+ """Get a specific query."""
257
+ return get_query_loader().get_query(language, query_name)
258
+
259
+
260
+ def list_queries(language: str) -> list[str]:
261
+ """List queries for a language."""
262
+ return get_query_loader().list_queries_for_language(language)
263
+
264
+
265
+ def list_supported_languages() -> list[str]:
266
+ """List all supported languages."""
267
+ return get_query_loader().list_supported_languages()
268
+
269
+
270
+ def is_language_supported(language: str) -> bool:
271
+ """Check if language is supported."""
272
+ return get_query_loader().is_language_supported(language)
@@ -0,0 +1,22 @@
1
+ #!/usr/bin/env python3
2
+ """
3
+ Security module for Tree-sitter Analyzer
4
+
5
+ This module provides unified security validation and protection mechanisms
6
+ for file path validation, regex pattern safety, and project boundary control.
7
+
8
+ Architecture:
9
+ - SecurityValidator: Unified validation framework
10
+ - ProjectBoundaryManager: Project access control
11
+ - RegexSafetyChecker: ReDoS attack prevention
12
+ """
13
+
14
+ from .boundary_manager import ProjectBoundaryManager
15
+ from .regex_checker import RegexSafetyChecker
16
+ from .validator import SecurityValidator
17
+
18
+ __all__ = [
19
+ "SecurityValidator",
20
+ "ProjectBoundaryManager",
21
+ "RegexSafetyChecker",
22
+ ]