Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 29 |
|
0.00% |
0 / 4 |
CRAP | |
0.00% |
0 / 1 |
PHPUnitTestTrait | |
0.00% |
0 / 29 |
|
0.00% |
0 / 4 |
240 | |
0.00% |
0 / 1 |
isTestFile | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
20 | |||
isTestClass | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
20 | |||
isTestFunction | |
0.00% |
0 / 2 |
|
0.00% |
0 / 1 |
6 | |||
getClassToken | |
0.00% |
0 / 9 |
|
0.00% |
0 / 1 |
30 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Sniffs\PHPUnit; |
4 | |
5 | use PHP_CodeSniffer\Files\DummyFile; |
6 | use PHP_CodeSniffer\Files\File; |
7 | use PHP_CodeSniffer\Util\Tokens; |
8 | use PHPUnit\Framework\TestCase; |
9 | |
10 | /** |
11 | * Check if a class is a test class |
12 | * |
13 | * @license GPL-2.0-or-later |
14 | */ |
15 | trait PHPUnitTestTrait { |
16 | |
17 | /** |
18 | * Set of PHPUnit base classes, without leading backslash |
19 | * @var string[] |
20 | */ |
21 | private static $PHPUNIT_CLASSES = [ |
22 | // @phan-suppress-previous-line PhanReadOnlyPrivateProperty Traits cannot have constants |
23 | 'MediaWikiTestCase' => 'MediaWikiTestCase', |
24 | 'MediaWikiUnitTestCase' => 'MediaWikiUnitTestCase', |
25 | 'MediaWikiIntegrationTestCase' => 'MediaWikiIntegrationTestCase', |
26 | 'PHPUnit_Framework_TestCase' => 'PHPUnit_Framework_TestCase', |
27 | // This class may be 'used', but checking for that would be complicated |
28 | TestCase::class => TestCase::class, |
29 | ]; |
30 | |
31 | /** |
32 | * @var bool[] |
33 | */ |
34 | private static $isTestFile = []; |
35 | |
36 | /** |
37 | * @param File $phpcsFile |
38 | * @param int|false $stackPtr |
39 | * |
40 | * @return bool |
41 | */ |
42 | private function isTestFile( File $phpcsFile, $stackPtr = false ): bool { |
43 | $fileName = $phpcsFile->getFilename(); |
44 | |
45 | if ( !isset( self::$isTestFile[$fileName] ) ) { |
46 | $classToken = $this->getClassToken( $phpcsFile, $stackPtr ) ?: |
47 | $phpcsFile->findNext( Tokens::$ooScopeTokens, 0 ); |
48 | $isTestFile = $this->isTestClass( $phpcsFile, $classToken ); |
49 | |
50 | // There is no file but STDIN when Helper::runPhpCs() is used |
51 | if ( $phpcsFile instanceof DummyFile ) { |
52 | return $isTestFile; |
53 | } |
54 | |
55 | self::$isTestFile[$fileName] = $isTestFile; |
56 | } |
57 | |
58 | return self::$isTestFile[$fileName]; |
59 | } |
60 | |
61 | /** |
62 | * @param File $phpcsFile |
63 | * @param int|false $classToken Must point at a T_CLASS token |
64 | * |
65 | * @return bool |
66 | */ |
67 | private function isTestClass( File $phpcsFile, $classToken ): bool { |
68 | $tokens = $phpcsFile->getTokens(); |
69 | if ( !$classToken || $tokens[$classToken]['code'] !== T_CLASS ) { |
70 | return false; |
71 | } |
72 | |
73 | $extendedClass = ltrim( $phpcsFile->findExtendedClassName( $classToken ), '\\' ); |
74 | return array_key_exists( $extendedClass, self::$PHPUNIT_CLASSES ) || |
75 | (bool)preg_match( |
76 | '/(?:Test(?:Case)?(?:Base)?|Suite)$/', |
77 | $phpcsFile->getDeclarationName( $classToken ) |
78 | ); |
79 | } |
80 | |
81 | /** |
82 | * @param File $phpcsFile |
83 | * @param int $functionToken Token position of the function declaration |
84 | * @return bool |
85 | */ |
86 | private function isTestFunction( File $phpcsFile, $functionToken ): bool { |
87 | return $this->isTestClass( $phpcsFile, $this->getClassToken( $phpcsFile, $functionToken ) ) |
88 | && preg_match( '/^(?:test|provide)|Provider$/', $phpcsFile->getDeclarationName( $functionToken ) ); |
89 | } |
90 | |
91 | /** |
92 | * @param File $phpcsFile |
93 | * @param int|false $stackPtr Should point at the T_CLASS token or a token in the class |
94 | * |
95 | * @return int|false |
96 | */ |
97 | private function getClassToken( File $phpcsFile, $stackPtr ) { |
98 | if ( !$stackPtr ) { |
99 | return false; |
100 | } |
101 | |
102 | $tokens = $phpcsFile->getTokens(); |
103 | if ( $tokens[$stackPtr]['code'] === T_CLASS ) { |
104 | return $stackPtr; |
105 | } |
106 | |
107 | foreach ( $tokens[$stackPtr]['conditions'] as $ptr => $type ) { |
108 | if ( $type === T_CLASS ) { |
109 | return $ptr; |
110 | } |
111 | } |
112 | |
113 | return false; |
114 | } |
115 | |
116 | } |