diff --git a/composer.json b/composer.json index 19ed2473..ac7308ab 100644 --- a/composer.json +++ b/composer.json @@ -1,19 +1,20 @@ { "name": "magento/magento-semver", "description": "Magento semantic version checker", - "version": "4.0.0", + "version": "6.0.0", "license": [ "OSL-3.0", "AFL-3.0" ], "bin": ["bin/svc"], "require": { - "php": "~7.1.3||~7.2.0||~7.3.0", + "php": "~7.2.29||~7.3.0||~7.4.0", "phpstan/phpdoc-parser": "^0.3.5", "symfony/console": "~4.1.0||~4.4.0", - "tomzx/php-semver-checker": "^0.13.0", + "tomzx/php-semver-checker": "^0.14.0", "wikimedia/less.php": "~1.8.0", - "zendframework/zend-stdlib": "^3.2.1" + "zendframework/zend-stdlib": "^3.2.1", + "nikic/php-parser": "^4.4" }, "require-dev": { "phpunit/phpunit": "^6.5.0", diff --git a/composer.lock b/composer.lock index a02995c1..3c957b3c 100644 --- a/composer.lock +++ b/composer.lock @@ -4,32 +4,33 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "bcf7e3c8b1127bce7f252f930c24435e", + "content-hash": "e66949a0d4e853678dd76cbca440f3f9", "packages": [ { "name": "hassankhan/config", - "version": "0.11.2", + "version": "v2.1.0", "source": { "type": "git", "url": "https://github.com/hassankhan/config.git", - "reference": "7fbc236c32dc6cc53a7b00992a2739cf8b41c085" + "reference": "16fa4d3320ac9bb611dda0c8ea980edb58d227c9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/hassankhan/config/zipball/7fbc236c32dc6cc53a7b00992a2739cf8b41c085", - "reference": "7fbc236c32dc6cc53a7b00992a2739cf8b41c085", + "url": "https://api.github.com/repos/hassankhan/config/zipball/16fa4d3320ac9bb611dda0c8ea980edb58d227c9", + "reference": "16fa4d3320ac9bb611dda0c8ea980edb58d227c9", "shasum": "" }, "require": { - "php": ">=5.3.0" + "php": ">=5.5.9" }, "require-dev": { - "phpunit/phpunit": "~4.0", + "phpunit/phpunit": "~4.8 || ~5.7 || ~6.5 || ~7.5", "scrutinizer/ocular": "~1.1", - "squizlabs/php_codesniffer": "~2.2" + "squizlabs/php_codesniffer": "~2.2", + "symfony/yaml": "~3.4" }, "suggest": { - "symfony/yaml": "~2.5" + "symfony/yaml": "~3.4" }, "type": "library", "autoload": { @@ -61,28 +62,29 @@ "yaml", "yml" ], - "time": "2017-11-07T22:49:43+00:00" + "time": "2019-09-01T15:51:42+00:00" }, { "name": "nikic/php-parser", - "version": "v3.1.5", + "version": "v4.5.0", "source": { "type": "git", "url": "https://github.com/nikic/PHP-Parser.git", - "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce" + "reference": "53c2753d756f5adb586dca79c2ec0e2654dd9463" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", - "reference": "bb87e28e7d7b8d9a7fda231d37457c9210faf6ce", + "url": "https://api.github.com/repos/nikic/PHP-Parser/zipball/53c2753d756f5adb586dca79c2ec0e2654dd9463", + "reference": "53c2753d756f5adb586dca79c2ec0e2654dd9463", "shasum": "" }, "require": { "ext-tokenizer": "*", - "php": ">=5.5" + "php": ">=7.0" }, "require-dev": { - "phpunit/phpunit": "~4.0|~5.0" + "ircmaxell/php-yacc": "0.0.5", + "phpunit/phpunit": "^6.5 || ^7.0 || ^8.0" }, "bin": [ "bin/php-parse" @@ -90,7 +92,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "3.0-dev" + "dev-master": "4.3-dev" } }, "autoload": { @@ -112,7 +114,7 @@ "parser", "php" ], - "time": "2018-02-28T20:30:58+00:00" + "time": "2020-06-03T07:24:19+00:00" }, { "name": "phpstan/phpdoc-parser", @@ -212,22 +214,23 @@ }, { "name": "symfony/console", - "version": "v4.4.4", + "version": "v4.4.10", "source": { "type": "git", "url": "https://github.com/symfony/console.git", - "reference": "f512001679f37e6a042b51897ed24a2f05eba656" + "reference": "326b064d804043005526f5a0494cfb49edb59bb0" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/console/zipball/f512001679f37e6a042b51897ed24a2f05eba656", - "reference": "f512001679f37e6a042b51897ed24a2f05eba656", + "url": "https://api.github.com/repos/symfony/console/zipball/326b064d804043005526f5a0494cfb49edb59bb0", + "reference": "326b064d804043005526f5a0494cfb49edb59bb0", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": ">=7.1.3", "symfony/polyfill-mbstring": "~1.0", "symfony/polyfill-php73": "^1.8", + "symfony/polyfill-php80": "^1.15", "symfony/service-contracts": "^1.1|^2" }, "conflict": { @@ -284,20 +287,34 @@ ], "description": "Symfony Console Component", "homepage": "https://symfony.com", - "time": "2020-01-25T12:44:29+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-05-30T20:06:45+00:00" }, { "name": "symfony/polyfill-ctype", - "version": "v1.14.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-ctype.git", - "reference": "fbdeaec0df06cf3d51c93de80c7eb76e271f5a38" + "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/fbdeaec0df06cf3d51c93de80c7eb76e271f5a38", - "reference": "fbdeaec0df06cf3d51c93de80c7eb76e271f5a38", + "url": "https://api.github.com/repos/symfony/polyfill-ctype/zipball/e94c8b1bbe2bc77507a1056cdb06451c75b427f9", + "reference": "e94c8b1bbe2bc77507a1056cdb06451c75b427f9", "shasum": "" }, "require": { @@ -309,7 +326,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.14-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -342,20 +359,20 @@ "polyfill", "portable" ], - "time": "2020-01-13T11:15:53+00:00" + "time": "2020-05-12T16:14:59+00:00" }, { "name": "symfony/polyfill-mbstring", - "version": "v1.14.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-mbstring.git", - "reference": "34094cfa9abe1f0f14f48f490772db7a775559f2" + "reference": "fa79b11539418b02fc5e1897267673ba2c19419c" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/34094cfa9abe1f0f14f48f490772db7a775559f2", - "reference": "34094cfa9abe1f0f14f48f490772db7a775559f2", + "url": "https://api.github.com/repos/symfony/polyfill-mbstring/zipball/fa79b11539418b02fc5e1897267673ba2c19419c", + "reference": "fa79b11539418b02fc5e1897267673ba2c19419c", "shasum": "" }, "require": { @@ -367,7 +384,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.14-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -401,20 +418,20 @@ "portable", "shim" ], - "time": "2020-01-13T11:15:53+00:00" + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/polyfill-php73", - "version": "v1.14.0", + "version": "v1.17.0", "source": { "type": "git", "url": "https://github.com/symfony/polyfill-php73.git", - "reference": "5e66a0fa1070bf46bec4bea7962d285108edd675" + "reference": "a760d8964ff79ab9bf057613a5808284ec852ccc" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/5e66a0fa1070bf46bec4bea7962d285108edd675", - "reference": "5e66a0fa1070bf46bec4bea7962d285108edd675", + "url": "https://api.github.com/repos/symfony/polyfill-php73/zipball/a760d8964ff79ab9bf057613a5808284ec852ccc", + "reference": "a760d8964ff79ab9bf057613a5808284ec852ccc", "shasum": "" }, "require": { @@ -423,7 +440,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.14-dev" + "dev-master": "1.17-dev" } }, "autoload": { @@ -459,24 +476,100 @@ "portable", "shim" ], - "time": "2020-01-13T11:15:53+00:00" + "time": "2020-05-12T16:47:27+00:00" + }, + { + "name": "symfony/polyfill-php80", + "version": "v1.17.0", + "source": { + "type": "git", + "url": "https://github.com/symfony/polyfill-php80.git", + "reference": "5e30b2799bc1ad68f7feb62b60a73743589438dd" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/symfony/polyfill-php80/zipball/5e30b2799bc1ad68f7feb62b60a73743589438dd", + "reference": "5e30b2799bc1ad68f7feb62b60a73743589438dd", + "shasum": "" + }, + "require": { + "php": ">=7.0.8" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "1.17-dev" + } + }, + "autoload": { + "psr-4": { + "Symfony\\Polyfill\\Php80\\": "" + }, + "files": [ + "bootstrap.php" + ], + "classmap": [ + "Resources/stubs" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Ion Bazan", + "email": "ion.bazan@gmail.com" + }, + { + "name": "Nicolas Grekas", + "email": "p@tchwork.com" + }, + { + "name": "Symfony Community", + "homepage": "https://symfony.com/contributors" + } + ], + "description": "Symfony polyfill backporting some PHP 8.0+ features to lower PHP versions", + "homepage": "https://symfony.com", + "keywords": [ + "compatibility", + "polyfill", + "portable", + "shim" + ], + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-05-12T16:47:27+00:00" }, { "name": "symfony/service-contracts", - "version": "v1.1.8", + "version": "v2.1.2", "source": { "type": "git", "url": "https://github.com/symfony/service-contracts.git", - "reference": "ffc7f5692092df31515df2a5ecf3b7302b3ddacf" + "reference": "66a8f0957a3ca54e4f724e49028ab19d75a8918b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/service-contracts/zipball/ffc7f5692092df31515df2a5ecf3b7302b3ddacf", - "reference": "ffc7f5692092df31515df2a5ecf3b7302b3ddacf", + "url": "https://api.github.com/repos/symfony/service-contracts/zipball/66a8f0957a3ca54e4f724e49028ab19d75a8918b", + "reference": "66a8f0957a3ca54e4f724e49028ab19d75a8918b", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": ">=7.2.5", "psr/container": "^1.0" }, "suggest": { @@ -485,7 +578,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "1.1-dev" + "dev-master": "2.1-dev" } }, "autoload": { @@ -517,24 +610,38 @@ "interoperability", "standards" ], - "time": "2019-10-14T12:27:06+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-05-20T17:43:50+00:00" }, { "name": "symfony/yaml", - "version": "v4.4.4", + "version": "v4.4.10", "source": { "type": "git", "url": "https://github.com/symfony/yaml.git", - "reference": "cd014e425b3668220adb865f53bff64b3ad21767" + "reference": "c2d2cc66e892322cfcc03f8f12f8340dbd7a3f8a" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/symfony/yaml/zipball/cd014e425b3668220adb865f53bff64b3ad21767", - "reference": "cd014e425b3668220adb865f53bff64b3ad21767", + "url": "https://api.github.com/repos/symfony/yaml/zipball/c2d2cc66e892322cfcc03f8f12f8340dbd7a3f8a", + "reference": "c2d2cc66e892322cfcc03f8f12f8340dbd7a3f8a", "shasum": "" }, "require": { - "php": "^7.1.3", + "php": ">=7.1.3", "symfony/polyfill-ctype": "~1.8" }, "conflict": { @@ -576,7 +683,21 @@ ], "description": "Symfony Yaml Component", "homepage": "https://symfony.com", - "time": "2020-01-21T11:12:16+00:00" + "funding": [ + { + "url": "https://symfony.com/sponsor", + "type": "custom" + }, + { + "url": "https://github.com/fabpot", + "type": "github" + }, + { + "url": "https://tidelift.com/funding/github/packagist/symfony/symfony", + "type": "tidelift" + } + ], + "time": "2020-05-20T08:37:50+00:00" }, { "name": "tomzx/finder", @@ -629,29 +750,29 @@ }, { "name": "tomzx/php-semver-checker", - "version": "v0.13.0", + "version": "v0.14.0", "source": { "type": "git", "url": "https://github.com/tomzx/php-semver-checker.git", - "reference": "d26fbefeb8405f4dc6ae7fb3a003af3b5b5f948a" + "reference": "4496ada7e8370e485054ffddc4c563fe74684ed1" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/tomzx/php-semver-checker/zipball/d26fbefeb8405f4dc6ae7fb3a003af3b5b5f948a", - "reference": "d26fbefeb8405f4dc6ae7fb3a003af3b5b5f948a", + "url": "https://api.github.com/repos/tomzx/php-semver-checker/zipball/4496ada7e8370e485054ffddc4c563fe74684ed1", + "reference": "4496ada7e8370e485054ffddc4c563fe74684ed1", "shasum": "" }, "require": { - "hassankhan/config": "^0.11", - "nikic/php-parser": "^3.1", - "php": ">=5.6.0", - "symfony/console": "^2.7|^3.0|^4.0", - "symfony/yaml": "^2.7|^3.0|^4.0", + "hassankhan/config": "^2.0", + "nikic/php-parser": "^4.0", + "php": ">=7.2.29", + "symfony/console": "^4.0", + "symfony/yaml": "^4.0", "tomzx/finder": "^0.1" }, "require-dev": { "mockery/mockery": "^1.0", - "phpunit/phpunit": "^4.0|^5.0" + "phpunit/phpunit": "^7.0|^8.0" }, "bin": [ "bin/php-semver-checker" @@ -659,7 +780,7 @@ "type": "library", "extra": { "branch-alias": { - "dev-master": "0.13-dev" + "dev-master": "0.14-dev" } }, "autoload": { @@ -685,27 +806,27 @@ "semantic versioning", "semver" ], - "time": "2019-03-09T19:02:35+00:00" + "time": "2020-04-17T04:34:42+00:00" }, { "name": "wikimedia/less.php", - "version": "1.8.1", + "version": "1.8.2", "source": { "type": "git", "url": "https://github.com/wikimedia/less.php.git", - "reference": "f0f7768f6fa8a9d2ac6a0274f6f477c72159bf9b" + "reference": "e238ad228d74b6ffd38209c799b34e9826909266" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/wikimedia/less.php/zipball/f0f7768f6fa8a9d2ac6a0274f6f477c72159bf9b", - "reference": "f0f7768f6fa8a9d2ac6a0274f6f477c72159bf9b", + "url": "https://api.github.com/repos/wikimedia/less.php/zipball/e238ad228d74b6ffd38209c799b34e9826909266", + "reference": "e238ad228d74b6ffd38209c799b34e9826909266", "shasum": "" }, "require": { - "php": ">=5.3" + "php": ">=7.2.9" }, "require-dev": { - "phpunit/phpunit": "~4.8.24" + "phpunit/phpunit": "7.5.14" }, "bin": [ "bin/lessc" @@ -724,6 +845,10 @@ "Apache-2.0" ], "authors": [ + { + "name": "Josh Schmidt", + "homepage": "https://github.com/oyejorge" + }, { "name": "Matt Agar", "homepage": "https://github.com/agar" @@ -731,10 +856,6 @@ { "name": "Martin Jantošovič", "homepage": "https://github.com/Mordred" - }, - { - "name": "Josh Schmidt", - "homepage": "https://github.com/oyejorge" } ], "description": "PHP port of the Javascript version of LESS http://lesscss.org (Originally maintained by Josh Schmidt)", @@ -746,7 +867,7 @@ "php", "stylesheet" ], - "time": "2019-01-19T01:01:33+00:00" + "time": "2019-11-06T18:30:11+00:00" }, { "name": "zendframework/zend-stdlib", @@ -799,20 +920,20 @@ "packages-dev": [ { "name": "doctrine/instantiator", - "version": "1.3.0", + "version": "1.3.1", "source": { "type": "git", "url": "https://github.com/doctrine/instantiator.git", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1" + "reference": "f350df0268e904597e3bd9c4685c53e0e333feea" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/doctrine/instantiator/zipball/ae466f726242e637cebdd526a7d991b9433bacf1", - "reference": "ae466f726242e637cebdd526a7d991b9433bacf1", + "url": "https://api.github.com/repos/doctrine/instantiator/zipball/f350df0268e904597e3bd9c4685c53e0e333feea", + "reference": "f350df0268e904597e3bd9c4685c53e0e333feea", "shasum": "" }, "require": { - "php": "^7.1" + "php": "^7.1 || ^8.0" }, "require-dev": { "doctrine/coding-standard": "^6.0", @@ -851,7 +972,21 @@ "constructor", "instantiate" ], - "time": "2019-10-21T16:45:58+00:00" + "funding": [ + { + "url": "https://www.doctrine-project.org/sponsorship.html", + "type": "custom" + }, + { + "url": "https://www.patreon.com/phpdoctrine", + "type": "patreon" + }, + { + "url": "https://tidelift.com/funding/github/packagist/doctrine%2Finstantiator", + "type": "tidelift" + } + ], + "time": "2020-05-29T17:27:14+00:00" }, { "name": "myclabs/deep-copy", @@ -1005,24 +1140,21 @@ }, { "name": "phpdocumentor/reflection-common", - "version": "2.0.0", + "version": "2.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionCommon.git", - "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a" + "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/63a995caa1ca9e5590304cd845c15ad6d482a62a", - "reference": "63a995caa1ca9e5590304cd845c15ad6d482a62a", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionCommon/zipball/6568f4687e5b41b054365f9ae03fcb1ed5f2069b", + "reference": "6568f4687e5b41b054365f9ae03fcb1ed5f2069b", "shasum": "" }, "require": { "php": ">=7.1" }, - "require-dev": { - "phpunit/phpunit": "~6" - }, "type": "library", "extra": { "branch-alias": { @@ -1053,45 +1185,42 @@ "reflection", "static analysis" ], - "time": "2018-08-07T13:53:10+00:00" + "time": "2020-04-27T09:25:28+00:00" }, { "name": "phpdocumentor/reflection-docblock", - "version": "4.3.4", + "version": "5.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/ReflectionDocBlock.git", - "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c" + "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/da3fd972d6bafd628114f7e7e036f45944b62e9c", - "reference": "da3fd972d6bafd628114f7e7e036f45944b62e9c", + "url": "https://api.github.com/repos/phpDocumentor/ReflectionDocBlock/zipball/cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", + "reference": "cd72d394ca794d3466a3b2fc09d5a6c1dc86b47e", "shasum": "" }, "require": { - "php": "^7.0", - "phpdocumentor/reflection-common": "^1.0.0 || ^2.0.0", - "phpdocumentor/type-resolver": "~0.4 || ^1.0.0", - "webmozart/assert": "^1.0" + "ext-filter": "^7.1", + "php": "^7.2", + "phpdocumentor/reflection-common": "^2.0", + "phpdocumentor/type-resolver": "^1.0", + "webmozart/assert": "^1" }, "require-dev": { - "doctrine/instantiator": "^1.0.5", - "mockery/mockery": "^1.0", - "phpdocumentor/type-resolver": "0.4.*", - "phpunit/phpunit": "^6.4" + "doctrine/instantiator": "^1", + "mockery/mockery": "^1" }, "type": "library", "extra": { "branch-alias": { - "dev-master": "4.x-dev" + "dev-master": "5.x-dev" } }, "autoload": { "psr-4": { - "phpDocumentor\\Reflection\\": [ - "src/" - ] + "phpDocumentor\\Reflection\\": "src" } }, "notification-url": "https://packagist.org/downloads/", @@ -1102,33 +1231,36 @@ { "name": "Mike van Riel", "email": "me@mikevanriel.com" + }, + { + "name": "Jaap van Otterdijk", + "email": "account@ijaap.nl" } ], "description": "With this component, a library can provide support for annotations via DocBlocks or otherwise retrieve information that is embedded in a DocBlock.", - "time": "2019-12-28T18:55:12+00:00" + "time": "2020-02-22T12:28:44+00:00" }, { "name": "phpdocumentor/type-resolver", - "version": "1.0.1", + "version": "1.1.0", "source": { "type": "git", "url": "https://github.com/phpDocumentor/TypeResolver.git", - "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9" + "reference": "7462d5f123dfc080dfdf26897032a6513644fc95" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", - "reference": "2e32a6d48972b2c1976ed5d8967145b6cec4a4a9", + "url": "https://api.github.com/repos/phpDocumentor/TypeResolver/zipball/7462d5f123dfc080dfdf26897032a6513644fc95", + "reference": "7462d5f123dfc080dfdf26897032a6513644fc95", "shasum": "" }, "require": { - "php": "^7.1", + "php": "^7.2", "phpdocumentor/reflection-common": "^2.0" }, "require-dev": { - "ext-tokenizer": "^7.1", - "mockery/mockery": "~1", - "phpunit/phpunit": "^7.0" + "ext-tokenizer": "^7.2", + "mockery/mockery": "~1" }, "type": "library", "extra": { @@ -1152,20 +1284,20 @@ } ], "description": "A PSR-5 based resolver of Class names, Types and Structural Element Names", - "time": "2019-08-22T18:11:29+00:00" + "time": "2020-02-18T18:59:58+00:00" }, { "name": "phpspec/prophecy", - "version": "v1.10.2", + "version": "v1.10.3", "source": { "type": "git", "url": "https://github.com/phpspec/prophecy.git", - "reference": "b4400efc9d206e83138e2bb97ed7f5b14b831cd9" + "reference": "451c3cd1418cf640de218914901e51b064abb093" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/phpspec/prophecy/zipball/b4400efc9d206e83138e2bb97ed7f5b14b831cd9", - "reference": "b4400efc9d206e83138e2bb97ed7f5b14b831cd9", + "url": "https://api.github.com/repos/phpspec/prophecy/zipball/451c3cd1418cf640de218914901e51b064abb093", + "reference": "451c3cd1418cf640de218914901e51b064abb093", "shasum": "" }, "require": { @@ -1215,7 +1347,7 @@ "spy", "stub" ], - "time": "2020-01-20T15:57:02+00:00" + "time": "2020-03-05T15:02:03+00:00" }, { "name": "phpunit/php-code-coverage", @@ -1537,8 +1669,8 @@ "authors": [ { "name": "Sebastian Bergmann", - "email": "sebastian@phpunit.de", - "role": "lead" + "role": "lead", + "email": "sebastian@phpunit.de" } ], "description": "The PHP Unit Testing framework.", @@ -2171,16 +2303,16 @@ }, { "name": "squizlabs/php_codesniffer", - "version": "3.5.4", + "version": "3.5.5", "source": { "type": "git", "url": "https://github.com/squizlabs/PHP_CodeSniffer.git", - "reference": "dceec07328401de6211037abbb18bda423677e26" + "reference": "73e2e7f57d958e7228fce50dc0c61f58f017f9f6" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/dceec07328401de6211037abbb18bda423677e26", - "reference": "dceec07328401de6211037abbb18bda423677e26", + "url": "https://api.github.com/repos/squizlabs/PHP_CodeSniffer/zipball/73e2e7f57d958e7228fce50dc0c61f58f017f9f6", + "reference": "73e2e7f57d958e7228fce50dc0c61f58f017f9f6", "shasum": "" }, "require": { @@ -2218,7 +2350,7 @@ "phpcs", "standards" ], - "time": "2020-01-30T22:20:29+00:00" + "time": "2020-04-17T01:09:41+00:00" }, { "name": "theseer/tokenizer", @@ -2262,16 +2394,16 @@ }, { "name": "webmozart/assert", - "version": "1.7.0", + "version": "1.9.0", "source": { "type": "git", "url": "https://github.com/webmozart/assert.git", - "reference": "aed98a490f9a8f78468232db345ab9cf606cf598" + "reference": "9dc4f203e36f2b486149058bade43c851dd97451" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/webmozart/assert/zipball/aed98a490f9a8f78468232db345ab9cf606cf598", - "reference": "aed98a490f9a8f78468232db345ab9cf606cf598", + "url": "https://api.github.com/repos/webmozart/assert/zipball/9dc4f203e36f2b486149058bade43c851dd97451", + "reference": "9dc4f203e36f2b486149058bade43c851dd97451", "shasum": "" }, "require": { @@ -2279,7 +2411,8 @@ "symfony/polyfill-ctype": "^1.8" }, "conflict": { - "vimeo/psalm": "<3.6.0" + "phpstan/phpstan": "<0.12.20", + "vimeo/psalm": "<3.9.1" }, "require-dev": { "phpunit/phpunit": "^4.8.36 || ^7.5.13" @@ -2306,7 +2439,7 @@ "check", "validate" ], - "time": "2020-02-14T12:15:55+00:00" + "time": "2020-06-16T10:16:42+00:00" } ], "aliases": [], @@ -2315,7 +2448,8 @@ "prefer-stable": false, "prefer-lowest": false, "platform": { - "php": "~7.1.3||~7.2.0||~7.3.0" + "php": "~7.2.29||~7.3.0||~7.4.0" }, - "platform-dev": [] + "platform-dev": [], + "plugin-api-version": "1.1.0" } diff --git a/src/Analyzer/ClassAnalyzer.php b/src/Analyzer/ClassAnalyzer.php index 51b4b8a2..c74dfa75 100644 --- a/src/Analyzer/ClassAnalyzer.php +++ b/src/Analyzer/ClassAnalyzer.php @@ -34,7 +34,7 @@ class ClassAnalyzer extends AbstractCodeAnalyzer */ protected function getNodeName($node) { - return $node->name; + return $node->name->toString(); } /** diff --git a/src/Analyzer/ClassConstantAnalyzer.php b/src/Analyzer/ClassConstantAnalyzer.php index 94f4c097..6d2bd9a8 100644 --- a/src/Analyzer/ClassConstantAnalyzer.php +++ b/src/Analyzer/ClassConstantAnalyzer.php @@ -39,7 +39,7 @@ class ClassConstantAnalyzer extends AbstractCodeAnalyzer */ protected function getNodeName($constant) { - return $constant->consts[0]->name; + return $constant->consts[0]->name->toString(); } /** diff --git a/src/Analyzer/ClassExtendsAnalyzer.php b/src/Analyzer/ClassExtendsAnalyzer.php index daa95506..110c6513 100644 --- a/src/Analyzer/ClassExtendsAnalyzer.php +++ b/src/Analyzer/ClassExtendsAnalyzer.php @@ -31,7 +31,7 @@ class ClassExtendsAnalyzer extends AbstractCodeAnalyzer */ protected function getNodeName($node) { - return $node->name; + return $node->name->toString(); } /** diff --git a/src/Analyzer/ClassImplementsAnalyzer.php b/src/Analyzer/ClassImplementsAnalyzer.php index 307516d0..8bdc1fa8 100644 --- a/src/Analyzer/ClassImplementsAnalyzer.php +++ b/src/Analyzer/ClassImplementsAnalyzer.php @@ -32,7 +32,7 @@ class ClassImplementsAnalyzer extends AbstractCodeAnalyzer */ protected function getNodeName($node) { - return $node->name; + return $node->name->toString(); } /** diff --git a/src/Analyzer/ClassMethodAnalyzer.php b/src/Analyzer/ClassMethodAnalyzer.php index f3c04a5a..7fdc0a7a 100644 --- a/src/Analyzer/ClassMethodAnalyzer.php +++ b/src/Analyzer/ClassMethodAnalyzer.php @@ -90,7 +90,7 @@ class ClassMethodAnalyzer extends AbstractCodeAnalyzer */ protected function getNodeName($method) { - return $method->name; + return $method->name->toString(); } /** @@ -125,7 +125,7 @@ protected function reportAddedNode($report, $fileAfter, $classAfter, $methodAfte foreach ($class->getExtends() as $entity) { $methods = $entity->getMethodList(); // checks if the method is already exiting in parent class - if (isset($methods[$methodAfter->name])) { + if (isset($methods[$methodAfter->name->toString()])) { $report->add( $this->context, new ClassMethodOverwriteAdded($this->context, $fileAfter, $classAfter, $methodAfter) @@ -252,7 +252,7 @@ protected function reportChanged($report, $contextBefore, $contextAfter, $method if (!$signatureChanged && $beforeCount > $afterCount) { $remainingBefore = array_slice($paramsBefore, $minCount); if ($sameVarNames) { - if (strtolower($methodBefore->name) === "__construct") { + if (strtolower($methodBefore->name->toString()) === "__construct") { $data = new ClassConstructorLastParameterRemoved( $this->context, $this->fileAfter, @@ -283,7 +283,7 @@ protected function reportChanged($report, $contextBefore, $contextAfter, $method if (!$signatureChanged && $beforeCount < $afterCount) { $remainingAfter = array_slice($paramsAfter, $minCount); - if (strtolower($methodBefore->name) === '__construct') { + if (strtolower($methodBefore->name->toString()) === '__construct') { $data = $this->analyzeRemainingConstructorParams($contextAfter, $methodAfter, $remainingAfter); } else { $data = $this->analyzeRemainingMethodParams($contextAfter, $methodAfter, $remainingAfter); diff --git a/src/Analyzer/ClassMethodExceptionAnalyzer.php b/src/Analyzer/ClassMethodExceptionAnalyzer.php index cf93ff4f..8fe08d25 100644 --- a/src/Analyzer/ClassMethodExceptionAnalyzer.php +++ b/src/Analyzer/ClassMethodExceptionAnalyzer.php @@ -48,7 +48,7 @@ class ClassMethodExceptionAnalyzer extends AbstractCodeAnalyzer */ protected function getNodeName($node) { - return $node->name; + return $node->name->toString(); } /** diff --git a/src/Analyzer/ClassTraitAnalyzer.php b/src/Analyzer/ClassTraitAnalyzer.php index 89d119ab..ce008afe 100644 --- a/src/Analyzer/ClassTraitAnalyzer.php +++ b/src/Analyzer/ClassTraitAnalyzer.php @@ -32,7 +32,7 @@ class ClassTraitAnalyzer extends AbstractCodeAnalyzer */ protected function getNodeName($node) { - return $node->name; + return $node->name->toString(); } /** diff --git a/src/Analyzer/InterfaceAnalyzer.php b/src/Analyzer/InterfaceAnalyzer.php index 165ef39f..718822c8 100644 --- a/src/Analyzer/InterfaceAnalyzer.php +++ b/src/Analyzer/InterfaceAnalyzer.php @@ -34,7 +34,7 @@ class InterfaceAnalyzer extends AbstractCodeAnalyzer */ protected function getNodeName($node) { - return $node->name; + return $node->name->toString(); } /** diff --git a/src/Analyzer/InterfaceExtendsAnalyzer.php b/src/Analyzer/InterfaceExtendsAnalyzer.php index 2ba6a946..206d9381 100644 --- a/src/Analyzer/InterfaceExtendsAnalyzer.php +++ b/src/Analyzer/InterfaceExtendsAnalyzer.php @@ -32,7 +32,7 @@ class InterfaceExtendsAnalyzer extends AbstractCodeAnalyzer */ protected function getNodeName($node) { - return $node->name; + return $node->name->toString(); } /** diff --git a/src/Analyzer/MethodDocBlockAnalyzer.php b/src/Analyzer/MethodDocBlockAnalyzer.php index a24d0155..58b599dc 100644 --- a/src/Analyzer/MethodDocBlockAnalyzer.php +++ b/src/Analyzer/MethodDocBlockAnalyzer.php @@ -15,6 +15,8 @@ use Magento\SemanticVersionChecker\Operation\DocblockAnnotations\ClassMethodReturnTypeMovedFromInlineToDoc; use Magento\SemanticVersionChecker\Operation\DocblockAnnotations\ClassMethodVariableTypeMovedFromDocToInline; use Magento\SemanticVersionChecker\Operation\DocblockAnnotations\ClassMethodVariableTypeMovedFromInlineToDoc; +use PhpParser\Node\Identifier; +use PhpParser\Node\Name\FullyQualified; use PhpParser\Node\Stmt\ClassLike; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Param; @@ -119,18 +121,8 @@ public function analyzeTypeHintMovementsBetweenDocAndMethod( $docParamTypesRemoved = array_diff($docParamTypesBefore, $docParamTypesAfter) ?? ['']; //check return type - $inlineReturnTypeBefore[] = $methodBefore->returnType ?? ''; - if (is_object($inlineReturnTypeBefore[0]) && property_exists($inlineReturnTypeBefore[0], 'parts')) { - $inlineReturnTypeBefore[0] = end($inlineReturnTypeBefore[0]->parts); - } elseif (is_object($inlineReturnTypeBefore[0]) && property_exists($inlineReturnTypeBefore[0], 'type')) { - $inlineReturnTypeBefore[0] = $inlineReturnTypeBefore[0]->type; - } - $inlineReturnTypeAfter[] = $methodAfter->returnType ?? ''; - if (is_object($inlineReturnTypeAfter[0]) && property_exists($inlineReturnTypeAfter[0], 'parts')) { - $inlineReturnTypeAfter[0] = end($inlineReturnTypeAfter[0]->parts); - } elseif (is_object($inlineReturnTypeAfter[0]) && property_exists($inlineReturnTypeAfter[0], 'type')) { - $inlineReturnTypeAfter[0] = $inlineReturnTypeAfter[0]->type; - } + $inlineReturnTypeBefore[] = $this->getTypeName($methodBefore->returnType); + $inlineReturnTypeAfter[] = $this->getTypeName($methodAfter->returnType); $docReturnTypeBefore = $this->getMethodDocDeclarationByTag($methodBefore, self::DOC_RETURN_TAG) ?? ['']; $docReturnTypeAfter = $this->getMethodDocDeclarationByTag($methodAfter, self::DOC_RETURN_TAG) ?? ['']; $returnTypeMovedFromInlineToDoc = false; @@ -207,15 +199,35 @@ private function getParamTypes(array $params): array $formattedParams = []; /** @var Param $param */ foreach ($params as $param) { - $paramType = $param->type; - if (!empty($paramType) && is_object($paramType)) { - $paramParts = property_exists($paramType, 'parts') ? $paramType->parts : []; - $formattedParams['$' . $param->name] = end($paramParts); - } elseif (!empty($paramType)) { - $formattedParams['$' . $param->name] = $paramType; + $paramType = $this->getTypeName($param->type); + if (!empty($paramType)) { + $formattedParams['$' . $param->var->name] = $paramType; } } return $formattedParams ?? ['']; } + + /** + * Resolve given type to name + * + * @param FullyQualified|Identifier|null $type + * + * @return string + */ + private function getTypeName($type) + { + $typeClass = (is_null($type)) ? '' : get_class($type); + switch ($typeClass) { + case FullyQualified::class: + $returnType = $type->getLast(); + break; + case Identifier::class: + $returnType = $type->toString(); + break; + default: + $returnType = ''; + } + return $returnType; + } } diff --git a/src/Analyzer/PropertyAnalyzer.php b/src/Analyzer/PropertyAnalyzer.php index e68a2a4d..4baba484 100644 --- a/src/Analyzer/PropertyAnalyzer.php +++ b/src/Analyzer/PropertyAnalyzer.php @@ -38,7 +38,7 @@ class PropertyAnalyzer extends AbstractCodeAnalyzer */ protected function getNodeName($property) { - return $property->props[0]->name; + return $property->props[0]->name->toString(); } /** diff --git a/src/Analyzer/TraitAnalyzer.php b/src/Analyzer/TraitAnalyzer.php index 084996a7..d21bb0ac 100644 --- a/src/Analyzer/TraitAnalyzer.php +++ b/src/Analyzer/TraitAnalyzer.php @@ -29,7 +29,7 @@ class TraitAnalyzer extends AbstractCodeAnalyzer */ protected function getNodeName($node) { - return $node->name; + return $node->name->toString(); } /** diff --git a/src/ClassHierarchy/DependencyInspectionVisitor.php b/src/ClassHierarchy/DependencyInspectionVisitor.php index 9a6c9ffe..48f8be92 100644 --- a/src/ClassHierarchy/DependencyInspectionVisitor.php +++ b/src/ClassHierarchy/DependencyInspectionVisitor.php @@ -15,8 +15,10 @@ use PhpParser\Node\Stmt\ClassLike; use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Interface_ as InterfaceNode; -use PhpParser\Node\Stmt\Property; +use PhpParser\Node\Stmt\PropertyProperty; use PhpParser\Node\Stmt\Trait_ as TraitNode; +use PhpParser\Node\Stmt\TraitUse; +use PhpParser\NodeTraverser; use PhpParser\NodeVisitorAbstract; /** @@ -24,12 +26,20 @@ */ class DependencyInspectionVisitor extends NodeVisitorAbstract { + /** @var DependencyGraph */ private $dependencyGraph; /** @var NodeHelper */ private $nodeHelper; + /** + * @var Entity + * Holds current Entity. Stored so we can populate this entity in our dependency graph upon walking relevant child + * nodes. + */ + private $currentClassLike = null; + /** * Constructor. * @@ -43,135 +53,115 @@ public function __construct(DependencyGraph $dependencyGraph, NodeHelper $nodeHe } /** - * @inheritDoc + * Logic to process current node. We aggressively halt walking the AST since this may contain many nodes + * If we are visiting a Classlike node, set currentClassLike so we can populate this entity in our dependency graph + * upon walking relevant child nodes like PropertyProperty and ClassMethod. * - * Inspect nodes after all visitors have run since we need the fully qualified names of nodes. - */ - public function leaveNode(Node $node) - { - if ($node instanceof ClassNode) { - $this->addClassNode($node); - } elseif ($node instanceof InterfaceNode) { - $this->addInterfaceNode($node); - } elseif ($node instanceof TraitNode) { - $this->addTraitNode($node); - } - } - - /** - * Getter for {@link DependencyInspectionVisitor::$dependencyGraph}. + * Subparse tree we want to traverse will be something like: + * Namespace -> ClassLike -> ClassMethod + * -> TraitUse + * -> PropertyProperty * - * @return DependencyGraph - */ - public function getDependencyGraph(): DependencyGraph - { - return $this->dependencyGraph; - } - - /** - * @param ClassNode $node + * + * @inheritdoc + * + * @param Node $node + * @return int tells NodeTraverser whether to continue traversing */ - private function addClassNode(ClassNode $node) + public function enterNode(Node $node) { - // name is not set for anonymous classes, therefore they cannot be part of the dependency graph - if ($node->isAnonymous()) { - return; - } - - $className = (string)$node->namespacedName; - $class = $this->dependencyGraph->findOrCreateClass($className); - - [$methodList, $propertyList] = $this->fetchStmtsNodes($node); - $class->setMethodList($methodList); - $class->setPropertyList($propertyList); - $class->setIsApi($this->nodeHelper->isApiNode($node)); - - if ($node->extends) { - $parentClassName = (string)$node->extends; - $parentClassEntity = $this->dependencyGraph->findOrCreateClass($parentClassName); - $class->addExtends($parentClassEntity); - } - - foreach ($node->implements as $implement) { - $interfaceName = (string)$implement; - $interfaceEntity = $this->dependencyGraph->findOrCreateInterface($interfaceName); - $class->addImplements($interfaceEntity); - } - - foreach ($this->nodeHelper->getTraitUses($node) as $traitUse) { - foreach ($traitUse->traits as $trait) { - $traitName = (string)$trait; - $traitEntity = $this->dependencyGraph->findOrCreateTrait($traitName); - $class->addUses($traitEntity); - } + switch (true) { + case $node instanceof Node\Stmt\Namespace_: + return null; + case $node instanceof ClassLike: + //set currentClassLike entity + return $this->handleClassLike($node); + case $node instanceof ClassMethod: + $this->currentClassLike->addMethod($node); + return NodeTraverser::DONT_TRAVERSE_CHILDREN; + case $node instanceof TraitUse: + foreach ($node->traits as $trait) { + $traitName = (string)$trait; + $traitEntity = $this->dependencyGraph->findOrCreateTrait($traitName); + $this->currentClassLike->addUses($traitEntity); + } + return NodeTraverser::DONT_TRAVERSE_CHILDREN; + case $node instanceof PropertyProperty: + $this->currentClassLike->addProperty($node); + return NodeTraverser::DONT_TRAVERSE_CHILDREN; + default: + return NodeTraverser::DONT_TRAVERSE_CHILDREN; } - - $this->dependencyGraph->addEntity($class); } /** - * @param InterfaceNode $node + * Handles Class, Interface, and Traits nodes. Sets currentClassLike entity and will populate extends, implements, + * and API information + * + * @param ClassLike $node + * @return int|null */ - private function addInterfaceNode(InterfaceNode $node) + private function handleClassLike(ClassLike $node) { - $interfaceName = (string)$node->namespacedName; - $interface = $this->dependencyGraph->findOrCreateInterface($interfaceName); - - $interface->setIsApi($this->nodeHelper->isApiNode($node)); - [$methodList] = $this->fetchStmtsNodes($node); - $interface->setMethodList($methodList); - - foreach ($node->extends as $extend) { - $interfaceName = (string)$extend; - $interfaceEntity = $this->dependencyGraph->findOrCreateInterface($interfaceName); - $interface->addExtends($interfaceEntity); + /** + * @var \PhpParser\Node\Name $namespacedName + * This is set in the NamespaceResolver visitor + */ + $namespacedName = $node->namespacedName; + switch (true) { + case $node instanceof ClassNode: + if ($node->isAnonymous()) { + return NodeTraverser::STOP_TRAVERSAL; + } + $this->currentClassLike = $this->dependencyGraph->findOrCreateClass((string)$namespacedName); + if ($node->extends) { + $parentClassName = (string)$node->extends; + $parentClassEntity = $this->dependencyGraph->findOrCreateClass($parentClassName); + $this->currentClassLike->addExtends($parentClassEntity); + } + foreach ($node->implements as $implement) { + $interfaceName = (string)$implement; + $interfaceEntity = $this->dependencyGraph->findOrCreateInterface($interfaceName); + $this->currentClassLike->addImplements($interfaceEntity); + } + break; + case $node instanceof InterfaceNode: + $this->currentClassLike = $this->dependencyGraph->findOrCreateInterface((string)$namespacedName); + foreach ($node->extends as $extend) { + $interfaceName = (string)$extend; + $interfaceEntity = $this->dependencyGraph->findOrCreateInterface($interfaceName); + $this->currentClassLike->addExtends($interfaceEntity); + } + break; + case $node instanceof TraitNode: + $this->currentClassLike = $this->dependencyGraph->findOrCreateTrait((string)$namespacedName); + break; } - - $this->dependencyGraph->addEntity($interface); + $this->currentClassLike->setIsApi($this->nodeHelper->isApiNode($node)); + return null; } - /** - * @param TraitNode $node + /* + * Unsets currentClassLike upon exiting ClassLike node. This is for cleanup, although this is not necessary since + * Classmethod, PropertyProperty, and TraitUse nodes will only be traversed after Classlike + * + * @param Node $node + * @return false|int|Node|Node[]|void|null */ - private function addTraitNode(TraitNode $node) + public function leaveNode(Node $node) { - $traitName = (string)$node->namespacedName; - $trait = $this->dependencyGraph->findOrCreateTrait($traitName); - - [$methodList, $propertyList] = $this->fetchStmtsNodes($node); - $trait->setMethodList($methodList); - $trait->setPropertyList($propertyList); - $trait->setIsApi($this->nodeHelper->isApiNode($node)); - - foreach ($this->nodeHelper->getTraitUses($node) as $traitUse) { - foreach ($traitUse->traits as $parentTrait) { - $parentTraitName = (string)$parentTrait; - $parentTraitEntity = $this->dependencyGraph->findOrCreateTrait($parentTraitName); - $trait->addUses($parentTraitEntity); - } + if ($node instanceof ClassLike) { + $this->currentClassLike = null; } - - $this->dependencyGraph->addEntity($trait); } /** - * @param ClassLike $node - * @return array + * Getter for {@link DependencyInspectionVisitor::$dependencyGraph}. + * + * @return DependencyGraph */ - private function fetchStmtsNodes(ClassLike $node): array + public function getDependencyGraph(): DependencyGraph { - $methodList = []; - $propertyList = []; - foreach ($node->stmts as $stmt) { - if ($stmt instanceof ClassMethod) { - $methodList[$stmt->name] = $stmt; - } elseif ($stmt instanceof Property) { - foreach ($stmt->props as $prop) { - $propertyList[$prop->name] = $prop; - } - } - } - - return [$methodList, $propertyList]; + return $this->dependencyGraph; } } diff --git a/src/ClassHierarchy/Entity.php b/src/ClassHierarchy/Entity.php index 53c1e517..43908545 100644 --- a/src/ClassHierarchy/Entity.php +++ b/src/ClassHierarchy/Entity.php @@ -11,6 +11,7 @@ use PhpParser\Node\Stmt\ClassMethod; use PhpParser\Node\Stmt\Property; +use PhpParser\Node\Stmt\PropertyProperty; /** * Implements an entity that reflects a `class`, `interface` or `trait` and its dependencies. @@ -368,7 +369,29 @@ private function addUsedBy(Entity $entity) */ public function setMethodList(array $methodList): void { - $this->methodList = $methodList; + $this->methodList = []; + foreach ($methodList as $method) { + $this->addMethod($method); + } + } + + /** + * Also cleans method to prevent memory leaks. + * @param ClassMethod $method + */ + public function addMethod(ClassMethod $method): void + { + //remove stmts from Method + $method->stmts = []; + $this->methodList[$method->name->toString()] = $method; + } + + /** + * @param PropertyProperty $property + */ + public function addProperty(PropertyProperty $property): void + { + $this->propertyList[$property->name] = $property; } /** @@ -376,7 +399,10 @@ public function setMethodList(array $methodList): void */ public function setPropertyList(array $propertyList): void { - $this->propertyList = $propertyList; + $this->propertyList = []; + foreach ($propertyList as $property) { + $this->addProperty($property); + } } /** diff --git a/src/Comparator/Signature.php b/src/Comparator/Signature.php index 7170db7c..b65131c9 100644 --- a/src/Comparator/Signature.php +++ b/src/Comparator/Signature.php @@ -55,7 +55,7 @@ public static function isOptionalParams(array $params) public static function isObjectParams(array $params) { foreach ($params as $param) { - if (is_object($param->type)) { + if ($param->type instanceof \PhpParser\Node\Name\FullyQualified) { return true; } } diff --git a/src/Helper/ClassParser.php b/src/Helper/ClassParser.php index 426b12d1..b115ba26 100644 --- a/src/Helper/ClassParser.php +++ b/src/Helper/ClassParser.php @@ -96,7 +96,7 @@ public function getParentFullClassName() } foreach ($nodeTree->stmts as $stmt) { - if ($stmt instanceof Use_ && $stmt->uses[0]->alias === $extendedClass) { + if ($stmt instanceof Use_ && $stmt->uses[0]->getAlias()->toString() === $extendedClass) { return implode("\\", $stmt->uses[0]->name->parts); } } @@ -262,7 +262,7 @@ public function getImplementedInterfacesNames() $namespace = $nodeTree->name->toString(); foreach ($nodeTree->stmts as $stmt) { if ($stmt instanceof Use_) { - $uses[$stmt->uses[0]->alias] = $stmt->uses[0]; + $uses[$stmt->uses[0]->getAlias()->toString()] = $stmt->uses[0]; } } @@ -310,9 +310,9 @@ public function getFullyQualifiedName(string $alias): string //is the class, interface, trait defined in the very same file? if ( $stmt instanceof ClassLike - && $stmt->name === $alias + && $stmt->name->toString() === $alias ) { - return $nodeTree->name->toString() . '\\' . $stmt->name; + return $nodeTree->name->toString() . '\\' . $stmt->name->toString(); } //is the class being imported? @@ -320,7 +320,7 @@ public function getFullyQualifiedName(string $alias): string foreach ($stmt->uses as $useUseStmnt) { $fullyQualifiedName = $useUseStmnt->name->toString(); - if ($useUseStmnt->alias === $alias || $fullyQualifiedName === $alias) { + if ($useUseStmnt->getAlias()->toString() === $alias || $fullyQualifiedName === $alias) { return $fullyQualifiedName; } } diff --git a/src/Helper/Node.php b/src/Helper/Node.php index f2a827e5..555841ba 100644 --- a/src/Helper/Node.php +++ b/src/Helper/Node.php @@ -31,29 +31,4 @@ public function isApiNode(PhpNode $node) return isset($comment[0]) && strpos($comment[0]->getText(), SemanticVersionChecker::ANNOTATION_API) !== false; } - - /** - * Workaround for different versions of `nikic/php-parser`. - * - * Later versions of the package `nikic/php-parser` add the convenience method `ClassLike::getTraitUses()`. If we - * happen to have such a version, that method is called and its result is returned, otherwise we extract the - * {@link \PhpParser\Node\Stmt\TraitUse} and return them. - * - * @param PhpNode $node - * @return TraitUse[] - */ - public function getTraitUses(PhpNode $node): array - { - if (method_exists($node, 'getTraitUses')) { - return $node->getTraitUses(); - } - - $traitUses = []; - foreach ($node->stmts as $stmt) { - if ($stmt instanceof TraitUse) { - $traitUses[] = $stmt; - } - } - return $traitUses; - } } diff --git a/src/Node/Statement/ClassConstant.php b/src/Node/Statement/ClassConstant.php index a3e49538..30a7a13c 100644 --- a/src/Node/Statement/ClassConstant.php +++ b/src/Node/Statement/ClassConstant.php @@ -23,11 +23,11 @@ class ClassConstant extends BaseClassConstant */ public static function getFullyQualifiedName(Stmt $context, BaseClassConstant $constant) { - $fqcn = $context->name; + $fqcn = $context->name->toString(); if ($context->namespacedName) { $fqcn = $context->namespacedName->toString(); } - return $fqcn . '::' . $constant->consts[0]->name; + return $fqcn . '::' . $constant->consts[0]->name->toString(); } } diff --git a/src/Operation/WhiteListWasRemoved.php b/src/Operation/WhiteListWasRemoved.php index 51bc567f..1670d951 100644 --- a/src/Operation/WhiteListWasRemoved.php +++ b/src/Operation/WhiteListWasRemoved.php @@ -29,7 +29,7 @@ class WhiteListWasRemoved extends Operation * * @var int */ - protected $level = Level::MINOR; + protected $level = Level::MAJOR; /** * Operation message diff --git a/src/ReportBuilder.php b/src/ReportBuilder.php index 3e7f93d9..6b3d55be 100644 --- a/src/ReportBuilder.php +++ b/src/ReportBuilder.php @@ -141,8 +141,14 @@ protected function buildReport() $sourceBeforeFiles = $fileIterator->findFromString($this->sourceBeforeDir, '', ''); $sourceAfterFiles = $fileIterator->findFromString($this->sourceAfterDir, '', ''); - //let static analyzer build a complete dependency graph + $staticAnalyzer = (new StaticAnalyzerFactory())->create(); + + /** + * Run dependency analysis over entire codebase. Necessary as we should parse parents and siblings of unchanged + * files. + */ + //MC-31705: Dependency graph get overwritten twice here. Document or fix this $staticAnalyzer->analyse($sourceBeforeFiles); $dependencyMap = $staticAnalyzer->analyse($sourceAfterFiles); @@ -151,6 +157,9 @@ protected function buildReport() $scannerBefore = new ScannerRegistry($scannerRegistryFactory->create($dependencyMap)); $scannerAfter = new ScannerRegistry($scannerRegistryFactory->create($dependencyMap)); + /** + * Filter unchanged files. (All json files will remain because of filter) + */ foreach ($this->getFilters($this->sourceBeforeDir, $this->sourceAfterDir) as $filter) { // filters modify arrays by reference $filter->filter($sourceBeforeFiles, $sourceAfterFiles); diff --git a/src/Visitor/AbstractApiVisitor.php b/src/Visitor/AbstractApiVisitor.php index 8f789f36..2d66e2be 100644 --- a/src/Visitor/AbstractApiVisitor.php +++ b/src/Visitor/AbstractApiVisitor.php @@ -10,6 +10,7 @@ use Magento\SemanticVersionChecker\ClassHierarchy\DependencyGraph; use Magento\SemanticVersionChecker\Helper\Node as NodeHelper; use PhpParser\Node; +use PhpParser\NodeTraverser; use PhpParser\NodeVisitorAbstract; use PHPSemVerChecker\Registry\Registry; @@ -43,8 +44,33 @@ public function __construct( } /** + * Halt walking when we reach Classlike node * @param Node $node - * @return void + * @return int + */ + public function enterNode(Node $node) + { + switch (true) { + case $node instanceof Node\Stmt\Namespace_: + case $node instanceof Node\Stmt\ClassLike: + return null; + default: + /* + * Note that by skipping traversal of ClassMethod children, NameResolver will not resolve namespaces on + * its method stmts. This will affect analyzing for ClassMethodImplementationChanged in + * src/Analyzer/ClassMethodAnalyzer.php + * For example changing: + * a = \Magento\Framework\App\ObjectManager::getInstance(); + * To: + * a = ObjectManager::getInstance(); + * will now be analyzed as a ClassMethodImplementationChanged (a PATCH change). + */ + return NodeTraverser::DONT_TRAVERSE_CHILDREN; + } + } + + /** + * @inheritdoc */ public function leaveNode(Node $node) { diff --git a/tests/Unit/Console/Command/CompareSourceCommandDatabaseSchemasTest.php b/tests/Unit/Console/Command/CompareSourceCommandDatabaseSchemasTest.php index 362a4db4..3633a212 100644 --- a/tests/Unit/Console/Command/CompareSourceCommandDatabaseSchemasTest.php +++ b/tests/Unit/Console/Command/CompareSourceCommandDatabaseSchemasTest.php @@ -215,10 +215,10 @@ public function changesDataProvider() $pathToFixtures . '/whitelist-was-removed/source-code-before', $pathToFixtures . '/whitelist-was-removed/source-code-after', [ - '/Database \(MINOR\)/', + '/Database \(MAJOR\)/', '/Magento_DbSchema\s*\|\s*Db Whitelist from module Magento_DbSchema was removed\s*\|\s*M109/' ], - 'Minor change is detected.' + 'Major change is detected.' ] ]; } diff --git a/tests/Unit/Helper/ClassParserTest.php b/tests/Unit/Helper/ClassParserTest.php new file mode 100644 index 00000000..2906b8c3 --- /dev/null +++ b/tests/Unit/Helper/ClassParserTest.php @@ -0,0 +1,46 @@ +assertEquals('Test\VcsA\ClassA', $parser->getParentFullClassName()); + } + + public function testExtendsFull() + { + $path = __DIR__ . '/_files/ClassExtendFull.php'; + $parser = new ClassParser($path); + $this->assertEquals('Test\VcsA\ClassA', $parser->getParentFullClassName()); + } + + public function testImplementsAlias() + { + $path = __DIR__ . '/_files/ClassExtendAlias.php'; + $parser = new ClassParser($path); + $result = $parser->getImplementedInterfacesNames(); + $this->assertCount(1, $result); + $this->assertArraySubset(['Test\VcsA\A\InterfaceA'], $parser->getImplementedInterfacesNames()); + } + + public function testImplementsFull() + { + $path = __DIR__ . '/_files/ClassExtendFull.php'; + $parser = new ClassParser($path); + $result = $parser->getImplementedInterfacesNames(); + $this->assertCount(1, $result); + $this->assertArraySubset(['Test\VcsA\A\InterfaceA'], $parser->getImplementedInterfacesNames()); + } +} diff --git a/tests/Unit/Helper/_files/ClassA.php b/tests/Unit/Helper/_files/ClassA.php new file mode 100644 index 00000000..e7451c0c --- /dev/null +++ b/tests/Unit/Helper/_files/ClassA.php @@ -0,0 +1,8 @@ +