Skip to content

Commit 083f566

Browse files
Merge pull request #24 from DaveLiddament/feature/allow-test-tag-on-class
UPDATE allow TestTag on class
2 parents 2d30213 + 68a2e82 commit 083f566

25 files changed

+433
-129
lines changed

composer.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@
66
"require": {
77
"php": "~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0",
88
"phpstan/phpstan": "^1.11",
9-
"dave-liddament/php-language-extensions": "^0.7.0"
9+
"dave-liddament/php-language-extensions": "^0.8.0"
1010
},
1111
"require-dev": {
1212
"phpunit/phpunit": "^9.6.12",

composer.lock

Lines changed: 7 additions & 7 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/Rules/AbstractTestTagRule.php

Lines changed: 20 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -40,25 +40,40 @@ protected function getErrorOrNull(
4040
string $class,
4141
string $methodName,
4242
): ?RuleError {
43+
$callingClass = $scope->getClassReflection()?->getName();
44+
4345
$classReflection = $this->reflectionProvider->getClass($class);
4446
$className = $classReflection->getName();
4547
$nativeReflection = $classReflection->getNativeReflection();
4648

4749
$fullMethodName = "{$className}::{$methodName}";
4850

51+
if ($this->cache->hasEntry($className)) {
52+
$isTestTagOnClass = $this->cache->getEntry($className);
53+
} else {
54+
$isTestTagOnClass = count($nativeReflection->getAttributes(TestTag::class)) > 0;
55+
$this->cache->addEntry($className, $isTestTagOnClass);
56+
}
57+
4958
if ($this->cache->hasEntry($fullMethodName)) {
50-
$isTestTag = $this->cache->getEntry($fullMethodName);
59+
$isTestTagOnMethod = $this->cache->getEntry($fullMethodName);
5160
} else {
5261
if ($nativeReflection->hasMethod($methodName)) {
5362
$methodReflection = $nativeReflection->getMethod($methodName);
54-
$isTestTag = count($methodReflection->getAttributes(TestTag::class)) > 0;
63+
$isTestTagOnMethod = count($methodReflection->getAttributes(TestTag::class)) > 0;
5564
} else {
56-
$isTestTag = false;
65+
$isTestTagOnMethod = false;
5766
}
58-
$this->cache->addEntry($fullMethodName, $isTestTag);
67+
$this->cache->addEntry($fullMethodName, $isTestTagOnMethod);
68+
}
69+
70+
$hasTestTag = $isTestTagOnClass || $isTestTagOnMethod;
71+
72+
if (!$hasTestTag) {
73+
return null;
5974
}
6075

61-
if (!$isTestTag) {
76+
if ($isTestTagOnClass && ($className === $callingClass)) {
6277
return null;
6378
}
6479

tests/Rules/AbstractTestTagRuleTest.php

Lines changed: 0 additions & 35 deletions
This file was deleted.
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DaveLiddament\PhpstanPhpLanguageExtensions\Tests\Rules;
6+
7+
use DaveLiddament\PhpstanPhpLanguageExtensions\Config\TestConfig;
8+
use DaveLiddament\PhpstanPhpLanguageExtensions\Rules\TestTagNewCallRule;
9+
use DaveLiddament\PhpstanRuleTestHelper\AbstractRuleTestCase;
10+
use DaveLiddament\PhpstanRuleTestHelper\ErrorMessageFormatter;
11+
use PHPStan\Rules\Rule;
12+
13+
/** @extends AbstractRuleTestCase<TestTagNewCallRule> */
14+
class TestTagClassOnConstructorIngoredOnTestClassTest extends AbstractRuleTestCase
15+
{
16+
protected function getRule(): Rule
17+
{
18+
return new TestTagNewCallRule(
19+
$this->createReflectionProvider(),
20+
new TestConfig(TestConfig::CLASS_NAME),
21+
);
22+
}
23+
24+
public function testMethodCall(): void
25+
{
26+
$this->assertIssuesReported(__DIR__.'/data/testTag/testTagClassOnConstructorIgnoredInTestClass.php');
27+
}
28+
29+
protected function getErrorFormatter(): ErrorMessageFormatter|string
30+
{
31+
return 'TestTagClassOnConstructorIgnoredOnTestClass\Person::__construct is a test tag and can only be called from test code';
32+
}
33+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DaveLiddament\PhpstanPhpLanguageExtensions\Tests\Rules;
6+
7+
use DaveLiddament\PhpstanPhpLanguageExtensions\Config\TestConfig;
8+
use DaveLiddament\PhpstanPhpLanguageExtensions\Rules\TestTagNewCallRule;
9+
use DaveLiddament\PhpstanRuleTestHelper\AbstractRuleTestCase;
10+
use DaveLiddament\PhpstanRuleTestHelper\ErrorMessageFormatter;
11+
use PHPStan\Rules\Rule;
12+
13+
/** @extends AbstractRuleTestCase<TestTagNewCallRule> */
14+
class TestTagClassOnConstructorTest extends AbstractRuleTestCase
15+
{
16+
protected function getRule(): Rule
17+
{
18+
return new TestTagNewCallRule(
19+
$this->createReflectionProvider(),
20+
new TestConfig(TestConfig::CLASS_NAME),
21+
);
22+
}
23+
24+
public function testMethodCall(): void
25+
{
26+
$this->assertIssuesReported(__DIR__.'/data/testTag/testTagClassOnConstructor.php');
27+
}
28+
29+
protected function getErrorFormatter(): ErrorMessageFormatter|string
30+
{
31+
return 'TestTagClassOnConstructor\Person::__construct is a test tag and can only be called from test code';
32+
}
33+
}
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DaveLiddament\PhpstanPhpLanguageExtensions\Tests\Rules;
6+
7+
use DaveLiddament\PhpstanPhpLanguageExtensions\Config\TestConfig;
8+
use DaveLiddament\PhpstanPhpLanguageExtensions\Rules\TestTagMethodCallRule;
9+
use DaveLiddament\PhpstanRuleTestHelper\AbstractRuleTestCase;
10+
use PHPStan\Rules\Rule;
11+
12+
/** @extends AbstractRuleTestCase<TestTagMethodCallRule> */
13+
class TestTagClassOnMethodIgnoredOnTestClassTest extends AbstractRuleTestCase
14+
{
15+
protected function getRule(): Rule
16+
{
17+
return new TestTagMethodCallRule(
18+
$this->createReflectionProvider(),
19+
new TestConfig(TestConfig::CLASS_NAME),
20+
);
21+
}
22+
23+
public function testMethodCall(): void
24+
{
25+
$this->assertIssuesReported(
26+
__DIR__.'/data/testTag/testTagClassOnMethodIgnoredInTestClass.php',
27+
);
28+
}
29+
}
Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,33 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DaveLiddament\PhpstanPhpLanguageExtensions\Tests\Rules;
6+
7+
use DaveLiddament\PhpstanPhpLanguageExtensions\Config\TestConfig;
8+
use DaveLiddament\PhpstanPhpLanguageExtensions\Rules\TestTagMethodCallRule;
9+
use DaveLiddament\PhpstanRuleTestHelper\AbstractRuleTestCase;
10+
use DaveLiddament\PhpstanRuleTestHelper\ErrorMessageFormatter;
11+
use PHPStan\Rules\Rule;
12+
13+
/** @extends AbstractRuleTestCase<TestTagMethodCallRule> */
14+
class TestTagClassOnMethodTest extends AbstractRuleTestCase
15+
{
16+
protected function getRule(): Rule
17+
{
18+
return new TestTagMethodCallRule(
19+
$this->createReflectionProvider(),
20+
new TestConfig(TestConfig::CLASS_NAME),
21+
);
22+
}
23+
24+
public function testMethodCall(): void
25+
{
26+
$this->assertIssuesReported(__DIR__.'/data/testTag/testTagClassOnMethod.php');
27+
}
28+
29+
protected function getErrorFormatter(): ErrorMessageFormatter|string
30+
{
31+
return 'TestTagClassOnMethod\Person::updateName is a test tag and can only be called from test code';
32+
}
33+
}
Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,27 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DaveLiddament\PhpstanPhpLanguageExtensions\Tests\Rules;
6+
7+
use DaveLiddament\PhpstanPhpLanguageExtensions\Config\TestConfig;
8+
use DaveLiddament\PhpstanPhpLanguageExtensions\Rules\TestTagStaticCallRule;
9+
use DaveLiddament\PhpstanRuleTestHelper\AbstractRuleTestCase;
10+
use PHPStan\Rules\Rule;
11+
12+
/** @extends AbstractRuleTestCase<TestTagStaticCallRule> */
13+
class TestTagClassOnStaticIgnoredOnTestClassTest extends AbstractRuleTestCase
14+
{
15+
protected function getRule(): Rule
16+
{
17+
return new TestTagStaticCallRule(
18+
$this->createReflectionProvider(),
19+
new TestConfig(TestConfig::CLASS_NAME),
20+
);
21+
}
22+
23+
public function testMethodCall(): void
24+
{
25+
$this->assertIssuesReported(__DIR__.'/data/testTag/testTagClassOnStaticMethodIgnoredInTestClass.php');
26+
}
27+
}
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
<?php
2+
3+
declare(strict_types=1);
4+
5+
namespace DaveLiddament\PhpstanPhpLanguageExtensions\Tests\Rules;
6+
7+
use DaveLiddament\PhpstanPhpLanguageExtensions\Config\TestConfig;
8+
use DaveLiddament\PhpstanPhpLanguageExtensions\Rules\TestTagStaticCallRule;
9+
use DaveLiddament\PhpstanRuleTestHelper\AbstractRuleTestCase;
10+
use PHPStan\Rules\Rule;
11+
12+
/** @extends AbstractRuleTestCase<TestTagStaticCallRule> */
13+
final class TestTagClassOnStaticTest extends AbstractRuleTestCase
14+
{
15+
protected function getRule(): Rule
16+
{
17+
return new TestTagStaticCallRule(
18+
$this->createReflectionProvider(),
19+
new TestConfig(TestConfig::CLASS_NAME),
20+
);
21+
}
22+
23+
public function testMethodCall(): void
24+
{
25+
$this->assertIssuesReported(__DIR__.'/data/testTag/testTagClassOnStaticMethod.php');
26+
}
27+
28+
protected function getErrorFormatter(): string
29+
{
30+
return 'TestTagClassOnStaticMethod\Person::updateName is a test tag and can only be called from test code';
31+
}
32+
}

tests/Rules/TestTagOnConstructorIgnoredInTestNamespaceTest.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66

77
use DaveLiddament\PhpstanPhpLanguageExtensions\Config\TestConfig;
88
use DaveLiddament\PhpstanPhpLanguageExtensions\Rules\TestTagNewCallRule;
9+
use DaveLiddament\PhpstanRuleTestHelper\AbstractRuleTestCase;
910
use PHPStan\Rules\Rule;
1011

11-
/** @extends AbstractTestTagRuleTest<TestTagNewCallRule> */
12-
class TestTagOnConstructorIgnoredInTestNamespaceTest extends AbstractTestTagRuleTest
12+
/** @extends AbstractRuleTestCase<TestTagNewCallRule> */
13+
class TestTagOnConstructorIgnoredInTestNamespaceTest extends AbstractRuleTestCase
1314
{
1415
protected function getRule(): Rule
1516
{
@@ -24,7 +25,7 @@ protected function getRule(): Rule
2425

2526
public function testMethodCall(): void
2627
{
27-
$this->assertNoErrorsReported(
28+
$this->assertIssuesReported(
2829
__DIR__.'/data/testTag/testTagOnConstructorIgnoredInTestNamespace.php',
2930
);
3031
}

tests/Rules/TestTagOnConstructorIgnoredOnTestClassTest.php

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,11 @@
66

77
use DaveLiddament\PhpstanPhpLanguageExtensions\Config\TestConfig;
88
use DaveLiddament\PhpstanPhpLanguageExtensions\Rules\TestTagNewCallRule;
9+
use DaveLiddament\PhpstanRuleTestHelper\AbstractRuleTestCase;
910
use PHPStan\Rules\Rule;
1011

11-
/** @extends AbstractTestTagRuleTest<TestTagNewCallRule> */
12-
class TestTagOnConstructorIgnoredOnTestClassTest extends AbstractTestTagRuleTest
12+
/** @extends AbstractRuleTestCase<TestTagNewCallRule> */
13+
class TestTagOnConstructorIgnoredOnTestClassTest extends AbstractRuleTestCase
1314
{
1415
protected function getRule(): Rule
1516
{
@@ -21,7 +22,7 @@ protected function getRule(): Rule
2122

2223
public function testMethodCall(): void
2324
{
24-
$this->assertNoErrorsReported(
25+
$this->assertIssuesReported(
2526
__DIR__.'/data/testTag/testTagOnConstructorIgnoredInTestClass.php',
2627
);
2728
}

0 commit comments

Comments
 (0)