Skip to content

Commit

Permalink
BC promise rule for trait use
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed May 27, 2021
1 parent 995bc29 commit 929d7c4
Show file tree
Hide file tree
Showing 5 changed files with 140 additions and 0 deletions.
5 changes: 5 additions & 0 deletions conf/config.level0.neon
Original file line number Diff line number Diff line change
Expand Up @@ -15,6 +15,8 @@ conditionalTags:
phpstan.rules.rule: %featureToggles.apiRules%
PHPStan\Rules\Api\ApiStaticCallRule:
phpstan.rules.rule: %featureToggles.apiRules%
PHPStan\Rules\Api\ApiTraitUseRule:
phpstan.rules.rule: %featureToggles.apiRules%
PHPStan\Rules\Api\PhpStanNamespaceIn3rdPartyPackageRule:
phpstan.rules.rule: %featureToggles.apiRules%
PHPStan\Rules\Functions\ClosureUsesThisRule:
Expand Down Expand Up @@ -90,6 +92,9 @@ services:
-
class: PHPStan\Rules\Api\ApiStaticCallRule

-
class: PHPStan\Rules\Api\ApiTraitUseRule

-
class: PHPStan\Rules\Api\PhpStanNamespaceIn3rdPartyPackageRule

Expand Down
66 changes: 66 additions & 0 deletions src/Rules/Api/ApiTraitUseRule.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,66 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Api;

use PhpParser\Node;
use PHPStan\Analyser\Scope;
use PHPStan\Reflection\ReflectionProvider;
use PHPStan\Rules\Rule;
use PHPStan\Rules\RuleErrorBuilder;

/**
* @implements Rule<Node\Stmt\TraitUse>
*/
class ApiTraitUseRule implements Rule
{

private ApiRuleHelper $apiRuleHelper;

private ReflectionProvider $reflectionProvider;

public function __construct(
ApiRuleHelper $apiRuleHelper,
ReflectionProvider $reflectionProvider
)
{
$this->apiRuleHelper = $apiRuleHelper;
$this->reflectionProvider = $reflectionProvider;
}

public function getNodeType(): string
{
return Node\Stmt\TraitUse::class;
}

public function processNode(Node $node, Scope $scope): array
{
if ($this->apiRuleHelper->isInPhpStanNamespace($scope->getNamespace())) {
return [];
}

$errors = [];
$tip = sprintf(
"If you think it should be covered by backward compatibility promise, open a discussion:\n %s\n\n See also:\n https://phpstan.org/developing-extensions/backward-compatibility-promise",
'https://github.com/phpstan/phpstan/discussions'
);
foreach ($node->traits as $traitName) {
$traitName = $traitName->toString();
if (!$this->reflectionProvider->hasClass($traitName)) {
continue;
}

$traitReflection = $this->reflectionProvider->getClass($traitName);
if (!$this->apiRuleHelper->isInPhpStanNamespace($traitReflection->getName())) {
continue;
}

$errors[] = RuleErrorBuilder::message(sprintf(
'Using %s is not covered by backward compatibility promise. The trait might change in a minor PHPStan version.',
$traitReflection->getDisplayName()
))->tip($tip)->build();
}

return $errors;
}

}
39 changes: 39 additions & 0 deletions tests/PHPStan/Rules/Api/ApiTraitUseRuleTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
<?php declare(strict_types = 1);

namespace PHPStan\Rules\Api;

use PHPStan\Testing\RuleTestCase;

/**
* @extends RuleTestCase<ApiTraitUseRule>
*/
class ApiTraitUseRuleTest extends RuleTestCase
{

protected function getRule(): \PHPStan\Rules\Rule
{
return new ApiTraitUseRule(new ApiRuleHelper(), $this->createReflectionProvider());
}

public function testRuleInPhpStan(): void
{
$this->analyse([__DIR__ . '/data/trait-use-in-phpstan.php'], []);
}

public function testRuleOutOfPhpStan(): void
{
$tip = sprintf(
"If you think it should be covered by backward compatibility promise, open a discussion:\n %s\n\n See also:\n https://phpstan.org/developing-extensions/backward-compatibility-promise",
'https://github.com/phpstan/phpstan/discussions'
);

$this->analyse([__DIR__ . '/data/trait-use-out-of-phpstan.php'], [
[
'Using PHPStan\Type\JustNullableTypeTrait is not covered by backward compatibility promise. The trait might change in a minor PHPStan version.',
15,
$tip,
],
]);
}

}
12 changes: 12 additions & 0 deletions tests/PHPStan/Rules/Api/data/trait-use-in-phpstan.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php declare(strict_types = 1);

namespace PHPStan\TraitUse;

use PHPStan\Type\JustNullableTypeTrait;

class Foo
{

use JustNullableTypeTrait;

}
18 changes: 18 additions & 0 deletions tests/PHPStan/Rules/Api/data/trait-use-out-of-phpstan.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php declare(strict_types = 1);

namespace App\TraitUse;

use PHPStan\Type\JustNullableTypeTrait;

trait FooTrait
{

}

class Foo
{

use JustNullableTypeTrait;
use FooTrait;

}

0 comments on commit 929d7c4

Please sign in to comment.