feat: implement composer classmap autoloading (#49)#1559
Closed
KorsarOfficial wants to merge 2 commits intoVKCOM:masterfrom
Closed
feat: implement composer classmap autoloading (#49)#1559KorsarOfficial wants to merge 2 commits intoVKCOM:masterfrom
KorsarOfficial wants to merge 2 commits intoVKCOM:masterfrom
Conversation
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).
84d5f0a to
ae71286
Compare
| // 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. |
Contributor
There was a problem hiding this comment.
That’s certainly an interesting solution, given that KPHP is capable of parsing PHP files and extracting all the necessary information from them ;)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Problem
KPHP's composer autoloader supported PSR-0, PSR-4, and
autoload/files— but notautoload/classmap. Packages that map classes to files via theclassmapkey incomposer.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/.cppAdded
AutoloadClassmapEntrystruct (analogous to the existingAutoloadFileItem) that stores a raw path (file or directory) from the"classmap"array. Parsing happens inparse_composer_json_autoload()alongside the existing psr-0/psr-4/files handling.compiler/composer.h/.cppscan_classmap_path(): walks a classmap entry — if it is a.phpfile, scans it directly; if it is a directory, usesstd::filesystem::recursive_directory_iteratorto find all.phpfiles. Each file is handed tocollect_php_class_names().collect_php_class_names(): line-by-line heuristic scanner that tracks the currentnamespacedeclaration and recognisesclass/abstract class/final class/interface/trait/enumdeclarations. Uses/as the namespace separator (same convention as the PSR lookup code).classmap_lookup(): direct flat-map lookup in the pre-builtautoload_classmap_map.compiler/pipes/collect-required-and-classes.cppclassmap_lookup()is called afterpsr0_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 (Loggerwithout a namespace andApi\ApiClientwith one), and a minimalvendor/autoload.phpstub.test_classmap_autoloadingadded totest_composer.py.Closes #49