contextl 1.2.32 → 1.2.34

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.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "contextl",
3
- "version": "1.2.32",
3
+ "version": "1.2.34",
4
4
  "description": "contextl — finds the most relevant files in your codebase for any change request. MCP server for AI coding agents.",
5
5
  "keywords": [
6
6
  "mcp",
@@ -836,27 +836,7 @@ def parse_imports(scan_result: ScanResult) -> ParseResult:
836
836
  if scanned_file.extension == ".py" and not _TS_AVAILABLE:
837
837
  pass # regex already handles this above
838
838
  elif scanned_file.extension == ".py" and _TS_AVAILABLE:
839
- # tree-sitter gives us just the module name; add symbol-level candidates
840
- # to match the legacy behaviour that resolves "scanner.ScannedFile" → scanner.py
841
- extra: list[str] = []
842
- for match in PYTHON_FROM_IMPORT_PATTERN.finditer(source_code):
843
- base = match.group(1)
844
- symbols_str = match.group(2) or match.group(3)
845
- if symbols_str:
846
- symbols_str = symbols_str.replace('(', '').replace(')', '').replace('\\', '').strip()
847
- for sym in symbols_str.split(','):
848
- sym = sym.split(' as ')[0].strip()
849
- if sym and sym != '*':
850
- if base.endswith("."):
851
- extra.append(f"{base}{sym}")
852
- else:
853
- extra.append(f"{base}.{sym}")
854
- # Merge without duplicates
855
- seen = set(raw_imports)
856
- for e in extra:
857
- if e not in seen:
858
- raw_imports.append(e)
859
- seen.add(e)
839
+ pass # tree-sitter gives us just the module name; add symbol-level candidates (legacy removed)
860
840
 
861
841
  for raw in raw_imports:
862
842
  if _is_external(raw, scanned_file.extension, alias_map):
@@ -980,6 +960,7 @@ def _skeleton_python(root: "Node", source_bytes: bytes) -> dict:
980
960
  name = ""
981
961
  bases: list[str] = []
982
962
  methods: list[dict] = []
963
+ nested_classes: list[dict] = []
983
964
  props: list[dict] = []
984
965
 
985
966
  for child in node.children:
@@ -1001,9 +982,16 @@ def _skeleton_python(root: "Node", source_bytes: bytes) -> dict:
1001
982
  if sub.type == "function_definition":
1002
983
  fn_node = sub
1003
984
  break
1004
- methods.append(visit_function(fn_node, is_method=True))
985
+ elif sub.type == "class_definition":
986
+ nested_classes.append(visit_class(sub))
987
+ fn_node = None
988
+ break
989
+ if fn_node is not None:
990
+ methods.append(visit_function(fn_node, is_method=True))
991
+ elif stmt.type == "class_definition":
992
+ nested_classes.append(visit_class(stmt))
1005
993
 
1006
- entry: dict = {"name": name, "bases": bases, "methods": methods, "properties": props}
994
+ entry: dict = {"name": name, "bases": bases, "methods": methods, "nested_classes": nested_classes, "properties": props}
1007
995
  return entry
1008
996
 
1009
997
  def visit_function(node: "Node", is_method: bool = False) -> dict:
@@ -1197,16 +1185,57 @@ def _skeleton_ts_js(root: "Node") -> dict:
1197
1185
  "is_exported": is_exported,
1198
1186
  }
1199
1187
 
1188
+ def visit_enum(node: "Node") -> dict:
1189
+ name = ""
1190
+ properties: list[dict] = []
1191
+ for child in node.children:
1192
+ if child.type == "identifier":
1193
+ name = _node_text(child)
1194
+ elif child.type == "enum_body":
1195
+ for member in child.children:
1196
+ if member.type == "property_identifier":
1197
+ properties.append({
1198
+ "name": _node_text(member),
1199
+ "type": "",
1200
+ "visibility": "public",
1201
+ })
1202
+ elif member.type == "enum_assignment":
1203
+ member_name = ""
1204
+ member_val = ""
1205
+ for sub in member.children:
1206
+ if sub.type == "property_identifier":
1207
+ member_name = _node_text(sub)
1208
+ elif sub.type not in ("=",):
1209
+ member_val = _node_text(sub)
1210
+ if member_name:
1211
+ properties.append({
1212
+ "name": member_name,
1213
+ "type": member_val,
1214
+ "visibility": "public",
1215
+ })
1216
+ return {
1217
+ "name": name,
1218
+ "extends": "",
1219
+ "implements": [],
1220
+ "methods": [],
1221
+ "properties": properties,
1222
+ }
1223
+
1200
1224
  def visit(node: "Node"):
1201
1225
  if node.type == "class_declaration":
1202
1226
  c = visit_class(node)
1203
1227
  classes.append(c)
1204
1228
  return
1205
- if node.type in ("function_declaration", "function"):
1229
+ if node.type in ("function_declaration", "function", "generator_function_declaration", "generator_function"):
1206
1230
  f = visit_function(node)
1207
1231
  if f["name"]:
1208
1232
  functions.append(f)
1209
1233
  return
1234
+ if node.type == "enum_declaration":
1235
+ c = visit_enum(node)
1236
+ if c["name"]:
1237
+ classes.append(c)
1238
+ return
1210
1239
  if node.type == "export_statement":
1211
1240
  # Track what is exported
1212
1241
  for child in node.children:
@@ -1217,13 +1246,37 @@ def _skeleton_ts_js(root: "Node") -> dict:
1217
1246
  if c["name"]:
1218
1247
  exports.append(c["name"])
1219
1248
  return
1220
- if child.type in ("function_declaration", "function"):
1249
+ if child.type in ("function_declaration", "function", "generator_function_declaration", "generator_function"):
1221
1250
  f = visit_function(child)
1222
1251
  if f["name"]:
1223
1252
  f["is_exported"] = True
1224
1253
  functions.append(f)
1225
1254
  exports.append(f["name"])
1226
1255
  return
1256
+ if child.type == "enum_declaration":
1257
+ c = visit_enum(child)
1258
+ if c["name"]:
1259
+ classes.append(c)
1260
+ exports.append(c["name"])
1261
+ return
1262
+ if child.type == "lexical_declaration":
1263
+ for sub in child.children:
1264
+ if sub.type == "variable_declarator":
1265
+ for sub2 in sub.children:
1266
+ if sub2.type == "identifier":
1267
+ name = _node_text(sub2)
1268
+ exports.append(name)
1269
+ is_callable = any(c.type in ("arrow_function", "function", "generator_function") for c in sub.children)
1270
+ if is_callable:
1271
+ functions.append({
1272
+ "name": name,
1273
+ "params": "",
1274
+ "return_type": "",
1275
+ "is_async": False,
1276
+ "is_exported": True,
1277
+ })
1278
+ break
1279
+ return
1227
1280
  if child.type == "export_clause":
1228
1281
  for spec in child.children:
1229
1282
  if spec.type == "export_specifier":
@@ -18,7 +18,7 @@ ENTRY_POINT_MARKERS = {
18
18
  "route.ts", "route.js",
19
19
  "globals.css", "global.css", "tailwind.css",
20
20
  "index.ts", "index.js", "index.tsx", "index.jsx",
21
- "main.ts", "main.js", "main.py",
21
+ "main.ts", "main.js", "main.py", "main.go", "main.rs", "main.c", "main.cpp", "main.cc", "main.java",
22
22
  "app.ts", "app.js", "app.tsx", "app.jsx", "app.py",
23
23
  "mcp_server.py", "server.ts", "server.js", "server.py",
24
24
  "__main__.py", "__init__.py", "setup.py", "conftest.py",