Skip to content

Bug in Python parsing, class/static methods not added as CALLS edges #228

Closed

Description

@mandricmihai

Try to index the attached example, is not able to find the methods and it results in false positives as dead code.

build_from_text build_from_mapping are not indexed, in degree 0, out degree 0

"""Module demonstrating direct class usage — baseline case."""
from core.schemas import ActionRecordX


def run_plain_flow():
    """Invokes constructor helper without aliasing."""
    return ActionRecordX.build_from_text("hello")


def adapt_plain_flow():
    """Invokes alternate constructor without aliasing."""
    return ActionRecordX.build_from_mapping({"label": "world"})


"""Module demonstrating aliased import — alias resolution case."""
from core.schemas import ActionRecordX as ActionAlias


def run_alias_flow():
    """Invokes constructor helper via alias."""
    return ActionAlias.build_from_text("hello")


def adapt_alias_flow():
    """Invokes alternate constructor via alias."""
    return ActionAlias.build_from_mapping({"label": "world"})


from pydantic import BaseModel


class ActionRecordX(BaseModel):
    label: str

    @classmethod
    def build_from_text(cls, raw: str) -> "ActionRecordX":
        return cls(label=raw)

    @classmethod
    def build_from_mapping(cls, payload: dict) -> "ActionRecordX":
        return cls(label=payload["label"])

Activity

  1. DeusData commented on Apr 10, 2026

    @DeusData
    Owner

    Hey, thanks for noticing. Will tackle this once I am back on the 15th :)

  2. added
    bugSomething isn't working
    parsing/qualityGraph extraction bugs, false positives, missing edges
    on Apr 15, 2026
  3. CDreselerGSD commented on Apr 30, 2026

    @CDreselerGSD

    We see a related symptom in the same codepath: not just missing CALLS edges, but the entire method nodes are absent from the index for @staticmethod, @classmethod, and @property methods.

    Repro on a Python project with codebase-memory-mcp v0.6.0:

    Decorator Method graph.search result
    @staticmethod _get_running_worktree_paths total=0
    @staticmethod _detect_repo_root total=0
    @classmethod from_env total=0
    @Property profile_names total=0

    Plain instance methods on the same classes ARE indexed. After graph.reindex (11910 → 13700 nodes) the bug persists, so it is not a stale-index issue.

    Likely root cause: the tree-sitter Python extractor walks function_definition without descending through decorated_definition wrappers — so decorated methods never reach the node-creation pass, which then makes #228's edges-missing case inevitable too.

    Both symptoms (missing nodes / missing edges) probably share the fix in the extractor's decorated_definition traversal.

  4. DeusData commented on May 31, 2026

    @DeusData
    Owner

    Verified resolved on v0.7.0. The missing CALLS edge for ActionRecordX.build_from_text(...) — a class/static method called directly on a cross-file imported class — is created correctly now; the py_lsp cross-file resolver was reworked since 0.6.0. I added a regression test (pylsp_crossfile_classmethod_on_class_issue228) that feeds your exact pattern (from core.schemas import ActionRecordX → ActionRecordX.build_from_text('hello')) through the resolver and asserts the run_plain_flow → build_from_text edge resolves (passes in the full suite, 3,629 tests).

    That removes the false "dead code" classification for those constructors. If you still see build_from_text/build_from_mapping at in-degree 0 after a fresh full index on v0.7.0, please reopen with the two files (the caller + core/schemas.py) and I'll add an end-to-end repro. 🙏

  5. added a commit that references this issue on May 31, 2026
  6. CDreselerGSD commented on Jun 1, 2026

    @CDreselerGSD

    Confirming v0.7.0 fixes our broader symptom too — not just the original
    classmethod edge case.

    We hit a wider variant of this in production: any @staticmethod,
    @classmethod, or @property method was completely missing from the graph
    (zero nodes, not just dropped edges). The hybrid Light-Semantic-Pass in v0.7.0
    resolves all four of our repro cases:

    Decorator Method v0.6.0 results v0.7.0 results
    @staticmethod _get_running_worktree_paths 0 1
    @staticmethod _detect_repo_root 0 1
    @classmethod from_env 0 17
    @property profile_names 0 1

    Verified the v0.7.0 hits return real structured data, not stubs:

    {
      "name": "_detect_repo_root",
      "qualified_name": "srv-repos-XYZ.worktree.WorktreeManager._detect_repo_root",
      "label": "Method",
      "file_path": "XYZ/worktree.py",
      "start_line": 159,
      "end_line": 162
    }

    Sanity checks alongside:

    • Negative control: xyzzy_doesnt_exist_42 → 0 results ✅
    • Positive controls on undecorated methods: handle_search → 6,
      handle_history → 2, WorktreeManager (class) → 20 ✅

    So the tree-sitter decorated_definition traversal fix in v0.7.0 generalizes
    correctly — closes our use case as well. Thanks for the quick turnaround.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    bugSomething isn't workingparsing/qualityGraph extraction bugs, false positives, missing edges

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions