Skip to content

PHP: method calls and plain function calls not extracted as CALLS edges #297

@kojiromike

Description

@kojiromike

Summary

When building a graph on a large PHP codebase (~4,400 PHP files, 33K functions, 3K classes), the parser produces only 58 CALLS edges from PHP files. Method calls ($this->method(), $obj->method()), static calls (Class::method()), and plain function calls (sqlQuery(...), xl(...)) are not being captured.

CONTAINS and IMPORTS_FROM edges work well (36K and 12K respectively), so the file/class/function structure is there — but without call edges, blast-radius analysis is effectively disabled for PHP.

Reproduction

git clone https://github.com/openemr/openemr.git
cd openemr
uvx code-review-graph build
sqlite3 .code-review-graph/graph.db "SELECT kind, COUNT(*) FROM edges WHERE file_path LIKE '%.php' GROUP BY kind ORDER BY COUNT(*) DESC;"

Output:

CONTAINS|36770
IMPORTS_FROM|12401
CALLS|58

The 58 CALLS edges that do exist are all global function calls with a \ prefix — \dirname(), \is_array(), \is_null(), etc. Calls without the leading backslash, method calls, and static calls are all missing.

Expected

PHP call extraction should capture at minimum:

  • Plain function calls: sqlQuery(...), xl(...), text(...)
  • Method calls: $this->execute(...), $service->search(...)
  • Static method calls: QueryUtils::fetchRecords(...), EncounterService::create(...)
  • Scoped calls: parent::__construct(...), self::factory(...)

Tree-sitter's PHP grammar exposes these as function_call_expression, member_call_expression, scoped_call_expression, and nullsafe_member_call_expression node types, so the AST data is available.

Environment

  • code-review-graph installed via uvx (latest from PyPI as of 2026-04-15)
  • Target repo: openemr/openemr at commit a7a3f0a (4,770 files, 64,600 nodes)
  • macOS, Python 3.12

Context

OpenEMR is a large open-source healthcare EHR. The PHP call extraction gap is the main blocker — the structural (CONTAINS) and import (IMPORTS_FROM) edges are already useful, but blast-radius analysis needs CALLS edges to be practical.

Related issues

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions