Squiz Labs Blog - The latest news from the R&D arm 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.


,    Permalink for 'PHP_CodeSniffer ruleset.xml support available in SVN'

PHP_CodeSniffer 1.2.2 released

PHP_CodeSniffer version 1.2.2 has just been uploaded to PEAR and is now available to install. Most of the changes are behind-the-scenes, but some of the highlights are:

  • An interactive reporting mode to check large code bases and make changes as you go
  • Closure support added into the core so sniffs can now check rules for PHP closures
  • A completely rewritten reporting system to make everything much easier to extend
  • Sniff violation codes that will be used to allow overriding of error messages in the future

All new features have been fully documented and are available on the PHP_CodeSniffer documentation page.

You can view the full changelog on the PHP_CodeSniffer download page.


,    Permalink for 'PHP_CodeSniffer 1.2.2 released'

PHP_CodeSniffer interactive mode

PHP_CodeSniffer is traditionally run over a set of files and a report printed after the run. A developer then uses the report to fix the errors and rechecks the files manually. This can be quite time consuming for large code bases because the error list may be long or may change as other errors are fixed. To make this process easier, a new interactive mode has just been committed to the PHP_CodeSniffer SVN repository.

When PHP_CodeSniffer is asked to run interactively, it will stop checking files as soon as it finds one with errors. It will then print the error report for this file and wait for user input. The idea here is that you go away, fix the errors in the file (focusing on one file at a time) and then ask PHP_CodeSniffer to recheck the file. If the errors are now gone, PHP_CodeSniffer will continue checking the code base from where it left off. If more errors are found, the new error report is shown for the file. You also have to option of skipping the file if you would prefer to fix the errors later.

The following example shows some sample output from interactive mode. This mode is enabled using the -a command line argument.

$ phpcs -a temp.php

FILE: /Users/gsherwood/PHP_CodeSniffer/trunk/temp.php
--------------------------------------------------------------------------
FOUND 2 ERROR(S) AND 1 WARNING(S) AFFECTING 1 LINE(S)
--------------------------------------------------------------------------
 2 | WARNING | Inline control structures are discouraged
 2 | ERROR   | Missing file doc comment
 2 | ERROR   | TRUE, FALSE and NULL must be lowercase; expected "true" but
   |         | found "TRUE"
--------------------------------------------------------------------------

<ENTER> to recheck, [s] to skip or [q] to quit :

Interactive mode also works with all other PHP_CodeSniffer command line options. So you can set the report format and standard to use, if you want to hide warnings, if you'd like to display verbose output, which files to ignore, etc.

So grab a copy of PHP_CodeSniffer from the SVN repository and give it a go. Just add -a to your normal PHP_CodeSniffer command. If you prefer to wait until the release, this feature will be in version 1.2.3 and released as stable in a few weeks time.


,    Permalink for 'PHP_CodeSniffer interactive mode'

Big plans for PHP_CodeSniffer

We've just put together our development plan for PHP_CodeSniffer 1.3.0 and it contains some great features that are going to make it dead-simple to customise the built-in standards without having to write any PHP code.

The biggest change is the concept of violation codes for sniffs. Currently, each sniff can throw different errors and warnings using different error messages, but there is no way to target each of them. Sniffs can now specify violation codes so each of those errors and warnings can be uniquely identified within PHP_CodeSniffer. We'll be adding violation codes for all sniffs that ship with PHP_CodeSniffer. For developers who have written their own sniffs, you can start testing violation codes now as this feature has just been committed to the PHP_CodeSniffer SVN repository.

To add a violation code, you simply specify a third argument to the addError() and addWarning() methods:

$error = 'Line exceeds maximum length of 85 characters';
$phpcsFile->addError($error, $stackPtr, 'LineTooLong'); 

The goal of the violation code development is to make it easy for developers to customise the messages and severities of errors and warnings. You will be able to do this via a ruleset.xml file (similiar to this one) where you can customise as much or as little of a standard as you want. You'll be able to translate messages into other languages, add more useful information into the messages for your team, turns errors into warnings, turn warnings into errors and even remove errors and warnings from the standard all together. And all this via a simple XML file.

Severities are also something we are working on. Currently, PHP_CodeSniffer only has two severity levels; error and warning. We are going to maintain these two different types of messages but add severity levels to them. So instead of having just 5 errors and 2 warnings, you might have 1 severity 10 error, 4 severity 4 errors and 2 severity 7 warnings. You can use the error and warning categories to decide between issues that must be fixed and issues they should be looked at, but then go a step further and decide on a severity to help you prioritise reviews. All these severities will be set in the ruleset.xml file, so sniff developers don't need to do anything if they are happy with the default values we will provide when adding errors and warnings. All reports will get an option to filter errors and warnings by a severity level that you define.

Once we have all this going, the next logical step we are looking at is to allow this ruleset.xml file to define parameters for sniffs. The line length sniff is a great example of where this would be useful. You may be using the PEAR standard, so you will see warnings for all lines over 85 characters in length. With this new feature, you could add a line into the ruleset.xml file so that when you run the PEAR standard you would only see warnings for lines longer than 95 characters. Previously, you had to write your own standard and custom sniff to override the protected member var of the PEAR sniff. With this feature, it will be as easy as an XML tag.

Lastly, we are restructuring the reporting system to remove all the report code out of CodeSniffer.php and put it into separate classes. This not only cleans the code up a bit and ensures we don't load any code we don't need, but it will also make it possible for you to write custom reports for to help you integrate PHP_CodeSniffer with other applications in your development and integration environments.

So that's an awful lot of development headed for PHP_CodeSniffer. Some of the smaller changes will roll out in the 1.2.x releases for developer testing, but most will not be available until a 1.3.0beta1 release sometime early next year. We'll keep you posted.


,    Permalink for 'Big plans for PHP_CodeSniffer'

PHP_CodeSniffer 1.2.1 released

PHP_CodeSniffer version 1.2.1 has just been uploaded to PEAR and is now available to install. It's been exactly 3 months since the 1.2.0 release and plenty of changes have made it into this version, including a few new features as well.

Some of the highlights are:

  • A new report type called svnblame that allows you to see which developers are causing the most errors
  • The ability to set the report width for all reports, which is really useful for developers with larger screens
  • The addition of @codingStandardsIgnore comments to tell PHP_CodeSniffer to ignore parts of a file or the entire file

There have also been some great changes made to the CSS and JavaScript tokenizers to improve their stability.

All new features have been fully documented and are available on the PHP_CodeSniffer documentation page.

You can view the full changelog on the PHP_CodeSniffer download page.


,    Permalink for 'PHP_CodeSniffer 1.2.1 released'

Squizlabs

Squiz Labs is the research and development arm of Squiz, the company behind the MySource Matrix and MySource Mini open source content management systems.

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.

Take a look at our product line-up:

MySource Matrix

MySource Matrix is a robust, scalable Content Management solution for the enterprise. It competes effectively with and surpasses the offerings of other CMS's such as Vignette and Interwoven.

Read Articles | Visit Website

MySource Mini

MySource Mini is the next generation CMS from Squiz boasting the first true inline editing experience. Simplicity is the key to MySource Mini with enterprise features as easy to use as common editing tools.

Read Articles | Visit Website

PHP_CodeSniffer

PHP_CodeSniffer is a tool that tokenises and sniffs PHP, JavaScript and CSS files to detect violations of a defined coding standard. It is an essential development tool that ensures your code remains clean and consistent.

Read Articles | Visit Website