Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[PHPStan] Add KeepRectorNamespaceForRectorRule #2850

Merged
merged 3 commits into from
Feb 13, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 0 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,6 @@ create-rector.yaml

# tests - travis
/laravel-dir
/utils

# compiler
/compiler/composer.lock
Expand Down
9 changes: 5 additions & 4 deletions composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -143,7 +143,8 @@
"Rector\\NetteToSymfony\\Tests\\": "rules/nette-to-symfony/tests",
"Rector\\Nette\\Tests\\": "packages/nette/tests",
"Rector\\NodeTypeResolver\\Tests\\": "packages/node-type-resolver/tests",
"Rector\\PHPStanExtensions\\": "utils/PHPStanExtensions/src",
"Rector\\PHPStanExtensions\\": "utils/phpstan-extensions/src",
"Rector\\PHPStanExtensions\\Tests\\": "utils/phpstan-extensions/tests",
"Rector\\PHPStan\\Tests\\": "rules/phpstan/tests",
"Rector\\PHPUnitSymfony\\Tests\\": "rules/phpunit-symfony/tests",
"Rector\\PHPUnit\\Tests\\": "rules/phpunit/tests",
Expand Down Expand Up @@ -178,9 +179,9 @@
"Rector\\DynamicTypeAnalysis\\Tests\\": "packages/dynamic-type-analysis/tests",
"Rector\\PhpDeglobalize\\Tests\\": "rules/php-deglobalize/tests",
"Rector\\Phalcon\\Tests\\": "rules/phalcon/tests",
"Rector\\Utils\\DocumentationGenerator\\": "utils/DocumentationGenerator/src",
"Rector\\Utils\\PHPStanAttributeTypeSyncer\\": "utils/PHPStanAttributeTypeSyncer/src",
"Rector\\Utils\\PHPStanStaticTypeMapperChecker\\": "utils/PHPStanStaticTypeMapperChecker/src",
"Rector\\Utils\\DocumentationGenerator\\": "utils/documentation-generator/src",
"Rector\\Utils\\PHPStanAttributeTypeSyncer\\": "utils/phpstan-attribute-type-syncer/src",
"Rector\\Utils\\PHPStanStaticTypeMapperChecker\\": "utils/phpstan-static-type-mapper-checker/src",
"Rector\\DoctrineGedmoToKnplabs\\Tests\\": "rules/doctrine-gedmo-to-knplabs/tests",
"Rector\\MinimalScope\\Tests\\": "rules/minimal-scope/tests",
"Rector\\Polyfill\\Tests\\": "packages/polyfill/tests",
Expand Down
3 changes: 0 additions & 3 deletions config/services.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -17,9 +17,6 @@ services:
- '../src/ValueObject/*'
- '../src/functions/*'

# extra services
Rector\Symfony\Rector\Form\Helper\FormTypeStringToTypeProvider: null

Symfony\Component\Console\Application:
alias: 'Rector\Core\Console\Application'

Expand Down
2 changes: 1 addition & 1 deletion ecs.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -93,7 +93,7 @@ parameters:
- "rules/coding-style/src/Rector/ClassMethod/NewlineBeforeNewAssignSetRector.php"

# per node logic
- 'utils/DocumentationGenerator/src/Command/DumpNodesCommand.php'
- 'utils/documentation-generator/src/Command/DumpNodesCommand.php'
# copied 3rd party logic
- 'rules/php-70/src/EregToPcreTransformer.php'
# dev
Expand Down
2 changes: 1 addition & 1 deletion phpstan.neon
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
includes:
- 'utils/PHPStanExtensions/config/phpstan-extensions.neon'
- 'utils/phpstan-extensions/config/phpstan-extensions.neon'
- 'vendor/symplify/phpstan-extensions/config/config.neon'
- 'vendor/thecodingmachine/phpstan-strict-rules/phpstan-strict-rules.neon'
- 'vendor/phpstan/phpstan/conf/bleedingEdge.neon'
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Rector\Symfony\Rector\Form\Helper;
namespace Rector\Symfony\FormHelper;

use Nette\Utils\Strings;

Expand Down
2 changes: 1 addition & 1 deletion rules/symfony/src/Rector/Form/FormTypeGetParentRector.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Rector\Symfony\Rector\Form\Helper\FormTypeStringToTypeProvider;
use Rector\Symfony\FormHelper\FormTypeStringToTypeProvider;
use Symfony\Component\Form\AbstractType;
use Symfony\Component\Form\AbstractTypeExtension;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
use Rector\Symfony\Rector\Form\Helper\FormTypeStringToTypeProvider;
use Rector\Symfony\FormHelper\FormTypeStringToTypeProvider;
use Symfony\Component\Form\FormBuilderInterface;

/**
Expand Down
2 changes: 1 addition & 1 deletion sonar-project.properties
Original file line number Diff line number Diff line change
Expand Up @@ -6,7 +6,7 @@ sonar.projectKey=rectorphp_rector
# wildcards don't work :(
sonar.sources=compiler/src,src,rules/autodiscovery/src,rules/architecture/src,packages/attribute-aware-php-doc/src,packages/better-php-doc-parser/src,rules/cakephp/src,rules/celebrity/src,rules/code-quality/src,rules/coding-style/src,packages/console-differ/src,rules/dead-code/src,rules/doctrine/src,rules/doctrine-code-quality/src,rules/framework-migration/src,packages/file-system-rector/src,rules/elastic-search-dsl/src,rules/guzzle/src,rules/laravel/src,packages/legacy/src,rules/mysql-to-mysqli/src,rules/nette-tester-to-phpunit/src,rules/nette-to-symfony/src,packages/nette/src,packages/node-collector/src,packages/node-type-resolver/src,packages/node-name-resolver/src,rules/phpstan/src,packages/phpstan-static-type-mapper/src,rules/phpunit-symfony/src,rules/phpunit/src,rules/psr4/src,rules/php-spec-to-phpunit/src,rules/php-52/src,rules/php-53/src,rules/php-54/src,rules/php-55/src,rules/php-56/src,rules/php-70/src,rules/php-71/src,rules/php-72/src,rules/php-73/src,rules/php-74/src,rules/php-80/src,rules/removing-static/src,rules/renaming/src,rules/restoration/src,packages/refactoring/src,rules/solid/src,rules/sensio/src,rules/shopware/src,rules/silverstripe/src,packages/static-type-mapper/src,rules/sylius/src,rules/symfony-code-quality/src,rules/symfony-phpunit/src,rules/symfony/src,rules/twig/src,rules/type-declaration/src,packages/vendor-locker/src,rules/zend-to-symfony/src,packages/rector-generator/src,rules/strict-code-quality/src,packages/dynamic-type-analysis/src,rules/php-deglobalize/src,rules/phalcon/src,rules/doctrine-gedmo-to-knplabs/src,rules/minimal-scope/src,packages/polyfill/src,rules/cakephp-to-symfony/src

sonar.tests=tests,rules/autodiscovery/tests,rules/architecture/tests,packages/better-php-doc-parser/tests,rules/cakephp/tests,rules/celebrity/tests,rules/code-quality/tests,rules/coding-style/tests,rules/dead-code/tests,rules/doctrine/tests,rules/doctrine-code-quality/tests,rules/elastic-search-dsl/tests,rules/guzzle/tests,rules/laravel/tests,packages/legacy/tests,rules/mysql-to-mysqli/tests,rules/nette-tester-to-phpunit/tests,rules/nette-to-symfony/tests,packages/nette/tests,packages/node-type-resolver/tests,utils/PHPStanExtensions/src,rules/phpstan/tests,rules/phpunit-symfony/tests,rules/phpunit/tests,rules/psr4/tests,rules/php-spec-to-phpunit/tests,rules/php-52/tests,rules/php-53/tests,rules/php-54/tests,rules/php-55/tests,rules/php-56/tests,rules/php-70/tests,rules/php-71/tests,rules/php-72/tests,rules/php-73/tests,rules/php-74/tests,rules/php-80/tests,rules/removing-static/tests,rules/renaming/tests,rules/restoration/tests,rules/solid/tests,rules/sensio/tests,rules/shopware/tests,rules/silverstripe/tests,rules/sylius/tests,rules/symfony-code-quality/tests,rules/symfony-phpunit/tests,rules/symfony/tests,rules/twig/tests,rules/type-declaration/tests,rules/zend-to-symfony/tests,rules/strict-code-quality/tests,packages/dynamic-type-analysis/tests,rules/php-deglobalize/tests,rules/phalcon/tests,utils/DocumentationGenerator/src,utils/PHPStanAttributeTypeSyncer/src,utils/PHPStanStaticTypeMapperChecker/src,rules/doctrine-gedmo-to-knplabs/tests,rules/minimal-scope/tests,packages/polyfill/tests,rules/cakephp-to-symfony/tests
sonar.tests=tests,rules/autodiscovery/tests,rules/architecture/tests,packages/better-php-doc-parser/tests,rules/cakephp/tests,rules/celebrity/tests,rules/code-quality/tests,rules/coding-style/tests,rules/dead-code/tests,rules/doctrine/tests,rules/doctrine-code-quality/tests,rules/elastic-search-dsl/tests,rules/guzzle/tests,rules/laravel/tests,packages/legacy/tests,rules/mysql-to-mysqli/tests,rules/nette-tester-to-phpunit/tests,rules/nette-to-symfony/tests,packages/nette/tests,packages/node-type-resolver/tests,utils/phpstan-extensions/src,rules/phpstan/tests,rules/phpunit-symfony/tests,rules/phpunit/tests,rules/psr4/tests,rules/php-spec-to-phpunit/tests,rules/php-52/tests,rules/php-53/tests,rules/php-54/tests,rules/php-55/tests,rules/php-56/tests,rules/php-70/tests,rules/php-71/tests,rules/php-72/tests,rules/php-73/tests,rules/php-74/tests,rules/php-80/tests,rules/removing-static/tests,rules/renaming/tests,rules/restoration/tests,rules/solid/tests,rules/sensio/tests,rules/shopware/tests,rules/silverstripe/tests,rules/sylius/tests,rules/symfony-code-quality/tests,rules/symfony-phpunit/tests,rules/symfony/tests,rules/twig/tests,rules/type-declaration/tests,rules/zend-to-symfony/tests,rules/strict-code-quality/tests,packages/dynamic-type-analysis/tests,rules/php-deglobalize/tests,rules/phalcon/tests,utils/documentation-generator/src,utils/phpstan-attribute-type-syncer/src,utils/phpstan-static-type-mapper-checker/src,rules/doctrine-gedmo-to-knplabs/tests,rules/minimal-scope/tests,packages/polyfill/tests,rules/cakephp-to-symfony/tests

# see https://docs.sonarqube.org/latest/project-administration/narrowing-the-focus/#NarrowingtheFocus-patterns
sonar.exclusions=src/**/*.php.inc,rules/**/*.php.inc,packages/**/*.php.inc,packages/**/Fixture/**/*,rules/**/Fixture/**/*,tests/**/Source/**/*
2 changes: 1 addition & 1 deletion src/Application/FileProcessor.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use Rector\Core\PhpParser\NodeTraverser\RectorNodeTraverser;
use Rector\Core\PhpParser\Parser\Parser;
use Rector\Core\PhpParser\Printer\FormatPerservingPrinter;
use Rector\Core\Rector\AffectedFilesCollector;
use Rector\Core\Report\AffectedFilesCollector;
use Rector\Core\Stubs\StubLoader;
use Rector\NodeTypeResolver\FileSystem\CurrentFileInfoProvider;
use Rector\NodeTypeResolver\NodeScopeAndMetadataDecorator;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Rector\Core\Configuration\Rector\Architecture\DependencyInjection;
namespace Rector\Core\Configuration\Collector;

use PHPStan\Type\Type;

Expand Down
2 changes: 1 addition & 1 deletion src/PhpParser/Node/Commander/NodeRemovingCommander.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@
use Rector\Core\Contract\PhpParser\Node\CommanderInterface;
use Rector\Core\Exception\ShouldNotHappenException;
use Rector\Core\PhpParser\Node\NodeVisitorFactory\NodeRemovingNodeVisitorFactory;
use Rector\Core\Rector\AffectedFilesCollector;
use Rector\Core\Report\AffectedFilesCollector;
use Rector\NodeTypeResolver\Node\AttributeKey;
use Symplify\SmartFileSystem\SmartFileInfo;

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
use PhpParser\Node\Stmt\Class_;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Type\ObjectType;
use Rector\Core\Configuration\Rector\Architecture\DependencyInjection\VariablesToPropertyFetchCollection;
use Rector\Core\Configuration\Collector\VariablesToPropertyFetchCollection;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
use PhpParser\Node\Expr\Variable;
use PhpParser\Node\Stmt\ClassMethod;
use PHPStan\Type\ObjectType;
use Rector\Core\Configuration\Rector\Architecture\DependencyInjection\VariablesToPropertyFetchCollection;
use Rector\Core\Configuration\Collector\VariablesToPropertyFetchCollection;
use Rector\Core\Rector\AbstractRector;
use Rector\Core\RectorDefinition\CodeSample;
use Rector\Core\RectorDefinition\RectorDefinition;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@

declare(strict_types=1);

namespace Rector\Core\Rector;
namespace Rector\Core\Report;

use Symplify\SmartFileSystem\SmartFileInfo;

Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
services:
- { class: Rector\PHPStanExtensions\Rule\ClassMethod\PreventParentMethodVisibilityOverrideRule, tags: [phpstan.rules.rule] }
- { class: Rector\PHPStanExtensions\Rule\ClassLike\KeepRectorNamespaceForRectorRule, tags: [phpstan.rules.rule] }

- Rector\PHPStanExtensions\Utils\PHPStanValueResolver

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,80 @@
<?php

declare(strict_types=1);

namespace Rector\PHPStanExtensions\Rule\ClassLike;

use Nette\Utils\Strings;
use PhpParser\Node;
use PhpParser\Node\Stmt\ClassLike;
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrorBuilder;

final class KeepRectorNamespaceForRectorRule implements Rule
{
public function getNodeType(): string
{
return ClassLike::class;
}

/**
* @param ClassLike $node
* @return RuleError[]
*/
public function processNode(Node $node, Scope $scope): array
{
if ($this->shouldSkip($node, $scope)) {
return [];
}

/** @var string $classLikeName */
$classLikeName = $node->name->toString();

$ruleError = $this->createRuleError($node, $scope, $classLikeName);

return [$ruleError];
}

private function shouldSkip(Node $node, Scope $scope): bool
{
$namespace = $scope->getNamespace();
if ($namespace === null) {
return true;
}

// skip interface and tests
if (Strings::match($namespace, '#\\\\(Contract|Exception|Tests)\\\\#')) {
return true;
}

if (! Strings::endsWith($namespace, '\\Rector') && ! Strings::match($namespace, '#\\\\Rector\\\\#')) {
return true;
}

$name = $node->name;
if ($name === null) {
return true;
}

// correct name
$classLikeName = $name->toString();

return (bool) Strings::match($classLikeName, '#(Rector|Test|Trait)$#');
}

private function createRuleError(Node $node, Scope $scope, string $classLikeName): RuleError
{
$message = sprintf(
'Change namespace for "%s". It cannot be in "Rector" namespace, unless Rector rule.',
$classLikeName
);

$ruleErrorBuilder = RuleErrorBuilder::message($message);
$ruleErrorBuilder->line($node->getLine());
$ruleErrorBuilder->file($scope->getFile());

return $ruleErrorBuilder->build();
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,8 @@
use PHPStan\Analyser\Scope;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleError;
use PHPStan\Rules\RuleErrors\RuleErrorWithMessageAndLineAndFile;
use Rector\Exception\NotImplementedException;
use PHPStan\Rules\RuleErrorBuilder;
use Rector\Core\Exception\NotImplementedException;
use ReflectionMethod;

final class PreventParentMethodVisibilityOverrideRule implements Rule
Expand Down Expand Up @@ -49,16 +49,7 @@ public function processNode(Node $node, Scope $scope): array

$methodVisibility = $this->resolveReflectionMethodVisibilityAsStrings($parentReflectionMethod);

$ruleError = new RuleErrorWithMessageAndLineAndFile(
sprintf(
'Change "%s()" method visibility to "%s" to respect parent method visibility.',
$methodName,
$methodVisibility
),
$node->getLine(),
$scope->getFile()
);

$ruleError = $this->createRuleError($node, $scope, $methodName, $methodVisibility);
return [$ruleError];
}

Expand Down Expand Up @@ -100,4 +91,19 @@ private function resolveReflectionMethodVisibilityAsStrings(ReflectionMethod $re

throw new NotImplementedException();
}

private function createRuleError(Node $node, Scope $scope, string $methodName, string $methodVisibility): RuleError
{
$message = sprintf(
'Change "%s()" method visibility to "%s" to respect parent method visibility.',
$methodName,
$methodVisibility
);

$ruleErrorBuilder = RuleErrorBuilder::message($message);
$ruleErrorBuilder->line($node->getLine());
$ruleErrorBuilder->file($scope->getFile());

return $ruleErrorBuilder->build();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php

declare(strict_types=1);

namespace Rector\PHPStanExtensions\Tests\Rule\ClassLike;

use Iterator;
use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
use Rector\PHPStanExtensions\Rule\ClassLike\KeepRectorNamespaceForRectorRule;

final class KeepRectorNamespaceForRectorRuleTest extends RuleTestCase
{
/**
* @param array<string|int> $expectedErrorsWithLines
* @dataProvider provideData()
*/
public function testRule(string $filePath, array $expectedErrorsWithLines): void
{
$this->analyse([$filePath], [$expectedErrorsWithLines]);
}

public function provideData(): Iterator
{
yield [__DIR__ . '/Source/Rector/ClassInCorrectNamespaceRector.php', []];
yield [
__DIR__ . '/Source/Rector/WrongClass.php',
['Change namespace for "WrongClass". It cannot be in Rector namespace, unless Rector rule.', 8],
];
}

protected function getRule(): Rule
{
return new KeepRectorNamespaceForRectorRule();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
<?php

declare(strict_types=1);

namespace Rector\PHPStanExtensions\Tests\Rule\ClassLike\Source\Rector;

final class ClassInCorrectNamespaceRector
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
<?php

declare(strict_types=1);


namespace Rector\PHPStanExtensions\Tests\Rule\ClassLike\Source\Rector;

final class WrongClass
{

}
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
<?php

declare(strict_types=1);

namespace Rector\PHPStanExtensions\Tests\Rule\ClassMethod;

use PHPStan\Rules\Rule;
use PHPStan\Testing\RuleTestCase;
use Rector\PHPStanExtensions\Rule\ClassMethod\PreventParentMethodVisibilityOverrideRule;

final class PreventParentMethodVisibilityOverrideRuleTest extends RuleTestCase
{
public function testRule(): void
{
$this->analyse(
[__DIR__ . '/Source/ClassWithOverridingVisibility.php'],
[['Change "run()" method visibility to "protected" to respect parent method visibility.', 10]]
);
}

protected function getRule(): Rule
{
return new PreventParentMethodVisibilityOverrideRule();
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<?php

declare(strict_types=1);


namespace Rector\PHPStanExtensions\Tests\Rule\ClassMethod\Source;

final class ClassWithOverridingVisibility extends GoodVisibility
{
public function run()
{
}
}

abstract class GoodVisibility
{
protected function run()
{

}
}