Last updated September 27, 2013. Created by LeeHunter on May 15, 2007.
Edited by douggreen, salvis, Dane Powell, superbaloo. Log in to edit this page.

Coder is the code review module. The name coder has a double meaning: a "coder" is obviously someone who writes code, and "code-r" is short for "code review".

User Reference

To be filled in...

Review and Rule Developer References

Reviews

A review is a set of rules designed to accomplish a task. There is a code standards review, a review for upgrading from 4.7.x->5.x, another review for upgrading from 5.x->6.x, there's the beginnings of a security review and a performance review. Each review has an array of rules. The reviews are shown on the UI pages and can be found in the includes directory.

Options

  • #title
  • #link - link to drupal.org page about the review
  • #rules - rule definition (see below)
  • #severity - default severity (minor, normal, critical) for all rules in the review. severity controls the color and icons displayed. this value can be over-riden by individual rules.

Rules

A rule is a single specific pattern to find. Rules can use the following #type:

  • regex - look for a particular pattern
  • grep - looks for a particular string, meant to be faster when regex is not needed
  • grep_invert - look for a particular string that does not exist
  • callback - do anything you want

More about regex rules

Thus, to find all _submit functions you could use

    array(
      '#type' => 'regex',
      '#value' => '_submit\s*\(',
    ),

This example regex looks for _submit followed by optional spaces, and a required left parenthesis. If you wanted to be more specific, since the _submit handler has very specific arguments that are changing, you could look for:

      '#value' => '_submit\s*\(\$form_id,',

Remember, coder is just a helpful tool. It's not going to catch every use-case (people who use different variable names), but a simple rule like this will find all 5.x submit handlers and warn you to upgrade it. If you wanted to be more generic, you could write a rule that looked for two arguments instead of 3, but the regex for that is a little harder.

You can also restrict your regex searches within a function. So, if you wanted to warn about the recent menu changes:

    array(
      '#type' => 'regex',
      '#function' => '_menu$',
      '#value' => '\$items\[\]\s*=|if\s*\(\$may_cache\)',
    ),

This rule looks for $items[] = or if ($maycache).

Quoted strings are replaced with '' in the php source (the default, but see below). Thus if you wanted to make sure that the above had a string array index (such as $items['something'] =, you could have written (BTW, this is a bogus example just to show quoted strings):

    array(
      '#type' => 'regex',
      '#value' => '\$items\[\'\'\]\s*=',
    ),

Rule warnings

Finding code patterns is only half the problem. You also need to write a warning. There are two warning options,

  1. #warning
  2. #warning_callback

So, using the first example above, we should add a warning

      '#value' => '_submit\s*\(\$form_id,',
      '#warning' => t('hook_submit() parameters have changed'),

Notice that this warning uses t for text processing. Since this function takes processing time, and since the rules files are read a lot, there also exists a warning_callback that should be used in most cases. So, the above really should be:

      '#value' => '_submit\s*\(\$form_id,',
      '#warning_callback' => '_coder_6x_fapi_submit_warning',
...
  functions _coder_6x_fapi_submit_warning() {
    return t('!hook_submit() parameters have changed',
      array(
        '!hook_submit' => theme('drupalapi', 'hook_submit'),
      )
    );
  }
Warning Callbacks

Warning callbacks support either a text string or an array. If an array is returned, it should contain:

  • #warning - this is the same as the simple text string (or #warning in the rule)
  • #description - a more detailed description. if supplied, the user can click on the down-arrow icon and receive more information about this warning
  • #link - link to more Detailed documentation, usually on d.o.

Available source options

Usually, you're just looking for something in the php. But coder supports these #source options:

  • php - this is the default
  • allphp - similar to php option, but also includes full quotes
  • html - anything not inside <?php ... ?>, but also looks for html tags inside quotes.
  • all - any line in the source. this is sometimes needed to override the default quote and/or comment handling.
  • quote - anything inside a single (') or double-quote (")
  • doublequote - anything inside a double-quote (")
  • comment - anything inside a comment, including the leading and trailing comment

So, for example, if you want to look for the string "hello world" (inside a doublequote), you can use the following:

    array(
      '#type' => 'regex',
      '#value' => 'hello world',
      '#source' => 'doublequote',
    ),

It should be noted that there isn't a 'comment' option and there probably should be. The only way to search for comments is to use '#source' option 'all'. Otherwise, all comments are stripped.

Other rules options

  • #case-sensitive - pattern matching ignores case by default. Use this to for case sensitive matching. This is needed for camelCase and capitalization rules.
  • #not - to make pattern matching rules simpler, use this to exclude matched values
  • #never - never match lines that also contain this regex (uses #source = all)
  • #severity - severity (minor, normal, critical) controls the color and icons displayed. values defined here over-ride values set in the review
  • #filename - apply this rule to files whose filename matches a regex
  • #filename-not - apply this rule to files whose filename does not match a regex

Ignore system

It is preferable to fix invalid warnings, but if coder is throwing invalid warnings, you can tell coder to ignore the warning in your code using a comment. In the UI, each warning now displays along with it's warning name. You can also enable warnings from the drush command line, see drush coder --ignorename.

A few quick examples:

This is comment scope:

// @ignore rule:comment
/*
* Let's assume that this line is OK
*
* But way down here, maybe,
* This is a comment that has some valid stuff in it that coder flags................................
**/

This would also work for coder, but would likely have doxygen problems:

/*
* @ignore rule:comment
* Let's assume that this line is OK
*
* But way down here, maybe,
* This is a comment that has some valid stuff in it that coder flags................................
**/

This is a function scope:

$a = 'nothing ignored yet';
/**
* My function
*/
function my_function() {
  // @ignore rule:function
  $b = 'the rule is ignored';
}
$c = 'the rule is no longer ignored';
function your_function() {
  $d = 'of course the rule is not ignored here either';
}

You can also enable function (or class scope) from anywhere within the function and class.

class MyClass {
  // @ignore rule:class
  protected function yourFunction() {
    $b = 'the rule is ignored here';
  }
  protected $c = 'the rule is also ignored here';
};
function another_function() {
  $d = 'the rule is not ignored here because we are outside the class now';
}
class AnotherClass {
  protected $a = 'nothing is ignored yet';
  function myFunction() {
    $b = 'the rule is not ignored here';
  }
  // @ignore rule:class
  protected function yourFunction() {
    $b = 'the rule is ignored here';
  }
  protected $c = 'the rule is also ignored here';
};
function another_function() {
  $d = 'the rule is not ignored here because we are outside the class now';
}

Looking for support? Visit the Drupal.org forums, or join #drupal-support in IRC.