forked from pfrenssen/coder
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathUseGlobalClassSniff.php
More file actions
137 lines (114 loc) · 5.06 KB
/
UseGlobalClassSniff.php
File metadata and controls
137 lines (114 loc) · 5.06 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
<?php
/**
* \Drupal\Sniffs\Classes\UseGlobalClassSniff.
*
* @category PHP
* @package PHP_CodeSniffer
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
namespace Drupal\Sniffs\Classes;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Util\Tokens;
/**
* Checks non-namespaced classes are referenced by FQN, not imported.
*
* @category PHP
* @package PHP_CodeSniffer
* @link http://pear.php.net/package/PHP_CodeSniffer
*/
class UseGlobalClassSniff implements Sniff
{
/**
* Returns an array of tokens this test wants to listen for.
*
* @return array<int|string>
*/
public function register()
{
return [T_USE];
}
/**
* Processes this test, when one of its tokens is encountered.
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The PHP_CodeSniffer file where the
* token was found.
* @param int $stackPtr The position in the PHP_CodeSniffer
* file's token stack where the token
* was found.
*
* @return void|int Optionally returns a stack pointer. The sniff will not be
* called again on the current file until the returned stack
* pointer is reached. Return $phpcsFile->numTokens + 1 to skip
* the rest of the file.
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
// Make sure this is not a closure USE group.
$next = $phpcsFile->findNext(Tokens::EMPTY_TOKENS, ($stackPtr + 1), null, true);
if ($tokens[$next]['code'] === T_OPEN_PARENTHESIS) {
return;
}
// Find the first declaration, marking the end of the use statements.
$bodyStart = $phpcsFile->findNext([T_CLASS, T_INTERFACE, T_TRAIT, T_ENUM, T_FUNCTION], 0);
// Ensure we are in the global scope, to exclude trait use statements.
if (empty($tokens[$stackPtr]['conditions']) === false) {
return;
}
// End of the full statement.
$stmtEnd = $phpcsFile->findNext(T_SEMICOLON, $stackPtr);
$lineStart = $stackPtr;
// Iterate through a potential multiline use statement.
while (($lineEnd = $phpcsFile->findNext([T_SEMICOLON, T_COMMA], ($lineStart + 1), ($stmtEnd + 1))) !== false) {
// Skip function imports.
if ($phpcsFile->findNext(T_STRING, $lineStart, $lineEnd, false, 'function') !== false) {
$lineStart = $lineEnd;
continue;
}
$class = $phpcsFile->findNext(Tokens::NAME_TOKENS, $lineStart, $lineEnd);
$className = $tokens[$class]['content'];
if (strpos($className, '\\') !== false) {
// This is a namespaced class, skip it.
$lineStart = $lineEnd;
continue;
}
// If there is more than one string token, the last one is the alias.
$alias = $phpcsFile->findPrevious(T_STRING, $lineEnd, $stackPtr);
$aliasName = $tokens[$alias]['content'];
$error = 'Non-namespaced classes/interfaces/traits should not be referenced with use statements';
$fix = $phpcsFile->addFixableError($error, $class, 'RedundantUseStatement');
if ($fix === true) {
$phpcsFile->fixer->beginChangeset();
// Remove the entire line by default.
$start = $lineStart;
$end = $lineEnd;
$next = $phpcsFile->findNext(T_WHITESPACE, ($end + 1), null, true);
if ($tokens[$lineStart]['code'] === T_COMMA) {
// If there are lines before this one,
// then leave the ending delimiter in place.
$end = ($lineEnd - 1);
} elseif ($tokens[$lineEnd]['code'] === T_COMMA) {
// If there are lines after, but not before,
// then leave the use keyword.
$start = $class;
} elseif ($tokens[$next]['code'] === T_USE) {
// If the whole statement is removed, and there is one after it,
// then also remove the linebreaks.
$end = ($next - 1);
}
for ($i = $start; $i <= $end; $i++) {
$phpcsFile->fixer->replaceToken($i, '');
}
// Find all usages of the class, and add a leading backslash.
// Only start looking after the end of the use statement block.
$i = $bodyStart;
while (($i = $phpcsFile->findNext(T_STRING, ($i + 1), null, false, $aliasName)) !== false) {
$phpcsFile->fixer->replaceToken($i, '\\' . $className);
}
$phpcsFile->fixer->endChangeset();
}//end if
$lineStart = $lineEnd;
}//end while
}
}