@@ -54,6 +54,7 @@ protected function processTokenWithinScope( File $phpcsFile, $stackPtr, $currSco
54
54
$ tokens = $ phpcsFile ->getTokens ();
55
55
56
56
if ( $ tokens [ $ stackPtr ]['content ' ] !== $ this ->delete_option ) {
57
+ // delete_option is not first function found.
57
58
$ stackPtr = $ phpcsFile ->findNext (
58
59
[ T_STRING ],
59
60
$ stackPtr + 1 ,
@@ -78,23 +79,58 @@ protected function processTokenWithinScope( File $phpcsFile, $stackPtr, $currSco
78
79
return ; // Not a function call, bail.
79
80
}
80
81
81
- $ delete_option_semicolon = $ phpcsFile ->findNext (
82
- [ T_SEMICOLON ] ,
83
- $ tokens [ $ delete_option_scope_start ][ ' parenthesis_closer ' ] + 1 ,
82
+ $ delete_option_name = $ phpcsFile ->findNext (
83
+ Tokens:: $ emptyTokens ,
84
+ $ delete_option_scope_start + 1 ,
84
85
null ,
85
- false
86
+ true
86
87
);
87
88
88
- $ delete_option_key = $ phpcsFile ->findNext (
89
+ $ delete_option_concat = $ phpcsFile ->findNext (
89
90
Tokens::$ emptyTokens ,
90
- $ delete_option_scope_start + 1 ,
91
+ $ delete_option_name + 1 ,
91
92
null ,
92
93
true
93
94
);
94
95
96
+ $ delete_option_name = $ this ->trim_strip_quotes ( $ tokens [ $ delete_option_name ]['content ' ] );
97
+
98
+ $ is_delete_option_concat = $ tokens [ $ delete_option_concat ]['code ' ] === T_STRING_CONCAT ;
99
+ if ( $ is_delete_option_concat ) {
100
+ // If option name is concatenated, we need to build it out.
101
+ $ delete_option_concat = $ phpcsFile ->findNext (
102
+ Tokens::$ emptyTokens ,
103
+ $ delete_option_concat + 1 ,
104
+ null ,
105
+ true
106
+ );
107
+
108
+ while ( $ delete_option_concat < $ tokens [ $ delete_option_scope_start ]['parenthesis_closer ' ] ) {
109
+ $ delete_option_name .= $ this ->trim_strip_quotes ( $ tokens [ $ delete_option_concat ]['content ' ] );
110
+
111
+ $ delete_option_concat = $ phpcsFile ->findNext (
112
+ array_merge ( Tokens::$ emptyTokens , [ T_STRING_CONCAT ] ),
113
+ $ delete_option_concat + 1 ,
114
+ null ,
115
+ true
116
+ );
117
+ }
118
+ }
119
+
120
+ $ delete_option_scope_end = $ phpcsFile ->findNext (
121
+ [ T_SEMICOLON ],
122
+ $ tokens [ $ delete_option_scope_start ]['parenthesis_closer ' ] + 1 ,
123
+ null ,
124
+ false
125
+ );
126
+
127
+ if ( ! $ delete_option_scope_end ) {
128
+ return ; // Something went wrong with the syntax.
129
+ }
130
+
95
131
$ add_option = $ phpcsFile ->findNext (
96
132
Tokens::$ emptyTokens ,
97
- $ delete_option_semicolon + 1 ,
133
+ $ delete_option_scope_end + 1 ,
98
134
null ,
99
135
true
100
136
);
@@ -126,15 +162,55 @@ protected function processTokenWithinScope( File $phpcsFile, $stackPtr, $currSco
126
162
return ; // Not a function call, bail.
127
163
}
128
164
129
- $ add_option_inside_if_option_key = $ phpcsFile ->findNext (
165
+ $ add_option_inside_if_option_name = $ phpcsFile ->findNext (
130
166
Tokens::$ emptyTokens ,
131
167
$ add_option_inside_if_scope_start + 1 ,
132
168
null ,
133
169
true
134
170
);
135
171
136
- if ( $ add_option_inside_if_option_key && $ this ->is_same_option_key ( $ tokens , $ add_option_inside_if_option_key , $ delete_option_key ) ) {
137
- $ phpcsFile ->addWarning ( $ message , $ add_option_inside_if_option_key , 'OptionsRaceCondition ' );
172
+ $ add_option_inside_if_concat = $ phpcsFile ->findNext (
173
+ Tokens::$ emptyTokens ,
174
+ $ add_option_inside_if_option_name + 1 ,
175
+ null ,
176
+ true
177
+ );
178
+
179
+ $ add_option_inside_if_option_name = $ this ->trim_strip_quotes ( $ tokens [ $ add_option_inside_if_option_name ]['content ' ] );
180
+
181
+ if ( $ is_delete_option_concat && $ tokens [ $ add_option_inside_if_concat ]['code ' ] === T_STRING_CONCAT ) {
182
+ $ add_option_inside_if_concat = $ phpcsFile ->findNext (
183
+ array_merge ( Tokens::$ emptyTokens , [ T_STRING_CONCAT ] ),
184
+ $ add_option_inside_if_concat + 1 ,
185
+ null ,
186
+ true
187
+ );
188
+
189
+ $ add_option_inside_if_scope_end = $ phpcsFile ->findNext (
190
+ [ T_COMMA ],
191
+ $ add_option_inside_if_concat + 1 ,
192
+ null ,
193
+ false
194
+ );
195
+
196
+ if ( ! $ add_option_inside_if_scope_end ) {
197
+ return ; // Something went wrong.
198
+ }
199
+
200
+ while ( $ add_option_inside_if_concat < $ add_option_inside_if_scope_end ) {
201
+ $ add_option_inside_if_option_name .= $ this ->trim_strip_quotes ( $ tokens [ $ add_option_inside_if_concat ]['content ' ] );
202
+
203
+ $ add_option_inside_if_concat = $ phpcsFile ->findNext (
204
+ array_merge ( Tokens::$ emptyTokens , [ T_STRING_CONCAT ] ),
205
+ $ add_option_inside_if_concat + 1 ,
206
+ null ,
207
+ true
208
+ );
209
+ }
210
+ }
211
+
212
+ if ( $ this ->is_same_option_key ( $ delete_option_name , $ add_option_inside_if_option_name ) ) {
213
+ $ phpcsFile ->addWarning ( $ message , $ add_option_inside_if_scope_start , 'OptionsRaceCondition ' );
138
214
}
139
215
140
216
// Walk ahead out of IF control structure.
@@ -180,16 +256,54 @@ protected function processTokenWithinScope( File $phpcsFile, $stackPtr, $currSco
180
256
return ; // Not a function call, bail.
181
257
}
182
258
183
- // Check if it's the same option being deleted earlier.
184
- $ add_option_key = $ phpcsFile ->findNext (
259
+ $ add_option_name = $ phpcsFile ->findNext (
185
260
Tokens::$ emptyTokens ,
186
261
$ add_option_scope_start + 1 ,
187
262
null ,
188
263
true
189
264
);
190
265
191
- if ( $ this ->is_same_option_key ( $ tokens , $ add_option_key , $ delete_option_key ) ) {
192
- $ phpcsFile ->addWarning ( $ message , $ add_option_key , 'OptionsRaceCondition ' );
266
+ $ add_option_concat = $ phpcsFile ->findNext (
267
+ Tokens::$ emptyTokens ,
268
+ $ add_option_name + 1 ,
269
+ null ,
270
+ true
271
+ );
272
+
273
+ $ add_option_name = $ this ->trim_strip_quotes ( $ tokens [ $ add_option_name ]['content ' ] );
274
+ if ( $ is_delete_option_concat && $ tokens [ $ add_option_concat ]['code ' ] === T_STRING_CONCAT ) {
275
+ $ add_option_concat = $ phpcsFile ->findNext (
276
+ Tokens::$ emptyTokens ,
277
+ $ add_option_concat + 1 ,
278
+ null ,
279
+ true
280
+ );
281
+
282
+ $ add_option_scope_end = $ phpcsFile ->findNext (
283
+ [ T_COMMA ],
284
+ $ add_option_concat + 1 ,
285
+ null ,
286
+ false
287
+ );
288
+
289
+ if ( ! $ add_option_scope_end ) {
290
+ return ; // Something went wrong.
291
+ }
292
+
293
+ while ( $ add_option_concat < $ add_option_scope_end ) {
294
+ $ add_option_name .= $ this ->trim_strip_quotes ( $ tokens [ $ add_option_concat ]['content ' ] );
295
+
296
+ $ add_option_concat = $ phpcsFile ->findNext (
297
+ array_merge ( Tokens::$ emptyTokens , [ T_STRING_CONCAT ] ),
298
+ $ add_option_concat + 1 ,
299
+ null ,
300
+ true
301
+ );
302
+ }
303
+ }
304
+
305
+ if ( $ this ->is_same_option_key ( $ delete_option_name , $ add_option_name ) ) {
306
+ $ phpcsFile ->addWarning ( $ message , $ add_option_scope_start , 'OptionsRaceCondition ' );
193
307
return ;
194
308
}
195
309
}
@@ -209,14 +323,22 @@ protected function processTokenOutsideScope( File $phpcsFile, $stackPtr ) {
209
323
/**
210
324
* Check if option is the same.
211
325
*
212
- * @param array $tokens List of PHPCS tokens.
213
- * @param int $first_option Stack position of first option.
214
- * @param int $second_option Stack position of second option to match against.
326
+ * @param string $option_name Option name.
327
+ * @param string $option_name_to_compare Option name to compare against.
215
328
*
216
329
* @return false
217
330
*/
218
- private function is_same_option_key ( $ tokens , $ first_option , $ second_option ) {
219
- return $ tokens [ $ first_option ]['code ' ] === $ tokens [ $ second_option ]['code ' ] &&
220
- $ tokens [ $ first_option ]['content ' ] === $ tokens [ $ second_option ]['content ' ];
331
+ private function is_same_option_key ( $ option_name , $ option_name_to_compare ) {
332
+ return $ option_name === $ option_name_to_compare ;
333
+ }
334
+
335
+ /**
336
+ * Trim whitespace and strip quotes surrounding an arbitrary string.
337
+ *
338
+ * @param string $string The raw string.
339
+ * @return string String without whitespace or quotes around it.
340
+ */
341
+ public function trim_strip_quotes ( $ string ) {
342
+ return trim ( preg_replace ( '`^([ \'"])(.*)\1$`Ds ' , '$2 ' , $ string ) );
221
343
}
222
344
}
0 commit comments