There are a few cases where the result of auto formatting results in code that fails a code style check from phpcs with PSR12 as the code standard. Three I believe to be bugs in Intelephense, and two are cases it does not handle yet.
Wrapping of long line with string concatenation (bug)
Input:
<?php
echo 'Result of ClassName::functionCallWithLongName - time: ' .
(microtime(true) - $starttime) . 's, mem: ' . (memory_get_usage(true) / 1024 / 1024) . "mb\n";
echo 'Result of ClassName::functionCallWithLongName - time: ' . (microtime(true) - $starttime) .
's, mem: ' . (memory_get_usage(true) / 1024 / 1024) . "mb\n";
Output:
<?php
echo 'Result of ClassName::functionCallWithLongName - time: ' . (microtime(true) - $starttime) . 's, mem: ' . (memory_get_usage(true) / 1024 / 1024) . "mb\n";
echo 'Result of ClassName::functionCallWithLongName - time: ' . (microtime(true) - $starttime) .
's, mem: ' . (memory_get_usage(true) / 1024 / 1024) . "mb\n";
Error: Line exceeds 120 characters; contains 158 characters
Placement of curly braces for empty blocks (bug)
Input:
<?php
try {
if (foo()) {
}
} catch (Exception $e) {
}
Output:
<?php
try {
if (foo()) { }
} catch (Exception $e) { }
Errors:
Newline required after opening braceClosing brace must be on a line by itselfWrapping of long line with ternary operator (bug)
Input
<?php
$foo = nuncSollicitudinSapienIdNuncInterdumSitAmetVehiculaNisiConsecteturQuisque() ?
sitAmetJustoRutrumConsecteturMetusTemporPorttitorOrciInteger() :
imperdietNibhAcMollisOrnareErosMaurisPellentesqueNullaSitAmetBlanditNequeLectus();
$bar = nuncSollicitudinSapienIdNuncInterdumSitAmetVehiculaNisiConsecteturQuisque()
? sitAmetJustoRutrumConsecteturMetusTemporPorttitorOrciInteger()
: imperdietNibhAcMollisOrnareErosMaurisPellentesqueNullaSitAmetBlanditNequeLectus();
Output:
<?php
$foo = nuncSollicitudinSapienIdNuncInterdumSitAmetVehiculaNisiConsecteturQuisque() ?
sitAmetJustoRutrumConsecteturMetusTemporPorttitorOrciInteger() : imperdietNibhAcMollisOrnareErosMaurisPellentesqueNullaSitAmetBlanditNequeLectus();
$bar = nuncSollicitudinSapienIdNuncInterdumSitAmetVehiculaNisiConsecteturQuisque()
? sitAmetJustoRutrumConsecteturMetusTemporPorttitorOrciInteger()
: imperdietNibhAcMollisOrnareErosMaurisPellentesqueNullaSitAmetBlanditNequeLectus();
Error: Line exceeds 120 characters; contains 151 characters
Multiple traits in class (missing feature)
Output is identical to input
<?php
namespace Foo;
class Bar
{
use A, B, C;
}
Expected output:
<?php
namespace Foo;
class Bar
{
use A;
use B;
use C;
}
Thanks @MaartenStaa , it shouldn't be removing line breaks, looks like a bug when : and ( is encountered. Though, I don't think it should fail PSR12 in this case as there is only a soft limit on line length, but maybe that's a phpcs setting.
I'm unsure what to do about edits that require more than just whitespace changes. In general this extension formats whitespace in a PSR12 compliant way. There's some PSR12 requirements like the trait usage above, member modifier order, import grouping by const, function, type etc that require larger transformations of the source code and I wonder if it is the right place to have them in the formatter.
Opened #728 for the trait issue.
@MaartenStaa If you are using phpcs to enforce coding standards (PSR-12 or otherwise) I would suggest disabling intelephense's formatting feature and use persoderlind.vscode-phpcbf extension which uses phpcbf included with phpcs for autoformatting.
@bmewburn I see there are other tickets too like #730 related to formatting. Is spending effort on your own formatter worth it, when well established tools like phpcbf and phpcs-fixer (and vscode extensions for them) are already available?
Lossless PSR-12 compatible document/range formatting. Formats combined HTML/PHP/JS/CSS files too.
Is "Formats combined HTML/PHP/JS/CSS files too." the reason for developing your own formatter? At least phpcbf can give wonky results for such mixed type files :).
@ADmad there's no reason other than this extension aims to be be Language Server Protocol complete.
I have custom PSR12 standard and I can set format with this custom file?
@tuannda , no there is very few config options
fixed in 1.3.5
@bmewburn there's few more PSR12 rules that PHP Intelephense doesn't follow:
PHPCS(PSR12.Traits.UseDeclaration.MultipleImport)
should be formated as

PHPCS(PSR12.Traits.UseDeclaration.UseAfterBrace)
should be formated as

PHPCS(Generic.WhiteSpace.DisallowTabIndent.NonIndentTabsUsed).
should be formated as

PHP Intelephense works for indentations at the start of each line but doesn't work inside DocBlock:

Is there any chance PHP Intelephense will follow all rules of PSR12? So far it doesn't even show these errors. In pictures above they are marked by PHP Sniffer
$ phpcs --standard=PSR12 -e
The PSR12 standard contains 59 sniffs
Generic (15 sniffs)
-------------------
Generic.ControlStructures.InlineControlStructure
Generic.Files.ByteOrderMark
Generic.Files.LineEndings
Generic.Files.LineLength
Generic.Formatting.DisallowMultipleStatements
Generic.Functions.FunctionCallArgumentSpacing
Generic.NamingConventions.UpperCaseConstantName
Generic.PHP.DisallowAlternativePHPTags
Generic.PHP.DisallowShortOpenTag
Generic.PHP.LowerCaseConstant
Generic.PHP.LowerCaseKeyword
Generic.PHP.LowerCaseType
Generic.WhiteSpace.DisallowTabIndent
Generic.WhiteSpace.IncrementDecrementSpacing
Generic.WhiteSpace.ScopeIndent
PEAR (1 sniff)
---------------
PEAR.Functions.ValidDefaultValue
PSR1 (3 sniffs)
---------------
PSR1.Classes.ClassDeclaration
PSR1.Files.SideEffects
PSR1.Methods.CamelCapsMethodName
PSR12 (16 sniffs)
-----------------
PSR12.Classes.AnonClassDeclaration
PSR12.Classes.ClassInstantiation
PSR12.Classes.ClosingBrace
PSR12.ControlStructures.BooleanOperatorPlacement
PSR12.ControlStructures.ControlStructureSpacing
PSR12.Files.DeclareStatement
PSR12.Files.FileHeader
PSR12.Files.ImportStatement
PSR12.Files.OpenTag
PSR12.Functions.NullableTypeDeclaration
PSR12.Functions.ReturnTypeDeclaration
PSR12.Keywords.ShortFormTypeKeywords
PSR12.Namespaces.CompoundNamespaceDepth
PSR12.Operators.OperatorSpacing
PSR12.Properties.ConstantVisibility
PSR12.Traits.UseDeclaration
PSR2 (9 sniffs)
---------------
PSR2.Classes.ClassDeclaration
PSR2.Classes.PropertyDeclaration
PSR2.ControlStructures.ElseIfDeclaration
PSR2.ControlStructures.SwitchDeclaration
PSR2.Files.ClosingTag
PSR2.Files.EndFileNewline
PSR2.Methods.FunctionCallSignature
PSR2.Methods.FunctionClosingBrace
PSR2.Methods.MethodDeclaration
Squiz (15 sniffs)
-----------------
Squiz.Classes.ValidClassName
Squiz.ControlStructures.ControlSignature
Squiz.ControlStructures.ForEachLoopDeclaration
Squiz.ControlStructures.ForLoopDeclaration
Squiz.ControlStructures.LowercaseDeclaration
Squiz.Functions.FunctionDeclaration
Squiz.Functions.FunctionDeclarationArgumentSpacing
Squiz.Functions.LowercaseFunctionKeywords
Squiz.Functions.MultiLineFunctionDeclaration
Squiz.Scope.MethodScope
Squiz.WhiteSpace.CastSpacing
Squiz.WhiteSpace.ControlStructureSpacing
Squiz.WhiteSpace.ScopeClosingBrace
Squiz.WhiteSpace.ScopeKeywordSpacing
Squiz.WhiteSpace.SuperfluousWhitespace
@SharakPL Apart from 1 they look like PHPCS standards not PSR12
@bmewburn https://www.php-fig.org/psr/psr-12/#42-using-traits
use inside classuse keyword used inside the classes to implement traits MUST be declared on the next line after the opening brace.
Generic.WhiteSpace.DisallowTabIndent.NonIndentTabsUsed. Linting file with tabs used inside phpdoc with command phpcs --standard=PSR12 throws errors:
@SharakPL fair enough, #1032 and #1033 opened