-
Notifications
You must be signed in to change notification settings - Fork 1.5k
Expand file tree
/
Copy pathDisallowCompactArrayBuilderSniff.php
More file actions
159 lines (125 loc) · 4.75 KB
/
DisallowCompactArrayBuilderSniff.php
File metadata and controls
159 lines (125 loc) · 4.75 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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
<?php
/**
* Bans the use of compact() function
*
* @author Paweł Bogut <pbogut@pbogut.me>
* @copyright 2006-2023 Squiz Pty Ltd (ABN 77 084 670 600)
* @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
*/
namespace PHP_CodeSniffer\Standards\Generic\Sniffs\Arrays;
use PHP_CodeSniffer\Files\File;
use PHP_CodeSniffer\Sniffs\Sniff;
use PHP_CodeSniffer\Util\Tokens;
class DisallowCompactArrayBuilderSniff implements Sniff
{
protected const VARIABLE_NAME_PATTERN = '/^[a-zA-Z_\x80-\xff][a-zA-Z0-9_\x80-\xff]*$/';
/**
* Registers the tokens that this sniff wants to listen for.
*
* @return int[]
*/
public function register()
{
return [T_STRING];
}//end register()
/**
* Processes this test, when one of its tokens is encountered.
*
* @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
*
* @return void
*/
public function process(File $phpcsFile, $stackPtr)
{
$tokens = $phpcsFile->getTokens();
$content = $tokens[$stackPtr]['content'];
if (strtolower($content) !== 'compact') {
return;
}
// Make sure this is a function call.
$next = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true);
if ($next === false || $tokens[$next]['code'] !== T_OPEN_PARENTHESIS) {
// Not a function call.
return;
}
$prev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($stackPtr - 1), null, true);
$prevPrev = $phpcsFile->findPrevious(Tokens::$emptyTokens, ($prev - 1), null, true);
$ignorePrev = [
T_BITWISE_AND,
T_NS_SEPARATOR,
];
$excludedPrev = [
T_NULLSAFE_OBJECT_OPERATOR,
T_OBJECT_OPERATOR,
T_DOUBLE_COLON,
T_NEW,
T_NAMESPACE,
T_STRING,
T_FUNCTION,
];
$significantPrev = $prev;
if (in_array($tokens[$prev]['code'], $ignorePrev) === true) {
$significantPrev = $prevPrev;
}
// Make sure it is built-in function call.
if (in_array($tokens[$significantPrev]['code'], $excludedPrev) === true) {
// Not a built-in function call.
return;
}
$error = 'Array must not be created with compact() function';
// Make sure it is not prepended by bitwise operator.
if ($tokens[$prev]['code'] === T_BITWISE_AND) {
// Can not be fixed as &[] is not valid syntax.
$phpcsFile->addError($error, $stackPtr, 'Found');
return;
}
$fixable = false;
$toExpand = [];
$openPtr = $next;
$closePtr = null;
// Find all params in compact() function call, and check if it is fixable.
while (($next = $phpcsFile->findNext(Tokens::$emptyTokens, ($next + 1), null, true)) !== false) {
if ($tokens[$next]['code'] === T_CONSTANT_ENCAPSED_STRING) {
$variableName = substr($tokens[$next]['content'], 1, -1);
$isValid = preg_match(self::VARIABLE_NAME_PATTERN, $variableName);
if ($isValid === false || $isValid === 0) {
break;
}
$toExpand[] = $next;
continue;
}
if ($tokens[$next]['code'] === T_CLOSE_PARENTHESIS) {
$fixable = true;
$closePtr = $next;
break;
}
if ($tokens[$next]['code'] !== T_COMMA) {
break;
}
}//end while
if ($fixable === false) {
$phpcsFile->addError($error, $stackPtr, 'Found');
return;
}
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'Found');
if ($fix === true) {
$phpcsFile->fixer->beginChangeset();
if ($tokens[$prev]['code'] === T_NS_SEPARATOR) {
$phpcsFile->fixer->replaceToken($prev, '');
}
$phpcsFile->fixer->replaceToken($stackPtr, '');
$phpcsFile->fixer->replaceToken($openPtr, '[');
$phpcsFile->fixer->replaceToken($closePtr, ']');
foreach ($toExpand as $ptr) {
$variableName = substr($tokens[$ptr]['content'], 1, -1);
$phpcsFile->fixer->replaceToken(
$ptr,
$tokens[$ptr]['content'].' => $'.$variableName
);
}
$phpcsFile->fixer->endChangeset();
}//end if
}//end process()
}//end class