@@ -116,14 +116,36 @@ public function process(File $phpcsFile, $stackPtr)
116116
117117 $ prev = $ phpcsFile ->findPrevious ($ ignore , ($ stackPtr - 1 ), null , true );
118118
119- while ($ tokens [$ prev ]['code ' ] === T_ATTRIBUTE_END ) {
120- // Skip past function attributes.
121- $ prev = $ phpcsFile ->findPrevious ($ ignore , ($ tokens [$ prev ]['attribute_opener ' ] - 1 ), null , true );
119+ $ startOfDeclarationLine = $ phpcsFile ->findNext (T_WHITESPACE , ($ prev + 1 ), null , true );
120+ for ($ i = $ startOfDeclarationLine ; $ i >= 0 ; $ i --) {
121+ if ($ tokens [$ i ]['line ' ] === $ tokens [$ startOfDeclarationLine ]['line ' ]) {
122+ $ startOfDeclarationLine = $ i ;
123+ continue ;
124+ }
125+
126+ break ;
122127 }
123128
124- if ($ tokens [$ prev ]['code ' ] === T_DOC_COMMENT_CLOSE_TAG ) {
125- // Skip past function docblocks.
126- $ prev = $ phpcsFile ->findPrevious ($ ignore , ($ tokens [$ prev ]['comment_opener ' ] - 1 ), null , true );
129+ // Skip past function docblocks and attributes.
130+ $ prev = $ startOfDeclarationLine ;
131+ if ($ startOfDeclarationLine > 0 ) {
132+ for ($ prev = ($ startOfDeclarationLine - 1 ); $ prev > 0 ; $ prev --) {
133+ if ($ tokens [$ prev ]['code ' ] === T_WHITESPACE ) {
134+ continue ;
135+ }
136+
137+ if ($ tokens [$ prev ]['code ' ] === T_DOC_COMMENT_CLOSE_TAG ) {
138+ $ prev = $ tokens [$ prev ]['comment_opener ' ];
139+ continue ;
140+ }
141+
142+ if ($ tokens [$ prev ]['code ' ] === T_ATTRIBUTE_END ) {
143+ $ prev = $ tokens [$ prev ]['attribute_opener ' ];
144+ continue ;
145+ }
146+
147+ break ;
148+ }
127149 }
128150
129151 if ($ tokens [$ prev ]['code ' ] === T_OPEN_CURLY_BRACKET ) {
@@ -224,9 +246,11 @@ public function process(File $phpcsFile, $stackPtr)
224246 before the function.
225247 */
226248
249+ $ startOfPreamble = $ phpcsFile ->findNext (T_WHITESPACE , ($ prev + 1 ), null , true );
250+
227251 $ prevLineToken = null ;
228- for ($ i = $ stackPtr ; $ i >= 0 ; $ i --) {
229- if ($ tokens [$ i ]['line ' ] === $ tokens [$ stackPtr ]['line ' ]) {
252+ for ($ i = $ startOfPreamble ; $ i >= 0 ; $ i --) {
253+ if ($ tokens [$ i ]['line ' ] === $ tokens [$ startOfPreamble ]['line ' ]) {
230254 continue ;
231255 }
232256
@@ -241,33 +265,15 @@ public function process(File $phpcsFile, $stackPtr)
241265 $ prevContent = 0 ;
242266 $ prevLineToken = 0 ;
243267 } else {
244- $ currentLine = $ tokens [$ stackPtr ]['line ' ];
245-
246- $ prevContent = $ phpcsFile ->findPrevious (T_WHITESPACE , $ prevLineToken , null , true );
247-
248- if ($ tokens [$ prevContent ]['code ' ] === T_COMMENT
249- || isset (Tokens::$ phpcsCommentTokens [$ tokens [$ prevContent ]['code ' ]]) === true
268+ $ firstBefore = $ phpcsFile ->findPrevious (T_WHITESPACE , ($ startOfDeclarationLine - 1 ), null , true );
269+ if ($ tokens [$ firstBefore ]['code ' ] === T_COMMENT
270+ || isset (Tokens::$ phpcsCommentTokens [$ tokens [$ firstBefore ]['code ' ]]) === true
250271 ) {
251272 // Ignore comments as they can have different spacing rules, and this
252273 // isn't a proper function comment anyway.
253274 return ;
254275 }
255276
256- while ($ tokens [$ prevContent ]['code ' ] === T_ATTRIBUTE_END
257- && $ tokens [$ prevContent ]['line ' ] === ($ currentLine - 1 )
258- ) {
259- // Account for function attributes.
260- $ currentLine = $ tokens [$ tokens [$ prevContent ]['attribute_opener ' ]]['line ' ];
261- $ prevContent = $ phpcsFile ->findPrevious (T_WHITESPACE , ($ tokens [$ prevContent ]['attribute_opener ' ] - 1 ), null , true );
262- }
263-
264- if ($ tokens [$ prevContent ]['code ' ] === T_DOC_COMMENT_CLOSE_TAG
265- && $ tokens [$ prevContent ]['line ' ] === ($ currentLine - 1 )
266- ) {
267- // Account for function comments.
268- $ prevContent = $ phpcsFile ->findPrevious (T_WHITESPACE , ($ tokens [$ prevContent ]['comment_opener ' ] - 1 ), null , true );
269- }
270-
271277 // Before we throw an error, check that we are not throwing an error
272278 // for another function. We don't want to error for no blank lines after
273279 // the previous function and no blank lines before this one as well.
@@ -278,38 +284,33 @@ public function process(File $phpcsFile, $stackPtr)
278284 $ stopAt = array_pop ($ conditions );
279285 }
280286
281- $ prevLineToken = $ prevContent ;
282- $ prevLine = ($ tokens [$ prevContent ]['line ' ] - 1 );
283- $ i = ($ stackPtr - 1 );
284- $ foundLines = 0 ;
287+ $ currentLine = $ tokens [$ startOfPreamble ]['line ' ];
288+ $ prevContent = $ prev ;
289+ $ prevLine = ($ tokens [$ prevContent ]['line ' ] - 1 );
290+ $ foundLines = ($ currentLine - $ tokens [$ prevContent ]['line ' ] - 1 );
291+
292+ for ($ i = $ prevContent ; $ i > $ stopAt ; $ i --) {
293+ if ($ tokens [$ i ]['code ' ] === T_CLOSE_CURLY_BRACKET ) {
294+ if (isset ($ tokens [$ i ]['scope_condition ' ]) === true
295+ && $ tokens [$ tokens [$ i ]['scope_condition ' ]]['code ' ] === T_FUNCTION
296+ ) {
297+ // Found a previous function.
298+ return ;
299+ } else {
300+ break ;
301+ }
302+ }
285303
286- while ($ currentLine !== $ prevLine && $ currentLine > 1 && $ i > $ stopAt ) {
287304 if ($ tokens [$ i ]['code ' ] === T_FUNCTION ) {
288305 // Found another interface or abstract function.
289306 return ;
290307 }
291308
292- if ($ tokens [$ i ]['code ' ] === T_CLOSE_CURLY_BRACKET
293- && $ tokens [$ tokens [$ i ]['scope_condition ' ]]['code ' ] === T_FUNCTION
294- ) {
295- // Found a previous function.
296- return ;
297- }
298-
299309 $ currentLine = $ tokens [$ i ]['line ' ];
300310 if ($ currentLine === $ prevLine ) {
301311 break ;
302312 }
303-
304- if ($ tokens [($ i - 1 )]['line ' ] < $ currentLine && $ tokens [($ i + 1 )]['line ' ] > $ currentLine ) {
305- // This token is on a line by itself. If it is whitespace, the line is empty.
306- if ($ tokens [$ i ]['code ' ] === T_WHITESPACE ) {
307- $ foundLines ++;
308- }
309- }
310-
311- $ i --;
312- }//end while
313+ }//end for
313314 }//end if
314315
315316 $ requiredSpacing = $ this ->spacing ;
0 commit comments