codecompass-mcp 3.0.1__tar.gz → 3.1.0__tar.gz
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.
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/PKG-INFO +1 -1
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/codecompass_mcp.egg-info/PKG-INFO +1 -1
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/ingestion/code_parser.py +74 -9
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/pyproject.toml +1 -1
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/tests/test_accuracy_fixes.py +15 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/LICENSE +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/README.md +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/codecompass_mcp.egg-info/SOURCES.txt +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/codecompass_mcp.egg-info/dependency_links.txt +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/codecompass_mcp.egg-info/entry_points.txt +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/codecompass_mcp.egg-info/requires.txt +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/codecompass_mcp.egg-info/top_level.txt +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/config.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/graph/__init__.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/graph/cli.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/graph/code_graph_client.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/graph/code_query_cli.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/graph/setup.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/ingestion/__init__.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/ingestion/chunker.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/ingestion/code_normalizer.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/ingestion/description_enricher.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/ingestion/entity_resolver.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/ingestion/file_watcher.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/ingestion/graph_writer.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/ingestion/hierarchy_builder.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/ingestion/reader_agent.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/ingestion/source_context.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/main.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/mcp_server.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/models/__init__.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/models/code_types.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/models/types.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/setup.cfg +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/tests/test_batch_impact.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/tests/test_blast_radius.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/tests/test_code_parser.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/tests/test_description_enricher.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/tests/test_ingestion.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/tests/test_lit_css_parser.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/tests/test_mcp_server.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/tests/test_php_parser.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/utils/__init__.py +0 -0
- {codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/utils/formatting.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codecompass-mcp
|
|
3
|
-
Version: 3.0
|
|
3
|
+
Version: 3.1.0
|
|
4
4
|
Summary: Structural code context for AI coding agents — a local code knowledge graph for blast radius, impact, deps, dead code, and flow tracing
|
|
5
5
|
Author: CodeCompass contributors
|
|
6
6
|
License: MIT
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: codecompass-mcp
|
|
3
|
-
Version: 3.0
|
|
3
|
+
Version: 3.1.0
|
|
4
4
|
Summary: Structural code context for AI coding agents — a local code knowledge graph for blast radius, impact, deps, dead code, and flow tracing
|
|
5
5
|
Author: CodeCompass contributors
|
|
6
6
|
License: MIT
|
|
@@ -206,6 +206,7 @@ def _extract_python(root: Node, source: bytes, file_path: str) -> list[CodeTripl
|
|
|
206
206
|
|
|
207
207
|
exported = _collect_python_exports(root)
|
|
208
208
|
type_env = _py_type_env(root)
|
|
209
|
+
class_parents = _py_class_parents(root)
|
|
209
210
|
|
|
210
211
|
for node in _walk(root):
|
|
211
212
|
match node.type:
|
|
@@ -298,7 +299,7 @@ def _extract_python(root: Node, source: bytes, file_path: str) -> list[CodeTripl
|
|
|
298
299
|
scope = _enclosing_scope(node)
|
|
299
300
|
caller = scope or module_name
|
|
300
301
|
caller_type = TYPE_FUNCTION if scope else TYPE_MODULE
|
|
301
|
-
receiver_type = _resolve_py_receiver_type(receiver, obj, node, type_env)
|
|
302
|
+
receiver_type = _resolve_py_receiver_type(receiver, obj, node, type_env, class_parents)
|
|
302
303
|
triples.append(CodeTriple(
|
|
303
304
|
from_entity=caller,
|
|
304
305
|
from_type=caller_type,
|
|
@@ -447,6 +448,20 @@ def _py_type_env(root: Node) -> dict[str, str]:
|
|
|
447
448
|
return types
|
|
448
449
|
|
|
449
450
|
|
|
451
|
+
def _py_class_parents(root: Node) -> dict[str, str]:
|
|
452
|
+
"""Map class name -> its first base class, for resolving `super()`."""
|
|
453
|
+
parents: dict[str, str] = {}
|
|
454
|
+
for node in _walk(root):
|
|
455
|
+
if node.type == "class_definition":
|
|
456
|
+
name = _get_node_name(node, ["identifier"])
|
|
457
|
+
arg = _child_of_type(node, "argument_list")
|
|
458
|
+
if name and arg:
|
|
459
|
+
bases = [c for c in arg.children if c.type == "identifier"]
|
|
460
|
+
if bases:
|
|
461
|
+
parents[name] = _text(bases[0])
|
|
462
|
+
return parents
|
|
463
|
+
|
|
464
|
+
|
|
450
465
|
def _enclosing_python_class(node: Node) -> str | None:
|
|
451
466
|
"""Name of the nearest enclosing `class C:`, for resolving `self`/`cls`."""
|
|
452
467
|
current = node.parent
|
|
@@ -459,13 +474,15 @@ def _enclosing_python_class(node: Node) -> str | None:
|
|
|
459
474
|
return None
|
|
460
475
|
|
|
461
476
|
|
|
462
|
-
def _resolve_py_receiver_type(receiver: str | None, obj: Node | None,
|
|
463
|
-
|
|
464
|
-
"""Infer a Python receiver's type from `self`/`cls`, inline `Foo()`, or env."""
|
|
477
|
+
def _resolve_py_receiver_type(receiver: str | None, obj: Node | None, call_node: Node,
|
|
478
|
+
env: dict[str, str], parents: dict[str, str] | None = None) -> str | None:
|
|
479
|
+
"""Infer a Python receiver's type from `self`/`cls`, `super()`, inline `Foo()`, or env."""
|
|
465
480
|
if _py_call_class(obj) is not None:
|
|
466
481
|
return _py_call_class(obj)
|
|
467
482
|
if receiver in ("self", "cls"):
|
|
468
483
|
return _enclosing_python_class(call_node)
|
|
484
|
+
if receiver in ("super()", "super") and parents:
|
|
485
|
+
return parents.get(_enclosing_python_class(call_node))
|
|
469
486
|
if receiver is not None and receiver in env:
|
|
470
487
|
return env[receiver]
|
|
471
488
|
return None
|
|
@@ -726,6 +743,20 @@ def _php_type_env(root: Node) -> dict[str, str]:
|
|
|
726
743
|
return types
|
|
727
744
|
|
|
728
745
|
|
|
746
|
+
def _php_class_parents(root: Node) -> dict[str, str]:
|
|
747
|
+
"""Map class name -> its parent (`extends`), for resolving `parent::`."""
|
|
748
|
+
parents: dict[str, str] = {}
|
|
749
|
+
for node in _walk(root):
|
|
750
|
+
if node.type == "class_declaration":
|
|
751
|
+
name = _php_name(node)
|
|
752
|
+
base = _child_of_type(node, "base_clause")
|
|
753
|
+
if name and base:
|
|
754
|
+
targets = _php_extends_targets(base)
|
|
755
|
+
if targets:
|
|
756
|
+
parents[name] = _php_basename(targets[0])
|
|
757
|
+
return parents
|
|
758
|
+
|
|
759
|
+
|
|
729
760
|
def _php_call_receiver(node: Node, env: dict[str, str]) -> tuple[str | None, str | None]:
|
|
730
761
|
"""Receiver text + inferred type for a member call `$obj->method()`."""
|
|
731
762
|
obj = node.child_by_field_name("object")
|
|
@@ -750,6 +781,7 @@ def _extract_php(root: Node, source: bytes, file_path: str) -> list[CodeTriple]:
|
|
|
750
781
|
module_name = _module_name_from_path(file_path)
|
|
751
782
|
triples: list[CodeTriple] = []
|
|
752
783
|
type_env = _php_type_env(root)
|
|
784
|
+
class_parents = _php_class_parents(root)
|
|
753
785
|
|
|
754
786
|
def defined_in(name: str, entity_type: str, line: int, is_exported: bool = True,
|
|
755
787
|
owner: str | None = None) -> None:
|
|
@@ -985,7 +1017,19 @@ def _extract_php(root: Node, source: bytes, file_path: str) -> list[CodeTriple]:
|
|
|
985
1017
|
case "scoped_call_expression":
|
|
986
1018
|
names = _children_of_type(node, "name")
|
|
987
1019
|
if names:
|
|
988
|
-
|
|
1020
|
+
method = _text(names[-1])
|
|
1021
|
+
scope_node = node.children[0] if node.children else None
|
|
1022
|
+
scope_text = _text(scope_node) if scope_node is not None else ""
|
|
1023
|
+
if scope_text == "parent":
|
|
1024
|
+
container = _enclosing_php_container(node)
|
|
1025
|
+
rtype = class_parents.get(container[0]) if container else None
|
|
1026
|
+
elif scope_text in ("self", "static"):
|
|
1027
|
+
container = _enclosing_php_container(node)
|
|
1028
|
+
rtype = container[0] if container else None
|
|
1029
|
+
else:
|
|
1030
|
+
rtype = _php_basename(scope_node) if scope_node is not None else None
|
|
1031
|
+
calls(method, TYPE_FUNCTION, _line(node), node,
|
|
1032
|
+
receiver=scope_text or None, receiver_type=rtype)
|
|
989
1033
|
|
|
990
1034
|
case "object_creation_expression":
|
|
991
1035
|
class_node = None
|
|
@@ -1014,6 +1058,7 @@ def _extract_javascript(root: Node, source: bytes, file_path: str) -> list[CodeT
|
|
|
1014
1058
|
|
|
1015
1059
|
# Best-effort variable → type map for receiver type inference on calls.
|
|
1016
1060
|
type_env = _js_type_env(root)
|
|
1061
|
+
class_parents = _js_class_parents(root)
|
|
1017
1062
|
|
|
1018
1063
|
def defined(name: str, line: int, owner: str | None = None) -> None:
|
|
1019
1064
|
triples.append(CodeTriple(
|
|
@@ -1089,7 +1134,7 @@ def _extract_javascript(root: Node, source: bytes, file_path: str) -> list[CodeT
|
|
|
1089
1134
|
scope = _enclosing_js_scope(node)
|
|
1090
1135
|
caller = scope or module_name
|
|
1091
1136
|
caller_type = TYPE_FUNCTION if scope else TYPE_MODULE
|
|
1092
|
-
receiver_type = _resolve_receiver_type(receiver, obj, node, type_env)
|
|
1137
|
+
receiver_type = _resolve_receiver_type(receiver, obj, node, type_env, class_parents)
|
|
1093
1138
|
triples.append(CodeTriple(
|
|
1094
1139
|
from_entity=caller,
|
|
1095
1140
|
from_type=caller_type,
|
|
@@ -1367,13 +1412,33 @@ def _enclosing_class_name(node: Node) -> str | None:
|
|
|
1367
1412
|
return None
|
|
1368
1413
|
|
|
1369
1414
|
|
|
1370
|
-
def
|
|
1371
|
-
|
|
1372
|
-
|
|
1415
|
+
def _js_class_parents(root: Node) -> dict[str, str]:
|
|
1416
|
+
"""Map class name -> the class it `extends`, for resolving `super`."""
|
|
1417
|
+
parents: dict[str, str] = {}
|
|
1418
|
+
for node in _walk(root):
|
|
1419
|
+
if node.type in ("class_declaration", "class"):
|
|
1420
|
+
name_node = _child_of_type(node, "type_identifier") or _child_of_type(node, "identifier")
|
|
1421
|
+
heritage = _child_of_type(node, "class_heritage")
|
|
1422
|
+
if name_node is not None and heritage is not None:
|
|
1423
|
+
base = None
|
|
1424
|
+
for desc in _walk(heritage):
|
|
1425
|
+
if desc.type in ("identifier", "type_identifier"):
|
|
1426
|
+
base = _text(desc)
|
|
1427
|
+
break
|
|
1428
|
+
if base:
|
|
1429
|
+
parents[_text(name_node)] = base
|
|
1430
|
+
return parents
|
|
1431
|
+
|
|
1432
|
+
|
|
1433
|
+
def _resolve_receiver_type(receiver: str | None, obj: Node | None, call_node: Node,
|
|
1434
|
+
env: dict[str, str], parents: dict[str, str] | None = None) -> str | None:
|
|
1435
|
+
"""Infer the receiver's type from an inline `new`, `this`, `super`, or the type env."""
|
|
1373
1436
|
if _new_expression_type(obj) is not None:
|
|
1374
1437
|
return _new_expression_type(obj)
|
|
1375
1438
|
if receiver in ("this",):
|
|
1376
1439
|
return _enclosing_class_name(call_node)
|
|
1440
|
+
if receiver == "super" and parents:
|
|
1441
|
+
return parents.get(_enclosing_class_name(call_node))
|
|
1377
1442
|
if receiver is not None and receiver in env:
|
|
1378
1443
|
return env[receiver]
|
|
1379
1444
|
return None
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
[project]
|
|
2
2
|
name = "codecompass-mcp"
|
|
3
|
-
version = "3.0
|
|
3
|
+
version = "3.1.0"
|
|
4
4
|
description = "Structural code context for AI coding agents — a local code knowledge graph for blast radius, impact, deps, dead code, and flow tracing"
|
|
5
5
|
readme = "README.md"
|
|
6
6
|
license = {text = "MIT"}
|
|
@@ -339,6 +339,21 @@ def test_python_public_method_marked_exported():
|
|
|
339
339
|
assert by_name.get("_private") is False, "underscore method is not exported"
|
|
340
340
|
|
|
341
341
|
|
|
342
|
+
def test_inheritance_super_resolution_all_langs():
|
|
343
|
+
cases = [
|
|
344
|
+
(".py", "class Command:\n def invoke(self, c): pass\n"
|
|
345
|
+
"class Group(Command):\n def invoke(self, c):\n return super().invoke(c)\n"),
|
|
346
|
+
(".js", "class Command { invoke(c){} }\n"
|
|
347
|
+
"class Group extends Command { invoke(c){ return super.invoke(c); } }\n"),
|
|
348
|
+
(".php", "<?php\nclass Command { function invoke($c){} }\n"
|
|
349
|
+
"class Group extends Command { function invoke($c){ return parent::invoke($c); } }\n"),
|
|
350
|
+
]
|
|
351
|
+
for suffix, src in cases:
|
|
352
|
+
triples = _parse(src, suffix=suffix)
|
|
353
|
+
call = next(t for t in triples if t.relation_type == "CALLS" and t.to_entity == "invoke")
|
|
354
|
+
assert call.call_receiver_type == "Command", f"{suffix}: super()/parent:: should type as the parent class"
|
|
355
|
+
|
|
356
|
+
|
|
342
357
|
def test_php_receiver_type_and_exports():
|
|
343
358
|
src = (
|
|
344
359
|
"<?php\n"
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
{codecompass_mcp-3.0.1 → codecompass_mcp-3.1.0}/codecompass_mcp.egg-info/dependency_links.txt
RENAMED
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|