Skip to content

Commit 07c94c7

Browse files
committed
Allow methods inside OOP structures within functions
1 parent 2dd54f0 commit 07c94c7

File tree

2 files changed

+50
-13
lines changed

2 files changed

+50
-13
lines changed

src/Standards/Squiz/Sniffs/PHP/InnerFunctionsSniff.php

Lines changed: 29 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -41,25 +41,41 @@ public function process(File $phpcsFile, $stackPtr)
4141
{
4242
$tokens = $phpcsFile->getTokens();
4343

44-
$function = $phpcsFile->getCondition($stackPtr, T_FUNCTION);
45-
if ($function === false) {
46-
$function = $phpcsFile->getCondition($stackPtr, T_CLOSURE);
47-
if ($function === false) {
48-
// Not a nested function.
49-
return;
44+
if (isset($tokens[$stackPtr]['conditions']) === false) {
45+
return;
46+
}
47+
48+
$conditions = $tokens[$stackPtr]['conditions'];
49+
50+
$outerFuncToken = null;
51+
foreach ($conditions as $condToken => $condition) {
52+
if ($condition === T_FUNCTION || $condition === T_CLOSURE) {
53+
$outerFuncToken = $condToken;
54+
break;
5055
}
5156
}
5257

53-
$class = $phpcsFile->getCondition($stackPtr, T_ANON_CLASS, false);
54-
if ($class !== false && $class > $function) {
55-
// Ignore methods in anon classes.
58+
if ($outerFuncToken === null) {
59+
// Not a nested function.
5660
return;
5761
}
5862

59-
$prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true);
60-
if ($tokens[$prev]['code'] === T_EQUAL) {
61-
// Ignore closures.
62-
return;
63+
$reversedConditions = array_reverse($conditions, true);
64+
$allowedOOPConditions = [
65+
T_ANON_CLASS => true,
66+
T_CLASS => true,
67+
T_TRAIT => true,
68+
T_INTERFACE => true,
69+
];
70+
foreach ($reversedConditions as $condToken => $condition) {
71+
if ($condToken <= $outerFuncToken) {
72+
break;
73+
}
74+
75+
if (\array_key_exists($condition, $allowedOOPConditions) === true) {
76+
// Ignore methods in OOP structures defined within functions.
77+
return;
78+
}
6379
}
6480

6581
$error = 'The use of inner functions is forbidden';

src/Standards/Squiz/Tests/PHP/InnerFunctionsUnitTest.inc

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -55,3 +55,24 @@ $outerClosure = function ()
5555
function innerFunction() {
5656
}
5757
};
58+
59+
// Allow methods in classes/traits/interfaces defined inside functions
60+
function foo() {
61+
if (class_exists('MyClass') === false) {
62+
class MyClass {
63+
function foo() {}
64+
}
65+
}
66+
67+
if (trait_exists('MyTrait') === false) {
68+
trait MyTrait {
69+
function foo() {}
70+
}
71+
}
72+
73+
if (interface_exists('MyInterface') === false) {
74+
interface MyInterface {
75+
function foo();
76+
}
77+
}
78+
}

0 commit comments

Comments
 (0)