Part of #2571965: [meta] Fix PHP coding standards in core.

Approach

We are testing coding standards with PHP CodeSniffer, using the Drupal coding standards from the Coder module. Both of these packages are not installed in Drupal core. We need to do a couple of steps in order to download and configure them so we can run a coding standards check.

Step 1: Add the coding standard to the whitelist

Every coding standard is identified by a "sniff". For example, an imaginary coding standard that would require all llamas to be placed inside a square bracket fence would be called the "Drupal.AnimalControlStructure.BracketedFence sniff". There are dozens of such coding standards, and to make the work easier we have started by only whitelisting the sniffs that pass. For the moment all coding standards that are not yet fixed are simply skipped during the test.

Open the file core/phpcs.xml.dist and add a line for the sniff of this ticket. The sniff name is in the issue title. Make sure your patch will include the addition of this line.

Step 2: Install PHP CodeSniffer and the ruleset from the Coder module

Both of these packages are not installed by default in Drupal core, so we need to download them. This can be done with Composer, from the root folder of your Drupal installation:

$ composer require drupal/coder squizlabs/php_codesniffer
$ ./vendor/bin/phpcs --config-set installed_paths ../../drupal/coder/coder_sniffer

Once you have installed the phpcs package, you can list all the sniffs available to you like this:

$ ./vendor/bin/phpcs --standard=Drupal -e

This will give you a big list of sniffs, and the Drupal-based ones should be present.

Step 3: Prepare the phpcs.xml file

To speed up the testing you should make a copy of the file phpcs.xml.dist (in the core/ folder) and save it as phpcs.xml. This is the configuration file for PHP CodeSniffer.

We only want this phpcs.xml file to specify the sniff we're interested in. So we need to remove all the rule items, and add only our own sniff's rule. Rule items look like this:

<rule ref="Drupal.Classes.UnusedUseStatement"/>

Remove all of them, and add only the sniff from this issue title. This will make sure that our tests run quickly, and are not going to contain any output from unrelated sniffs.

Step 4: Run the test

Now you are ready to run the test! From within the core/ folder, run the following command to launch the test:

$ cd core/
$ ../vendor/bin/phpcs -p

This takes a couple of minutes. The -p flag shows the progress, so you have a bunch of nice dots to look at while it is running.

Step 5: Fix the failures

When the test is complete it will present you a list of all the files that contain violations of your sniff, and the line numbers where the violations occur. You could fix all of these manually, but thankfully phpcbf can fix many of them. You can call phpcbf like this:

$ ../vendor/bin/phpcbf

This will fix the errors in place. You can then make a diff of the changes using git. You can also re-run the test with phpcs and determine if that fixed all of them.

Support from Acquia helps fund testing for Drupal Acquia logo

Comments

attiks created an issue. See original summary.

Status: Needs review » Needs work

The last submitted patch, Drupal.Classes.ClassDeclaration.patch, failed testing.

attiks’s picture

Coder error

diff --git a/core/lib/Drupal/Core/Render/Element/Pager.php b/core/lib/Drupal/Core/Render/Element/Pager.php
index 8e87cca..cab5fa1 100644
--- a/core/lib/Drupal/Core/Render/Element/Pager.php
+++ b/core/lib/Drupal/Core/Render/Element/Pager.php
@@ -14,7 +14,7 @@
  *
  * @RenderElement("pager")
  */
-class Pager extends RenderElement{
+class Pager extends {
 
   /**
    * {@inheritdoc}
diff --git a/core/modules/book/src/Access/BookNodeIsRemovableAccessCheck.php b/core/modules/book/src/Access/BookNodeIsRemovableAccessCheck.php
index 53207b7..949ff1c 100644
--- a/core/modules/book/src/Access/BookNodeIsRemovableAccessCheck.php
+++ b/core/modules/book/src/Access/BookNodeIsRemovableAccessCheck.php
@@ -15,7 +15,7 @@
 /**
  * Determines whether the requested node can be removed from its book.
  */
-class BookNodeIsRemovableAccessCheck implements AccessInterface{
+class BookNodeIsRemovableAccessCheck implements {
 
   /**
    * Book Manager Service.
diff --git a/core/modules/user/src/UserStorageInterface.php b/core/modules/user/src/UserStorageInterface.php
index 2614bc3..d86a1d4 100644
--- a/core/modules/user/src/UserStorageInterface.php
+++ b/core/modules/user/src/UserStorageInterface.php
@@ -13,7 +13,7 @@
 /**
  * Defines an interface for user entity storage classes.
  */
-interface UserStorageInterface extends EntityStorageInterface{
+interface UserStorageInterface extends {
 
   /**
    * Update the last login timestamp of the user.

The last submitted patch, Drupal.Classes.ClassDeclaration.patch, failed testing.

tatarbj’s picture

Status: Needs work » Needs review
FileSize
424.08 KB

I've used the latest patch which didn't fix these problems:

FILE: ...MAMP/htdocs/drupal/core/lib/Drupal/Core/Render/Element/Pager.php
----------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
----------------------------------------------------------------------
 17 | ERROR | [x] Expected 1 space before opening brace; found 0
----------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------


FILE: .../core/modules/book/src/Access/BookNodeIsRemovableAccessCheck.php
----------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
----------------------------------------------------------------------
 18 | ERROR | [x] Expected 1 space before opening brace; found 0
----------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------

FILE: ...AMP/htdocs/drupal/core/modules/user/src/UserStorageInterface.php
----------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
----------------------------------------------------------------------
 16 | ERROR | [x] Expected 1 space before opening brace; found 0
----------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------


FILE: ...pal/core/tests/Drupal/Tests/Core/Database/Stub/Driver/Schema.php
----------------------------------------------------------------------
FOUND 1 ERROR AFFECTING 1 LINE
----------------------------------------------------------------------
 20 | ERROR | [x] The closing brace for the class must have an empty
    |       |     line before it
----------------------------------------------------------------------
PHPCBF CAN FIX THE 1 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------

Attached a patch which solves these as well.

Status: Needs review » Needs work

attiks’s picture

Issue summary: View changes
tatarbj’s picture

I'm reattach the patch because it was broken with one already changed system module part.

DuaelFr’s picture

Issue tags: -Novice

As agreed between the mentors at Drupalcon, according to issues to avoid for novices, I am untagging this issue as "Beginner". This issue contains changes across a very wide range of files and might create too many other patches to need to be rerolled at this particular time. This patch has an automated way to be rerolled later so better to implement it after Drupalcon.

attiks’s picture

Filed patch upstream #2575407: Drupal.Classes.ClassDeclaration fixer breaks code, uploading auto generated patch for testing

andriyun’s picture

Issue tags: +Needs reroll

Patch is outdated. Need reroll

andriyun’s picture

Status: Needs review » Needs work

Status: Needs review » Needs work

andypost’s picture

+++ b/core/lib/Drupal/Core/Render/Element/Pager.php
@@ -14,7 +14,7 @@
  *
  * @RenderElement("pager")
  */
-class Pager extends RenderElement{
+class Pager extends {

wtf?

+++ b/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTest.php
@@ -138,7 +138,8 @@ public function testFindSitePath() {
       $request->server->set('SCRIPT_NAME', '/index.php');
       $this->assertEquals('sites/example', DrupalKernel::findSitePath($request));
     }
-  }
+
+}

wrong indent, class inside namespace wrapper

+++ b/core/tests/Drupal/Tests/Core/Database/Stub/Driver/Schema.php
@@ -15,4 +15,6 @@
  */
 class Schema {
   // No-op.
+
+
 }

questionable

andypost’s picture

Manually fixed after upgrading coder to dev after #2575407: Drupal.Classes.ClassDeclaration fixer breaks code
core/tests/Drupal/Tests/Core/Database/Stub/Driver/Schema.php
core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTest.php
...and filed #2611258: Drupal.Classes.ClassDeclaration fixer breaks indent

The interesting moment that sniffer is dumb on it

andriyun’s picture

phpcbf with class declaration sniffer also added extra line after fixing emty class.
#2611238: Drupal.Classes.ClassDeclaration fixer added extra line

pfrenssen’s picture

Issue summary: View changes
andriyun’s picture

Assigned: Unassigned » andriyun
Status: Needs review » Needs work

patch is outdated

andriyun’s picture

Status: Needs work » Postponed
--- a/core/lib/Drupal/Core/Archiver/ArchiveTar.php
+++ b/core/lib/Drupal/Core/Archiver/ArchiveTar.php
@@ -108,8 +108,7 @@ function gzseek($zp, $offset, $whence = SEEK_SET)
  * @version $Revision$
  */
 // Drupal change class Archive_Tar extends PEAR.
-class ArchiveTar
-{
+class ArchiveTar {
     /**
      * @var string Name of the Tar
      */

this change blocked on #2610984: Add Archive Tar via Composer, with BC shim

Version: 8.0.x-dev » 8.1.x-dev

Drupal 8.0.6 was released on April 6 and is the final bugfix release for the Drupal 8.0.x series. Drupal 8.0.x will not receive any further development aside from security fixes. Drupal 8.1.0-rc1 is now available and sites should prepare to update to 8.1.0.

Bug reports should be targeted against the 8.1.x-dev branch from now on, and new development or disruptive changes should be targeted against the 8.2.x-dev branch. For more information see the Drupal 8 minor version schedule and the Allowed changes during the Drupal 8 release cycle.

andypost’s picture

Status: Postponed » Needs work

this no more depends on related issue, just skip ArchiverTar

vprocessor’s picture

Assigned: andriyun » vprocessor
vprocessor’s picture

Version: 8.1.x-dev » 8.2.x-dev
vprocessor’s picture

rerolled & refixed with phpcbf

vprocessor’s picture

Status: Needs work » Needs review
vprocessor’s picture

Sorry, forgot to remove changes in ArchiveTar

Now it's ready

vprocessor’s picture

Assigned: vprocessor » Unassigned
pfrenssen’s picture

I reviewed the entire thing. At some point I thought it was never going to end. But it looks great! Everything is perfect.

Interesting to see how some specific whitespace mistakes proliferate through sections the codebase, you can see how much copy/pasting is going on.

Still need to run a full test with PHPCS to see if everything has been caught.

  1. +++ b/core/tests/Drupal/Tests/Core/Logger/LoggerChannelTest.php
    @@ -147,7 +147,7 @@ function ($context) {
    -class NaughtyRecursiveLogger implements LoggerInterface  {
    +class NaughtyRecursiveLogger implements LoggerInterface {
    

    NaughtyRecursiveLogger? :)

  2. +++ b/core/lib/Drupal/Core/Menu/LocalActionInterface.php
    @@ -59,6 +59,4 @@ public function getOptions(RouteMatchInterface $route_match);
       public function getTitle();
     
    -
    -
     }
    

    This is my all-time favourite.

pfrenssen’s picture

Status: Needs review » Reviewed & tested by the community
[pieter@thinkarch core (8.2.x *+$%=)]$ ../vendor/bin/phpcs --runtime-set installed_paths ../../drupal/coder/coder_sniffer/

FILE: ...drupal/core/modules/file/tests/src/Kernel/EntityStringIdTest.php
----------------------------------------------------------------------
FOUND 1 ERROR AND 2 WARNINGS AFFECTING 3 LINES
----------------------------------------------------------------------
  3 | ERROR   | [x] Namespaced classes, interfaces and traits should
    |         |     not begin with a file doc comment
 10 | WARNING | [x] Unused use statement
 16 | WARNING | [x] Unused use statement
----------------------------------------------------------------------
PHPCBF CAN FIX THE 3 MARKED SNIFF VIOLATIONS AUTOMATICALLY
----------------------------------------------------------------------

Time: 2 mins, 22.45 secs; Memory: 88Mb

This was the result. This was actually a file that was present on my installation from an old issue I was working on, this file is NOT present in core. The actual code in core is perfectly fine.

This is looking good, setting to RTBC!

andypost’s picture

RTBC++

no false-positives
phpcs -p --sniffs=Drupal.Classes.ClassDeclaration
Time: 59.58 secs; Memory: 124.25Mb

pfrenssen’s picture

Issue summary: View changes
pfrenssen’s picture

Issue summary: View changes
alexpott’s picture

Status: Reviewed & tested by the community » Needs work
  1. +++ b/core/lib/Drupal/Core/DependencyInjection/YamlFileLoader.php
    @@ -26,8 +26,7 @@
    -class YamlFileLoader
    -{
    +class YamlFileLoader {
    

    This file is not our coding standards and already has the ignore.

  2. +++ b/core/lib/Drupal/Core/ProxyClass/Batch/BatchStorage.php
    @@ -12,8 +12,7 @@
    -    class BatchStorage implements \Drupal\Core\Batch\BatchStorageInterface
    -    {
    +    class BatchStorage implements \Drupal\Core\Batch\BatchStorageInterface {
    
    +++ b/core/lib/Drupal/Core/ProxyClass/Config/ConfigInstaller.php
    @@ -12,8 +12,7 @@
    -    class ConfigInstaller implements \Drupal\Core\Config\ConfigInstallerInterface
    -    {
    +    class ConfigInstaller implements \Drupal\Core\Config\ConfigInstallerInterface {
    
    +++ b/core/lib/Drupal/Core/ProxyClass/Cron.php
    @@ -12,8 +12,7 @@
    -    class Cron implements \Drupal\Core\CronInterface
    -    {
    +    class Cron implements \Drupal\Core\CronInterface {
    

    All of these too. I don't think phpcbf has been properly run here. Please don't apply and reroll coding standards patches - the correct way to make a coding standards patch is too add the rule to phpxml.dist.xml and run the fixer if possible.

pfrenssen’s picture

Issue summary: View changes
pfrenssen’s picture

Status: Needs work » Needs review
FileSize
408.6 KB
18.84 KB

Here's the raw result from phpcbf + interdiff. The files that @alexpott mentioned that are exempt are now correctly reverted, but there are now a few problems coming up which are not caught. These were fixed manually before.

diff --git a/core/lib/Drupal/Core/TypedData/Validation/ConstraintViolationBuilder.php b/core/lib/Drupal/Core/TypedData/Validation/ConstraintViolationBuilder.php
index 72fcb62..bfee7f0 100644
--- a/core/lib/Drupal/Core/TypedData/Validation/ConstraintViolationBuilder.php
+++ b/core/lib/Drupal/Core/TypedData/Validation/ConstraintViolationBuilder.php
@@ -251,5 +251,4 @@ public function addViolation()
         $this->cause
       ));
     }
-
 }

The code above is incorrectly indented, causing this sniff to fail. I guess this is acceptable for now. When the incorrect indenting is fixed in the respective issue this will be correctly detected and fixed.

diff --git a/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php b/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
index e04606b..4419d0e 100644
--- a/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
+++ b/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
@@ -176,4 +176,4 @@ public function testGetListenerPriority()
         // getListenerPriority().
     }
 
-}
+ }

Same as above. The preceding code is incorrectly indented, and this cascades to this sniff working incorrectly. When the indenting is fixed, this will be fixed along with it.

diff --git a/core/tests/Drupal/Tests/Core/Database/Stub/Driver/Schema.php b/core/tests/Drupal/Tests/Core/Database/Stub/Driver/Schema.php
index ae85a8f..41c7c6e 100644
--- a/core/tests/Drupal/Tests/Core/Database/Stub/Driver/Schema.php
+++ b/core/tests/Drupal/Tests/Core/Database/Stub/Driver/Schema.php
@@ -10,5 +10,4 @@
  */
 class Schema {
   // No-op.
-
 }

I think this is not a coding standards violation. This is an empty class. If the comment would not be there then we also wouldn't have a space there. So this is actually an improvement over the previous patch.

diff --git a/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTest.php b/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTest.php
index c028e0a..4d31ebdb 100644
--- a/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTest.php
+++ b/core/tests/Drupal/Tests/Core/DrupalKernel/DrupalKernelTest.php
@@ -134,7 +134,7 @@ public function testFindSitePath() {
       $this->assertEquals('sites/example', DrupalKernel::findSitePath($request));
     }
 
-  }
+}
 
 }
 

This is a bug in coder. This should be indented by two spaces, since this is a class which is wrapped by a namespace. This is also like the most edgy of all edge cases. I would report this in Coder, but not hold up this issue on it.

Status: Needs review » Needs work

The last submitted patch, 38: 2572619-38.patch, failed testing.

pfrenssen’s picture

Status: Needs work » Needs review
FileSize
408.56 KB

The drop is on the move again. The conflict seems to have been in the context. There was no visible interdiff.

alexpott’s picture

@pfrenssen can we split this issue up into specific errors defined by Drupal.Classes.ClassDeclaration this way the issue becomes reviewable. See the current phpcs.xml.dist for how to do this - I committed #2707641: Ensure core compliance to Drupal.Commenting.FunctionComment.ParamCommentIndentation (part 2) which does this.

pfrenssen’s picture

Status: Needs review » Needs work

Sure! I won't have time for it today though.

andypost’s picture

Status: Needs work » Needs review
FileSize
14.29 KB

Filed #2719695: Fix 'Drupal.Classes.ClassDeclaration.CloseBraceAfterBody' coding standard

      1 Drupal.Classes.ClassDeclaration.BraceOnNewLine
      1 Drupal.Classes.ClassDeclaration.SpaceBeforeExtends
      1 Drupal.Classes.ClassDeclaration.SpaceBeforeImplements
      5 Drupal.Classes.ClassDeclaration.SpaceAfterName
     21 Drupal.Classes.ClassDeclaration.SpaceBeforeBrace
    855 Drupal.Classes.ClassDeclaration.CloseBraceAfterBody
alexpott’s picture

Fixing all the sub-sniffs that are left.

Doing a git diff -w

diff --git a/core/phpcs.xml.dist b/core/phpcs.xml.dist
index 52bc19a..aa93c42 100644
--- a/core/phpcs.xml.dist
+++ b/core/phpcs.xml.dist
@@ -13,13 +13,7 @@
   <!-- Only include specific sniffs that pass. This ensures that, if new sniffs are added, HEAD does not fail.-->
   <!-- Drupal sniffs -->
   <rule ref="Drupal.Classes.ClassCreateInstance"/>
-  <rule ref="Drupal.Classes.ClassDeclaration">
-    <exclude name="Drupal.Classes.ClassDeclaration.BraceOnNewLine"/>
-    <exclude name="Drupal.Classes.ClassDeclaration.SpaceAfterName"/>
-    <exclude name="Drupal.Classes.ClassDeclaration.SpaceBeforeBrace"/>
-    <exclude name="Drupal.Classes.ClassDeclaration.SpaceBeforeExtends"/>
-    <exclude name="Drupal.Classes.ClassDeclaration.SpaceBeforeImplements"/>
-  </rule>
+  <rule ref="Drupal.Classes.ClassDeclaration"/>
   <rule ref="Drupal.Classes.FullyQualifiedNamespace"/>
   <rule ref="Drupal.Classes.UnusedUseStatement"/>
   <rule ref="Drupal.CSS.ClassDefinitionNameSpacing"/>
diff --git a/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php b/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
index 930dbe5..dfd12bb 100644
--- a/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
+++ b/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
@@ -1,4 +1,5 @@
 <?php
+// @codingStandardsIgnoreFile
 
 namespace Drupal\Tests\Component\EventDispatcher;
 
alexpott’s picture

+++ b/core/tests/Drupal/Tests/Component/EventDispatcher/ContainerAwareEventDispatcherTest.php
@@ -1,4 +1,5 @@
 <?php
+// @codingStandardsIgnoreFile

This file is a copy of the symfony test so ignoring coding standards is a good idea.

klausi’s picture

Status: Needs review » Reviewed & tested by the community

Looks good.

alexpott’s picture

Status: Reviewed & tested by the community » Fixed

Committed 92187c5 and pushed to 8.1.x and 8.2.x. Thanks!

  • alexpott committed 853202a on 8.2.x
    Issue #2572619 by attiks, andypost, pfrenssen, vprocessor, tatarbj,...

Status: Fixed » Closed (fixed)

Automatically closed - issue fixed for 2 weeks with no activity.