[Feature] Consistent foreach style
dereuromark opened this issue · comments
I see code like
foreach ($usecases as $usecase) :
$usecase->setDirty('name', true);
$usecasesTable->save($usecase);
endforeach;
in some of the projects.
I would like to auto fix this via sniffer to the cleaner version
foreach ($usecases as $usecase) {
$usecase->setDirty('name', true);
$usecasesTable->save($usecase);
}
Especially since the former cannot be properly used by modern IDEs as PHPStorm. Even latest version doesnt show the closing part to the opening.
Is there an easy way to add this without accidentally killing the code or levels of nesting?
I checked existing sniffers and didnt find a matching one so far.
I wonder which other tokens might also be of the same type we can replace:
T_ENDIF => T_ENDIF,
T_ENDFOR => T_ENDFOR,
T_ENDFOREACH => T_ENDFOREACH,
T_ENDWHILE => T_ENDWHILE,
T_ENDSWITCH => T_ENDSWITCH,
T_ENDDECLARE => T_ENDDECLARE,
I analyzed the phpcs tokens
<?php
foreach ($usecases as $usecase) :
// T_WHITESPACE (216) code=392, line=42, column=1, length=8, level=2, conditions={"65":333,"199":310}, content=` `
// T_FOREACH (217) code=297, line=42, column=9, length=7, parenthesis_opener=219, parenthesis_closer=225, parenthesis_owner=217, scope_condition=217, scope_opener=227, scope_closer=251, level=2, conditions={"65":333,"199":310}, content=`foreach`
// T_WHITESPACE (218) code=392, line=42, column=16, length=1, level=2, conditions={"65":333,"199":310}, content=` `
// T_OPEN_PARENTHESIS (219) code=PHPCS_T_OPEN_PARENTHESIS, line=42, column=17, length=1, parenthesis_opener=219, parenthesis_owner=217, parenthesis_closer=225, level=2, conditions={"65":333,"199":310}, content=`(`
// T_VARIABLE (220) code=266, line=42, column=18, length=9, nested_parenthesis={"219":225}, level=2, conditions={"65":333,"199":310}, content=`$usecases`
// T_WHITESPACE (221) code=392, line=42, column=27, length=1, nested_parenthesis={"219":225}, level=2, conditions={"65":333,"199":310}, content=` `
// T_AS (222) code=301, line=42, column=28, length=2, nested_parenthesis={"219":225}, level=2, conditions={"65":333,"199":310}, content=`as`
// T_WHITESPACE (223) code=392, line=42, column=30, length=1, nested_parenthesis={"219":225}, level=2, conditions={"65":333,"199":310}, content=` `
// T_VARIABLE (224) code=266, line=42, column=31, length=8, nested_parenthesis={"219":225}, level=2, conditions={"65":333,"199":310}, content=`$usecase`
// T_CLOSE_PARENTHESIS (225) code=PHPCS_T_CLOSE_PARENTHESIS, line=42, column=39, length=1, parenthesis_owner=217, parenthesis_opener=219, parenthesis_closer=225, level=2, conditions={"65":333,"199":310}, content=`)`
// T_WHITESPACE (226) code=392, line=42, column=40, length=1, level=2, conditions={"65":333,"199":310}, content=` `
// T_COLON (227) code=PHPCS_T_COLON, line=42, column=41, length=1, scope_condition=217, scope_opener=227, scope_closer=251, level=2, conditions={"65":333,"199":310}, content=`:`
// T_WHITESPACE (228) code=392, line=42, column=42, length=0, level=3, conditions={"65":333,"199":310,"217":297}, content=`\n`
$usecase->setDirty('name', true);
// T_WHITESPACE (229) code=392, line=43, column=1, length=12, level=3, conditions={"65":333,"199":310,"217":297}, content=` `
// T_VARIABLE (230) code=266, line=43, column=13, length=8, level=3, conditions={"65":333,"199":310,"217":297}, content=`$usecase`
// T_OBJECT_OPERATOR (231) code=384, line=43, column=21, length=2, level=3, conditions={"65":333,"199":310,"217":297}, content=`->`
// T_STRING (232) code=262, line=43, column=23, length=8, level=3, conditions={"65":333,"199":310,"217":297}, content=`setDirty`
// T_OPEN_PARENTHESIS (233) code=PHPCS_T_OPEN_PARENTHESIS, line=43, column=31, length=1, parenthesis_opener=233, parenthesis_closer=238, level=3, conditions={"65":333,"199":310,"217":297}, content=`(`
// T_CONSTANT_ENCAPSED_STRING (234) code=269, line=43, column=32, length=6, nested_parenthesis={"233":238}, level=3, conditions={"65":333,"199":310,"217":297}, content=`'name'`
// T_COMMA (235) code=PHPCS_T_COMMA, line=43, column=38, length=1, nested_parenthesis={"233":238}, level=3, conditions={"65":333,"199":310,"217":297}, content=`,`
// T_WHITESPACE (236) code=392, line=43, column=39, length=1, nested_parenthesis={"233":238}, level=3, conditions={"65":333,"199":310,"217":297}, content=` `
// T_TRUE (237) code=PHPCS_T_TRUE, line=43, column=40, length=4, nested_parenthesis={"233":238}, level=3, conditions={"65":333,"199":310,"217":297}, content=`true`
// T_CLOSE_PARENTHESIS (238) code=PHPCS_T_CLOSE_PARENTHESIS, line=43, column=44, length=1, parenthesis_opener=233, parenthesis_closer=238, level=3, conditions={"65":333,"199":310,"217":297}, content=`)`
// T_SEMICOLON (239) code=PHPCS_T_SEMICOLON, line=43, column=45, length=1, level=3, conditions={"65":333,"199":310,"217":297}, content=`;`
// T_WHITESPACE (240) code=392, line=43, column=46, length=0, level=3, conditions={"65":333,"199":310,"217":297}, content=`\n`
$usecasesTable->save($usecase);
// T_WHITESPACE (241) code=392, line=44, column=1, length=12, level=3, conditions={"65":333,"199":310,"217":297}, content=` `
// T_VARIABLE (242) code=266, line=44, column=13, length=14, level=3, conditions={"65":333,"199":310,"217":297}, content=`$usecasesTable`
// T_OBJECT_OPERATOR (243) code=384, line=44, column=27, length=2, level=3, conditions={"65":333,"199":310,"217":297}, content=`->`
// T_STRING (244) code=262, line=44, column=29, length=4, level=3, conditions={"65":333,"199":310,"217":297}, content=`save`
// T_OPEN_PARENTHESIS (245) code=PHPCS_T_OPEN_PARENTHESIS, line=44, column=33, length=1, parenthesis_opener=245, parenthesis_closer=247, level=3, conditions={"65":333,"199":310,"217":297}, content=`(`
// T_VARIABLE (246) code=266, line=44, column=34, length=8, nested_parenthesis={"245":247}, level=3, conditions={"65":333,"199":310,"217":297}, content=`$usecase`
// T_CLOSE_PARENTHESIS (247) code=PHPCS_T_CLOSE_PARENTHESIS, line=44, column=42, length=1, parenthesis_opener=245, parenthesis_closer=247, level=3, conditions={"65":333,"199":310,"217":297}, content=`)`
// T_SEMICOLON (248) code=PHPCS_T_SEMICOLON, line=44, column=43, length=1, level=3, conditions={"65":333,"199":310,"217":297}, content=`;`
// T_WHITESPACE (249) code=392, line=44, column=44, length=0, level=3, conditions={"65":333,"199":310,"217":297}, content=`\n`
endforeach;
// T_WHITESPACE (250) code=392, line=45, column=1, length=8, level=3, conditions={"65":333,"199":310,"217":297}, content=` `
// T_ENDFOREACH (251) code=298, line=45, column=9, length=10, scope_condition=217, scope_opener=227, scope_closer=251, level=2, conditions={"65":333,"199":310}, content=`endforeach`
// T_SEMICOLON (252) code=PHPCS_T_SEMICOLON, line=45, column=19, length=1, level=2, conditions={"65":333,"199":310}, content=`;`
// T_WHITESPACE (253) code=392, line=45, column=20, length=0, level=2, conditions={"65":333,"199":310}, content=`\n`
It seems we just have to sniff for the T_ENDFOREACH, go to the scope_opener index and replace both.
Seems like it should work safely.
Any interest in a sniff for this in the community or maintainer group?
I whipped sth up that seems to work fine already:
php-collective/code-sniffer#6