tree-sitter-analyzer 1.8.4__py3-none-any.whl → 1.9.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.

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 -64
  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 +26 -15
  60. {tree_sitter_analyzer-1.8.4.dist-info → tree_sitter_analyzer-1.9.1.dist-info}/METADATA +23 -6
  61. tree_sitter_analyzer-1.9.1.dist-info/RECORD +109 -0
  62. tree_sitter_analyzer-1.8.4.dist-info/RECORD +0 -109
  63. {tree_sitter_analyzer-1.8.4.dist-info → tree_sitter_analyzer-1.9.1.dist-info}/WHEEL +0 -0
  64. {tree_sitter_analyzer-1.8.4.dist-info → tree_sitter_analyzer-1.9.1.dist-info}/entry_points.txt +0 -0
@@ -175,7 +175,9 @@ class TypeScriptElementExtractor(ElementExtractor):
175
175
  self.is_module = "import " in self.source_code or "export " in self.source_code
176
176
 
177
177
  # Check if it contains TSX/JSX
178
- self.is_tsx = "</" in self.source_code and self.current_file.lower().endswith(('.tsx', '.jsx'))
178
+ self.is_tsx = "</" in self.source_code and self.current_file.lower().endswith(
179
+ (".tsx", ".jsx")
180
+ )
179
181
 
180
182
  # Detect framework
181
183
  if "react" in self.source_code.lower() or "jsx" in self.source_code:
@@ -329,7 +331,9 @@ class TypeScriptElementExtractor(ElementExtractor):
329
331
  if not function_info:
330
332
  return None
331
333
 
332
- name, parameters, is_async, is_generator, return_type, generics = function_info
334
+ name, parameters, is_async, is_generator, return_type, generics = (
335
+ function_info
336
+ )
333
337
 
334
338
  # Extract TSDoc
335
339
  tsdoc = self._extract_tsdoc_for_line(start_line)
@@ -603,7 +607,7 @@ class TypeScriptElementExtractor(ElementExtractor):
603
607
  class_name = None
604
608
  superclass = None
605
609
  interfaces = []
606
- generics = []
610
+ # generics = [] # Commented out as not used yet
607
611
  is_abstract = node.type == "abstract_class_declaration"
608
612
 
609
613
  for child in node.children:
@@ -615,12 +619,16 @@ class TypeScriptElementExtractor(ElementExtractor):
615
619
  extends_match = re.search(r"extends\s+(\w+)", heritage_text)
616
620
  if extends_match:
617
621
  superclass = extends_match.group(1)
618
-
619
- implements_matches = re.findall(r"implements\s+([\w,\s]+)", heritage_text)
622
+
623
+ implements_matches = re.findall(
624
+ r"implements\s+([\w,\s]+)", heritage_text
625
+ )
620
626
  if implements_matches:
621
- interfaces = [iface.strip() for iface in implements_matches[0].split(",")]
627
+ interfaces = [
628
+ iface.strip() for iface in implements_matches[0].split(",")
629
+ ]
622
630
  elif child.type == "type_parameters":
623
- generics = self._extract_generics(child)
631
+ self._extract_generics(child)
624
632
 
625
633
  if not class_name:
626
634
  return None
@@ -664,7 +672,7 @@ class TypeScriptElementExtractor(ElementExtractor):
664
672
  # Extract interface name
665
673
  interface_name = None
666
674
  extends_interfaces = []
667
- generics = []
675
+ # generics = [] # Commented out as not used yet
668
676
 
669
677
  for child in node.children:
670
678
  if child.type == "type_identifier":
@@ -674,9 +682,11 @@ class TypeScriptElementExtractor(ElementExtractor):
674
682
  extends_text = self._get_node_text_optimized(child)
675
683
  extends_matches = re.findall(r"extends\s+([\w,\s]+)", extends_text)
676
684
  if extends_matches:
677
- extends_interfaces = [iface.strip() for iface in extends_matches[0].split(",")]
685
+ extends_interfaces = [
686
+ iface.strip() for iface in extends_matches[0].split(",")
687
+ ]
678
688
  elif child.type == "type_parameters":
679
- generics = self._extract_generics(child)
689
+ self._extract_generics(child)
680
690
 
681
691
  if not interface_name:
682
692
  return None
@@ -713,13 +723,13 @@ class TypeScriptElementExtractor(ElementExtractor):
713
723
 
714
724
  # Extract type alias name
715
725
  type_name = None
716
- generics = []
726
+ # generics = [] # Commented out as not used yet
717
727
 
718
728
  for child in node.children:
719
729
  if child.type == "type_identifier":
720
730
  type_name = child.text.decode("utf8") if child.text else None
721
731
  elif child.type == "type_parameters":
722
- generics = self._extract_generics(child)
732
+ self._extract_generics(child)
723
733
 
724
734
  if not type_name:
725
735
  return None
@@ -813,14 +823,22 @@ class TypeScriptElementExtractor(ElementExtractor):
813
823
  visibility = "public"
814
824
 
815
825
  # Handle children if they exist
816
- if hasattr(node, 'children') and node.children:
826
+ if hasattr(node, "children") and node.children:
817
827
  for child in node.children:
818
- if hasattr(child, 'type'):
828
+ if hasattr(child, "type"):
819
829
  if child.type == "property_identifier":
820
830
  prop_name = self._get_node_text_optimized(child)
821
831
  elif child.type == "type_annotation":
822
- prop_type = self._get_node_text_optimized(child).lstrip(": ")
823
- elif child.type in ["string", "number", "true", "false", "null"]:
832
+ prop_type = self._get_node_text_optimized(child).lstrip(
833
+ ": "
834
+ )
835
+ elif child.type in [
836
+ "string",
837
+ "number",
838
+ "true",
839
+ "false",
840
+ "null",
841
+ ]:
824
842
  prop_value = self._get_node_text_optimized(child)
825
843
 
826
844
  # Check modifiers from parent or node text
@@ -865,7 +883,7 @@ class TypeScriptElementExtractor(ElementExtractor):
865
883
  # Extract property signature name and type
866
884
  prop_name = None
867
885
  prop_type = None
868
- is_optional = False
886
+ # is_optional = False # Commented out as not used yet
869
887
 
870
888
  for child in node.children:
871
889
  if child.type == "property_identifier":
@@ -874,8 +892,9 @@ class TypeScriptElementExtractor(ElementExtractor):
874
892
  prop_type = self._get_node_text_optimized(child).lstrip(": ")
875
893
 
876
894
  # Check for optional property
877
- node_text = self._get_node_text_optimized(node)
878
- is_optional = "?" in node_text
895
+ # node_text = self._get_node_text_optimized(node) # Commented out as not used yet
896
+ # Check for optional property (not used but kept for future reference)
897
+ # is_optional = "?" in node_text
879
898
 
880
899
  if not prop_name:
881
900
  return None
@@ -1007,7 +1026,10 @@ class TypeScriptElementExtractor(ElementExtractor):
1007
1026
 
1008
1027
  def _parse_method_signature_optimized(
1009
1028
  self, node: "tree_sitter.Node"
1010
- ) -> tuple[str, list[str], bool, bool, bool, bool, bool, str | None, str, list[str]] | None:
1029
+ ) -> (
1030
+ tuple[str, list[str], bool, bool, bool, bool, bool, str | None, str, list[str]]
1031
+ | None
1032
+ ):
1011
1033
  """Parse method signature for TypeScript class methods"""
1012
1034
  try:
1013
1035
  name = None
@@ -1036,8 +1058,12 @@ class TypeScriptElementExtractor(ElementExtractor):
1036
1058
  if child.type in ["property_identifier", "identifier"]:
1037
1059
  name = self._get_node_text_optimized(child)
1038
1060
  # Fallback to direct text attribute if _get_node_text_optimized returns empty
1039
- if not name and hasattr(child, 'text') and child.text:
1040
- name = child.text.decode('utf-8') if isinstance(child.text, bytes) else str(child.text)
1061
+ if not name and hasattr(child, "text") and child.text:
1062
+ name = (
1063
+ child.text.decode("utf-8")
1064
+ if isinstance(child.text, bytes)
1065
+ else str(child.text)
1066
+ )
1041
1067
  is_constructor = name == "constructor"
1042
1068
  elif child.type == "formal_parameters":
1043
1069
  parameters = self._extract_parameters_with_types(child)
@@ -1051,10 +1077,14 @@ class TypeScriptElementExtractor(ElementExtractor):
1051
1077
  node_text = self._get_node_text_optimized(node)
1052
1078
  # Try to extract method name from the text
1053
1079
  import re
1054
- match = re.search(r'(?:async\s+)?(?:static\s+)?(?:public\s+|private\s+|protected\s+)?(\w+)\s*\(', node_text)
1080
+
1081
+ match = re.search(
1082
+ r"(?:async\s+)?(?:static\s+)?(?:public\s+|private\s+|protected\s+)?(\w+)\s*\(",
1083
+ node_text,
1084
+ )
1055
1085
  if match:
1056
1086
  name = match.group(1)
1057
-
1087
+
1058
1088
  # Set constructor flag after name is determined
1059
1089
  if name:
1060
1090
  is_constructor = name == "constructor"
@@ -1080,7 +1110,9 @@ class TypeScriptElementExtractor(ElementExtractor):
1080
1110
  except Exception:
1081
1111
  return None
1082
1112
 
1083
- def _extract_parameters_with_types(self, params_node: "tree_sitter.Node") -> list[str]:
1113
+ def _extract_parameters_with_types(
1114
+ self, params_node: "tree_sitter.Node"
1115
+ ) -> list[str]:
1084
1116
  """Extract function parameters with TypeScript type annotations"""
1085
1117
  parameters = []
1086
1118
 
@@ -1122,7 +1154,7 @@ class TypeScriptElementExtractor(ElementExtractor):
1122
1154
  """Extract import information from import_statement node"""
1123
1155
  try:
1124
1156
  # Handle Mock objects in tests
1125
- if hasattr(node, 'start_point') and hasattr(node, 'end_point'):
1157
+ if hasattr(node, "start_point") and hasattr(node, "end_point"):
1126
1158
  start_line = node.start_point[0] + 1
1127
1159
  end_line = node.end_point[0] + 1
1128
1160
  else:
@@ -1131,55 +1163,72 @@ class TypeScriptElementExtractor(ElementExtractor):
1131
1163
 
1132
1164
  # Get raw text
1133
1165
  raw_text = ""
1134
- if hasattr(node, 'start_byte') and hasattr(node, 'end_byte') and self.source_code:
1166
+ if (
1167
+ hasattr(node, "start_byte")
1168
+ and hasattr(node, "end_byte")
1169
+ and self.source_code
1170
+ ):
1135
1171
  # Real tree-sitter node
1136
1172
  start_byte = node.start_byte
1137
1173
  end_byte = node.end_byte
1138
1174
  source_bytes = self.source_code.encode("utf-8")
1139
1175
  raw_text = source_bytes[start_byte:end_byte].decode("utf-8")
1140
- elif hasattr(node, 'text'):
1176
+ elif hasattr(node, "text"):
1141
1177
  # Mock object
1142
1178
  text = node.text
1143
1179
  if isinstance(text, bytes):
1144
- raw_text = text.decode('utf-8')
1180
+ raw_text = text.decode("utf-8")
1145
1181
  else:
1146
1182
  raw_text = str(text)
1147
1183
  else:
1148
1184
  # Fallback
1149
- raw_text = self._get_node_text_optimized(node) if hasattr(self, '_get_node_text_optimized') else ""
1185
+ raw_text = (
1186
+ self._get_node_text_optimized(node)
1187
+ if hasattr(self, "_get_node_text_optimized")
1188
+ else ""
1189
+ )
1150
1190
 
1151
1191
  # Extract import details from AST structure
1152
1192
  import_names = []
1153
1193
  module_path = ""
1154
- is_type_import = "type" in raw_text
1194
+ # Check for type import (not used but kept for future reference)
1195
+ # is_type_import = "type" in raw_text
1155
1196
 
1156
1197
  # Handle children
1157
- if hasattr(node, 'children') and node.children:
1198
+ if hasattr(node, "children") and node.children:
1158
1199
  for child in node.children:
1159
1200
  if child.type == "import_clause":
1160
1201
  import_names.extend(self._extract_import_names(child))
1161
1202
  elif child.type == "string":
1162
1203
  # Module path
1163
- if hasattr(child, 'start_byte') and hasattr(child, 'end_byte') and self.source_code:
1204
+ if (
1205
+ hasattr(child, "start_byte")
1206
+ and hasattr(child, "end_byte")
1207
+ and self.source_code
1208
+ ):
1164
1209
  source_bytes = self.source_code.encode("utf-8")
1165
1210
  module_text = source_bytes[
1166
1211
  child.start_byte : child.end_byte
1167
1212
  ].decode("utf-8")
1168
1213
  module_path = module_text.strip("\"'")
1169
- elif hasattr(child, 'text'):
1214
+ elif hasattr(child, "text"):
1170
1215
  # Mock object
1171
1216
  text = child.text
1172
1217
  if isinstance(text, bytes):
1173
- module_path = text.decode('utf-8').strip("\"'")
1218
+ module_path = text.decode("utf-8").strip("\"'")
1174
1219
  else:
1175
1220
  module_path = str(text).strip("\"'")
1176
1221
 
1177
1222
  # If no import names found but we have a mocked _extract_import_names, try calling it
1178
- if not import_names and hasattr(self, '_extract_import_names'):
1223
+ if not import_names and hasattr(self, "_extract_import_names"):
1179
1224
  # For test scenarios where _extract_import_names is mocked
1180
1225
  try:
1181
1226
  # Try to find import_clause in children
1182
- for child in (node.children if hasattr(node, 'children') and node.children else []):
1227
+ for child in (
1228
+ node.children
1229
+ if hasattr(node, "children") and node.children
1230
+ else []
1231
+ ):
1183
1232
  if child.type == "import_clause":
1184
1233
  import_names.extend(self._extract_import_names(child))
1185
1234
  break
@@ -1189,7 +1238,7 @@ class TypeScriptElementExtractor(ElementExtractor):
1189
1238
  # If no module path found, return None for edge case tests
1190
1239
  if not module_path and not import_names:
1191
1240
  return None
1192
-
1241
+
1193
1242
  # Use first import name or "unknown"
1194
1243
  primary_name = import_names[0] if import_names else "unknown"
1195
1244
 
@@ -1213,84 +1262,108 @@ class TypeScriptElementExtractor(ElementExtractor):
1213
1262
  ) -> list[str]:
1214
1263
  """Extract import names from import clause"""
1215
1264
  names = []
1216
-
1265
+
1217
1266
  try:
1218
1267
  # Handle Mock objects in tests
1219
- if hasattr(import_clause_node, 'children') and import_clause_node.children is not None:
1268
+ if (
1269
+ hasattr(import_clause_node, "children")
1270
+ and import_clause_node.children is not None
1271
+ ):
1220
1272
  children = import_clause_node.children
1221
1273
  else:
1222
1274
  return names
1223
-
1275
+
1224
1276
  source_bytes = self.source_code.encode("utf-8") if self.source_code else b""
1225
1277
 
1226
1278
  for child in children:
1227
1279
  if child.type == "import_default_specifier":
1228
1280
  # Default import
1229
- if hasattr(child, 'children') and child.children:
1281
+ if hasattr(child, "children") and child.children:
1230
1282
  for grandchild in child.children:
1231
1283
  if grandchild.type == "identifier":
1232
- if hasattr(grandchild, 'start_byte') and hasattr(grandchild, 'end_byte') and source_bytes:
1284
+ if (
1285
+ hasattr(grandchild, "start_byte")
1286
+ and hasattr(grandchild, "end_byte")
1287
+ and source_bytes
1288
+ ):
1233
1289
  name_text = source_bytes[
1234
1290
  grandchild.start_byte : grandchild.end_byte
1235
1291
  ].decode("utf-8")
1236
1292
  names.append(name_text)
1237
- elif hasattr(grandchild, 'text'):
1293
+ elif hasattr(grandchild, "text"):
1238
1294
  # Handle Mock objects
1239
1295
  text = grandchild.text
1240
1296
  if isinstance(text, bytes):
1241
- names.append(text.decode('utf-8'))
1297
+ names.append(text.decode("utf-8"))
1242
1298
  else:
1243
1299
  names.append(str(text))
1244
1300
  elif child.type == "named_imports":
1245
1301
  # Named imports
1246
- if hasattr(child, 'children') and child.children:
1302
+ if hasattr(child, "children") and child.children:
1247
1303
  for grandchild in child.children:
1248
1304
  if grandchild.type == "import_specifier":
1249
1305
  # For Mock objects, use _get_node_text_optimized
1250
- if hasattr(self, '_get_node_text_optimized'):
1251
- name_text = self._get_node_text_optimized(grandchild)
1306
+ if hasattr(self, "_get_node_text_optimized"):
1307
+ name_text = self._get_node_text_optimized(
1308
+ grandchild
1309
+ )
1252
1310
  if name_text:
1253
1311
  names.append(name_text)
1254
- elif hasattr(grandchild, 'children') and grandchild.children:
1312
+ elif (
1313
+ hasattr(grandchild, "children")
1314
+ and grandchild.children
1315
+ ):
1255
1316
  for ggchild in grandchild.children:
1256
1317
  if ggchild.type == "identifier":
1257
- if hasattr(ggchild, 'start_byte') and hasattr(ggchild, 'end_byte') and source_bytes:
1318
+ if (
1319
+ hasattr(ggchild, "start_byte")
1320
+ and hasattr(ggchild, "end_byte")
1321
+ and source_bytes
1322
+ ):
1258
1323
  name_text = source_bytes[
1259
1324
  ggchild.start_byte : ggchild.end_byte
1260
1325
  ].decode("utf-8")
1261
1326
  names.append(name_text)
1262
- elif hasattr(ggchild, 'text'):
1327
+ elif hasattr(ggchild, "text"):
1263
1328
  # Handle Mock objects
1264
1329
  text = ggchild.text
1265
1330
  if isinstance(text, bytes):
1266
- names.append(text.decode('utf-8'))
1331
+ names.append(text.decode("utf-8"))
1267
1332
  else:
1268
1333
  names.append(str(text))
1269
1334
  elif child.type == "identifier":
1270
1335
  # Direct identifier (default import case)
1271
- if hasattr(child, 'start_byte') and hasattr(child, 'end_byte') and source_bytes:
1336
+ if (
1337
+ hasattr(child, "start_byte")
1338
+ and hasattr(child, "end_byte")
1339
+ and source_bytes
1340
+ ):
1272
1341
  name_text = source_bytes[
1273
1342
  child.start_byte : child.end_byte
1274
1343
  ].decode("utf-8")
1275
1344
  names.append(name_text)
1276
- elif hasattr(child, 'text'):
1345
+ elif hasattr(child, "text"):
1277
1346
  # Handle Mock objects
1278
1347
  text = child.text
1279
1348
  if isinstance(text, bytes):
1280
- names.append(text.decode('utf-8'))
1349
+ names.append(text.decode("utf-8"))
1281
1350
  else:
1282
1351
  names.append(str(text))
1283
1352
  elif child.type == "namespace_import":
1284
1353
  # Namespace import (import * as name)
1285
- if hasattr(child, 'children') and child.children:
1354
+ if hasattr(child, "children") and child.children:
1286
1355
  for grandchild in child.children:
1287
1356
  if grandchild.type == "identifier":
1288
- if hasattr(grandchild, 'start_byte') and hasattr(grandchild, 'end_byte') and source_bytes:
1357
+ if (
1358
+ hasattr(grandchild, "start_byte")
1359
+ and hasattr(grandchild, "end_byte")
1360
+ and source_bytes
1361
+ ):
1289
1362
  name_text = source_bytes[
1290
1363
  grandchild.start_byte : grandchild.end_byte
1291
1364
  ].decode("utf-8")
1292
1365
  names.append(f"* as {name_text}")
1293
- elif hasattr(grandchild, 'text'):
1366
+ elif hasattr(grandchild, "text"):
1294
1367
  # Handle Mock objects
1295
1368
  text = grandchild.text
1296
1369
  if isinstance(text, bytes):
@@ -1299,7 +1372,7 @@ class TypeScriptElementExtractor(ElementExtractor):
1299
1372
  names.append(f"* as {str(text)}")
1300
1373
  except Exception as e:
1301
1374
  log_debug(f"Failed to extract import names: {e}")
1302
-
1375
+
1303
1376
  return names
1304
1377
 
1305
1378
  def _extract_dynamic_import(self, node: "tree_sitter.Node") -> Import | None:
@@ -1313,9 +1386,7 @@ class TypeScriptElementExtractor(ElementExtractor):
1313
1386
  )
1314
1387
  if not import_match:
1315
1388
  # Try alternative pattern without quotes
1316
- import_match = re.search(
1317
- r"import\s*\(\s*([^)]+)\s*\)", node_text
1318
- )
1389
+ import_match = re.search(r"import\s*\(\s*([^)]+)\s*\)", node_text)
1319
1390
  if import_match:
1320
1391
  source = import_match.group(1).strip("\"'")
1321
1392
  else:
@@ -1345,10 +1416,12 @@ class TypeScriptElementExtractor(ElementExtractor):
1345
1416
 
1346
1417
  try:
1347
1418
  # Test if _get_node_text_optimized is working (for error handling tests)
1348
- if hasattr(self, '_get_node_text_optimized'):
1419
+ if hasattr(self, "_get_node_text_optimized"):
1349
1420
  # This will trigger the mocked exception in tests
1350
- self._get_node_text_optimized(tree.root_node if tree and hasattr(tree, 'root_node') else None)
1351
-
1421
+ self._get_node_text_optimized(
1422
+ tree.root_node if tree and hasattr(tree, "root_node") else None
1423
+ )
1424
+
1352
1425
  # Use regex to find require statements
1353
1426
  require_pattern = r"(?:const|let|var)\s+(\w+)\s*=\s*require\s*\(\s*[\"']([^\"']+)[\"']\s*\)"
1354
1427
 
@@ -1377,7 +1450,9 @@ class TypeScriptElementExtractor(ElementExtractor):
1377
1450
 
1378
1451
  return imports
1379
1452
 
1380
- def _is_framework_component(self, node: "tree_sitter.Node", class_name: str) -> bool:
1453
+ def _is_framework_component(
1454
+ self, node: "tree_sitter.Node", class_name: str
1455
+ ) -> bool:
1381
1456
  """Check if class is a framework component"""
1382
1457
  if self.framework_type == "react":
1383
1458
  # Check if extends React.Component or Component
@@ -1396,7 +1471,10 @@ class TypeScriptElementExtractor(ElementExtractor):
1396
1471
  def _is_exported_class(self, class_name: str) -> bool:
1397
1472
  """Check if class is exported"""
1398
1473
  # Simple check for export statements
1399
- return f"export class {class_name}" in self.source_code or f"export default {class_name}" in self.source_code
1474
+ return (
1475
+ f"export class {class_name}" in self.source_code
1476
+ or f"export default {class_name}" in self.source_code
1477
+ )
1400
1478
 
1401
1479
  def _infer_type_from_value(self, value: str | None) -> str:
1402
1480
  """Infer TypeScript type from value"""
@@ -1447,7 +1525,7 @@ class TypeScriptElementExtractor(ElementExtractor):
1447
1525
  # Check for TSDoc end or single-line TSDoc
1448
1526
  if current_line > 0:
1449
1527
  line = self.content_lines[current_line - 1].strip()
1450
-
1528
+
1451
1529
  # Check for single-line TSDoc comment
1452
1530
  if line.startswith("/**") and line.endswith("*/"):
1453
1531
  # Single line TSDoc
@@ -1532,16 +1610,18 @@ class TypeScriptElementExtractor(ElementExtractor):
1532
1610
  self._complexity_cache[node_id] = complexity
1533
1611
  return complexity
1534
1612
 
1535
- def extract_elements(self, tree: "tree_sitter.Tree", source_code: str) -> list[CodeElement]:
1613
+ def extract_elements(
1614
+ self, tree: "tree_sitter.Tree", source_code: str
1615
+ ) -> list[CodeElement]:
1536
1616
  """Legacy method for backward compatibility with tests"""
1537
1617
  all_elements: list[CodeElement] = []
1538
-
1618
+
1539
1619
  # Extract all types of elements
1540
1620
  all_elements.extend(self.extract_functions(tree, source_code))
1541
1621
  all_elements.extend(self.extract_classes(tree, source_code))
1542
1622
  all_elements.extend(self.extract_variables(tree, source_code))
1543
1623
  all_elements.extend(self.extract_imports(tree, source_code))
1544
-
1624
+
1545
1625
  return all_elements
1546
1626
 
1547
1627
 
@@ -1715,20 +1795,24 @@ class TypeScriptPlugin(LanguagePlugin):
1715
1795
  error_message=str(e),
1716
1796
  )
1717
1797
 
1718
- def extract_elements(self, tree: "tree_sitter.Tree", source_code: str) -> list[CodeElement]:
1798
+ def extract_elements(
1799
+ self, tree: "tree_sitter.Tree", source_code: str
1800
+ ) -> list[CodeElement]:
1719
1801
  """Legacy method for backward compatibility with tests"""
1720
1802
  extractor = self.create_extractor()
1721
1803
  all_elements: list[CodeElement] = []
1722
-
1804
+
1723
1805
  # Extract all types of elements
1724
1806
  all_elements.extend(extractor.extract_functions(tree, source_code))
1725
1807
  all_elements.extend(extractor.extract_classes(tree, source_code))
1726
1808
  all_elements.extend(extractor.extract_variables(tree, source_code))
1727
1809
  all_elements.extend(extractor.extract_imports(tree, source_code))
1728
-
1810
+
1729
1811
  return all_elements
1730
1812
 
1731
- def execute_query_strategy(self, tree: "tree_sitter.Tree", source_code: str, query_key: str) -> list[CodeElement]:
1813
+ def execute_query_strategy(
1814
+ self, tree: "tree_sitter.Tree", source_code: str, query_key: str
1815
+ ) -> list[CodeElement]:
1732
1816
  """Execute TypeScript-specific query strategy based on query_key"""
1733
1817
  if not tree or not source_code:
1734
1818
  return []
@@ -1743,33 +1827,84 @@ class TypeScriptPlugin(LanguagePlugin):
1743
1827
  query_mapping = {
1744
1828
  # Function-related queries
1745
1829
  "function": lambda: self._extractor.extract_functions(tree, source_code),
1746
- "async_function": lambda: [f for f in self._extractor.extract_functions(tree, source_code) if getattr(f, 'is_async', False)],
1747
- "arrow_function": lambda: [f for f in self._extractor.extract_functions(tree, source_code) if getattr(f, 'is_arrow', False)],
1748
- "method": lambda: [f for f in self._extractor.extract_functions(tree, source_code) if getattr(f, 'is_method', False)],
1749
- "constructor": lambda: [f for f in self._extractor.extract_functions(tree, source_code) if getattr(f, 'is_constructor', False)],
1750
- "signature": lambda: [f for f in self._extractor.extract_functions(tree, source_code) if getattr(f, 'is_signature', False)],
1751
-
1830
+ "async_function": lambda: [
1831
+ f
1832
+ for f in self._extractor.extract_functions(tree, source_code)
1833
+ if getattr(f, "is_async", False)
1834
+ ],
1835
+ "arrow_function": lambda: [
1836
+ f
1837
+ for f in self._extractor.extract_functions(tree, source_code)
1838
+ if getattr(f, "is_arrow", False)
1839
+ ],
1840
+ "method": lambda: [
1841
+ f
1842
+ for f in self._extractor.extract_functions(tree, source_code)
1843
+ if getattr(f, "is_method", False)
1844
+ ],
1845
+ "constructor": lambda: [
1846
+ f
1847
+ for f in self._extractor.extract_functions(tree, source_code)
1848
+ if getattr(f, "is_constructor", False)
1849
+ ],
1850
+ "signature": lambda: [
1851
+ f
1852
+ for f in self._extractor.extract_functions(tree, source_code)
1853
+ if getattr(f, "is_signature", False)
1854
+ ],
1752
1855
  # Class-related queries
1753
1856
  "class": lambda: self._extractor.extract_classes(tree, source_code),
1754
- "interface": lambda: [c for c in self._extractor.extract_classes(tree, source_code) if getattr(c, 'class_type', '') == 'interface'],
1755
- "type_alias": lambda: [c for c in self._extractor.extract_classes(tree, source_code) if getattr(c, 'class_type', '') == 'type'],
1756
- "enum": lambda: [c for c in self._extractor.extract_classes(tree, source_code) if getattr(c, 'class_type', '') == 'enum'],
1757
-
1857
+ "interface": lambda: [
1858
+ c
1859
+ for c in self._extractor.extract_classes(tree, source_code)
1860
+ if getattr(c, "class_type", "") == "interface"
1861
+ ],
1862
+ "type_alias": lambda: [
1863
+ c
1864
+ for c in self._extractor.extract_classes(tree, source_code)
1865
+ if getattr(c, "class_type", "") == "type"
1866
+ ],
1867
+ "enum": lambda: [
1868
+ c
1869
+ for c in self._extractor.extract_classes(tree, source_code)
1870
+ if getattr(c, "class_type", "") == "enum"
1871
+ ],
1758
1872
  # Variable-related queries
1759
1873
  "variable": lambda: self._extractor.extract_variables(tree, source_code),
1760
-
1761
1874
  # Import/Export queries
1762
1875
  "import": lambda: self._extractor.extract_imports(tree, source_code),
1763
- "export": lambda: [i for i in self._extractor.extract_imports(tree, source_code) if 'export' in getattr(i, 'raw_text', '')],
1764
-
1876
+ "export": lambda: [
1877
+ i
1878
+ for i in self._extractor.extract_imports(tree, source_code)
1879
+ if "export" in getattr(i, "raw_text", "")
1880
+ ],
1765
1881
  # TypeScript-specific queries
1766
- "generic": lambda: [c for c in self._extractor.extract_classes(tree, source_code) if 'generics' in getattr(c, 'raw_text', '')],
1767
- "decorator": lambda: [f for f in self._extractor.extract_functions(tree, source_code) if '@' in getattr(f, 'raw_text', '')],
1768
-
1882
+ "generic": lambda: [
1883
+ c
1884
+ for c in self._extractor.extract_classes(tree, source_code)
1885
+ if "generics" in getattr(c, "raw_text", "")
1886
+ ],
1887
+ "decorator": lambda: [
1888
+ f
1889
+ for f in self._extractor.extract_functions(tree, source_code)
1890
+ if "@" in getattr(f, "raw_text", "")
1891
+ ],
1769
1892
  # Framework-specific queries
1770
- "react_component": lambda: [c for c in self._extractor.extract_classes(tree, source_code) if getattr(c, 'is_react_component', False)],
1771
- "angular_component": lambda: [c for c in self._extractor.extract_classes(tree, source_code) if getattr(c, 'framework_type', '') == 'angular'],
1772
- "vue_component": lambda: [c for c in self._extractor.extract_classes(tree, source_code) if getattr(c, 'framework_type', '') == 'vue'],
1893
+ "react_component": lambda: [
1894
+ c
1895
+ for c in self._extractor.extract_classes(tree, source_code)
1896
+ if getattr(c, "is_react_component", False)
1897
+ ],
1898
+ "angular_component": lambda: [
1899
+ c
1900
+ for c in self._extractor.extract_classes(tree, source_code)
1901
+ if getattr(c, "framework_type", "") == "angular"
1902
+ ],
1903
+ "vue_component": lambda: [
1904
+ c
1905
+ for c in self._extractor.extract_classes(tree, source_code)
1906
+ if getattr(c, "framework_type", "") == "vue"
1907
+ ],
1773
1908
  }
1774
1909
 
1775
1910
  # Execute the appropriate extraction method
@@ -1791,68 +1926,42 @@ class TypeScriptPlugin(LanguagePlugin):
1791
1926
  "function_declaration",
1792
1927
  "function_expression",
1793
1928
  "arrow_function",
1794
- "generator_function_declaration"
1929
+ "generator_function_declaration",
1795
1930
  ],
1796
1931
  "async_function": [
1797
1932
  "function_declaration",
1798
1933
  "function_expression",
1799
1934
  "arrow_function",
1800
- "method_definition"
1801
- ],
1802
- "arrow_function": ["arrow_function"],
1803
- "method": [
1804
1935
  "method_definition",
1805
- "method_signature"
1806
1936
  ],
1937
+ "arrow_function": ["arrow_function"],
1938
+ "method": ["method_definition", "method_signature"],
1807
1939
  "constructor": ["method_definition"],
1808
1940
  "signature": ["method_signature"],
1809
-
1810
1941
  # Class-related categories
1811
- "class": [
1812
- "class_declaration",
1813
- "abstract_class_declaration"
1814
- ],
1942
+ "class": ["class_declaration", "abstract_class_declaration"],
1815
1943
  "interface": ["interface_declaration"],
1816
1944
  "type_alias": ["type_alias_declaration"],
1817
1945
  "enum": ["enum_declaration"],
1818
-
1819
1946
  # Variable-related categories
1820
1947
  "variable": [
1821
1948
  "variable_declaration",
1822
1949
  "lexical_declaration",
1823
1950
  "property_definition",
1824
- "property_signature"
1951
+ "property_signature",
1825
1952
  ],
1826
-
1827
1953
  # Import/Export categories
1828
1954
  "import": ["import_statement"],
1829
- "export": [
1830
- "export_statement",
1831
- "export_declaration"
1832
- ],
1833
-
1955
+ "export": ["export_statement", "export_declaration"],
1834
1956
  # TypeScript-specific categories
1835
- "generic": [
1836
- "type_parameters",
1837
- "type_parameter"
1838
- ],
1839
- "decorator": [
1840
- "decorator",
1841
- "decorator_call_expression"
1842
- ],
1843
-
1957
+ "generic": ["type_parameters", "type_parameter"],
1958
+ "decorator": ["decorator", "decorator_call_expression"],
1844
1959
  # Framework-specific categories
1845
1960
  "react_component": [
1846
1961
  "class_declaration",
1847
1962
  "function_declaration",
1848
- "arrow_function"
1849
- ],
1850
- "angular_component": [
1851
- "class_declaration",
1852
- "decorator"
1963
+ "arrow_function",
1853
1964
  ],
1854
- "vue_component": [
1855
- "class_declaration",
1856
- "function_declaration"
1857
- ]
1858
- }
1965
+ "angular_component": ["class_declaration", "decorator"],
1966
+ "vue_component": ["class_declaration", "function_declaration"],
1967
+ }