Vscode-intelephense: Code formatting does not fully follow PSR-12

Created on 18 Oct 2019  路  11Comments  路  Source: bmewburn/vscode-intelephense

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 brace
  • Closing brace must be on a line by itself

Wrapping 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;
}
bug

All 11 comments

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:

  1. Each imported trait must have its own "use" import statement PHPCS(PSR12.Traits.UseDeclaration.MultipleImport)

obraz

should be formated as

obraz

  1. The first trait import statement must be declared on the first non-comment line after the class opening brace PHPCS(PSR12.Traits.UseDeclaration.UseAfterBrace)

obraz

should be formated as

obraz

  1. Spaces must be used for alignment; tabs are not allowed PHPCS(Generic.WhiteSpace.DisallowTabIndent.NonIndentTabsUsed).

obraz

should be formated as

obraz

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

obraz

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

  1. #728 is tracking this.
  2. PSR12 requires a single blank line here https://www.php-fig.org/psr/psr-12/#3-declare-statements-namespace-and-import-statements.
  3. I don't see any mention of phpdoc in PSR12.

@bmewburn https://www.php-fig.org/psr/psr-12/#42-using-traits


  1. > Each individual trait that is imported into a class MUST be included one-per-line and each inclusion MUST have its own use import statement.
  2. You're talking about header of the file, but this one is about use inside class
    > The use keyword used inside the classes to implement traits MUST be declared on the next line after the opening brace.

obraz

  1. It's not about phpdoc but about avoiding tabs: Generic.WhiteSpace.DisallowTabIndent.NonIndentTabsUsed. Linting file with tabs used inside phpdoc with command phpcs --standard=PSR12 throws errors:

obraz

@SharakPL fair enough, #1032 and #1033 opened

Was this page helpful?
0 / 5 - 0 ratings

Related issues

superadmini picture superadmini  路  4Comments

umpirsky picture umpirsky  路  4Comments

vanasis picture vanasis  路  4Comments

ghost picture ghost  路  3Comments

pseudoanime picture pseudoanime  路  3Comments