diff --git a/src/PHPStan/DataProviderMethodResolver.php b/src/PHPStan/DataProviderMethodResolver.php deleted file mode 100644 index fbdbf00..0000000 --- a/src/PHPStan/DataProviderMethodResolver.php +++ /dev/null @@ -1,32 +0,0 @@ -getDocComment(); - if (! $docComment instanceof Doc) { - return null; - } - - if (! str_contains($docComment->getText(), '@dataProvider')) { - return null; - } - - preg_match('/@dataProvider\s+(?\w+)/', $docComment->getText(), $matches); - - // reference to static call on another class - if (! isset($matches['method_name'])) { - return null; - } - - return $matches['method_name']; - } -} diff --git a/src/PHPStan/DoctrineEntityDocumentAnalyser.php b/src/PHPStan/DoctrineEntityDocumentAnalyser.php deleted file mode 100644 index 347a226..0000000 --- a/src/PHPStan/DoctrineEntityDocumentAnalyser.php +++ /dev/null @@ -1,32 +0,0 @@ -getResolvedPhpDoc(); - if (! $resolvedPhpDocBlock instanceof ResolvedPhpDocBlock) { - return false; - } - - foreach (self::ENTITY_DOCBLOCK_MARKERS as $entityDocBlockMarkers) { - if (str_contains($resolvedPhpDocBlock->getPhpDocString(), $entityDocBlockMarkers)) { - return true; - } - } - - return false; - } -} diff --git a/src/PHPStan/PHPUnitTestAnalyser.php b/src/PHPStan/PHPUnitTestAnalyser.php deleted file mode 100644 index b431647..0000000 --- a/src/PHPStan/PHPUnitTestAnalyser.php +++ /dev/null @@ -1,40 +0,0 @@ -getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return false; - } - - return $classReflection->isSubclassOf(self::TEST_CASE_CLASS); - } - - public static function isTestClassMethod(ClassMethod $classMethod): bool - { - if (! $classMethod->isPublic()) { - return false; - } - - if (! $classMethod->isMagic()) { - return true; - } - - return str_starts_with($classMethod->name->toString(), 'test'); - } -} diff --git a/src/PHPStan/Rule/NoAbstractControllerConstructorRule.php b/src/PHPStan/Rule/NoAbstractControllerConstructorRule.php deleted file mode 100644 index ca70d9d..0000000 --- a/src/PHPStan/Rule/NoAbstractControllerConstructorRule.php +++ /dev/null @@ -1,61 +0,0 @@ - - */ -final class NoAbstractControllerConstructorRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Abstract controller should not have constructor, to avoid override by child classes. Use #[Require] or @require and autowire() method instead'; - - public function getNodeType(): string - { - return Class_::class; - } - - /** - * @param Class_ $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->isAbstract()) { - return []; - } - - if (! $node->name instanceof Identifier) { - return []; - } - - $className = $node->name->toString(); - if (! str_ends_with($className, 'Controller')) { - return []; - } - - if (! $node->getMethod('__construct')) { - return []; - } - - $ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)->build(); - return [$ruleError]; - } -} diff --git a/src/PHPStan/Rule/NoConstructorOverrideRule.php b/src/PHPStan/Rule/NoConstructorOverrideRule.php deleted file mode 100644 index 66976e1..0000000 --- a/src/PHPStan/Rule/NoConstructorOverrideRule.php +++ /dev/null @@ -1,75 +0,0 @@ - - */ -final class NoConstructorOverrideRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Possible __construct() override, this can cause missing dependencies or setup'; - - /** - * @var string - */ - private const CONSTRUCTOR_NAME = '__construct'; - - public function getNodeType(): string - { - return ClassMethod::class; - } - - /** - * @param ClassMethod $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! fast_node_named($node->name, self::CONSTRUCTOR_NAME)) { - return []; - } - - if ($node->stmts === null) { - return []; - } - - // has parent constructor call? - if (! $scope->isInClass()) { - return []; - } - - if (! fast_has_parent_constructor($scope)) { - return []; - } - - $nodeFinder = new NodeFinder(); - $parentConstructorStaticCall = $nodeFinder->findFirst($node->stmts, function (Node $node): bool { - if (! $node instanceof StaticCall) { - return false; - } - - return fast_node_named($node->name, self::CONSTRUCTOR_NAME); - }); - - if ($parentConstructorStaticCall instanceof StaticCall) { - return []; - } - - $ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)->build(); - return [$ruleError]; - } -} diff --git a/src/PHPStan/Rule/NoDocumentMockingRule.php b/src/PHPStan/Rule/NoDocumentMockingRule.php deleted file mode 100644 index 65ecfbe..0000000 --- a/src/PHPStan/Rule/NoDocumentMockingRule.php +++ /dev/null @@ -1,59 +0,0 @@ - - */ -final class NoDocumentMockingRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Instead of document mocking, create object directly to get better type support'; - - public function getNodeType(): string - { - return MethodCall::class; - } - - /** - * @param MethodCall $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($node->isFirstClassCallable()) { - return []; - } - - if (! $node->name instanceof Identifier) { - return []; - } - - $methodName = $node->name->toString(); - if ($methodName !== 'createMock') { - return []; - } - - $firstArg = $node->getArgs()[0]; - $mockedClassType = $scope->getType($firstArg->value); - foreach ($mockedClassType->getConstantStrings() as $constantString) { - if (! str_contains($constantString->getValue(), '\\Document\\')) { - continue; - } - - return [self::ERROR_MESSAGE]; - } - - return []; - } -} diff --git a/src/PHPStan/Rule/NoEntityMockingRule.php b/src/PHPStan/Rule/NoEntityMockingRule.php deleted file mode 100644 index d4432c4..0000000 --- a/src/PHPStan/Rule/NoEntityMockingRule.php +++ /dev/null @@ -1,86 +0,0 @@ - - */ -final readonly class NoEntityMockingRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Instead of entity or document mocking, create object directly to get better type support'; - - public function __construct( - private ReflectionProvider $reflectionProvider - ) { - } - - public function getNodeType(): string - { - return MethodCall::class; - } - - /** - * @param MethodCall $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $this->isCreateMockMethod($node)) { - return []; - } - - $firstArg = $node->getArgs()[0]; - $mockedClassType = $scope->getType($firstArg->value); - - foreach ($mockedClassType->getConstantStrings() as $constantStringType) { - if (! $this->reflectionProvider->hasClass($constantStringType->getValue())) { - continue; - } - - $classReflection = $this->reflectionProvider->getClass($constantStringType->getValue()); - if (! DoctrineEntityDocumentAnalyser::isEntityClass($classReflection)) { - continue; - } - - $ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->build(); - - return [$ruleError]; - } - - return []; - } - - private function isCreateMockMethod(MethodCall $methodCall): bool - { - if ($methodCall->isFirstClassCallable()) { - return false; - } - - if (! $methodCall->name instanceof Identifier) { - return false; - } - - $methodName = $methodCall->name->toString(); - return $methodName === 'createMock'; - } -} diff --git a/src/PHPStan/Rule/NoGetRepositoryOutsideServiceRule.php b/src/PHPStan/Rule/NoGetRepositoryOutsideServiceRule.php deleted file mode 100644 index 92ea43b..0000000 --- a/src/PHPStan/Rule/NoGetRepositoryOutsideServiceRule.php +++ /dev/null @@ -1,63 +0,0 @@ - - */ -final class NoGetRepositoryOutsideServiceRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Instead of getting repository from EntityManager, use constructor injection and service pattern to keep code clean'; - - public function getNodeType(): string - { - return MethodCall::class; - } - - /** - * @param MethodCall $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->name instanceof Identifier) { - return []; - } - - if ($node->name->toString() !== 'getRepository') { - return []; - } - - if (! $scope->isInClass()) { - $ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)->build(); - return [$ruleError]; - } - - // dummy check - $classReflection = $scope->getClassReflection(); - if (str_ends_with($classReflection->getName(), 'Repository')) { - return []; - } - - $ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)->build(); - return [$ruleError]; - } -} diff --git a/src/PHPStan/Rule/NoListenerWithoutContractRule.php b/src/PHPStan/Rule/NoListenerWithoutContractRule.php deleted file mode 100644 index 1bb2910..0000000 --- a/src/PHPStan/Rule/NoListenerWithoutContractRule.php +++ /dev/null @@ -1,61 +0,0 @@ - - */ -final class NoListenerWithoutContractRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'There should be no listeners defined in yaml config, use contract + PHP instead'; - - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $scope->isInClass()) { - return []; - } - - $classReflection = $scope->getClassReflection(); - if (! str_ends_with($classReflection->getName(), 'Listener')) { - return []; - } - - $class = $node->getOriginalNode(); - if (! $class instanceof Class_) { - return []; - } - - if ($class->implements !== []) { - return []; - } - - $ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)->build(); - - return [$ruleError]; - } -} diff --git a/src/PHPStan/Rule/NoMockOnlyTestRule.php b/src/PHPStan/Rule/NoMockOnlyTestRule.php deleted file mode 100644 index e6ff2a4..0000000 --- a/src/PHPStan/Rule/NoMockOnlyTestRule.php +++ /dev/null @@ -1,80 +0,0 @@ - - */ -final readonly class NoMockOnlyTestRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Test should have at least one non-mocked property, to test something'; - - /** - * @var string - */ - private const MOCK_OBJECT_CLASS = 'PHPUnit\Framework\MockObject\MockObject'; - - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! PHPUnitTestAnalyser::isTestClass($scope)) { - return []; - } - - $classLike = $node->getOriginalNode(); - if (! $classLike instanceof Class_) { - return []; - } - - if ($classLike->getProperties() === []) { - return []; - } - - $hasExclusivelyMockedProperties = true; - - foreach ($classLike->getProperties() as $property) { - if (! $property->type instanceof Name) { - continue; - } - - $propertyClassName = $property->type->toString(); - - if ($propertyClassName !== self::MOCK_OBJECT_CLASS) { - $hasExclusivelyMockedProperties = false; - } - } - - if ($hasExclusivelyMockedProperties === false) { - return []; - } - - $ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->build(); - return [$ruleError]; - } -} diff --git a/src/PHPStan/Rule/NoParentRepositoryRule.php b/src/PHPStan/Rule/NoParentRepositoryRule.php deleted file mode 100644 index cbd8b3a..0000000 --- a/src/PHPStan/Rule/NoParentRepositoryRule.php +++ /dev/null @@ -1,60 +0,0 @@ - - */ -final class NoParentRepositoryRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Extending EntityRepository is not allowed, use constructor injection and pass entity manager instead'; - - /** - * @var string - */ - private const ENTITY_REPOSITORY_CLASS = 'Doctrine\ORM\EntityRepository'; - - public function getNodeType(): string - { - return Class_::class; - } - - /** - * @param Class_ $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->extends instanceof Name) { - return []; - } - - $parentClass = $node->extends->toString(); - if ($parentClass !== self::ENTITY_REPOSITORY_CLASS) { - return []; - } - - $ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->build(); - - return [$ruleError]; - } -} diff --git a/src/PHPStan/Rule/NoRepositoryCallInDataFixtureRule.php b/src/PHPStan/Rule/NoRepositoryCallInDataFixtureRule.php deleted file mode 100644 index bcba4f2..0000000 --- a/src/PHPStan/Rule/NoRepositoryCallInDataFixtureRule.php +++ /dev/null @@ -1,70 +0,0 @@ - - */ -final class NoRepositoryCallInDataFixtureRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Refactor read-data fixtures to write-only, make use of references'; - - /** - * @var string - */ - private const FIXTURE_INTERFACE = 'Doctrine\Common\DataFixtures\FixtureInterface'; - - public function getNodeType(): string - { - return MethodCall::class; - } - - /** - * @param MethodCall $node - * @return string[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($node->isFirstClassCallable()) { - return []; - } - - if (! $this->isDataFixtureClass($scope)) { - return []; - } - - if (! $node->name instanceof Identifier) { - return []; - } - - $methodName = $node->name->toString(); - if (! in_array($methodName, ['getRepository', 'find', 'findAll', 'findBy', 'findOneBy'])) { - return []; - } - - return [self::ERROR_MESSAGE]; - } - - private function isDataFixtureClass(Scope $scope): bool - { - if (! $scope->isInClass()) { - return false; - } - - $classReflection = $scope->getClassReflection(); - return $classReflection->isSubclassOf(self::FIXTURE_INTERFACE); - } -} diff --git a/src/PHPStan/Rule/NoRequiredOutsideClassRule.php b/src/PHPStan/Rule/NoRequiredOutsideClassRule.php deleted file mode 100644 index c769c2f..0000000 --- a/src/PHPStan/Rule/NoRequiredOutsideClassRule.php +++ /dev/null @@ -1,71 +0,0 @@ - - */ -final class NoRequiredOutsideClassRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'Symfony #[Require]/@required should be used only in classes to avoid missuse'; - - /** - * @var string - */ - private const REQUIRED_ATTRIBUTE = 'Symfony\Contracts\Service\Attribute\Required'; - - public function getNodeType(): string - { - return Trait_::class; - } - - /** - * @param Trait_ $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - $ruleErrors = []; - - foreach ($node->getMethods() as $classMethod) { - if ($this->isAutowiredClassMethod($classMethod)) { - $ruleErrors[] = RuleErrorBuilder::message(self::ERROR_MESSAGE) - ->file($scope->getFile()) - ->line($classMethod->getLine()) - ->build(); - } - } - - return $ruleErrors; - } - - private function isAutowiredClassMethod(ClassMethod $classMethod): bool - { - foreach ($classMethod->getAttrGroups() as $attributeGroup) { - foreach ($attributeGroup->attrs as $attr) { - if ($attr->name->toString() === self::REQUIRED_ATTRIBUTE) { - return true; - } - } - } - - $docComment = $classMethod->getDocComment(); - return $docComment instanceof Doc && str_contains($docComment->getText(), '@required'); - } -} diff --git a/src/PHPStan/Rule/NoStringInGetSubscribedEventsRule.php b/src/PHPStan/Rule/NoStringInGetSubscribedEventsRule.php deleted file mode 100644 index 05cbfef..0000000 --- a/src/PHPStan/Rule/NoStringInGetSubscribedEventsRule.php +++ /dev/null @@ -1,104 +0,0 @@ - - */ -final class NoStringInGetSubscribedEventsRule implements Rule -{ - /** - * @var string - */ - private const EVENT_SUBSCRIBER_INTERFACE = 'Symfony\Component\EventDispatcher\EventSubscriberInterface'; - - /** - * @var string - */ - private const ERROR_MESSAGE = 'Symfony getSubscribedEvents() method must contain only event class references, no strings'; - - public function getNodeType(): string - { - return ClassMethod::class; - } - - /** - * @param ClassMethod $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - if ($node->stmts === null) { - return []; - } - - if ($node->name->toString() !== 'getSubscribedEvents') { - return []; - } - - $classReflection = $scope->getClassReflection(); - if (! $classReflection instanceof ClassReflection) { - return []; - } - - // only handle symfony one - if (! $classReflection->implementsInterface(self::EVENT_SUBSCRIBER_INTERFACE)) { - return []; - } - - $nodeFinder = new NodeFinder(); - - /** @var ArrayItem[] $arrayItems */ - $arrayItems = $nodeFinder->findInstanceOf($node->stmts, ArrayItem::class); - - foreach ($arrayItems as $arrayItem) { - if (! $arrayItem->key instanceof Expr) { - continue; - } - - // must be class const fetch - if ($arrayItem->key instanceof ClassConstFetch) { - $classConstFetch = $arrayItem->key; - - if ($classConstFetch->class instanceof Expr) { - continue; - } - - // skip Symfony FormEvents::class - if ($classConstFetch->class->toString() === ClassName::FORM_EVENTS) { - continue; - } - - if ($classConstFetch->name instanceof Expr) { - continue; - } - - if ($classConstFetch->name->toString() === 'class') { - continue; - } - - continue; - } - - $ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)->build(); - return [$ruleError]; - } - - return []; - } -} diff --git a/src/PHPStan/Rule/PublicStaticDataProviderRule.php b/src/PHPStan/Rule/PublicStaticDataProviderRule.php deleted file mode 100644 index 09e4adb..0000000 --- a/src/PHPStan/Rule/PublicStaticDataProviderRule.php +++ /dev/null @@ -1,86 +0,0 @@ - - */ -final class PublicStaticDataProviderRule implements Rule -{ - /** - * @api used in test - * @var string - */ - public const PUBLIC_ERROR_MESSAGE = 'PHPUnit data provider method "%s" must be public'; - - /** - * @api used in test - * @var string - */ - public const STATIC_ERROR_MESSAGE = 'PHPUnit data provider method "%s" must be static'; - - public function getNodeType(): string - { - return InClassNode::class; - } - - /** - * @param InClassNode $node - */ - public function processNode(Node $node, Scope $scope): array - { - if (! PHPUnitTestAnalyser::isTestClass($scope)) { - return []; - } - - $ruleErrors = []; - - $classLike = $node->getOriginalNode(); - foreach ($classLike->getMethods() as $classMethod) { - if (! PHPUnitTestAnalyser::isTestClassMethod($classMethod)) { - continue; - } - - $dataProviderMethodName = DataProviderMethodResolver::match($classMethod); - if (! is_string($dataProviderMethodName)) { - continue; - } - - $dataProviderClassMethod = $classLike->getMethod($dataProviderMethodName); - if (! $dataProviderClassMethod instanceof ClassMethod) { - continue; - } - - if (! $dataProviderClassMethod->isStatic()) { - $errorMessage = sprintf(self::STATIC_ERROR_MESSAGE, $dataProviderMethodName); - $ruleErrors[] = RuleErrorBuilder::message($errorMessage) - ->identifier('phpunit.staticDataProvider') - ->line($dataProviderClassMethod->getLine()) - ->build(); - } - - if (! $dataProviderClassMethod->isStatic()) { - $errorMessage = sprintf(self::PUBLIC_ERROR_MESSAGE, $dataProviderMethodName); - $ruleErrors[] = RuleErrorBuilder::message($errorMessage) - ->identifier('phpunit.publicDataProvider') - ->line($dataProviderClassMethod->getLine()) - ->build(); - } - } - - return $ruleErrors; - } -} diff --git a/src/PHPStan/Rule/SingleArgEventDispatchRule.php b/src/PHPStan/Rule/SingleArgEventDispatchRule.php deleted file mode 100644 index b1f2868..0000000 --- a/src/PHPStan/Rule/SingleArgEventDispatchRule.php +++ /dev/null @@ -1,63 +0,0 @@ - - */ -final class SingleArgEventDispatchRule implements Rule -{ - /** - * @var string - */ - public const ERROR_MESSAGE = 'The event dispatch() method can have only 1 arg - the event object'; - - public function getNodeType(): string - { - return MethodCall::class; - } - - /** - * @param MethodCall $node - * @return RuleError[] - */ - public function processNode(Node $node, Scope $scope): array - { - if (! $node->name instanceof Identifier) { - return []; - } - - if ($node->name->toString() !== 'dispatch') { - return []; - } - - // all good - if (count($node->getArgs()) === 1) { - return []; - } - - $callerType = $scope->getType($node->var); - if (! $callerType instanceof ObjectType) { - return []; - } - - if (! $callerType->isInstanceOf(ClassName::EVENT_DISPATCHER_INTERFACE)->yes()) { - return []; - } - - $ruleError = RuleErrorBuilder::message(self::ERROR_MESSAGE)->build(); - return [$ruleError]; - } -} diff --git a/templates/downgrade/.github/workflows/downgraded_release.yaml b/templates/downgrade/.github/workflows/downgraded_release.yaml new file mode 100644 index 0000000..411dd78 --- /dev/null +++ b/templates/downgrade/.github/workflows/downgraded_release.yaml @@ -0,0 +1,67 @@ +name: Downgraded Release + +on: + push: + tags: + # avoid infinite looping, skip tags that ends with ".72" + # see https://docs.github.com/en/actions/using-workflows/workflow-syntax-for-github-actions#example-including-and-excluding-branches + - '*' + +jobs: + downgrade_release: + runs-on: ubuntu-latest + + steps: + - + uses: "actions/checkout@v3" + with: + token: ${{ secrets.ACCESS_TOKEN }} + + - + uses: "shivammathur/setup-php@v2" + with: + php-version: 8.2 + coverage: none + + # invoke patches + - run: composer install --ansi + + # but no dev packages + - run: composer update --no-dev --ansi + + # get rector to "rector-local" directory, to avoid downgrading itself in the /vendor + - run: mkdir rector-local + - run: composer require rector/rector --working-dir rector-local --ansi + + # downgrade to PHP 7.2 + - run: rector-local/vendor/bin/rector process src bin vendor --config build/rector-downgrade-php-72.php --ansi + + # clear the dev files + - run: rm -rf tests ecs.php phpstan.neon phpunit.xml .gitignore .editorconfig + + # prefix and scope + - run: sh prefix-code.sh + + # copy PHP 7.2 composer + workflows + - run: cp -r build/target-repository/. . + + # clear the dev files + - run: rm -rf build prefix-code.sh full-tool-build.sh scoper.php rector.php rector-local php-scoper.phar + + # setup git user + - + run: | + git config user.email "action@github.com" + git config user.name "GitHub Action" + # publish to the same repository with a new tag + # see https://tomasvotruba.com/blog/how-to-release-php-81-and-72-package-in-the-same-repository/ + - + name: "Tag Downgraded Code" + run: | + # separate a "git add" to add untracked (new) files too + git add --all + git commit -m "release PHP 7.2 downgraded" + + # force push tag, so there is only 1 version + git tag "${GITHUB_REF#refs/tags/}" --force + git push origin "${GITHUB_REF#refs/tags/}" --force diff --git a/templates/downgrade/build/rector-downgrade-php-72.php b/templates/downgrade/build/rector-downgrade-php-72.php new file mode 100644 index 0000000..beb46ce --- /dev/null +++ b/templates/downgrade/build/rector-downgrade-php-72.php @@ -0,0 +1,14 @@ +withDowngradeSets(php72: true) + ->withSkip([ + // typical tests locations + '*/Tests/*', + '*/tests/*', + __DIR__ . '/../../tests', + ]); diff --git a/templates/downgrade/prefix-code.sh b/templates/downgrade/prefix-code.sh new file mode 100644 index 0000000..6066ce5 --- /dev/null +++ b/templates/downgrade/prefix-code.sh @@ -0,0 +1,49 @@ +#!/usr/bin/env bash + +# inspired from https://github.com/rectorphp/rector/blob/main/build/build-rector-scoped.sh + +# 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 + + +# functions +note() +{ + MESSAGE=$1; + printf "\n"; + echo "\033[0;33m[NOTE] $MESSAGE\033[0m"; +} + +# --------------------------- + +# 2. scope it +note "Downloading php-scoper 0.18.3" +wget https://github.com/humbug/php-scoper/releases/download/0.18.3/php-scoper.phar -N --no-verbose + + +note "Running php-scoper" + +# Work around possible PHP memory limits +# @todo detect dirs, that exist +php -d memory_limit=-1 php-scoper.phar add-prefix src bin vendor composer.json --config scoper.php --force --ansi --output-dir scoped-code + +# the output code is in "/scoped-code", lets move it up +# the local directories have to be empty to move easily +rm -r src bin vendor composer.json +mv scoped-code/* . + +note "Dumping Composer Autoload" +composer dump-autoload --ansi --classmap-authoritative --no-dev + +# make bin runnable without "php" +# @todo detect bin files if any +chmod 777 "bin/class-leak" +chmod 777 "bin/class-leak.php" + +note "Finished" \ No newline at end of file diff --git a/templates/downgrade/scoper.php b/templates/downgrade/scoper.php new file mode 100644 index 0000000..5c788ea --- /dev/null +++ b/templates/downgrade/scoper.php @@ -0,0 +1,23 @@ +format('Ym'); + +// see https://github.com/humbug/php-scoper +return [ + // @todo detect :) + 'prefix' => 'ClassLeak' . $timestamp, + 'expose-constants' => ['#^SYMFONY\_[\p{L}_]+$#'], + // @todo detect + 'exclude-namespaces' => ['#^TomasVotruba\\\\ClassLeak#', '#^Symfony\\\\Polyfill#'], + 'exclude-files' => [ + // do not prefix "trigger_deprecation" from symfony - https://github.com/symfony/symfony/commit/0032b2a2893d3be592d4312b7b098fb9d71aca03 + // these paths are relative to this file location, so it should be in the root directory + 'vendor/symfony/deprecation-contracts/function.php', + ], + 'patchers' => [], +]; diff --git a/tests/PHPStan/Rule/NoAbstractControllerConstructorRule/Fixture/SkipNonAbstractController.php b/tests/PHPStan/Rule/NoAbstractControllerConstructorRule/Fixture/SkipNonAbstractController.php deleted file mode 100644 index 04bc149..0000000 --- a/tests/PHPStan/Rule/NoAbstractControllerConstructorRule/Fixture/SkipNonAbstractController.php +++ /dev/null @@ -1,12 +0,0 @@ -analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public static function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SomeAbstractController.php', [[ - NoAbstractControllerConstructorRule::ERROR_MESSAGE, - 7, - ]]]; - - yield [__DIR__ . '/Fixture/SkipNonAbstractController.php', []]; - } - - protected function getRule(): Rule - { - return new NoAbstractControllerConstructorRule(); - } -} diff --git a/tests/PHPStan/Rule/NoEntityMockingRule/Fixture/MockingDocument.php b/tests/PHPStan/Rule/NoEntityMockingRule/Fixture/MockingDocument.php deleted file mode 100644 index d14d9aa..0000000 --- a/tests/PHPStan/Rule/NoEntityMockingRule/Fixture/MockingDocument.php +++ /dev/null @@ -1,14 +0,0 @@ -createMock(SomeDocument::class); - } -} diff --git a/tests/PHPStan/Rule/NoEntityMockingRule/Fixture/MockingEntity.php b/tests/PHPStan/Rule/NoEntityMockingRule/Fixture/MockingEntity.php deleted file mode 100644 index 8b891f9..0000000 --- a/tests/PHPStan/Rule/NoEntityMockingRule/Fixture/MockingEntity.php +++ /dev/null @@ -1,14 +0,0 @@ -createMock(SomeEntity::class); - } -} diff --git a/tests/PHPStan/Rule/NoEntityMockingRule/Fixture/SkipMockingOtherObject.php b/tests/PHPStan/Rule/NoEntityMockingRule/Fixture/SkipMockingOtherObject.php deleted file mode 100644 index f65adcc..0000000 --- a/tests/PHPStan/Rule/NoEntityMockingRule/Fixture/SkipMockingOtherObject.php +++ /dev/null @@ -1,14 +0,0 @@ -createMock(SimpleObject::class); - } -} diff --git a/tests/PHPStan/Rule/NoEntityMockingRule/NoEntityMockingRuleTest.php b/tests/PHPStan/Rule/NoEntityMockingRule/NoEntityMockingRuleTest.php deleted file mode 100644 index d53f7c6..0000000 --- a/tests/PHPStan/Rule/NoEntityMockingRule/NoEntityMockingRuleTest.php +++ /dev/null @@ -1,41 +0,0 @@ -analyse([$filePath], $expectedErrorsWithLines); - } - - public static function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/MockingEntity.php', [[NoEntityMockingRule::ERROR_MESSAGE, 12]]]; - - yield [__DIR__ . '/Fixture/MockingDocument.php', [[NoEntityMockingRule::ERROR_MESSAGE, 12]]]; - - yield [__DIR__ . '/Fixture/SkipMockingOtherObject.php', []]; - } - - /** - * @return string[] - */ - public static function getAdditionalConfigFiles(): array - { - return [__DIR__ . '/config/configured_rule.neon']; - } - - protected function getRule(): Rule - { - $container = self::getContainer(); - return $container->getByType(NoEntityMockingRule::class); - } -} diff --git a/tests/PHPStan/Rule/NoEntityMockingRule/Source/SimpleObject.php b/tests/PHPStan/Rule/NoEntityMockingRule/Source/SimpleObject.php deleted file mode 100644 index 68a43bd..0000000 --- a/tests/PHPStan/Rule/NoEntityMockingRule/Source/SimpleObject.php +++ /dev/null @@ -1,7 +0,0 @@ -entityManager->getRepository(self::class); - } -} diff --git a/tests/PHPStan/Rule/NoGetRepositoryOutsideServiceRule/Fixture/SkipInRepository.php b/tests/PHPStan/Rule/NoGetRepositoryOutsideServiceRule/Fixture/SkipInRepository.php deleted file mode 100644 index a53e907..0000000 --- a/tests/PHPStan/Rule/NoGetRepositoryOutsideServiceRule/Fixture/SkipInRepository.php +++ /dev/null @@ -1,17 +0,0 @@ -entityManager->getRepository(SomeRandomEntity::class); - } -} diff --git a/tests/PHPStan/Rule/NoGetRepositoryOutsideServiceRule/NoGetRepositoryOutsideServiceRuleTest.php b/tests/PHPStan/Rule/NoGetRepositoryOutsideServiceRule/NoGetRepositoryOutsideServiceRuleTest.php deleted file mode 100644 index d0cfeeb..0000000 --- a/tests/PHPStan/Rule/NoGetRepositoryOutsideServiceRule/NoGetRepositoryOutsideServiceRuleTest.php +++ /dev/null @@ -1,38 +0,0 @@ -analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public static function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/NonRepositoryUsingEntityManager.php', [[ - NoGetRepositoryOutsideServiceRule::ERROR_MESSAGE, - 18, - ]]]; - - yield [__DIR__ . '/Fixture/SkipInRepository.php', []]; - } - - protected function getRule(): Rule - { - return new NoGetRepositoryOutsideServiceRule(); - } -} diff --git a/tests/PHPStan/Rule/NoGetRepositoryOutsideServiceRule/Source/SomeRandomEntity.php b/tests/PHPStan/Rule/NoGetRepositoryOutsideServiceRule/Source/SomeRandomEntity.php deleted file mode 100644 index 998bba1..0000000 --- a/tests/PHPStan/Rule/NoGetRepositoryOutsideServiceRule/Source/SomeRandomEntity.php +++ /dev/null @@ -1,7 +0,0 @@ -firstClass = new FirstClass(); - - $this->anotherMock = $this->createMock(SecondClass::class); - } -} diff --git a/tests/PHPStan/Rule/NoMockOnlyTestRule/Fixture/SomeTestWithOnlyMocks.php b/tests/PHPStan/Rule/NoMockOnlyTestRule/Fixture/SomeTestWithOnlyMocks.php deleted file mode 100644 index 382b3c4..0000000 --- a/tests/PHPStan/Rule/NoMockOnlyTestRule/Fixture/SomeTestWithOnlyMocks.php +++ /dev/null @@ -1,21 +0,0 @@ -someMock = $this->createMock(FirstClass::class); - - $this->anotherMock = $this->createMock(SecondClass::class); - } -} diff --git a/tests/PHPStan/Rule/NoMockOnlyTestRule/NoMockOnlyTestRuleTest.php b/tests/PHPStan/Rule/NoMockOnlyTestRule/NoMockOnlyTestRuleTest.php deleted file mode 100644 index 434f658..0000000 --- a/tests/PHPStan/Rule/NoMockOnlyTestRule/NoMockOnlyTestRuleTest.php +++ /dev/null @@ -1,36 +0,0 @@ -analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public static function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SomeTestWithOnlyMocks.php', [[NoMockOnlyTestRule::ERROR_MESSAGE, 9]]]; - - yield [__DIR__ . '/Fixture/SkipTestWithClass.php', []]; - yield [__DIR__ . '/Fixture/SkipNoProperty.php', []]; - } - - protected function getRule(): Rule - { - return new NoMockOnlyTestRule(); - } -} diff --git a/tests/PHPStan/Rule/NoMockOnlyTestRule/Source/FirstClass.php b/tests/PHPStan/Rule/NoMockOnlyTestRule/Source/FirstClass.php deleted file mode 100644 index 958991b..0000000 --- a/tests/PHPStan/Rule/NoMockOnlyTestRule/Source/FirstClass.php +++ /dev/null @@ -1,7 +0,0 @@ -analyse([$filePath], $expectedErrorMessagesWithLines); - } - - public static function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/SomeRepository.php', [[NoParentRepositoryRule::ERROR_MESSAGE, 9]]]; - } - - protected function getRule(): Rule - { - return new NoParentRepositoryRule(); - } -} diff --git a/tests/PHPStan/Rule/NoRepositoryCallInDataFixtureRule/Fixture/SkipNonFixtureClass.php b/tests/PHPStan/Rule/NoRepositoryCallInDataFixtureRule/Fixture/SkipNonFixtureClass.php deleted file mode 100644 index 748d7d2..0000000 --- a/tests/PHPStan/Rule/NoRepositoryCallInDataFixtureRule/Fixture/SkipNonFixtureClass.php +++ /dev/null @@ -1,17 +0,0 @@ -getRepository('someEntity'); - - $alsoNotAllowed = $notAllowed->find(5); - } -} diff --git a/tests/PHPStan/Rule/NoRepositoryCallInDataFixtureRule/Fixture/SomeRepositoryCallInFixture.php b/tests/PHPStan/Rule/NoRepositoryCallInDataFixtureRule/Fixture/SomeRepositoryCallInFixture.php deleted file mode 100644 index 4660b5a..0000000 --- a/tests/PHPStan/Rule/NoRepositoryCallInDataFixtureRule/Fixture/SomeRepositoryCallInFixture.php +++ /dev/null @@ -1,18 +0,0 @@ -getRepository('someEntity'); - - $alsoNotAllowed = $notAllowed->find(5); - } -} diff --git a/tests/PHPStan/Rule/NoRepositoryCallInDataFixtureRule/NoRepositoryCallInDataFixtureRuleTest.php b/tests/PHPStan/Rule/NoRepositoryCallInDataFixtureRule/NoRepositoryCallInDataFixtureRuleTest.php deleted file mode 100644 index 4b50d48..0000000 --- a/tests/PHPStan/Rule/NoRepositoryCallInDataFixtureRule/NoRepositoryCallInDataFixtureRuleTest.php +++ /dev/null @@ -1,38 +0,0 @@ -analyse([$filePath], $expectedErrorsWithLines); - } - - public static function provideData(): Iterator - { - yield [ - __DIR__ . '/Fixture/SomeRepositoryCallInFixture.php', - [ - [NoRepositoryCallInDataFixtureRule::ERROR_MESSAGE, 14], - [NoRepositoryCallInDataFixtureRule::ERROR_MESSAGE, 16], - ], - ]; - - yield [__DIR__ . '/Fixture/SkipNonFixtureClass.php', []]; - } - - protected function getRule(): Rule - { - return new NoRepositoryCallInDataFixtureRule(); - } -} diff --git a/tests/PHPStan/Rule/NoRequiredOutsideClassRule/Fixture/SomeClassUsingTrait.php b/tests/PHPStan/Rule/NoRequiredOutsideClassRule/Fixture/SomeClassUsingTrait.php deleted file mode 100644 index 7c58cbb..0000000 --- a/tests/PHPStan/Rule/NoRequiredOutsideClassRule/Fixture/SomeClassUsingTrait.php +++ /dev/null @@ -1,9 +0,0 @@ -analyse($filePaths, $expectedErrorsWithLines); - } - - public static function provideData(): Iterator - { - yield [[ - __DIR__ . '/Fixture/SomeClassUsingTrait.php', - __DIR__ . '/Fixture/TraitWithRequireAttribute.php', - __DIR__ . '/Fixture/TraitWithRequire.php', - ], [[NoRequiredOutsideClassRule::ERROR_MESSAGE, 9], [NoRequiredOutsideClassRule::ERROR_MESSAGE, 10]]]; - } - - protected function getRule(): Rule - { - return new NoRequiredOutsideClassRule(); - } -} diff --git a/tests/PHPStan/Rule/PublicStaticDataProviderRule/Fixture/SkipStaticTest.php b/tests/PHPStan/Rule/PublicStaticDataProviderRule/Fixture/SkipStaticTest.php deleted file mode 100644 index a830b28..0000000 --- a/tests/PHPStan/Rule/PublicStaticDataProviderRule/Fixture/SkipStaticTest.php +++ /dev/null @@ -1,20 +0,0 @@ -analyse($filePaths, $expectedErrorsWithLines); - } - - public static function provideData(): Iterator - { - yield [[__DIR__ . '/Fixture/SomeSimpleTest.php'], [ - [sprintf(PublicStaticDataProviderRule::STATIC_ERROR_MESSAGE, 'provideData'), 16], - [sprintf(PublicStaticDataProviderRule::PUBLIC_ERROR_MESSAGE, 'provideData'), 16], - ]]; - - yield [[__DIR__ . '/Fixture/SkipStaticTest.php'], []]; - } - - protected function getRule(): Rule - { - return new PublicStaticDataProviderRule(); - } -} diff --git a/tests/PHPStan/Rule/SingleArgEventDispatchRule/Fixture/ReportEventDispatcher.php b/tests/PHPStan/Rule/SingleArgEventDispatchRule/Fixture/ReportEventDispatcher.php deleted file mode 100644 index f1aa438..0000000 --- a/tests/PHPStan/Rule/SingleArgEventDispatchRule/Fixture/ReportEventDispatcher.php +++ /dev/null @@ -1,13 +0,0 @@ -dispatch('one', 'two'); - } -} diff --git a/tests/PHPStan/Rule/SingleArgEventDispatchRule/Fixture/SkipSingleDispatch.php b/tests/PHPStan/Rule/SingleArgEventDispatchRule/Fixture/SkipSingleDispatch.php deleted file mode 100644 index e32b96f..0000000 --- a/tests/PHPStan/Rule/SingleArgEventDispatchRule/Fixture/SkipSingleDispatch.php +++ /dev/null @@ -1,13 +0,0 @@ -dispatch('one'); - } -} diff --git a/tests/PHPStan/Rule/SingleArgEventDispatchRule/Fixture/SkipUnrelatedDispatch.php b/tests/PHPStan/Rule/SingleArgEventDispatchRule/Fixture/SkipUnrelatedDispatch.php deleted file mode 100644 index 849878d..0000000 --- a/tests/PHPStan/Rule/SingleArgEventDispatchRule/Fixture/SkipUnrelatedDispatch.php +++ /dev/null @@ -1,13 +0,0 @@ -dispatch('one', 'two'); - } -} diff --git a/tests/PHPStan/Rule/SingleArgEventDispatchRule/SingleArgEventDispatchRuleTest.php b/tests/PHPStan/Rule/SingleArgEventDispatchRule/SingleArgEventDispatchRuleTest.php deleted file mode 100644 index 62ed6ee..0000000 --- a/tests/PHPStan/Rule/SingleArgEventDispatchRule/SingleArgEventDispatchRuleTest.php +++ /dev/null @@ -1,36 +0,0 @@ -analyse([$filePath], $expectedErrorsWithLines); - } - - public static function provideData(): Iterator - { - yield [__DIR__ . '/Fixture/ReportEventDispatcher.php', [[SingleArgEventDispatchRule::ERROR_MESSAGE, 11]]]; - - yield [__DIR__ . '/Fixture/SkipSingleDispatch.php', []]; - yield [__DIR__ . '/Fixture/SkipUnrelatedDispatch.php', []]; - } - - protected function getRule(): Rule - { - return new SingleArgEventDispatchRule(); - } -} diff --git a/tests/PHPStan/Rule/SingleArgEventDispatchRule/Source/NotEventDispatcher.php b/tests/PHPStan/Rule/SingleArgEventDispatchRule/Source/NotEventDispatcher.php deleted file mode 100644 index 1cba5c4..0000000 --- a/tests/PHPStan/Rule/SingleArgEventDispatchRule/Source/NotEventDispatcher.php +++ /dev/null @@ -1,11 +0,0 @@ -