Skip to content

fix(composer): position tracking incorrect for out-of-alphabetical-order packages #84

@bug-ops

Description

@bug-ops

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/guzzlelaravel/frameworksymfony/console.

  1. guzzlehttp/guzzle (line 3) is found; search_start advances past line 3.
  2. laravel/framework (line 2) is searched from position past line 3 — missed. name_range = (0,0)→(0,0).
  3. 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

  1. Enable serde_json preserve_order feature in deps-composer to keep file insertion order.
  2. Alternatively, reset search_start = 0 per dependency (correct but O(n²) for large files).
  3. Or pre-scan all positions into a map indexed by name, then assign.

Metadata

Metadata

Assignees

Labels

P1High: wrong behavior, broken featurebugSomething isn't workingparserParser changes

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions