[CI] Downgrade Rector to PHP 7.1 + prefix it (#5880)

* [downgrade] simplify to 2 configs

* rename downgrade_packages.sh to downgrade_rector_to_php71.sh

* add test case stub

* [CI] add linter for php code

* [CI] update tagged workflow

* update for covariance

* [ci-review] Rector Rectify

Co-authored-by: kaizen-ci <info@kaizen-ci.org>
This commit is contained in:
Tomas Votruba 2021-03-18 02:48:44 +01:00 committed by GitHub
parent 940ed63d54
commit a389839c5c
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
46 changed files with 282 additions and 1087 deletions

View File

@ -2,12 +2,12 @@
name: Build Scoped Rector
on:
pull_request: null
push:
branches:
- main
# to avoid running tagged and non-tagged workflows at the same time
tags-ignore:
tags:
- '*'
jobs:
@ -16,26 +16,67 @@ jobs:
steps:
-
uses: actions/checkout@v2
with:
fetch-depth: 0
-
uses: shivammathur/setup-php@v2
with:
php-version: 7.3
coverage: none
# fixes https://github.com/rectorphp/rector/pull/4559/checks?check_run_id=1359814403, see https://github.com/shivammathur/setup-php#composer-github-oauth
env:
COMPOSER_TOKEN: ${{ secrets.ACCESS_TOKEN }}
# 1. prepare dependencies
- run: sh build/build-rector-scoped.sh
# install only prod dependencies - do not use ramsey, it uses cache including "dev", we want to avoid it here
- run: composer install --no-dev --ansi
# 2. publish it to remote repository
# 1. copy files to $NESTED_DIRECTORY directory Exclude the scoped/nested directories to prevent rsync from copying in a loop
- run: rsync --exclude rector-build -av * rector-build --quiet
- run: rm -rf rector-build/packages-tests rector-build/rules-tests rector-build/tests
# 2. downgrade rector
- run: sh build/downgrade-rector.sh rector-build
# 3. prefix classes
- run: sh build/build-rector-scoped.sh rector-build rector-prefixed-downgraded
# 4. lint the code for PHP 7.1 - this must happen here, as setup-php allows only one PHP version switch: https://github.com/shivammathur/setup-php/issues/434
-
uses: shivammathur/setup-php@v2
with:
php-version: 7.1
coverage: none
- run: composer create-project php-parallel-lint/php-parallel-lint php-parallel-lint --ansi
- run: php-parallel-lint/parallel-lint rector-prefixed-downgraded --exclude rector-prefixed-downgraded/stubs --exclude rector-prefixed-downgraded/vendor/symfony/polyfill-intl-grapheme/bootstrap80.php --exclude rector-prefixed-downgraded/vendor/symfony/polyfill-intl-normalizer/bootstrap80.php --exclude rector-prefixed-downgraded/vendor/symfony/polyfill-mbstring/bootstrap80.php --exclude rector-prefixed-downgraded/vendor/symfony/error-handler/Resources --exclude rector-prefixed-downgraded/vendor/symfony/http-kernel/Resources --exclude rector-prefixed-downgraded/vendor/symfony/polyfill/src/Mbstring/bootstrap80.php --exclude rector-prefixed-downgraded/vendor/symfony/polyfill/src/Apcu/bootstrap80.php --exclude rector-prefixed-downgraded/vendor/symfony/polyfill/src/Iconv/bootstrap80.php --exclude rector-prefixed-downgraded/vendor/symfony/polyfill/src/Intl/Idn/bootstrap80.php --exclude rector-prefixed-downgraded/vendor/symfony/polyfill/src/Intl/Normalizer/bootstrap80.php --exclude rector-prefixed-downgraded/vendor/symfony/polyfill/src/Intl/Grapheme/bootstrap80.php
# 5. copy repository meta files
- run: cp -R build/target-repository/. rector-prefixed-downgraded
# 6. publish it to remote repository without tag
-
uses: symplify/github-action-monorepo-split@1.1
if: "!startsWith(github.ref, 'refs/tags/')"
env:
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
with:
package-directory: 'rector-scoped'
package-directory: 'rector-prefixed-downgraded'
split-repository-organization: 'rectorphp'
split-repository-name: 'rector-prefixed'
user-name: "kaizen-ci"
user-email: "info@kaizen-ci.org"
# 7. publish it to remote repository with tag
-
uses: symplify/github-action-monorepo-split@1.1
if: "startsWith(github.ref, 'refs/tags/')"
env:
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
with:
package-directory: 'rector-prefixed-downgraded'
split-repository-organization: 'rectorphp'
split-repository-name: 'rector-prefixed'
tag: ${GITHUB_REF#refs/tags/}
user-name: "kaizen-ci"
user-email: "info@kaizen-ci.org"

View File

@ -1,48 +0,0 @@
# builds the content of https://github.com/rectorphp/rector-prefixed
name: Build Scoped Rector Tagged
on:
push:
# see https://github.community/t/how-to-run-github-actions-workflow-only-for-new-tags/16075/10?u=tomasvotruba
tags:
- '*'
jobs:
build_scoped_rector_tagged:
runs-on: ubuntu-latest
steps:
-
uses: actions/checkout@v2
# this is required for "WyriHaximus/github-action-get-previous-tag" workflow
# see https://github.com/actions/checkout#fetch-all-history-for-all-tags-and-branches
with:
fetch-depth: 0
-
uses: shivammathur/setup-php@v2
with:
php-version: 7.3
# fixes https://github.com/rectorphp/rector/pull/4559/checks?check_run_id=1359814403, see https://github.com/shivammathur/setup-php#composer-github-oauth
env:
COMPOSER_TOKEN: ${{ secrets.ACCESS_TOKEN }}
# 1. prepare dependencies
- run: sh build/build-rector-scoped.sh
# 2. get tag - see https://github.com/WyriHaximus/github-action-get-previous-tag
-
id: previous_tag
uses: "WyriHaximus/github-action-get-previous-tag@master"
# 3. publish it
-
uses: symplify/github-action-monorepo-split@1.1
env:
GITHUB_TOKEN: ${{ secrets.ACCESS_TOKEN }}
with:
package-directory: 'rector-scoped'
split-repository-organization: 'rectorphp'
split-repository-name: 'rector-prefixed'
tag: ${{ steps.previous_tag.outputs.tag }}
user-name: "kaizen-ci"
user-email: "info@kaizen-ci.org"

2
.gitignore vendored
View File

@ -12,7 +12,9 @@ rector-recipe.php
# testing
abz
# scoped & downgraded version
php-scoper.phar
box.phar
php-parallel-lint
tmp

View File

@ -44,7 +44,6 @@ if (class_exists(Debugger::class)) {
try {
$bootstrapConfigs = $rectorConfigsResolver->provide();
$rectorContainerFactory = new RectorContainerFactory();
$container = $rectorContainerFactory->createFromBootstrapConfigs($bootstrapConfigs);
} catch (SetNotFoundException $setNotFoundException) {

View File

@ -1,5 +1,8 @@
#!/bin/sh -l
# see https://stackoverflow.com/questions/66644233/how-to-propagate-colors-from-bash-script-to-github-action?noredirect=1#comment117811853_66644233
export TERM=xterm-color
# show errors
set -e
@ -19,48 +22,39 @@ note()
# configure here
NESTED_DIRECTORY="rector-nested"
SCOPED_DIRECTORY="rector-scoped"
BUILD_DIRECTORY=$1
RESULT_DIRECTORY=$2
# ---------------------------
note "Starts"
note "Coping root files to $NESTED_DIRECTORY directory"
# Exclude the scoped/nested directories to prevent rsync from copying in a loop
rsync --exclude "$NESTED_DIRECTORY" --exclude "$SCOPED_DIRECTORY" -av * "$NESTED_DIRECTORY" --quiet
note "Running composer update without dev"
composer update --no-dev --no-progress --ansi --working-dir "$NESTED_DIRECTORY"
# this will remove dependency on dev packages that are imported in phpstan.neon
rm -f "$NESTED_DIRECTORY/phpstan-for-rector.neon"
# Avoid Composer v2 platform checks (composer.json requires PHP 7.4+, but below we are running 7.3)
note "Disabling platform check"
composer config platform-check false
rm -f "$BUILD_DIRECTORY/phpstan-for-rector.neon"
# 2. scope it
note "Running scoper to $SCOPED_DIRECTORY"
note "Running scoper to $RESULT_DIRECTORY"
wget https://github.com/humbug/php-scoper/releases/download/0.14.0/php-scoper.phar -N --no-verbose
# Work around possible PHP memory limits
php -d memory_limit=-1 php-scoper.phar add-prefix bin config packages rules src templates vendor composer.json --output-dir "../$SCOPED_DIRECTORY" --config scoper.php --force --ansi --working-dir "$NESTED_DIRECTORY"
php -d memory_limit=-1 php-scoper.phar add-prefix bin config src packages rules vendor composer.json --output-dir "../$RESULT_DIRECTORY" --config scoper.php --force --ansi --working-dir "$BUILD_DIRECTORY"
# add polyfill for downgraded code
composer require symfony/polyfill-php80 symfony/polyfill-php74 symfony/polyfill-php73 symfony/polyfill-php72 --update-no-dev --working-dir $RESULT_DIRECTORY --ansi
note "Dumping Composer Autoload"
composer dump-autoload --working-dir "$SCOPED_DIRECTORY" --ansi --optimize --classmap-authoritative --no-dev
composer dump-autoload --working-dir "$RESULT_DIRECTORY" --ansi --optimize --classmap-authoritative --no-dev
rm -rf "$NESTED_DIRECTORY"
rm -rf "$BUILD_DIRECTORY"
# copy metafiles needed for release
note "Copy metafiles like composer.json, .github etc to repository"
rm -f "$SCOPED_DIRECTORY/composer.json"
cp -R scoped/. "$SCOPED_DIRECTORY"
rm -f "$RESULT_DIRECTORY/composer.json"
# make bin/rector runnable without "php"
chmod 777 "$SCOPED_DIRECTORY/bin/rector"
chmod 777 "$SCOPED_DIRECTORY/bin/rector.php"
chmod 777 "$RESULT_DIRECTORY/bin/rector"
chmod 777 "$RESULT_DIRECTORY/bin/rector.php"
note "Finished"

View File

@ -0,0 +1,64 @@
<?php
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Rector\Core\Stubs\PHPStanStubLoader;
use Rector\Set\ValueObject\DowngradeSetList;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
$phpStanStubLoader = new PHPStanStubLoader();
$phpStanStubLoader->loadStubs();
return static function (ContainerConfigurator $containerConfigurator): void {
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::SKIP, DowngradeRectorConfig::DEPENDENCY_EXCLUDE_PATHS);
$parameters->set(Option::PHPSTAN_FOR_RECTOR_PATH, __DIR__ . '/phpstan-for-downgrade.neon');
$parameters->set(Option::SETS, [
DowngradeSetList::PHP_80,
DowngradeSetList::PHP_74,
DowngradeSetList::PHP_73,
DowngradeSetList::PHP_72,
]);
};
/**
* Configuration consts for the different rector.php config files
*/
final class DowngradeRectorConfig
{
/**
* Exclude paths when downgrading a dependency
*/
public const DEPENDENCY_EXCLUDE_PATHS = [
'*/tests/*',
// symfony test are parts of package
'*/Test/*',
// missing phpunit test case
'packages/Testing/PHPUnit/AbstractCommunityRectorTestCase.php',
'packages/Testing/PHPUnit/AbstractRectorTestCase.php',
// Individual classes that can be excluded because
// they are not used by Rector, and they use classes
// loaded with "require-dev" so it'd throw an error
// use relative paths, so files are excluded on nested directory too
'vendor/symfony/http-kernel/HttpKernelBrowser.php',
'vendor/symfony/string/Slugger/AsciiSlugger.php',
// always excluded
'*vendor/symfony/polyfill*/bootstrap80.php',
// This class has an issue for PHP 7.1:
// https://github.com/rectorphp/rector/issues/4816#issuecomment-743209526
// It doesn't happen often, and Rector doesn't use it, so then
// we simply skip downgrading this class
'vendor/symfony/dependency-injection/ExpressionLanguage.php',
'vendor/symfony/dependency-injection/ExpressionLanguageProvider.php',
'vendor/symfony/var-dumper/Caster/*',
'vendor/symplify/package-builder/src/Testing/AbstractKernelTestCase.php',
];
}

View File

@ -0,0 +1,11 @@
# this config has extensions, that helps PHPStan inside Rector to resolve more precise types
parameters:
inferPrivatePropertyTypeFromConstructor: true
scanDirectories:
# this is needed for symfony/dependendency-injection as it has hidden dependency on symfony/expression-language that we don't use here
- ../../stubs
# see https://github.com/rectorphp/rector/issues/3490#issue-634342324
featureToggles:
disableRuntimeReflectionProvider: true

34
build/downgrade-rector.sh Normal file
View File

@ -0,0 +1,34 @@
#!/bin/sh -l
# see https://stackoverflow.com/questions/66644233/how-to-propagate-colors-from-bash-script-to-github-action?noredirect=1#comment117811853_66644233
export TERM=xterm-color
# show errors
set -e
# script fails if trying to access to an undefined variable
set -u
# configure - 1st argument, use like
# sh build/downgrade-rector.sh <directory-with-code-to-downgrade>
BUILD_DIRECTORY=$1
#---------------------------------------------
# 1. downgrade it
echo "[NOTE] Running downgrade in '$BUILD_DIRECTORY' directory\n";
# 3. provide directories to downgrade; includes the rector dirs
directories=$(php -d memory_limit=-1 bin/rector downgrade-paths 7.1 --config build/config/config-downgrade.php --working-dir $BUILD_DIRECTORY --ansi)
# split array see https://stackoverflow.com/a/1407098/1348344
export IFS=";"
# 4. downgrade the directories
for directory in $directories; do
echo "[NOTE] Downgrading '$directory' directory\n"
# --working-dir is needed, so "SKIP" parameter is applied in absolute path of nested directory
php -d memory_limit=-1 bin/rector process $directory --config build/config/config-downgrade.php --working-dir $BUILD_DIRECTORY --ansi
done

View File

@ -1,371 +0,0 @@
#!/bin/bash
########################################################################
# This bash script downgrades the code to the selected PHP version
#
# Usage from within a GitHub workflow:
# build/downgrade/downgrade_packages.sh $target_php_version
# where $target_php_version is one of the following values:
# - 7.0
# - 7.1
# - 7.2
# - 7.3
# - 7.4
#
# Currently highest PHP version from which we can downgrade:
# - 8.0
#
# Eg: To downgrade to PHP 7.1, execute:
# build/downgrade/downgrade_packages.sh 7.1
########################################################################
# show errors
set -e
########################################################################
# Variables to modify when new PHP versions are released
# ----------------------------------------------------------------------
supported_target_php_versions=(7.0 7.1 7.2 7.3 7.4)
# Rector configs carry the previous downgrade sets starting from php80
# (eg: latest-to-php73 has downgrade sets php80 and php74)
# so even though we're storing all the stages, only the last item must be executed
# (only latest-to-php73, no need for latest-to-php74) or a same downgrade will be executed more than once
# This logic is a bit redundant, but it enables to execute several config files on each package,
# eg: defining the set to execute using `--set` in the CLI (not supported anymore)
GROUP_RECTOR_CONFIGS=true
# Execute a single call to Rector for all dependencies together?
DOWNGRADE_DEPENDENCIES_TOGETHER=true
# If grouping rector configs, analyze if the libraries support
# only the target PHP version
# Otherwise, analyze PHP support starting from the latest PHP version
# (currently 8.0) to the target one, so different libraries can be
# downgraded only for their needed versions, not all of them
declare -A downgrade_php_whynots
declare -A downgrade_php_rectorconfigs
if [ -n "$GROUP_RECTOR_CONFIGS" ]; then
downgrade_php_whynots=( \
["7.0"]="7.0.*" \
["7.1"]="7.1.*" \
["7.2"]="7.2.*" \
["7.3"]="7.3.*" \
["7.4"]="7.4.*" \
)
downgrade_php_rectorconfigs=( \
["7.0"]="latest-to-php70" \
["7.1"]="latest-to-php71" \
["7.2"]="latest-to-php72" \
["7.3"]="latest-to-php73" \
["7.4"]="latest-to-php74" \
)
else
downgrade_php_whynots=( \
["7.0"]="7.4.* 7.3.* 7.2.* 7.1.* 7.0.*" \
["7.1"]="7.4.* 7.3.* 7.2.* 7.1.*" \
["7.2"]="7.4.* 7.3.* 7.2.*" \
["7.3"]="7.4.* 7.3.*" \
["7.4"]="7.4.*" \
)
downgrade_php_rectorconfigs=( \
["7.0"]="php80-to-74 php74-to-73 php73-to-72 php72-to-71 php71-to-70" \
["7.1"]="php80-to-74 php74-to-73 php73-to-72 php72-to-71" \
["7.2"]="php80-to-74 php74-to-73 php73-to-72" \
["7.3"]="php80-to-74 php74-to-73" \
["7.4"]="php80-to-74" \
)
fi
########################################################################
# Helper functions
# ----------------------------------------------------------------------
# Failure helper function (https://stackoverflow.com/a/24597941)
function fail {
printf '%s\n' "$1" >&2 ## Send message to stderr. Exclude >&2 if you don't want it that way.
exit "${2-1}" ## Return a code specified by $2 or 1 by default.
}
# Print array helpers (https://stackoverflow.com/a/17841619)
function join_by { local d=$1; shift; local f=$1; shift; printf %s "$f" "${@/#/$d}"; }
function note {
MESSAGE=$1;
printf "\n";
echo "[NOTE] $MESSAGE";
printf "\n";
}
########################################################################
target_php_version=$1
if [ -z "$target_php_version" ]; then
versions=$(join_by ", " ${supported_target_php_versions[@]})
fail "Please provide to which PHP version to downgrade to ($versions) as first argument to the bash script"
fi
# Check the version is supported
if [[ ! " ${supported_target_php_versions[@]} " =~ " ${target_php_version} " ]]; then
versions=$(join_by ", " ${supported_target_php_versions[@]})
fail "Version $target_php_version is not supported for downgrading. Supported versions: $versions"
fi
target_downgrade_php_whynots=($(echo ${downgrade_php_whynots[$target_php_version]} | tr " " "\n"))
target_downgrade_php_rectorconfigs=($(echo ${downgrade_php_rectorconfigs[$target_php_version]} | tr " " "\n"))
packages_to_downgrade=()
rectorconfigs_to_downgrade=()
declare -A package_paths
declare -A packages_by_rectorconfig
# Switch to production
composer install --no-dev --no-progress --ansi
rootPackage=$(composer info -s -N)
numberTargetPHPVersions=${#target_downgrade_php_whynots[@]}
counter=1
while [ $counter -le $numberTargetPHPVersions ]
do
pos=$(( $counter - 1 ))
whynot=${target_downgrade_php_whynots[$pos]}
rector_config=${target_downgrade_php_rectorconfigs[$pos]}
note "Analyzing which packages do not support PHP version $whynot"
# Obtain the list of packages for production that need a higher version that the input one.
# Those must be downgraded
PACKAGES=$(composer why-not php $whynot --no-interaction | grep -o "\S*\/\S*")
if [ -n "$PACKAGES" ]; then
for package in $PACKAGES
do
note "Enqueueing rector_config $rector_config on package $package"
# Composer also analyzes the root project but its path is directly the root folder
if [ $package = "$rootPackage" ]
then
path=$(pwd)
else
# Obtain the package's path from Composer
# Format is "package path", so extract everything after the 1st word with cut to obtain the path
path=$(composer info $package --path | cut -d' ' -f2-)
fi
packages_to_downgrade+=($package)
rectorconfigs_to_downgrade+=($rector_config)
package_paths[$package]=$path
packages_by_rectorconfig[$rector_config]=$(echo "${packages_by_rectorconfig[$rector_config]} ${package}")
done
else
note "No packages to downgrade"
fi
((counter++))
done
# Switch to dev again
composer install --no-progress --ansi
# Make sure that the number of packages, paths and sets is the same
# otherwise something went wrong
numberPackages=${#packages_to_downgrade[@]}
numberRectorConfigs=${#rectorconfigs_to_downgrade[@]}
if [ ! $numberRectorConfigs -eq $numberPackages ]; then
fail "Number of Rector configs ($numberRectorConfigs) and number of packages ($numberPackages) should not be different"
fi
# Execute a single call to Rector for all dependencies together:
# If grouping the PHP-version downgrades together, and downgrading the packages together
if [ -n "$GROUP_RECTOR_CONFIGS" ] && [ -n "$DOWNGRADE_DEPENDENCIES_TOGETHER" ]
then
# The config is the last element on the array
target_rector_configs=($(echo ${downgrade_php_rectorconfigs[$target_php_version]} | tr " " "\n"))
numberElems=${#target_rector_configs[@]}
lastPos=$(( $numberElems - 1 ))
rector_config=${target_rector_configs[$lastPos]}
# Collect the list of all dependencies and their paths
dependency_packages=()
dependency_package_paths=()
# Iterate all the packages, and obtain their paths
for package_to_downgrade in "${packages_to_downgrade[@]}"; do
path_to_downgrade=${package_paths[$package_to_downgrade]}
if [ $package_to_downgrade != "$rootPackage" ]
then
#Check it's not been added yet (eg: from needing downgrade for several PHP versions)
if [[ " ${dependency_packages[@]} " =~ " ${package_to_downgrade} " ]]; then
continue;
fi
dependency_packages+=($package_to_downgrade)
dependency_package_path=${package_paths[$package_to_downgrade]}
dependency_package_paths+=($dependency_package_path)
fi
done
# Execute the downgrade
# Downgrade Rector first
path_to_downgrade=${package_paths[$rootPackage]}
config=ci/downgrade/rector-downgrade-rector
config="${config}-${rector_config}.php"
note "Running rector_config ${rector_config} for main package ${rootPackage} on path(s) ${path_to_downgrade}"
bin/rector process $path_to_downgrade --config=$config --ansi --no-diffs --debug
#Downgrade all the dependencies then
packages_to_downgrade=$(join_by " " ${dependency_packages[@]})
paths_to_downgrade=$(join_by " " ${dependency_package_paths[@]})
config=ci/downgrade/rector-downgrade-dependency
config="${config}-${rector_config}.php"
note "Running rector_config ${rector_config} for dependency packages ${packages_to_downgrade} on paths ${paths_to_downgrade}"
bin/rector process $paths_to_downgrade --config=$config --ansi --no-diffs --debug
# Success
exit 0
fi
# We must downgrade packages in the strict dependency order,
# such as sebastian/diff => symfony/event-dispatcher-contracts => psr/event-dispatcher,
# or otherwise there may be PHP error from inconsistencies (such as from a modified interface)
# To do this, have a double loop to downgrade packages,
# asking if all the "ancestors" for the package have already been downgraded,
# or let it keep iterating until next loop
# Calculate all the dependents for all packages,
# including only packages to be downgraded
note "Calculating package execution order"
declare -A package_dependents
counter=1
while [ $counter -le $numberPackages ]
do
pos=$(( $counter - 1 ))
package_to_downgrade=${packages_to_downgrade[$pos]}
rector_config=${rectorconfigs_to_downgrade[$pos]}
IFS=' ' read -r -a packages_to_downgrade_by_rectorconfig <<< "${packages_by_rectorconfig[$rector_config]}"
dependents_to_downgrade=()
# Obtain recursively the list of dependents, keep the first word only,
# (which is the package name), and remove duplicates
dependentsAsString=$(composer why "$package_to_downgrade" -r | cut -d' ' -f1 | awk '!a[$0]++' | tr "\n" " ")
IFS=' ' read -r -a dependents <<< "$dependentsAsString"
for dependent in "${dependents[@]}"; do
# A package could provide itself in why (as when using "replaces"). Ignore them
if [ $dependent = $package_to_downgrade ]; then
continue
fi
# Only add the ones which must themselves be downgraded for that same rector config
if [[ ! " ${packages_to_downgrade_by_rectorconfig[@]} " =~ " ${dependent} " ]]; then
continue;
fi
dependents_to_downgrade+=($dependent)
done
# The dependents are identified per package and rector_config, because a same dependency
# downgraded for 2 rector_config might have dependencies downgraded for one rector_config and not the other
key="${package_to_downgrade}_${rector_config}"
package_dependents[$key]=$(echo "${dependents_to_downgrade[@]}")
note "Dependents for package ${package_to_downgrade} and rector_config ${rector_config}: ${dependents_to_downgrade[@]}"
((counter++))
done
# In case of circular dependencies (eg: package1 requires package2
# and package2 requires package1), the process will fail
# hasNonDowngradedDependents=()
declare -A circular_reference_packages_by_rector_config
note "Executing Rector to downgrade $numberDowngradedPackages packages"
downgraded_packages=()
numberDowngradedPackages=1
previousNumberDowngradedPackages=1
until [ $numberDowngradedPackages -gt $numberPackages ]
do
counter=1
while [ $counter -le $numberPackages ]
do
pos=$(( $counter - 1 ))
((counter++))
package_to_downgrade=${packages_to_downgrade[$pos]}
rector_config=${rectorconfigs_to_downgrade[$pos]}
key="${package_to_downgrade}_${rector_config}"
# Check if this package has already been downgraded on a previous iteration
if [[ " ${downgraded_packages[@]} " =~ " ${key} " ]]; then
continue
fi
# Check if all dependents have already been downgraded. Otherwise, keep iterating
hasNonDowngradedDependent=""
IFS=' ' read -r -a dependents <<< "${package_dependents[$key]}"
for dependent in "${dependents[@]}"; do
dependentKey="${dependent}_${rector_config}"
if [[ ! " ${downgraded_packages[@]} " =~ " ${dependentKey} " ]]; then
hasNonDowngradedDependent="true"
circular_reference_packages_by_rector_config[${rector_config}]=$(echo "${circular_reference_packages_by_rector_config[$rector_config]} ${dependent}")
fi
done
if [ -n "${hasNonDowngradedDependent}" ]; then
continue
fi
# Mark this package as downgraded
downgraded_packages+=($key)
((numberDowngradedPackages++))
path_to_downgrade=${package_paths[$package_to_downgrade]}
if [ $package_to_downgrade = "$rootPackage" ]
then
config=ci/downgrade/rector-downgrade-rector
else
config=ci/downgrade/rector-downgrade-dependency
fi
# Attach the specific rector config as a file suffix
config="${config}-${rector_config}.php"
note "Running rector_config ${rector_config} for package ${package_to_downgrade} on path(s) ${path_to_downgrade}"
# Execute the downgrade
bin/rector process $path_to_downgrade --config=$config --ansi --debug
# If Rector fails, already exit
if [ "$?" -gt 0 ]; then
fail "Rector downgrade failed on rector_config ${rector_config} for package ${package_to_downgrade}"
fi
done
# If no new package was downgraded, it must be because of circular dependencies
if [ $numberDowngradedPackages -eq $previousNumberDowngradedPackages ]
then
if [ ${#circular_reference_packages_by_rector_config[@]} -eq 0 ]; then
fail "For some unknown reason, not all packages have been downgraded"
fi
# Resolve all involved packages all together
note "Resolving circular reference packages all together"
for rector_config in "${!circular_reference_packages_by_rector_config[@]}";
do
circular_packages_to_downgrade=($(echo "${circular_reference_packages_by_rector_config[$rector_config]}" | tr ' ' '\n' | sort -u))
circular_packages_to_downgrade_for_rectorconfig=()
circular_paths_to_downgrade_for_rectorconfig=()
for package_to_downgrade in "${circular_packages_to_downgrade[@]}";
do
# Mark this package as downgraded
key="${package_to_downgrade}_${rector_config}"
downgraded_packages+=($key)
((numberDowngradedPackages++))
# This package does need downgrading (eg: it had not been already downgraded via GROUP_RECTOR_CONFIGS)
circular_packages_to_downgrade_for_rectorconfig+=($package_to_downgrade)
# Obtain the path
circular_paths_to_downgrade_for_rectorconfig+=(${package_paths[$package_to_downgrade]})
done
# Check that possibly all packages had already been downgraded via GROUP_RECTOR_CONFIGS
if [ ${#circular_packages_to_downgrade_for_rectorconfig[@]} -gt 0 ]; then
paths_to_downgrade=$(join_by " " ${circular_paths_to_downgrade_for_rectorconfig[@]})
note "Running rector_config ${rector_config} for packages ${circular_packages_to_downgrade_for_rectorconfig[@]}"
config="ci/downgrade/rector-downgrade-dependency-${rector_config}.php"
bin/rector process $paths_to_downgrade --config=$config --ansi --debug
# If Rector fails, already exit
if [ "$?" -gt 0 ]; then
fail "Rector downgrade failed on rector_config ${rector_config} for package ${package_to_downgrade}"
fi
else
note "All circular packages had already been downgraded: ${circular_packages_to_downgrade[@]}"
fi
done
fi
circular_reference_packages_by_rector_config=()
previousNumberDowngradedPackages=$numberDowngradedPackages
done

View File

@ -9,7 +9,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php_version: ['7.3', '7.4', '8.0']
php_version: ['7.1', '7.2', '7.3', '7.4', '8.0']
name: "PHP ${{ matrix.php_version }}"

View File

@ -9,7 +9,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php_version: ['7.3', '7.4', '8.0']
php_version: ['7.1', '7.2', '7.3', '7.4', '8.0']
steps:
- uses: actions/checkout@v2

View File

@ -9,22 +9,8 @@ jobs:
strategy:
fail-fast: false
matrix:
php_version: ['7.3', '7.4', '8.0']
symfony_version: ['5.2']
# see https://docs.github.com/en/free-pro-team@latest/actions/reference/workflow-syntax-for-github-actions#example-including-additional-values-into-combinations
include:
-
php_version: '7.3'
symfony_version: '2.8'
-
php_version: '7.3'
symfony_version: '3.4'
-
php_version: '7.3'
symfony_version: '4.4'
-
php_version: '7.4'
symfony_version: '4.4'
php_version: ['7.1', '7.2', '7.3', '7.4', '8.0']
symfony_version: ['2.8', '3.4', '4.4']
name: "PHP ${{ matrix.php_version }} and Symfony ${{ matrix.symfony_version }}"

View File

@ -9,7 +9,7 @@ jobs:
strategy:
fail-fast: false
matrix:
php_version: ['7.3', '7.4', '8.0']
php_version: ['7.1', '7.2', '7.3', '7.4', '8.0']
name: "PHP ${{ matrix.php_version }}"

View File

@ -3,9 +3,9 @@
[![Build Status Github Actions](https://img.shields.io/github/workflow/status/rectorphp/rector-prefixed/Code_Checks?style=flat-square)](https://github.com/rectorphp/rector-prefixed/actions)
[![Downloads](https://img.shields.io/packagist/dt/rector/rector-prefixed.svg?style=flat-square)](https://packagist.org/packages/rector/rector-prefixed)
Do you have conflicts on Rector install? You're in the right place.
Do you have conflicts on Rector install? You're in the right place. Prefixed Rector can [be installed even on very old Symfony](https://getrector.org/blog/2020/01/20/how-to-install-rector-despite-composer-conflicts).
Prefixed Rector can [be installed even on very old Symfony](https://getrector.org/blog/2020/01/20/how-to-install-rector-despite-composer-conflicts).
Do you have older PHP? Rector prefixed goes down to PHP 7.1, so you can install it even on older projects.
## Install

View File

@ -9,9 +9,4 @@ use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigura
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(FinalizeClassesWithoutChildrenRector::class);
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::AUTOLOAD_PATHS, [
__DIR__ . '/../tests/fixture-finalize'
]);
};

View File

@ -0,0 +1,12 @@
{
"name": "rector/rector-prefixed",
"description": "Prefixed and PHP 7.1 downgraded version of rector/rector",
"license": "MIT",
"bin": [
"bin/rector"
],
"require": {
"php": "^7.1|^8.0",
"phpstan/phpstan": "^0.12.81"
}
}

View File

@ -1,277 +0,0 @@
{
"name": "rector/rector-php71",
"description": "PHP 7.1-compatible version of rector/rector package",
"license": "MIT",
"require": {
"php": "^7.1",
"ext-dom": "*",
"ext-json": "*",
"composer/semver": "^3.2",
"composer/xdebug-handler": "^1.4",
"doctrine/annotations": "^1.11",
"doctrine/inflector": "^2.0",
"jean85/pretty-package-versions": "^1.5.1|^2.0.1",
"nette/robot-loader": "^3.2",
"nette/utils": "^3.2",
"nikic/php-parser": "^4.10.4",
"phpstan/phpdoc-parser": "^0.4.9",
"phpstan/phpstan": "^0.12.69, <0.12.70",
"phpstan/phpstan-phpunit": "^0.12.17",
"psr/simple-cache": "^1.0",
"sebastian/diff": "^4.0.4",
"symfony/cache": "^4.4.8|^5.1",
"symfony/console": "^4.4.8|^5.1",
"symfony/dependency-injection": "^5.1",
"symfony/expression-language": "^4.4.8|^5.1",
"symfony/finder": "^4.4.8|^5.1",
"symfony/http-kernel": "^4.4.8|^5.1",
"symfony/process": "^4.4.8|^5.1",
"symplify/astral": "^9.1.4",
"symplify/autowire-array-parameter": "^9.1.4",
"symplify/console-color-diff": "^9.1.4",
"symplify/package-builder": "^9.1.4",
"symplify/rule-doc-generator": "^9.1.4",
"symplify/set-config-resolver": "^9.1.4",
"symplify/simple-php-doc-parser": "^9.1.4",
"symplify/skipper": "^9.1.4",
"symplify/smart-file-system": "^9.1.4",
"symplify/symfony-php-config": "^9.1.4",
"webmozart/assert": "^1.9"
},
"require-dev": {
"friendsofphp/php-cs-fixer": "^2.18.2",
"nette/application": "^3.0.7",
"nette/di": "^3.0",
"nette/forms": "^3.0",
"ocramius/package-versions": "^1.9",
"php-parallel-lint/php-parallel-lint": "^1.2",
"phpstan/phpstan-nette": "^0.12.14",
"phpunit/phpunit": "^9.5",
"symfony/security-core": "^5.2",
"symfony/security-http": "^5.2",
"symplify/changelog-linker": "^9.1.4",
"symplify/coding-standard": "^9.1.4",
"symplify/easy-coding-standard": "^9.1.4",
"symplify/easy-ci": "^9.1.0",
"symplify/easy-testing": "^9.1.4",
"symplify/phpstan-extensions": "^9.1.4",
"symplify/phpstan-rules": "^9.1.4",
"tracy/tracy": "^2.8"
},
"bin": [
"bin/rector"
],
"replace": {
"rector/rector": "self.version"
},
"autoload": {
"psr-4": {
"Rector\\Testing\\": "packages/testing/src",
"Rector\\Comments\\": "packages/comments/src",
"Rector\\AttributeAwarePhpDoc\\": "packages/attribute-aware-php-doc/src",
"Rector\\Autodiscovery\\": "rules/autodiscovery/src",
"Rector\\BetterPhpDocParser\\": "packages/better-php-doc-parser/src",
"Rector\\Caching\\": "packages/caching/src",
"Rector\\CakePHP\\": "rules/cakephp/src",
"Rector\\ChangesReporting\\": "packages/changes-reporting/src",
"Rector\\CodeQuality\\": "rules/code-quality/src",
"Rector\\CodingStyle\\": "rules/coding-style/src",
"Rector\\Composer\\": "rules/composer/src",
"Rector\\Core\\": "src",
"Rector\\DeadCode\\": "rules/dead-code/src",
"Rector\\DependencyInjection\\": "rules/dependency-injection/src",
"Rector\\EarlyReturn\\": "rules/early-return/src",
"Rector\\DeadDocBlock\\": "rules/dead-doc-block/src",
"Rector\\DoctrineAnnotationGenerated\\": "packages/doctrine-annotation-generated/src",
"Rector\\DoctrineCodeQuality\\": "rules/doctrine-code-quality/src",
"Rector\\DoctrineGedmoToKnplabs\\": "rules/doctrine-gedmo-to-knplabs/src",
"Rector\\Doctrine\\": "rules/doctrine/src",
"Rector\\DowngradePhp70\\": "rules/downgrade-php70/src",
"Rector\\DowngradePhp71\\": "rules/downgrade-php71/src",
"Rector\\DowngradePhp72\\": "rules/downgrade-php72/src",
"Rector\\DowngradePhp73\\": "rules/downgrade-php73/src",
"Rector\\ReadWrite\\": "packages/read-write/src",
"Rector\\DowngradePhp74\\": "rules/downgrade-php74/src",
"Rector\\DowngradePhp80\\": "rules/downgrade-php80/src",
"Rector\\FamilyTree\\": "packages/family-tree/src",
"Rector\\FileSystemRector\\": "packages/file-system-rector/src",
"Rector\\Generic\\": "rules/generic/src",
"Rector\\Laravel\\": "rules/laravel/src",
"Rector\\Legacy\\": "rules/legacy/src",
"Rector\\MockeryToProphecy\\": "rules/mockery-to-prophecy/src",
"Rector\\MysqlToMysqli\\": "rules/mysql-to-mysqli/src",
"Rector\\Naming\\": "rules/naming/src",
"Rector\\NetteCodeQuality\\": "rules/nette-code-quality/src",
"Rector\\NetteKdyby\\": "rules/nette-kdyby/src",
"Rector\\NetteTesterToPHPUnit\\": "rules/nette-tester-to-phpunit/src",
"Rector\\NetteToSymfony\\": "rules/nette-to-symfony/src",
"Rector\\NetteUtilsCodeQuality\\": "rules/nette-utils-code-quality/src",
"Rector\\Nette\\": "rules/nette/src",
"Rector\\Defluent\\": "rules/defluent/src",
"Rector\\NodeCollector\\": "packages/node-collector/src",
"Rector\\NodeNameResolver\\": "packages/node-name-resolver/src",
"Rector\\NodeNestingScope\\": "packages/node-nesting-scope/src",
"Rector\\NodeRemoval\\": "packages/node-removal/src",
"Rector\\NodeTypeResolver\\": "packages/node-type-resolver/src",
"Rector\\Order\\": "rules/order/src",
"Rector\\PHPOffice\\": "rules/php-office/src",
"Rector\\PHPStanStaticTypeMapper\\": "packages/phpstan-static-type-mapper/src",
"Rector\\PHPUnitSymfony\\": "rules/phpunit-symfony/src",
"Rector\\PHPUnit\\": "rules/phpunit/src",
"Rector\\PSR4\\": "rules/psr4/src",
"Rector\\Php52\\": "rules/php52/src",
"Rector\\Php53\\": "rules/php53/src",
"Rector\\Php54\\": "rules/php54/src",
"Rector\\Php55\\": "rules/php55/src",
"Rector\\Php56\\": "rules/php56/src",
"Rector\\Php70\\": "rules/php70/src",
"Rector\\Php71\\": "rules/php71/src",
"Rector\\Php72\\": "rules/php72/src",
"Rector\\Php73\\": "rules/php73/src",
"Rector\\Php74\\": "rules/php74/src",
"Rector\\Php80\\": "rules/php80/src",
"Rector\\PhpAttribute\\": "packages/php-attribute/src",
"Rector\\PhpSpecToPHPUnit\\": "rules/php-spec-to-phpunit/src",
"Rector\\Compiler\\": "utils/compiler/src",
"Rector\\PostRector\\": "packages/post-rector/src",
"Rector\\Visibility\\": "rules/visibility/src",
"Rector\\Removing\\": "rules/removing/src",
"Rector\\Privatization\\": "rules/privatization/src",
"Rector\\RectorGenerator\\": "packages/rector-generator/src",
"Rector\\RemovingStatic\\": "rules/removing-static/src",
"Rector\\Renaming\\": "rules/renaming/src",
"Rector\\Restoration\\": "rules/restoration/src",
"Rector\\Sensio\\": "rules/sensio/src",
"Rector\\Set\\": "packages/set/src",
"Rector\\StaticTypeMapper\\": "packages/static-type-mapper/src",
"Rector\\CodeQualityStrict\\": "rules/code-quality-strict/src",
"Rector\\Symfony\\": "rules/symfony-code-quality/src",
"Rector\\SymfonyPhpConfig\\": "rules/symfony-php-config/src",
"Rector\\Symfony\\": "rules/symfony/src",
"Rector\\Symfony2\\": "rules/symfony2/src",
"Rector\\Symfony3\\": "rules/symfony3/src",
"Rector\\Symfony4\\": "rules/symfony4/src",
"Rector\\Symfony5\\": "rules/symfony5/src",
"Rector\\Transform\\": "rules/transform/src",
"Rector\\TypeDeclaration\\": "rules/type-declaration/src",
"Rector\\VendorLocker\\": "packages/vendor-locker/src",
"Rector\\Carbon\\": "rules/carbon/src",
"Rector\\Generics\\": "rules/generics/src"
}
},
"autoload-dev": {
"classmap": [
"rules/autodiscovery/tests/Rector/FileNode/MoveInterfacesToContractNamespaceDirectoryRector/Expected",
"rules/autodiscovery/tests/Rector/FileNode/MoveServicesBySuffixToDirectoryRector/Expected",
"rules/cakephp/tests/Rector/FileWithoutNamespace/ImplicitShortClassNameUseStatementRector/Source",
"rules/cakephp/tests/Rector/Namespace_/AppUsesStaticCallToUseStatementRector/Source",
"rules/psr4/tests/Rector/Namespace_/MultipleClassFileToPsr4ClassesRector/Source",
"rules/renaming/tests/Rector/FileWithoutNamespace/PseudoNamespaceToNamespaceRector/Source",
"rules/symfony4/tests/Rector/MethodCall/ContainerGetToConstructorInjectionRector/Source"
],
"files": [
"rules/restoration/tests/Rector/Use_/RestoreFullyQualifiedNameRector/Source/ShortClassOnly.php",
"rules/coding-style/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Source/AnotherClass.php",
"rules/coding-style/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Source/Foo.php",
"rules/coding-style/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Source/Function_/count.php",
"rules/coding-style/tests/Rector/Namespace_/ImportFullyQualifiedNamesRector/Source/YetAnotherClass.php",
"rules/coding-style/tests/Rector/Throw_/AnnotateThrowablesRector/Source/i_throw_an_exception.func.php",
"rules/dead-code/tests/Rector/MethodCall/RemoveDefaultArgumentValueRector/Source/UserDefined.php",
"rules/naming/tests/ValueObjectFactory/PropertyRenameFactory/Fixture/skip_some_class.php.inc",
"rules/renaming/tests/Rector/FileWithoutNamespace/PseudoNamespaceToNamespaceRector/Source/ChangeMeAnotherNamespace.php",
"rules/renaming/tests/Rector/Name/RenameClassRector/Source/SkipClassImportingSameName.php",
"rules/renaming/tests/Rector/Name/RenameClassRector/Source/SkipSameNamedInterface.php",
"rules/renaming/tests/Rector/Name/RenameClassRector/Source/Manual_Twig_Filter.php",
"rules/renaming/tests/Rector/Name/RenameClassRector/Source/TwigFilter.php",
"rules/renaming/tests/Rector/Name/RenameClassRector/Source/Twig_Extension_Sandbox.php",
"rules/transform/tests/Rector/FuncCall/FuncCallToMethodCallRector/Source/some_view_function.php",
"rules/type-declaration/tests/Rector/FunctionLike/ReturnTypeDeclarationRector/Source/MyBar.php",
"rules/type-declaration/tests/Rector/Property/CompleteVarDocTypePropertyRector/Source/EventDispatcher.php",
"vendor/symfony/dependency-injection/Loader/Configurator/ContainerConfigurator.php",
"tests/debug_functions.php"
],
"psr-4": {
"Rector\\Autodiscovery\\Tests\\": "rules/autodiscovery/tests",
"Rector\\BetterPhpDocParser\\Tests\\": "packages/better-php-doc-parser/tests",
"Rector\\Caching\\Tests\\": "packages/caching/tests",
"Rector\\CakePHP\\Tests\\": "rules/cakephp/tests",
"Rector\\CodeQuality\\Tests\\": "rules/code-quality/tests",
"Rector\\CodingStyle\\Tests\\": "rules/coding-style/tests",
"Rector\\Composer\\Tests\\": "rules/composer/tests",
"Rector\\Core\\Tests\\": "tests",
"Rector\\EarlyReturn\\Tests\\": "rules/early-return/tests",
"Rector\\DeadCode\\Tests\\": "rules/dead-code/tests",
"Rector\\DependencyInjection\\Tests\\": "rules/dependency-injection/tests",
"Rector\\DoctrineCodeQuality\\Tests\\": "rules/doctrine-code-quality/tests",
"Rector\\DoctrineGedmoToKnplabs\\Tests\\": "rules/doctrine-gedmo-to-knplabs/tests",
"Rector\\Comments\\Tests\\": "packages/comments/tests",
"Rector\\Doctrine\\Tests\\": "rules/doctrine/tests",
"Rector\\DowngradePhp70\\Tests\\": "rules/downgrade-php70/tests",
"Rector\\Removing\\Tests\\": "rules/removing/tests",
"Rector\\DowngradePhp71\\Tests\\": "rules/downgrade-php71/tests",
"Rector\\DowngradePhp72\\Tests\\": "rules/downgrade-php72/tests",
"Rector\\DowngradePhp73\\Tests\\": "rules/downgrade-php73/tests",
"Rector\\DowngradePhp74\\Tests\\": "rules/downgrade-php74/tests",
"Rector\\DowngradePhp80\\Tests\\": "rules/downgrade-php80/tests",
"Rector\\Generic\\Tests\\": "rules/generic/tests",
"Rector\\Laravel\\Tests\\": "rules/laravel/tests",
"Rector\\Legacy\\Tests\\": "rules/legacy/tests",
"Rector\\Defluent\\Tests\\": "rules/defluent/tests",
"Rector\\MockeryToProphecy\\Tests\\": "rules/mockery-to-prophecy/tests",
"Rector\\MysqlToMysqli\\Tests\\": "rules/mysql-to-mysqli/tests",
"Rector\\Naming\\Tests\\": "rules/naming/tests",
"Rector\\DeadDocBlock\\Tests\\": "rules/dead-doc-block/tests",
"Rector\\NetteCodeQuality\\Tests\\": "rules/nette-code-quality/tests",
"Rector\\NetteKdyby\\Tests\\": "rules/nette-kdyby/tests",
"Rector\\NetteTesterToPHPUnit\\Tests\\": "rules/nette-tester-to-phpunit/tests",
"Rector\\NetteToSymfony\\Tests\\": "rules/nette-to-symfony/tests",
"Rector\\NetteUtilsCodeQuality\\Tests\\": "rules/nette-utils-code-quality/tests",
"Rector\\Nette\\Tests\\": "rules/nette/tests",
"Rector\\NodeTypeResolver\\Tests\\": "packages/node-type-resolver/tests",
"Rector\\Order\\Tests\\": "rules/order/tests",
"Rector\\PHPOffice\\Tests\\": "rules/php-office/tests",
"Rector\\Visibility\\Tests\\": "rules/visibility/tests",
"Rector\\PHPStanExtensions\\": "utils/phpstan-extensions/src",
"Rector\\RuleDocGenerator\\": "utils/rule-doc-generator/src",
"Rector\\PHPStanExtensions\\Tests\\": "utils/phpstan-extensions/tests",
"Rector\\PHPStanStaticTypeMapper\\Tests\\": "packages/phpstan-static-type-mapper/tests",
"Rector\\StaticTypeMapper\\Tests\\": "packages/static-type-mapper/tests",
"Rector\\PHPUnitSymfony\\Tests\\": "rules/phpunit-symfony/tests",
"Rector\\PHPUnit\\Tests\\": "rules/phpunit/tests",
"Rector\\PSR4\\Tests\\": "rules/psr4/tests",
"Rector\\Php52\\Tests\\": "rules/php52/tests",
"Rector\\Php53\\Tests\\": "rules/php53/tests",
"Rector\\Php54\\Tests\\": "rules/php54/tests",
"Rector\\Php55\\Tests\\": "rules/php55/tests",
"Rector\\Php56\\Tests\\": "rules/php56/tests",
"Rector\\Php70\\Tests\\": "rules/php70/tests",
"Rector\\Php71\\Tests\\": "rules/php71/tests",
"Rector\\Php72\\Tests\\": "rules/php72/tests",
"Rector\\Php73\\Tests\\": "rules/php73/tests",
"Rector\\Php74\\Tests\\": "rules/php74/tests",
"Rector\\Php80\\Tests\\": "rules/php80/tests",
"Rector\\PhpSpecToPHPUnit\\Tests\\": "rules/php-spec-to-phpunit/tests",
"Rector\\Privatization\\Tests\\": "rules/privatization/tests",
"Rector\\RectorGenerator\\Tests\\": "packages/rector-generator/tests",
"Rector\\RemovingStatic\\Tests\\": "rules/removing-static/tests",
"Rector\\Renaming\\Tests\\": "rules/renaming/tests",
"Rector\\Restoration\\Tests\\": "rules/restoration/tests",
"Rector\\Sensio\\Tests\\": "rules/sensio/tests",
"Rector\\CodeQualityStrict\\Tests\\": "rules/code-quality-strict/tests",
"Rector\\Symfony\\Tests\\": "rules/symfony-code-quality/tests",
"Rector\\SymfonyPhpConfig\\Tests\\": "rules/symfony-php-config/tests",
"Rector\\Symfony\\Tests\\": "rules/symfony/tests",
"Rector\\Symfony2\\Tests\\": "rules/symfony2/tests",
"Rector\\Symfony3\\Tests\\": "rules/symfony3/tests",
"Rector\\Symfony4\\Tests\\": "rules/symfony4/tests",
"Rector\\Symfony5\\Tests\\": "rules/symfony5/tests",
"Rector\\Transform\\Tests\\": "rules/transform/tests",
"Rector\\TypeDeclaration\\Tests\\": "rules/type-declaration/tests",
"Rector\\Utils\\DoctrineAnnotationParserSyncer\\": "utils/doctrine-annotation-parser-syncer/src",
"Rector\\Utils\\PHPStanTypeMapperChecker\\": "utils/phpstan-type-mapper-checker/src",
"Rector\\Utils\\ProjectValidator\\": "utils/project-validator/src",
"Rector\\Carbon\\Tests\\": "rules/carbon/tests",
"Rector\\Generics\\Tests\\": "rules/generics/tests"
}
}
}

View File

@ -1,14 +0,0 @@
{
"name": "rector/rector-php71",
"description": "PHP 7.1-compatible version of rector/rector package",
"license": "MIT",
"require": {
"php": "^7.1"
},
"bin": [
"bin/rector"
],
"replace": {
"rector/rector": "self.version"
}
}

View File

@ -1,43 +0,0 @@
<?php
declare(strict_types=1);
use Rector\Core\Stubs\PHPStanStubLoader;
$phpStanStubLoader = new PHPStanStubLoader();
$phpStanStubLoader->loadStubs();
/**
* Configuration consts for the different rector.php config files
*/
final class DowngradeRectorConfig
{
/**
* Exclude paths when downgrading a dependency
*/
public const DEPENDENCY_EXCLUDE_PATHS = [
'*/tests/*',
// Individual classes that can be excluded because
// they are not used by Rector, and they use classes
// loaded with "require-dev" so it'd throw an error
__DIR__ . '/../../vendor/symfony/cache/DoctrineProvider.php',
__DIR__ . '/../../vendor/symfony/cache/Messenger/EarlyExpirationHandler.php',
__DIR__ . '/../../vendor/symfony/http-kernel/HttpKernelBrowser.php',
__DIR__ . '/../../vendor/symfony/string/Slugger/AsciiSlugger.php',
// This class has an issue for PHP 7.1:
// https://github.com/rectorphp/rector/issues/4816#issuecomment-743209526
// It doesn't happen often, and Rector doesn't use it, so then
// we simply skip downgrading this class
__DIR__ . '/../../vendor/symfony/cache/Adapter/CouchbaseBucketAdapter.php',
];
/**
* Exclude paths when downgrading the Rector source code
*/
public const RECTOR_EXCLUDE_PATHS = [
'*/tests/*',
__DIR__ . '/../../packages/rector-generator/templates/*',
__DIR__ . '/../../vendor/*',
__DIR__ . '/../../ci/*',
__DIR__ . '/../../stubs/*',
];
}

View File

@ -1,33 +0,0 @@
parameters:
level: 0
paths:
- ../../src
- ../../rules
- ../../packages
- ../../utils
reportUnmatchedIgnoredErrors: false
scanDirectories:
- ../../stubs
excludes_analyse:
# List of all excluded elements for Rector and its dependencies
# from ci/downgrade/configuration.php
# Rector:
- */tests/*
- ../../ci/*
# - ../../stubs/* # Even if not downgraded, they are needed to run PHPStan
- ../../packages/rector-generator/templates/*
- ../../packages/doctrine-annotation-generated/src/*
# Dependencies:
- ../../vendor/symfony/cache/DoctrineProvider.php
- ../../vendor/symfony/cache/Messenger/EarlyExpirationHandler.php
- ../../vendor/symfony/http-kernel/HttpKernelBrowser.php
- ../../vendor/symfony/string/Slugger/AsciiSlugger.php
- ../../vendor/symfony/cache/Adapter/CouchbaseBucketAdapter.php
# broken in PHPStan https://github.com/rectorphp/rector/runs/1305002460#step:5:56
- ../../utils/phpstan-extensions/*
- ../../packages/testing/src/PHPUnit/*.php

View File

@ -1,17 +0,0 @@
<?php
declare(strict_types=1);
use Rector\Core\Configuration\Option;
use Rector\Privatization\Rector\Class_\FinalizeClassesWithoutChildrenRector;
use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator;
return static function (ContainerConfigurator $containerConfigurator): void {
$services = $containerConfigurator->services();
$services->set(FinalizeClassesWithoutChildrenRector::class);
$parameters = $containerConfigurator->parameters();
$parameters->set(Option::AUTOLOAD_PATHS, [
__DIR__ . '/tests/Finalize/Fixture/Source'
]);
};

View File

@ -1,23 +0,0 @@
name: Bare Run
on: [pull_request, push]
jobs:
bare_run:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php_version: ['7.1', '7.2']
steps:
- uses: actions/checkout@v2
-
uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php_version }}
coverage: none
- run: php bin/rector --ansi

View File

@ -1,28 +0,0 @@
name: PHPStan
on: [pull_request, push]
jobs:
along_phpstan:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php_version: ['7.1', '7.2']
name: "PHP ${{ matrix.php_version }}"
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php_version }}
coverage: none
- run: |
mkdir temp && cd temp
composer require phpstan/phpstan --dev --ansi --no-interaction
cd ..
temp/vendor/bin/phpstan analyse -c ci/downgrade/phpstan.neon --ansi

View File

@ -1,39 +0,0 @@
name: Tests
on: [pull_request, push]
jobs:
finalize_classes:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php_version: ['7.1', '7.2']
name: "PHP ${{ matrix.php_version }}"
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php_version }}
coverage: none
# Use library versions compatible with PHP 7.1
- run: |
mkdir temp && cd temp
composer require "doctrine/orm:~2.7.5" --ansi --no-interaction
composer require "phpunit/phpunit:~7.5" --dev --ansi --no-interaction
# Apply Rector on a few sources
- run: |
cd temp
../bin/rector process ../ci/downgrade/tests/Finalize/Fixture/Source --config ../ci/downgrade/rector-test-downgrade.php --ansi
# Validate the results are the expected ones
- run: |
cd temp
vendor/bin/phpunit ../ci/downgrade/tests/

View File

@ -1,32 +0,0 @@
name: Tests Root Directory
on: [pull_request, push]
jobs:
finalize_classes:
runs-on: ubuntu-latest
strategy:
fail-fast: false
matrix:
php_version: ['7.1', '7.2']
name: "PHP ${{ matrix.php_version }}"
steps:
- uses: actions/checkout@v2
- uses: shivammathur/setup-php@v2
with:
php-version: ${{ matrix.php_version }}
coverage: none
# Use library versions compatible with PHP 7.1
- run: |
composer require "doctrine/orm:~2.7.5" --ansi --no-interaction
composer require "phpunit/phpunit:~7.5" --dev --ansi --no-interaction
# Validate the results are the expected ones
- run: |
vendor/bin/phpunit

View File

@ -1,32 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\RectorPhp71\Tests\Finalize;
use PHPUnit\Framework\TestCase;
final class FinalizeTest extends TestCase
{
/**
* @dataProvider getFiles
*/
public function testRectoredFileEquals($rectoredFile, $expectedFile): void
{
$this->assertFileEquals($rectoredFile, $expectedFile);
}
public function getFiles(): array
{
$files = glob(__DIR__ . '/Fixture/Source/*.php');
return array_map(
function ($file) {
return [
$file,
__DIR__ . '/Fixture/Expected/' . basename($file),
];
},
$files
);
}
}

View File

@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\RectorPhp71\Tests\Finalize;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class SkipSomeEntity
{
}

View File

@ -1,9 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\RectorPhp71\Tests\Finalize;
final class SomeClassWithoutChildren
{
}

View File

@ -1,14 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\RectorPhp71\Tests\Finalize;
use Doctrine\ORM\Mapping as ORM;
/**
* @ORM\Entity
*/
class SkipSomeEntity
{
}

View File

@ -1,9 +0,0 @@
<?php
declare(strict_types=1);
namespace Rector\RectorPhp71\Tests\Finalize;
class SomeClassWithoutChildren
{
}

21
full_build.sh Normal file
View File

@ -0,0 +1,21 @@
#!/bin/sh -l
# see https://stackoverflow.com/questions/66644233/how-to-propagate-colors-from-bash-script-to-github-action?noredirect=1#comment117811853_66644233
export TERM=xterm-color
# show errors
set -e
# script fails if trying to access to an undefined variable
set -u
composer install --no-dev --ansi
rsync --exclude rector-build -av * rector-build --quiet
rm -rf rector-build/packages-tests rector-build/rules-tests rector-build/tests
sh build/downgrade-rector.sh rector-build
sh build/build-rector-scoped.sh rector-build rector-prefixed-downgraded

View File

@ -126,13 +126,6 @@ final class PHPStanNodeScopeResolver
// skip chain method calls, performance issue: https://github.com/phpstan/phpstan/issues/254
$nodeCallback = function (Node $node, Scope $scope): void {
// the class reflection is resolved AFTER entering to class node
// so we need to get it from the first after this one
if ($node instanceof Class_ || $node instanceof Interface_) {
/** @var Scope $scope */
$scope = $this->resolveClassOrInterfaceScope($node, $scope);
}
// traversing trait inside class that is using it scope (from referenced) - the trait traversed by Rector is different (directly from parsed file)
if ($scope->isInTrait()) {
/** @var ClassReflection $classReflection */
@ -143,6 +136,13 @@ final class PHPStanNodeScopeResolver
return;
}
// the class reflection is resolved AFTER entering to class node
// so we need to get it from the first after this one
if ($node instanceof Class_ || $node instanceof Interface_) {
/** @var Scope $scope */
$scope = $this->resolveClassOrInterfaceScope($node, $scope);
}
// special case for unreachable nodes
if ($node instanceof UnreachableStatementNode) {
$originalNode = $node->getOriginalStatement();
@ -185,10 +185,10 @@ final class PHPStanNodeScopeResolver
// is anonymous class? - not possible to enter it since PHPStan 0.12.33, see https://github.com/phpstan/phpstan-src/commit/e87fb0ec26f9c8552bbeef26a868b1e5d8185e91
if ($classLike instanceof Class_ && Strings::match($className, self::ANONYMOUS_CLASS_START_REGEX)) {
$classReflection = $this->reflectionProvider->getAnonymousClassReflection($classLike, $scope);
} elseif ($this->reflectionProvider->hasClass($className)) {
$classReflection = $this->reflectionProvider->getClass($className);
} else {
} elseif (! $this->reflectionProvider->hasClass($className)) {
return $scope;
} else {
$classReflection = $this->reflectionProvider->getClass($className);
}
/** @var MutatingScope $scope */

View File

@ -577,10 +577,10 @@ parameters:
- rules/Privatization/Rector/Class_/ChangeReadOnlyVariableWithDefaultValueToConstantRector.php
- rules/Privatization/Naming/ConstantNaming.php
-
message: '#Cannot cast array<string\>\|string\|null to string#'
paths:
- utils/compiler/src/Command/DowngradePathsCommand.php
- '#Method Rector\\Testing\\Finder\\RectorsFinder\:\:findClassesInDirectoriesByName\(\) should return array<class\-string\> but returns array<int, string\>#'
- '#Cannot cast array<string\>\|string\|null to string#'

View File

@ -76,8 +76,11 @@ return static function (ContainerConfigurator $containerConfigurator): void {
// test paths
'*/Fixture/*',
'*/Fixture/*',
'*/Source/*',
'*/Source*/*',
'*/Expected/*',
'*/Expected*/*',
__DIR__ . '/packages/DoctrineAnnotationGenerated',
]);

View File

@ -0,0 +1,22 @@
<?php
namespace Rector\Tests\DowngradePhp72\Rector\FunctionLike\DowngradeObjectTypeDeclarationRector\Fixture;
interface AdapterInterface
{
public function getItems(array $items);
}
final class SomeAdapter implements AdapterInterface
{
use BaseAdapterTrait;
}
trait BaseAdapterTrait
{
public function getItems($items)
{
}
}
?>

View File

@ -30,7 +30,7 @@ try {
}
CODE_SAMPLE
,
<<<'CODE_SAMPLE'
<<<'CODE_SAMPLE'
try {
// Some code...
} catch (ExceptionType1 $exception) {

View File

@ -57,7 +57,8 @@ final class NativeTypeClassTreeResolver
return TypehintHelper::decideTypeFromReflection(
$parameterReflection->getType(),
null,
$classReflection->getName()
$classReflection->getName(),
$parameterReflection->isVariadic()
);
}

View File

@ -61,7 +61,6 @@ CODE_SAMPLE
public function refactor(Node $node): ?Node
{
$stringKind = $node->getAttribute(AttributeKey::KIND);
if (! in_array($stringKind, self::HERENOW_DOC_KINDS, true)) {
return null;
}

View File

@ -1,12 +0,0 @@
{
"name": "rector/rector-prefixed",
"description": "Prefixed scoped version of rector/rector package",
"license": "MIT",
"bin": [
"bin/rector"
],
"require": {
"php": "^7.3|^8.0",
"phpstan/phpstan": "^0.12.64"
}
}

View File

@ -5,6 +5,7 @@ declare(strict_types=1);
namespace Rector\Core\Configuration;
use Jean85\PrettyVersions;
use Nette\Utils\Strings;
use Rector\ChangesReporting\Output\ConsoleOutputFormatter;
use Rector\Core\Exception\Configuration\InvalidConfigurationException;
use Rector\Core\ValueObject\Bootstrap\BootstrapConfigs;
@ -106,8 +107,10 @@ final class Configuration
$this->outputFormat = (string) $input->getOption(Option::OPTION_OUTPUT_FORMAT);
$commandLinePaths = (array) $input->getArgument(Option::SOURCE);
// manual command line value has priority
if ($commandLinePaths !== []) {
$commandLinePaths = $this->correctBashSpacePaths($commandLinePaths);
$this->paths = $commandLinePaths;
}
}
@ -266,4 +269,20 @@ final class Configuration
return $outputFileOption;
}
/**
* @param string[] $commandLinePaths
* @return string[]
*/
private function correctBashSpacePaths(array $commandLinePaths): array
{
// fixes bash edge-case that to merges string with space to one
foreach ($commandLinePaths as $commandLinePath) {
if (Strings::contains($commandLinePath, ' ')) {
$commandLinePaths = explode(' ', $commandLinePath);
}
}
return $commandLinePaths;
}
}

View File

@ -199,7 +199,6 @@ final class ProcessCommand extends Command
$this->configuration->validateConfigParameters();
$paths = $this->configuration->getPaths();
$phpFileInfos = $this->phpFilesFinder->findInPaths($paths);
$this->additionalAutoloader->autoloadWithInputAndSource($input);

View File

@ -28,7 +28,7 @@ final class RectorContainerFactory
$environment = $this->createEnvironment($configFileInfos);
// mt_rand is needed to invalidate container cache in case of class changes to be registered as services
$rectorKernel = new RectorKernel($environment . mt_rand(0, 10000), $isDebug);
$rectorKernel = new RectorKernel($environment . mt_rand(0, 1000), $isDebug);
if ($configFileInfos !== []) {
$configFilePaths = $this->unpackRealPathsFromFileInfos($configFileInfos);
$rectorKernel->setConfigs($configFilePaths);

View File

@ -28,6 +28,9 @@ use Symplify\PhpConfigPrinter\Bundle\PhpConfigPrinterBundle;
use Symplify\SimplePhpDocParser\Bundle\SimplePhpDocParserBundle;
use Symplify\Skipper\Bundle\SkipperBundle;
/**
* @todo possibly remove symfony/http-kernel and use the container build only
*/
final class RectorKernel extends Kernel implements ExtraConfigAwareKernelInterface
{
/**

View File

@ -48,6 +48,10 @@ final class DowngradePathsCommand extends Command
$rulesPaths = $this->resolveRulesPaths();
$downgradePaths = array_merge($downgradePaths, $rulesPaths);
// make symplify grouped into 1 directory, to make covariance downgrade work with all dependent classes
$rulesPaths = $this->resolveRulesPaths();
$downgradePaths = array_merge($downgradePaths, $rulesPaths);
// make symplify grouped into 1 directory, to make covariance downgrade work with all dependent classes
foreach ($downgradePaths as $key => $downgradePath) {
if (Strings::startsWith($downgradePath, 'vendor/symplify')) {
@ -74,6 +78,7 @@ final class DowngradePathsCommand extends Command
// bash format
$downgradePathsLine = implode(';', $downgradePaths);
echo $downgradePathsLine . PHP_EOL;
return ShellCode::SUCCESS;