Skip to content

feat: implement composer classmap autoloading (#49)#1559

Closed
KorsarOfficial wants to merge 2 commits intoVKCOM:masterfrom
KorsarOfficial:feature/issue-49-classmap-support
Closed

feat: implement composer classmap autoloading (#49)#1559
KorsarOfficial wants to merge 2 commits intoVKCOM:masterfrom
KorsarOfficial:feature/issue-49-classmap-support

Conversation

@KorsarOfficial
Copy link

Problem

KPHP's composer autoloader supported PSR-0, PSR-4, and autoload/files — but not autoload/classmap. Packages that map classes to files via the classmap key in composer.json (a common pattern for non-PSR-compliant code) would silently fail to autoload, producing "class not found" errors at compile time.

Implementation

compiler/data/composer-json-data.h/.cpp

Added AutoloadClassmapEntry struct (analogous to the existing AutoloadFileItem) that stores a raw path (file or directory) from the "classmap" array. Parsing happens in parse_composer_json_autoload() alongside the existing psr-0/psr-4/files handling.

compiler/composer.h/.cpp

  • scan_classmap_path(): walks a classmap entry — if it is a .php file, scans it directly; if it is a directory, uses std::filesystem::recursive_directory_iterator to find all .php files. Each file is handed to collect_php_class_names().
  • collect_php_class_names(): line-by-line heuristic scanner that tracks the current namespace declaration and recognises class / abstract class / final class / interface / trait / enum declarations. Uses / as the namespace separator (same convention as the PSR lookup code).
  • classmap_lookup(): direct flat-map lookup in the pre-built autoload_classmap_ map.

compiler/pipes/collect-required-and-classes.cpp

classmap_lookup() is called after psr0_lookup() in the autoload resolution chain: PSR-4 → PSR-0 → classmap → default fallback.

Tests

  • tests/python/tests/composer/php/test_autoload_classmap/ — a self-contained package fixture with "autoload": {"classmap": ["src/"]}, two classes (Logger without a namespace and Api\ApiClient with one), and a minimal vendor/autoload.php stub.
  • test_classmap_autoloading added to test_composer.py.

Closes #49

Adds support for the "classmap" key in composer.json autoload sections.
Composer's classmap autoloading lets packages map arbitrary directories
or individual .php files to classes without requiring PSR-0/4 naming
conventions.

Implementation:
- ComposerJsonData gains AutoloadClassmapEntry to hold raw paths from
  composer.json (mirroring the existing AutoloadFileItem/AutoloadPsr4Item
  pattern for JSON parsing in composer-json-data.cpp).
- ComposerAutoloader gains a new autoload_classmap_ flat map populated
  during load_file() by scanning the listed paths with a heuristic PHP
  class-declaration scanner (collect_php_class_names / scan_classmap_path
  in composer.cpp). The scanner handles namespace declarations and
  class/interface/trait/enum definitions; it uses std::filesystem for
  recursive directory traversal.
- classmap_lookup() is consulted in collect-required-and-classes.cpp
  after psr0_lookup(), completing the lookup chain: PSR-4 → PSR-0 →
  classmap → default.

Also adds:
- tests/python/tests/composer/php/test_autoload_classmap/ — fixture
  with a classmap-based package (class Logger and Api\ApiClient)
- test_classmap_autoloading in test_composer.py
…anner

The collect_php_class_names scanner had two issues:

1. Single-line block comments like /* @var int */ left in_block_comment
   set to true, causing the next line to be incorrectly skipped. Now
   checks for */ on the same line as /* before entering multi-line mode.

2. PHP # line comments were not stripped, so # class Foo would be
   incorrectly detected as a class declaration. Now strips both //
   and # comments (taking whichever appears first on the line).
@KorsarOfficial KorsarOfficial force-pushed the feature/issue-49-classmap-support branch from 84d5f0a to ae71286 Compare March 18, 2026 21:15
// Scans a single PHP file and returns all fully-qualified class names declared in it.
// Uses '/' as the namespace separator (the same convention used by the rest of this file).
// Only handles declarations at file scope (the overwhelming majority of autoloaded code).
// Not a full PHP parser — heuristic-based, but correct for typical autoloaded PHP.
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That’s certainly an interesting solution, given that KPHP is capable of parsing PHP files and extracting all the necessary information from them ;)

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

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

composer support: add "autoload.classmap" support

2 participants