Skip to content

Commit c3a7ec5

Browse files
committed
Squiz.WhiteSpace.FunctionSpacing now applies beforeFirst and afterLast spacing rules to nested functions (ref #2406)
1 parent 8ff9283 commit c3a7ec5

File tree

5 files changed

+128
-20
lines changed

5 files changed

+128
-20
lines changed

package.xml

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,9 @@ http://pear.php.net/dtd/package-2.0.xsd">
7070
-- The new error code is Squiz.PHP.DisallowMultipleAssignments.FoundInControlStructure
7171
-- All other multiple assignment cases use the existing error code Squiz.PHP.DisallowMultipleAssignments.Found
7272
-- Thanks to Juliette Reinders Folmer for the patch
73+
- Squiz.WhiteSpace.FunctionSpacing now applies beforeFirst and afterLast spacing rules to nested functions
74+
-- Previously, these rules only applied to the first and last function in a class, interface, or trait
75+
-- These rules now apply to functions nested in any statement block, including other functions and conditions
7376
- Fixed bug #2391 : Sniff-specific ignore rules inside rulesets are filtering out too many files
7477
-- Thanks to Juliette Reinders Folmer and Willington Vega for the patch
7578
- Fixed bug #2478 : FunctionCommentThrowTag.WrongNumber when exception is thrown once but built conditionally

src/Standards/Squiz/Sniffs/WhiteSpace/FunctionSpacingSniff.php

Lines changed: 24 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -115,18 +115,12 @@ public function process(File $phpcsFile, $stackPtr)
115115
$ignore = (Tokens::$emptyTokens + Tokens::$methodPrefixes);
116116

117117
$prev = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true);
118-
if (isset($tokens[$prev]['scope_opener']) === true
119-
&& $tokens[$prev]['scope_opener'] === $prev
120-
&& isset(Tokens::$ooScopeTokens[$tokens[$tokens[$prev]['scope_condition']]['code']]) === true
121-
) {
118+
if ($tokens[$prev]['code'] === T_OPEN_CURLY_BRACKET) {
122119
$isFirst = true;
123120
}
124121

125122
$next = $phpcsFile->findNext($ignore, ($closer + 1), null, true);
126-
if (isset($tokens[$next]['scope_closer']) === true
127-
&& $tokens[$next]['scope_closer'] === $next
128-
&& isset(Tokens::$ooScopeTokens[$tokens[$tokens[$next]['scope_condition']]['code']]) === true
129-
) {
123+
if ($tokens[$next]['code'] === T_CLOSE_CURLY_BRACKET) {
130124
$isLast = true;
131125
}
132126

@@ -202,12 +196,12 @@ public function process(File $phpcsFile, $stackPtr)
202196

203197
$prevLineToken = null;
204198
for ($i = $stackPtr; $i >= 0; $i--) {
205-
if (strpos($tokens[$i]['content'], $phpcsFile->eolChar) === false) {
199+
if ($tokens[$i]['line'] === $tokens[$stackPtr]['line']) {
206200
continue;
207-
} else {
208-
$prevLineToken = $i;
209-
break;
210201
}
202+
203+
$prevLineToken = $i;
204+
break;
211205
}
212206

213207
if ($prevLineToken === null) {
@@ -220,6 +214,7 @@ public function process(File $phpcsFile, $stackPtr)
220214
$currentLine = $tokens[$stackPtr]['line'];
221215

222216
$prevContent = $phpcsFile->findPrevious(T_WHITESPACE, $prevLineToken, null, true);
217+
223218
if ($tokens[$prevContent]['code'] === T_COMMENT
224219
|| isset(Tokens::$phpcsCommentTokens[$tokens[$prevContent]['code']]) === true
225220
) {
@@ -243,18 +238,27 @@ public function process(File $phpcsFile, $stackPtr)
243238
$prevLine = ($tokens[$prevContent]['line'] - 1);
244239
$i = ($stackPtr - 1);
245240
$foundLines = 0;
246-
while ($currentLine !== $prevLine && $currentLine > 1 && $i > 0) {
247-
if (isset($tokens[$i]['scope_condition']) === true) {
248-
$scopeCondition = $tokens[$i]['scope_condition'];
249-
if ($tokens[$scopeCondition]['code'] === T_FUNCTION) {
250-
// Found a previous function.
251-
return;
252-
}
253-
} else if ($tokens[$i]['code'] === T_FUNCTION) {
241+
242+
$stopAt = 0;
243+
if (isset($tokens[$stackPtr]['conditions']) === true) {
244+
$conditions = $tokens[$stackPtr]['conditions'];
245+
$conditions = array_keys($conditions);
246+
$stopAt = array_pop($conditions);
247+
}
248+
249+
while ($currentLine !== $prevLine && $currentLine > 1 && $i > $stopAt) {
250+
if ($tokens[$i]['code'] === T_FUNCTION) {
254251
// Found another interface or abstract function.
255252
return;
256253
}
257254

255+
if ($tokens[$i]['code'] === T_CLOSE_CURLY_BRACKET
256+
&& $tokens[$tokens[$i]['scope_condition']]['code'] === T_FUNCTION
257+
) {
258+
// Found a previous function.
259+
return;
260+
}
261+
258262
$currentLine = $tokens[$i]['line'];
259263
if ($currentLine === $prevLine) {
260264
break;

src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.1.inc

Lines changed: 31 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -449,3 +449,34 @@ $anon_class = new class() {
449449
private function c(){}
450450

451451
};
452+
453+
// phpcs:set Squiz.WhiteSpace.FunctionSpacing spacing 2
454+
// phpcs:set Squiz.WhiteSpace.FunctionSpacing spacingBeforeFirst 1
455+
// phpcs:set Squiz.WhiteSpace.FunctionSpacing spacingAfterLast 3
456+
457+
class MyClass {
458+
function a(){}
459+
function b(){}
460+
function c(){}
461+
}
462+
463+
$bar = function () {
464+
{
465+
function forbiddenToo() {}
466+
}
467+
};
468+
class Foo {
469+
public function returnAnonymousClass() {
470+
return new class() {
471+
public function baz() {}
472+
};
473+
}
474+
475+
public function bar() {
476+
function forbidden() {}
477+
}
478+
}
479+
480+
if (function_exists('foo') === false) {
481+
function foo(){}
482+
}

src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.1.inc.fixed

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -500,3 +500,63 @@ $anon_class = new class() {
500500

501501

502502
};
503+
504+
// phpcs:set Squiz.WhiteSpace.FunctionSpacing spacing 2
505+
// phpcs:set Squiz.WhiteSpace.FunctionSpacing spacingBeforeFirst 1
506+
// phpcs:set Squiz.WhiteSpace.FunctionSpacing spacingAfterLast 3
507+
508+
class MyClass {
509+
510+
function a(){}
511+
512+
513+
function b(){}
514+
515+
516+
function c(){}
517+
518+
519+
520+
}
521+
522+
$bar = function () {
523+
{
524+
525+
function forbiddenToo() {}
526+
527+
528+
529+
}
530+
};
531+
class Foo {
532+
533+
public function returnAnonymousClass() {
534+
return new class() {
535+
536+
public function baz() {}
537+
538+
539+
540+
};
541+
}
542+
543+
544+
public function bar() {
545+
546+
function forbidden() {}
547+
548+
549+
550+
}
551+
552+
553+
554+
}
555+
556+
if (function_exists('foo') === false) {
557+
558+
function foo(){}
559+
560+
561+
562+
}

src/Standards/Squiz/Tests/WhiteSpace/FunctionSpacingUnitTest.php

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -75,6 +75,16 @@ public function getErrorList($testFile='')
7575
442 => 2,
7676
444 => 1,
7777
449 => 1,
78+
458 => 2,
79+
459 => 1,
80+
460 => 1,
81+
465 => 2,
82+
469 => 1,
83+
471 => 2,
84+
473 => 1,
85+
476 => 2,
86+
477 => 1,
87+
481 => 2,
7888
];
7989

8090
case 'FunctionSpacingUnitTest.2.inc':

0 commit comments

Comments
 (0)