Summary
In deps-composer, the parse_section() function advances search_start sequentially as each dependency is found. However, serde_json::Map (without preserve_order feature) uses a BTreeMap and iterates in alphabetical order — not file order.
When a package whose name comes later alphabetically appears earlier in the file, search_start is already advanced past its file position by the time it's searched. The package is not found, and name_range / version_range remain at Range::default() (i.e., (0,0)→(0,0)).
Reproduction
Given composer.json:
{
"require": {
"laravel/framework": "^10.0",
"guzzlehttp/guzzle": "^7.5",
"symfony/console": "~6.0"
}
}
BTreeMap iteration order: guzzlehttp/guzzle → laravel/framework → symfony/console.
guzzlehttp/guzzle (line 3) is found; search_start advances past line 3.
laravel/framework (line 2) is searched from position past line 3 — missed. name_range = (0,0)→(0,0).
symfony/console (line 4) is found correctly.
Impact
- Hover: returns
null for affected packages (position check against (0,0)→(0,0) range fails).
- Inlay hints: missing version badge for affected packages.
- Diagnostics: may not flag outdated versions for affected packages.
Affects any composer.json where packages are not in strict alphabetical order.
Root cause
serde_json workspace dependency has no preserve_order feature → Map<String, Value> is a BTreeMap.
Suggested fix
- Enable
serde_json preserve_order feature in deps-composer to keep file insertion order.
- Alternatively, reset
search_start = 0 per dependency (correct but O(n²) for large files).
- Or pre-scan all positions into a map indexed by name, then assign.
Summary
In
deps-composer, theparse_section()function advancessearch_startsequentially as each dependency is found. However,serde_json::Map(withoutpreserve_orderfeature) uses aBTreeMapand iterates in alphabetical order — not file order.When a package whose name comes later alphabetically appears earlier in the file,
search_startis already advanced past its file position by the time it's searched. The package is not found, andname_range/version_rangeremain atRange::default()(i.e.,(0,0)→(0,0)).Reproduction
Given
composer.json:{ "require": { "laravel/framework": "^10.0", "guzzlehttp/guzzle": "^7.5", "symfony/console": "~6.0" } }BTreeMap iteration order:
guzzlehttp/guzzle→laravel/framework→symfony/console.guzzlehttp/guzzle(line 3) is found;search_startadvances past line 3.laravel/framework(line 2) is searched from position past line 3 — missed.name_range = (0,0)→(0,0).symfony/console(line 4) is found correctly.Impact
nullfor affected packages (position check against(0,0)→(0,0)range fails).Affects any
composer.jsonwhere packages are not in strict alphabetical order.Root cause
serde_jsonworkspace dependency has nopreserve_orderfeature →Map<String, Value>is aBTreeMap.Suggested fix
serde_jsonpreserve_orderfeature indeps-composerto keep file insertion order.search_start = 0per dependency (correct but O(n²) for large files).