PHP/Drupal Code Quality Quick Wins, Part 1: Linting

Joeri Poesen //

In this first part we’re looking at a few tools that are very easy to set up and use, yet can make a dramatic impact in the quality and coherence of your team’s codebase.

From validating syntax to detecting dead code to graphing dependency chains and measuring cyclometric complexity, static analysis tools help you analyse code without actually executing it.

For ages we kept saying “we’ve got no time to waste on trying to figure out this stuff, we have bugs to fix”. We kept chasing after elusive bugs, weird regressions (once-solved bugs that suddenly pop up again) and new breakages and we "never had time” to start improving the core of our development process.

Once we actually took the time, we discovered it’s pretty easy to get started. If you come from a workflow with zero attention to code analysis, testing and automated integration, there are some very easy and interesting quick wins out there.

We’ll try to cover several approaches, flows and tools in the weeks and months to come. We’ll likely discover new tools and new ways of improving our internal way of doing things, and we’ll share those as we encounter them - they may in some form be useful to you and your team as well.

On to the linting

In a nutshell, linters check checks if your source code is syntactically valid; it does not necessarily have any opinions about your coding style or about the soundness of your architecture. PHP's built-in linter is such a basic sanity-checking tool. Other tools such as jshint and jslint can be more opinionated.

Though this is a very simplistic check, you’d be amazed of how useful it can be to integrate automatic linting in your commit, test and deployment process.

1. PHP linting

Installation:
Linting comes built-in with php-cli, the command line version of PHP, so if you’ve got that up and running you’re ready to start linting.

Example file:

[php]
<br /?foo()
$a = 1;
// etc.
[/php]

Usage:
[bash]
# Example 1: Lint a single php file.
$ php -l example.php
[/bash]

Example output:

[text]
PHP Parse error: parse error in example.php on line 2
[/text]

When the linter encounters an error, the return code (a.k.a. exit status) will be non-zero, which means you can easily integrate php -l in scripts that perform certain actions (like deploying code) based on whether or not the linter encountered errors.

[bash]
# Example 2: Lint all php files in a directory.
$ php -l .
[/bash]

2. JavaScript linting

Though there are several javascript linters out there, JSHint (http://jshint.com/install/) is nowadays the most popular one. As of Drupal 8 requires all core and contrib JavaScript changes to pass JSHint checks, so it's a pretty good idea to add JSHint to your linting toolchain today.

If you want to validate JavaScript code in the context of a D8 project, you don't need to do anything specific: D8 core now contains the two required JSHint configuration files (https://drupal.org/node/1955232):

  • .jshintrc: some Drupal-specific rules
  • .jshintignore: which files JSHint should ignore

If you're working on a D7 project and want to validate your custom JavaScript code according to the D8 standards, just grab the 2 config files and put them in your D7 project's root.

The most convenient way to use JSHint is to run it from the command line. For this you'll need to install nodejs (http://nodejs.org/download/) and use its package manager npm to install jshint. Installing nodejs for this may seem like overkill, but there's an incredible array of interesting stuff available in nodejs land :)

[text]
# Install JSHint.
$ npm install -g jshint
[/text]

Usage:
[text]
# Example 1: Lint a single js file.
$ jshint example.js
[/text]

[text]
# Example 2: Lint all of D8's core js.
$ cd /path/to/example.com
$ jshint core
[/text]

[text]
# Example 3: Lint all of a D8 project's js (core+contrib).
$ cd /path/to/example.com
$ jshint .
[/text]

More info:

3. CSS linting

The standard ruleset used by CSS Lint (http://csslint.net) is pretty sane, though it does have some conflicts with the proposed Drupal CSS code standards (discussed here: https://drupal.org/node/1886770).

At the time of writing (March 2014) there doesn't seem to be a specific Drupal CSS ruleset available for CSS Lint, though efforts are underway to create a .csslintrc config file, similar to .jshintrc. For now, the standard CSS Lint ruleset is already a huge help.

[text]
# Install CSS Lint.
$ npm install -g csslint

Usage:
# Example 1: Lint a single css file.
$ csslint example.css

# Example 2: Lint all css files in a directory.
$ csslint .

[/text]

More info:

4. SASS/SCSS linting

If you're a front-end developer chances are you're using something like SASS (http://sass-lang.com) or Compass (http://compass-style.org) to infuse to your css files with variables, loops, extensions and more. The CSS extensions defined by sass can become tricky, so it makes sense to bring a specialized linter into play… enter scss-lint (https://github.com/causes/scss-lint):

[text]
# If you haven't already, install the SASS gem.
$ gem install sass

# Install scss-lint.
$ gem install scss-lint

Usage:
#Example 1: Lint a single scss file.
# scss-lint example.css

#Example 2: Lint all scss files in a directory.
# scss-lint .
[/text]

Note: scss-lint has built-in support for the Compass framework; you just need to explicitly specify you want to enable the compass linter. Check out the docs (https://github.com/causes/scss-lint/blob/master/lib/scss_lint/linter/co…) to see how.

More info:

Conclusion

Linting tools help you validate source code. Command-line linters can be run ad-hoc and integrated into IDEs and build scripts. Setting them up and running them is pretty straightfoward and can have huge benefits for your team's code quality.

Look out for follow-up articles where we'll go into validating custom Drupal code and enforcing our code validations with git pre-commit hooks.