Squiz Labs Blog - The latest news from the R&D division of Squiz®

Subscribe to our RSS feeds

PHP_CodeSniffer ruleset.xml support available in SVN

The current SVN checkout of PHP_CodeSniffer contains some really big changes to the way custom standards are written and used. The changes make it much easier to create and distribute your own coding standards, giving you the flexibility to pick and choose from the available sniffs and override some of the internal rules the sniffs use, like line lengths and messages.

Creating a custom coding standard

Before ruleset.xml support was added to PHP_CodeSniffer, you needed to write a PHP class for all custom standards. This class had to reside at the top level of your standard's directory structure and extend PHP_CodeSniffer_Standards_CodingStandard. This class was used to both indicate that you have a custom standard and provide a list of sniffs or standards you want to include or exclude.

This file is no longer used. Instead, you must provide a ruleset.xml file (called ruleset.xml) if you wish to distribute a custom standard with your own sniffs. If you do not have any sniffs to distribute and you simply want to use some of the sniffs that are distributed with PHP_CodeSniffer, you only need a single XML file, named whatever you want.

The format is really easy. Here is a very simple ruleset.xml file for a custom standard for PHP_CodeSniffer itself. It uses the whole PEAR standard but also grabs some of the Squiz sniffs. It does this by including the whole Squiz standard and then excluding some specific sniffs from it.

<?xml version="1.0"?>
<ruleset name="PHP_CodeSniffer">
 <description>The coding standard for PHP_CodeSniffer.</description>

 <!-- Include the whole PEAR standard -->
 <rule ref="PEAR"/>

 <!-- Include most of the Squiz standard -->
 <rule ref="Squiz">
  <exclude name="Squiz.Classes.ClassFileName"/>
  <exclude name="Squiz.Classes.ValidClassName"/>
  <exclude name="Squiz.Commenting.ClassComment"/>
  <exclude name="Squiz.Commenting.FileComment"/>
  <exclude name="Squiz.Commenting.FunctionComment"/>
  <exclude name="Squiz.Commenting.VariableComment"/>
  <exclude name="Squiz.ControlStructures.SwitchDeclaration"/>
  <exclude name="Squiz.Files.FileExtension"/>
  <exclude name="Squiz.NamingConventions.ConstantCase"/>
  <exclude name="Squiz.WhiteSpace.ScopeIndent"/>
 </rule>

</ruleset>

If we assume this file is called phpcs.xml, to use this standard with PHP_CodeSniffer you simply run the command:

phpcs --standard=/path/to/phpcs.xml /path/to/code

No need for a directory structure or special naming. And obviously this single file is easy to distribute, maintain and document.

Overriding sniffs options

One of the biggest frustrations when building a custom standard, or even just using an existing one, has been the inability to easily override some of those sniff-specific options. For example, when the Line Length sniff should generate a warning; at 80 chars, 85 chars, 90 chars or another length.

Previously, you had to create your own sniff class that extended the main Line Length sniff and overrode the protected member var. Now, you can do it directly from your ruleset.xml file without needing to create any PHP classes.

Suppose you love the PEAR standard, but you hate the fact that it generates a warning when your line is 85 characters long because you would rather have it happen at 90 characters. Now you can create your own ruleset.xml file, mypear.xml:

<?xml version="1.0"?>
<ruleset name="My PEAR">
 <description>The PEAR standard, but warnings at 90 chars.</description>

 <!-- Include the whole PEAR standard -->
 <rule ref="PEAR"/>
 
 <!-- Lines can be no longer than 90 chars -->
 <rule ref="Generic.Files.LineLength">
  <properties>
   <property name="lineLimit" value="90"/>
  </properties>
 </rule>

</ruleset>

Now run PHP_CodeSniffer like this:

phpcs --standard=/path/to/mypear.xml /path/to/code

Changing sniff messages

The new ruleset.xml file also allows you to customise the messages that sniffs produce. For those messages with variables inside them, you use a sprintf format. Just add this to your ruleset.xml file to change the TODO sniff's warning message:

<rule ref="Generic.Commenting.Todo.CommentFound">
 <message>Please review this comment: %s</message>
</rule>

Or even use this feature to provide translations:

<rule ref="Generic.Commenting.Todo.CommentFound">
 <message>Lütfen bu yorumu gözden geçirin: %s</message>
</rule> 

Changing sniff severity levels

Another new feature available in SVN is the ability for PHP_CodeSniffer to filter out errors and warnings based on a severity level. By default, all errors and warnings have a severity of 5 and PHP_CodeSniffer will show them all. This feature needs its own blog post, but it revolves around the ruleset.xml file as well so I wanted to include it briefly here.

Here is an example of making the TODO sniff less severe. You may want to do this so it does not appear when running PHP_CodeSniffer normally, but you can do a full run to get all warnings during a manual code review:

<rule ref="Generic.Commenting.Todo.CommentFound">
 <severity>3</severity>
</rule> 

A complete example

The following sample file does pretty much everything you can do with this new ruleset.xml file format:

<?xml version="1.0"?>
<ruleset name="Sample">
 <description>A sample coding standard</description>

 <!-- Include all sniffs in the PEAR standard -->
 <rule ref="PEAR"/>

 <!-- Include all sniffs in an external standard directory -->
 <rule ref="/home/gsherwood/standards/mystandard"/>

 <!-- Include everything in another ruleset.xml file -->
 <rule ref="/home/gsherwood/standards/custom.xml"/>

 <!-- Include all sniffs in the MySource standard except one -->
 <rule ref="MySource">
  <exclude name="MySource.Channels.DisallowSelfActions"/>
 </rule>

 <!-- Include some specific sniffs -->
 <rule ref="Generic.CodeAnalysis.UnusedFunctionParameter"/>
 <rule ref="Generic.Commenting.Todo"/>
 <rule ref="Generic.ControlStructures.InlineControlStructure"/>

 <!-- Drop the severity of the todo sniff and change the message -->
 <rule ref="Generic.Commenting.Todo.CommentFound">
  <message>Please review this TODO comment: %s</message>
  <severity>3</severity>
 </rule>

 <!-- Change the settings of the Line Length sniff -->
 <rule ref="Generic.Files.LineLength">
  <properties>
   <property name="lineLimit" value="90"/>
   <property name="absoluteLineLimit" value="100"/>
  </properties>
 </rule>

  <!-- Change both Line Length messages -->
 <rule ref="Generic.Files.LineLength.MaxExceeded">
  <message>Line contains %s chars, longer than the max of %s</message>
 </rule>
 <rule ref="Generic.Files.LineLength.TooLong">
  <message>Line longer than %s chars; has %s chars</message>
 </rule>

 <!-- Disable internal message for missing code and short open tags -->
 <rule ref="Internal.NoCodeFound">
  <severity>0</severity>
 </rule>
</ruleset> 

An alpha release of PHP_CodeSniffer 1.3.0 will happen this week or next. So you can grab the code from SVN directly or wait for this alpha release. Developers of existing custom standards should use this long alpha/RC release process to convert their PHP classes to the new ruleset.xml format.

Squiz Labs

R & D division of Squiz Pty Ltd

Open source web experience management solutions

Squiz Labs is the research and development division of Squiz, the company behind the Squiz Suite of web experience management and development tools.

Our PHP and JavaScript developers are responsible for producing innovative enterprise-quality software while our interface designers and testing team ensure our products both look great and are easy to use.