Skip to content

Commit bcd5ae7

Browse files
authored
Add test case for issue found in the CMS with closures (#250)
1 parent ce73dc3 commit bcd5ae7

File tree

4 files changed

+158
-3
lines changed

4 files changed

+158
-3
lines changed

Joomla/Sniffs/ControlStructures/ControlStructuresBracketsSniff.php

Lines changed: 35 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -173,18 +173,50 @@ public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
173173
}
174174
}
175175

176-
$nested = 0;
176+
$baseLevel = $tokens[$stackPtr]['level'];
177177

178178
/**
179179
* Take into account any nested parenthesis that don't contribute to the level (often required for
180180
* closures and anonymous classes
181181
*/
182182
if (array_key_exists('nested_parenthesis', $tokens[$stackPtr]) === true)
183183
{
184-
$nested = count($tokens[$stackPtr]['nested_parenthesis']);
184+
$nestedStructures = $tokens[$stackPtr]['nested_parenthesis'];
185+
$nestedCount = 0;
186+
187+
foreach ($nestedStructures as $start => $end)
188+
{
189+
/**
190+
* Crude way of checking for a chained method which requires an extra indent. We navigate to the open
191+
* parenthesis of the nested structure. The element before that is the function name. Before that we
192+
* check for an operator (->) and a whitespace before it (which makes it a chained method on a new line)
193+
* TODO: Is there a better way to check for a chained method? This feels very dirty!
194+
*/
195+
if ($tokens[$start - 2]['type'] === 'T_OBJECT_OPERATOR' && $tokens[$start - 3]['type'] === 'T_WHITESPACE')
196+
{
197+
/**
198+
* If we have an anonymous function/class on the same line as our chained method then we
199+
* balance out so only increase the count by 1. Else by 2.
200+
*/
201+
if ($tokens[$start + 1]['type'] === 'T_CLOSURE' || $tokens[$start + 1]['type'] === 'T_ANON_CLASS')
202+
{
203+
$nestedCount++;
204+
}
205+
else
206+
{
207+
$nestedCount += 2;
208+
}
209+
}
210+
else
211+
{
212+
$nestedCount++;
213+
}
214+
}
215+
216+
$baseLevel += $nestedCount;
185217
}
186218

187-
$expected = ($tokens[$stackPtr]['level'] + $nested) * $this->indent;
219+
$expected = $baseLevel * $this->indent;
188220

189221
// We need to divide by 4 here since there is a space vs tab intent in the check vs token
190222
$expected /= $this->indent;

Joomla/Tests/ControlStructures/ControlStructuresBracketsUnitTest.inc

Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -248,3 +248,61 @@ $this->attachRule(
248248
}
249249
}
250250
);
251+
252+
class Application
253+
{
254+
public function doThings($container)
255+
{
256+
$container->alias(MyClass::class, 'MyClass')
257+
->share(
258+
'MyClass',
259+
function (Container $container) {
260+
doThing();
261+
262+
if ($thing)
263+
{
264+
bar();
265+
}
266+
267+
return foo();
268+
},
269+
true
270+
);
271+
}
272+
}
273+
274+
class Application
275+
{
276+
public function doThings($container)
277+
{
278+
$container->share(
279+
'MyClass',
280+
function (Container $container) {
281+
doThing();
282+
283+
if ($thing)
284+
{
285+
bar();
286+
}
287+
else {
288+
something();
289+
290+
if (somethingelse())
291+
{
292+
bar();
293+
}
294+
295+
anotherFunction()
296+
->withNested(function() {
297+
if ($foo){
298+
bar();
299+
}
300+
});
301+
302+
return foo();
303+
}
304+
},
305+
true
306+
);
307+
}
308+
}

Joomla/Tests/ControlStructures/ControlStructuresBracketsUnitTest.inc.fixed

Lines changed: 60 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -247,3 +247,63 @@ $this->attachRule(
247247
}
248248
}
249249
);
250+
251+
class Application
252+
{
253+
public function doThings($container)
254+
{
255+
$container->alias(MyClass::class, 'MyClass')
256+
->share(
257+
'MyClass',
258+
function (Container $container) {
259+
doThing();
260+
261+
if ($thing)
262+
{
263+
bar();
264+
}
265+
266+
return foo();
267+
},
268+
true
269+
);
270+
}
271+
}
272+
273+
class Application
274+
{
275+
public function doThings($container)
276+
{
277+
$container->share(
278+
'MyClass',
279+
function (Container $container) {
280+
doThing();
281+
282+
if ($thing)
283+
{
284+
bar();
285+
}
286+
else
287+
{
288+
something();
289+
290+
if (somethingelse())
291+
{
292+
bar();
293+
}
294+
295+
anotherFunction()
296+
->withNested(function() {
297+
if ($foo)
298+
{
299+
bar();
300+
}
301+
});
302+
303+
return foo();
304+
}
305+
},
306+
true
307+
);
308+
}
309+
}

Joomla/Tests/ControlStructures/ControlStructuresBracketsUnitTest.php

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,11 @@ public function getErrorList()
4646
210 => 1,
4747
226 => 1,
4848
235 => 1,
49+
263 => 1,
50+
284 => 1,
51+
287 => 1,
52+
291 => 1,
53+
297 => 1,
4954
);
5055
}
5156

0 commit comments

Comments
 (0)