22
33namespace staabm \PHPStanTodoBy ;
44
5+ use OutOfBoundsException ;
6+ use Override ;
57use Composer \InstalledVersions ;
68use Composer \Semver \Comparator ;
79use Composer \Semver \VersionParser ;
1214use PHPStan \Rules \IdentifierRuleError ;
1315use PHPStan \Rules \Rule ;
1416use PHPStan \Rules \RuleError ;
17+ use ReflectionClass ;
1518use staabm \PHPStanTodoBy \utils \CommentMatcher ;
1619use staabm \PHPStanTodoBy \utils \ExpiredCommentErrorBuilder ;
1720use UnexpectedValueException ;
@@ -61,6 +64,11 @@ final class TodoByPackageVersionRule implements Rule
6164 */
6265 private array $ virtualPackages ;
6366
67+ /**
68+ * @var array{versions: array<string, array{version: string, pretty_version: string}>}
69+ */
70+ private array $ installedVersions = [];
71+
6472 /**
6573 * @param array<string, string> $virtualPackages
6674 */
@@ -74,9 +82,9 @@ public function __construct(
7482 $ this ->errorBuilder = $ errorBuilder ;
7583
7684 // require the top level installed versions, so we don't mix it up with the one in phpstan.phar
77- $ installedVersions = $ this ->workingDirectory . '/vendor/composer/InstalledVersions .php ' ;
78- if (! class_exists (InstalledVersions::class, false ) && is_readable ($ installedVersions )) {
79- require_once $ installedVersions ;
85+ $ installedVersions = $ this ->workingDirectory . '/vendor/composer/installed .php ' ;
86+ if (is_readable ($ installedVersions )) {
87+ $ this -> installedVersions = require $ installedVersions ;
8088 }
8189 }
8290
@@ -261,7 +269,7 @@ private function satisfiesInstalledPackage(string $package, string $version, Com
261269 $ versionParser = new VersionParser ();
262270
263271 // see https://getcomposer.org/doc/07-runtime.md#installed-versions
264- if (!InstalledVersions:: isInstalled ( $ package )) {
272+ if (!isset ( $ this -> installedVersions [ ' versions ' ][ $ package] )) {
265273 return $ this ->errorBuilder ->buildError (
266274 $ comment ->getText (),
267275 $ comment ->getStartLine (),
@@ -273,8 +281,11 @@ private function satisfiesInstalledPackage(string $package, string $version, Com
273281 }
274282
275283 try {
276- return InstalledVersions::satisfies ($ versionParser , $ package , $ version );
277- } catch (UnexpectedValueException $ e ) {
284+ $ constraint = $ versionParser ->parseConstraints ($ version );
285+ $ provided = $ versionParser ->parseConstraints ($ this ->getVersionRanges ($ package ));
286+
287+ return $ provided ->matches ($ constraint );
288+ } catch (UnexpectedValueException ) {
278289 return $ this ->errorBuilder ->buildError (
279290 $ comment ->getText (),
280291 $ comment ->getStartLine (),
@@ -298,4 +309,27 @@ private function getVersionComparator(string $version): ?string
298309
299310 return $ comparator ;
300311 }
312+
313+ public function getVersionRanges (string $ packageName ) : string
314+ {
315+ if (!isset ($ this ->installedVersions ['versions ' ][$ packageName ])) {
316+ throw new OutOfBoundsException ('Package " ' . $ packageName . '" is not installed ' );
317+ }
318+
319+ $ ranges = array ();
320+ if (isset ($ this ->installedVersions ['versions ' ][$ packageName ]['pretty_version ' ])) {
321+ $ ranges [] = $ this ->installedVersions ['versions ' ][$ packageName ]['pretty_version ' ];
322+ }
323+ if (array_key_exists ('aliases ' , $ this ->installedVersions ['versions ' ][$ packageName ])) {
324+ $ ranges = array_merge ($ ranges , $ this ->installedVersions ['versions ' ][$ packageName ]['aliases ' ]);
325+ }
326+ if (array_key_exists ('replaced ' , $ this ->installedVersions ['versions ' ][$ packageName ])) {
327+ $ ranges = array_merge ($ ranges , $ this ->installedVersions ['versions ' ][$ packageName ]['replaced ' ]);
328+ }
329+ if (array_key_exists ('provided ' , $ this ->installedVersions ['versions ' ][$ packageName ])) {
330+ $ ranges = array_merge ($ ranges , $ this ->installedVersions ['versions ' ][$ packageName ]['provided ' ]);
331+ }
332+
333+ return implode (' || ' , $ ranges );
334+ }
301335}
0 commit comments