1010use Codeception \Module \Cli ;
1111use Codeception \Module \Filesystem ;
1212use Codeception \TestInterface ;
13- use Composer \Semver \Comparator ;
13+ use Composer \InstalledVersions ;
14+ use Composer \Semver \Semver ;
1415use Composer \Semver \VersionParser ;
1516use Muglug \PackageVersions \Versions as LegacyVersions ;
1617use PackageVersions \Versions ;
2122
2223class Module extends BaseModule
2324{
24- /** @var array<string,string */
25+ /** @var array<string,string> */
2526 private const VERSION_OPERATORS = [
2627 'newer than ' => '> ' ,
2728 'older than ' => '< ' ,
@@ -101,7 +102,7 @@ public function _before(TestInterface $test): void
101102 */
102103 public function runPsalmOn (string $ filename , array $ options = []): void
103104 {
104- $ suppressProgress = $ this ->seePsalmVersionIs ( ' >= ' , '3.4.0 ' );
105+ $ suppressProgress = $ this ->packageSatisfiesVersionConstraint ( ' vimeo/psalm ' , '>= 3.4.0 ' );
105106
106107 $ options = array_map ('escapeshellarg ' , $ options );
107108 $ cmd = $ this ->config ['psalm_path ' ]
@@ -192,11 +193,11 @@ public function seeNoErrors(): void
192193 }
193194 }
194195
195- public function seePsalmVersionIs (string $ operator , string $ version ): bool
196+ private function packageSatisfiesVersionConstraint (string $ package , string $ versionConstraint ): bool
196197 {
197- $ currentVersion = $ this ->getShortVersion (' vimeo/psalm ' );
198+ $ currentVersion = $ this ->getShortVersion ($ package );
198199
199- $ this ->debug (sprintf ("Current version: %s " , $ currentVersion ));
200+ $ this ->debug (sprintf ("Current version of %s : %s " , $ package , $ currentVersion ));
200201
201202 // todo: move to init/construct/before?
202203 $ parser = new VersionParser ();
@@ -207,14 +208,22 @@ public function seePsalmVersionIs(string $operator, string $version): bool
207208 $ currentVersion = '9999999-dev ' ;
208209 }
209210
210- $ version = $ parser -> normalize ( $ version );
211+ $ result = Semver:: satisfies ( $ currentVersion , $ versionConstraint );
211212
212- $ result = Comparator::compare ($ currentVersion , $ operator , $ version );
213- $ this ->debug ("Comparing $ currentVersion $ operator $ version => $ result " );
213+ $ this ->debug ("Comparing $ currentVersion against $ versionConstraint => " . ($ result ? 'ok ' : 'ko ' ));
214214
215215 return $ result ;
216216 }
217217
218+ /**
219+ * @deprecated
220+ * This method is only to maintain the public API; please use `self::haveADependencySatisfied` instead.
221+ */
222+ public function seePsalmVersionIs (string $ operator , string $ version ): bool
223+ {
224+ return $ this ->packageSatisfiesVersionConstraint ('vimeo/psalm ' , $ operator . $ version );
225+ }
226+
218227 /**
219228 * @Given I have the following code preamble :code
220229 */
@@ -243,7 +252,7 @@ public function runPsalmWithDeadCodeDetection(): void
243252
244253 public function seePsalmHasTaintAnalysis (): bool
245254 {
246- $ taintAnalysisAvailable = $ this ->seePsalmVersionIs ( ' >= ' , '3.10.0 ' );
255+ $ taintAnalysisAvailable = $ this ->packageSatisfiesVersionConstraint ( ' vimeo/psalm ' , '>= 3.10.0 ' );
247256 return $ taintAnalysisAvailable ;
248257 }
249258
@@ -330,7 +339,7 @@ public function havePsalmOfACertainVersionRangeBecauseOf(string $operator, strin
330339
331340 $ op = (string ) self ::VERSION_OPERATORS [$ operator ];
332341
333- if (!$ this ->seePsalmVersionIs ( $ op, $ version )) {
342+ if (!$ this ->packageSatisfiesVersionConstraint ( ' vimeo/psalm ' , $ op . $ version )) {
334343 /** @psalm-suppress InternalClass */
335344 throw new SkippedTestError ("This scenario requires Psalm $ op $ version because of $ reason " );
336345 }
@@ -407,6 +416,19 @@ function (array $row): string {
407416 $ this ->hasAutoload = true ;
408417 }
409418
419+ /**
420+ * @Given I have the :package package satisfying the :versionConstraint
421+ */
422+ public function haveADependencySatisfied (string $ package , string $ versionConstraint ): void
423+ {
424+ if ($ this ->packageSatisfiesVersionConstraint ($ package , $ versionConstraint )) {
425+ return ;
426+ }
427+
428+ /** @psalm-suppress InternalClass */
429+ throw new SkippedTestError ("This scenario requires $ package to match $ versionConstraint " );
430+ }
431+
410432 private function convertToRegexp (string $ in ): string
411433 {
412434 return '@ ' . str_replace ('% ' , '.* ' , preg_quote ($ in , '@ ' )) . '@ ' ;
@@ -452,7 +474,11 @@ function (array $error): array {
452474
453475 private function getShortVersion (string $ package ): string
454476 {
455- if (class_exists (Versions::class)) {
477+ /** @psalm-suppress DeprecatedClass Support of legacy code */
478+ if (class_exists (InstalledVersions::class)) {
479+ /** @psalm-suppress UndefinedClass Composer\InstalledVersions is undefined when using Composer 1.x */
480+ return (string ) InstalledVersions::getPrettyVersion ($ package );
481+ } elseif (class_exists (Versions::class)) {
456482 /** @psalm-suppress UndefinedClass psalm 3.0 ignores class_exists check */
457483 $ version = (string ) Versions::getVersion ($ package );
458484 } elseif (class_exists (LegacyVersions::class)) {
0 commit comments