Code Coverage |
||||||||||
Lines |
Functions and Methods |
Classes and Traits |
||||||||
Total | |
0.00% |
0 / 33 |
|
0.00% |
0 / 2 |
CRAP | |
0.00% |
0 / 1 |
FullQualifiedClassNameSniff | |
0.00% |
0 / 33 |
|
0.00% |
0 / 2 |
272 | |
0.00% |
0 / 1 |
register | |
0.00% |
0 / 1 |
|
0.00% |
0 / 1 |
2 | |||
process | |
0.00% |
0 / 32 |
|
0.00% |
0 / 1 |
240 |
1 | <?php |
2 | |
3 | namespace MediaWiki\Sniffs\Classes; |
4 | |
5 | use PHP_CodeSniffer\Files\File; |
6 | use PHP_CodeSniffer\Sniffs\Sniff; |
7 | use PHP_CodeSniffer\Util\Tokens; |
8 | |
9 | /** |
10 | * Custom sniff that disallows full qualified class names outside of the "use …" section. |
11 | * Exceptions: |
12 | * - Full qualified class names in the main namespace (e.g. \Title) are allowed, by default. This is |
13 | * a very common code style in MediaWiki-related codebases. Removing these backslash characters |
14 | * doesn't really make code better readable. |
15 | * - Full qualified class names in "extends" and "implements" are allowed, by default. This is a |
16 | * very common code style, especially in tests. Since these can only appear once per class, and |
17 | * are guaranteed to be at the very top, moving them to "use" statements doesn't really make code |
18 | * better readable. |
19 | * - Function calls like \Wikimedia\suppressWarnings() are allowed, by default. |
20 | * |
21 | * Note this sniff is disabled by default. You need to increase it's severity in your .phpcs.xml to |
22 | * enable it. |
23 | * |
24 | * Example configuration: |
25 | * <rule ref="MediaWiki.Classes.FullQualifiedClassName"> |
26 | * <severity>5</severity> |
27 | * <properties> |
28 | * <property name="allowMainNamespace" value="false" /> |
29 | * <property name="allowInheritance" value="false" /> |
30 | * <property name="allowFunctions" value="false" /> |
31 | * </properties> |
32 | * </rule> |
33 | * |
34 | * Note this sniff currently does not check class names mentioned in PHPDoc comments. |
35 | * |
36 | * @author Thiemo Kreuz |
37 | */ |
38 | class FullQualifiedClassNameSniff implements Sniff { |
39 | |
40 | /** |
41 | * @var bool Allows full qualified class names in the main namespace, e.g. \Title |
42 | */ |
43 | public bool $allowMainNamespace = true; |
44 | |
45 | /** |
46 | * @var bool Allows to use full qualified class names in "extends" and "implements" |
47 | */ |
48 | public bool $allowInheritance = true; |
49 | |
50 | /** |
51 | * @var bool Allows function calls like \Wikimedia\suppressWarnings() |
52 | */ |
53 | public bool $allowFunctions = true; |
54 | |
55 | /** |
56 | * @inheritDoc |
57 | */ |
58 | public function register(): array { |
59 | return [ T_NS_SEPARATOR ]; |
60 | } |
61 | |
62 | /** |
63 | * @inheritDoc |
64 | */ |
65 | public function process( File $phpcsFile, $stackPtr ) { |
66 | $tokens = $phpcsFile->getTokens(); |
67 | |
68 | if ( !isset( $tokens[$stackPtr + 2] ) |
69 | // The current backslash is not the last one in the full qualified class name |
70 | || $tokens[$stackPtr + 2]['code'] === T_NS_SEPARATOR |
71 | // Some unexpected backslash that's not part of a class name |
72 | || $tokens[$stackPtr + 1]['code'] !== T_STRING |
73 | ) { |
74 | return; |
75 | } |
76 | |
77 | if ( $this->allowMainNamespace |
78 | && $tokens[$stackPtr - 1]['code'] !== T_STRING |
79 | ) { |
80 | return; |
81 | } |
82 | |
83 | if ( $this->allowFunctions |
84 | && $tokens[$stackPtr + 2]['code'] === T_OPEN_PARENTHESIS |
85 | ) { |
86 | return; |
87 | } |
88 | |
89 | $skip = Tokens::$emptyTokens; |
90 | $skip[] = T_STRING; |
91 | $skip[] = T_NS_SEPARATOR; |
92 | $prev = $phpcsFile->findPrevious( $skip, $stackPtr - 2, null, true ); |
93 | if ( !$prev ) { |
94 | return; |
95 | } |
96 | $prev = $tokens[$prev]['code']; |
97 | |
98 | // "namespace" and "use" statements must use full qualified class names |
99 | if ( $prev === T_NAMESPACE || $prev === T_USE ) { |
100 | return; |
101 | } |
102 | |
103 | if ( $this->allowInheritance |
104 | && ( $prev === T_EXTENDS || $prev === T_IMPLEMENTS ) |
105 | ) { |
106 | return; |
107 | } |
108 | |
109 | $phpcsFile->addError( |
110 | 'Full qualified class name "%s\\%s" found, please utilize "use …"', |
111 | $stackPtr, |
112 | 'Found', |
113 | [ |
114 | $tokens[$stackPtr - 1]['code'] === T_STRING ? '…' : '', |
115 | $tokens[$stackPtr + 1]['content'], |
116 | ] |
117 | ); |
118 | } |
119 | |
120 | } |