Composer Parser Improvements
May 28, 2026 · View on GitHub
Summary
Rust now intentionally differs from or improves on current Python ScanCode Composer handling in several concrete ways:
- supports alternate Composer manifest/lockfile names such as
symfony.composer.json,composer.symfony.json, and analogous lockfile names - assigns ordinary files under Composer package roots to the correct package, including nested Composer packages
- keeps lockfile extraction lightweight by emitting one synthetic lock package plus dependency objects, while avoiding unnecessary array cloning on large
composer.lockfiles - enriches manifest-level provenance and party typing beyond the earlier lock-only focus
Python Status
- Python Composer support is split between
composer.jsonandcomposer.lockhandlers and only advertises glob-style*composer.json/*composer.lockrecognition. - Upstream explicitly tracks:
- slow
composer.lockscanning on very large lockfiles - nested Composer package/file assignment gaps
- missing support for alternate Composer file names
- slow
- Python also maps manifest
sourceanddistmetadata but Rust previously left those fields empty forcomposer.json.
Rust Improvements
Alternate file names
- Rust now recognizes:
composer.jsonsymfony.composer.jsonphp.composer.jsoncomposer.symfony.json- and the analogous
*.lockvariants
- Assembly config now uses matching glob patterns so alternate-name manifests participate in sibling merge instead of only standalone parsing.
Nested Composer package assignment
- Composer package-root resource assignment now associates ordinary files under a Composer package root with that package.
- Nested Composer packages no longer lose file ownership to a parent package just because they live under the parent directory tree.
- In nested Composer repositories:
- root package files remain on the root package
- nested package files like
packages/plugin/README.mdstay with the nested package
Large lockfile handling
- Rust keeps Composer lock parsing lightweight by:
- emitting one synthetic lock package plus dependency edges instead of materializing every locked package as a top-level package
- iterating lockfile package arrays by reference instead of cloning them first
- pre-reserving dependency capacity for the combined
packages+packages-devlists
- This does not replicate Python’s slow-path object expansion, which is the right behavior because the upstream issue is a performance bug, not a semantic contract.
Manifest provenance and party typing
- Composer manifest parsing now extracts:
vcs_urlfrom manifestsourcedownload_urlfrom manifestdistParty.type = personfor authors and vendor parties
Coverage
Coverage spans alternate Composer filenames, nested file assignment, lockfile handling, richer manifest provenance behavior, and a parser golden for Composer manifest output.