学习使用PHP_CodeSniffer(二)

PHP_CodeSniffer所使用的编码标准

   
PHP_CodeSniffer中的编码标准是指一系列sniff文件的集合,每个sniff文件对应某个编码标准的特定部分(如代码对齐,或注释)。PHP_CodeSniffer中可以同时安装有多个编码标准,也就是说你可以用PHP_CodeSniffer对多个项目应用各自的编码标准进行检查。
   
    用下列命令可以查看PHP_CodeSniffer中已经安装的编码标准:

$ phpcs -i

The installed coding standards are PHPCS, Squiz, MySource, PEAR and Zend


   
PHP_CodeSniffer中的编码标准都在XXX/CodeSniffer/Standards目录下各自有一个以标准名称命名的独立目录,如现在PHP_CodeSniffer安装目录下已经安有PHPCS,Squiz,MySource,PEAR,Zend目录。每个目录下都包含了sniff文件目录,其中包含了用来定义编码标准各个部分的sniff文件,也可以用子目录将sniff文件分类存放。所以可以使用下列命令在PHP_CodeSniffer创建一个名为Seagull的编码标准的目录结构:

$ cd XXX/CodeSniffer/Standards
$ mkdir Seagull
$ mkdir Seagull/Sniffs



   
除此之外,我们还需要在Seagull目录下创建一个类文件,向PHP_CodeSniffer说明关于这个标准的基本信息并告诉PHP_CodeSniffer这个目录中包含这个标准的sniffs文件。这个类文件必须以此编码标准的名称为前缀,CodingStandard为后缀:

$ touch Seagull/SeagullCodingStandard.php



    内容应该如下:
  1. <?php
  2. /**
  3.  * Seagull Coding Standard.
  4.  *
  5.  * PHP version 5
  6.  *
  7.  * @category  PHP
  8.  * @package   PHP_CodeSniffer
  9.  * @author    Your Name <[email protected]>
  10.  * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
  11.  * @version   CVS: $Id: coding-standard-tutorial.xml,v 1.6 2007/10/15 03:28:17 squiz Exp $
  12.  * @link      http://pear.php.net/package/PHP_CodeSniffer
  13.  */
  14. require_once 'PHP/CodeSniffer/Standards/CodingStandard.php';
  15. /**
  16.  * Seagull Coding Standard.
  17.  *
  18.  * @category  PHP
  19.  * @package   PHP_CodeSniffer
  20.  * @author    Your Name <[email protected]>
  21.  * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
  22.  * @version   Release: @package_version@
  23.  * @link      http://pear.php.net/package/PHP_CodeSniffer
  24.  */
  25. class PHP_CodeSniffer_Standards_Seagull_SeagullCodingStandard extends PHP_CodeSniffer_Standards_CodingStandard
  26. {
  27. }//end class
  28. ?>
注:上面的这个代码示例中类的实体是空的。你也可以添加方法,详细的后面会介绍。

这样你就可以往Seagull编码标准的sniff文件目录中添加自己定义的sniff文件了,当然为了查找方便,你可以在Sniff文件目录中创建子目录将不同目的的sniff文件分门别类。

创建sniff文件

   
每个sniff对应一个PHP文件,文件命名最好是描述该sniff所强调的编码标准格式,并以Sniff.php结尾。比如我们不想让代码中使用#注释,我们可以创建一个名为DisallowHashCommentsSniff.php,并将它归入到Commenting子目录下。


$ cd XXX/CodeSniffer/Standards/Seagull/Sniffs
$ mkdir Commenting
$ touch Commenting/DisallowHashCommentsSniff.php

    每个sniff类必须实现 PHP_CodeSniffer_Sniff接口,这样在调用时 PHP_CodeSniffer才会创建一个sniff实例, PHP_CodeSniffer_Sniff定义两个在sniff文件中的类必须要实现的方法:register和process。

    sniff通过调用register告诉PHP_CodeSniffer它要检查编码标准哪些方面(也就是这个sniff要处理或者说会处理哪些类型的token)。这样当PHP_CodeSniffer在检查代码文件时碰到这些token时就会调用process方法来处理,同时付给process两个参数,第一个是 PHP_CodeSniffer_File 对象(即当前正在被处理的代码文件),另一个是出现错误的token在token堆栈中的索引。
    什么是token堆栈?我的认识是类似于php在解析php代码时会先将php代码分解成一个token数组。在sniff文件中通过调用 PHP_CodeSniffer_File对象的 getTokens()可以获取一个token数组,数组元素是以每个token在堆栈中的位置为索引。所有的token对应一个数组,包含 code , type, content索引对应的元素。其中code索引对应的元素是这个token类型对应的唯一整数值,type则对应token类型的字符串名称,type还以一个与此字符串同名的全局常量。content索引的值是这个token所对应的代码。
    注:有些token可能拥有更多的的元素。可以查看 PHP/CodeSniffer/File.php中的类类注释有一个token列表和相应的索引说明。
    这样我们就可以写一个自己的sniff文件了,先通过register向PHP_CodeSniffer注册此sniff要检查的token类型,然后在process里按照自已需要的编码标准进行处理,如果有错误发生就可以调用 PHP_CodeSniffer_File 对象 的addError来指示出错,其实也就是在PHP_CodeSniffer的检查结果中增加一条错误信息。当然如果错误不是太严重,你可以调用 addWarning来输出一个警告信息。

    下面代码示例了不允许在代码中使用类似PERL的#开头的单选注释:
  1. <?php
  2. /**
  3.  * PHP_CodeSniffer tokenises PHP code and detects violations of a
  4.  * defined set of coding standards.
  5.  *
  6.  * PHP version 5
  7.  *
  8.  * @category  PHP
  9.  * @package   PHP_CodeSniffer
  10.  * @author    Your Name <[email protected]>
  11.  * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
  12.  * @version   CVS: $Id: coding-standard-tutorial.xml,v 1.6 2007/10/15 03:28:17 squiz Exp $
  13.  * @link      http://pear.php.net/package/PHP_CodeSniffer
  14.  */

  15. require_once 'PHP/CodeSniffer/Sniff.php';

  16. /**
  17.  * This sniff prohibits the use of Perl style hash comments.
  18.  *
  19.  * An example of a hash comment is:
  20.  *
  21.  * <code>
  22.  *  # This is a hash comment, which is prohibited.
  23.  *  $hello = 'hello';
  24.  * </code>
  25.  * 
  26.  * @category  PHP
  27.  * @package   PHP_CodeSniffer
  28.  * @author    Your Name <[email protected]>
  29.  * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
  30.  * @version   Release: @package_version@
  31.  * @link      http://pear.php.net/package/PHP_CodeSniffer
  32.  */
  33. class Seagull_Sniffs_Commenting_DisallowHashCommentsSniff implements PHP_CodeSniffer_Sniff
  34. {


  35.     /**
  36.      * Returns the token types that this sniff is interested in.
  37.      *
  38.      * @return array(int)
  39.      */
  40.     public function register()
  41.     {
  42.         return array(T_COMMENT);

  43.     }//end register()


  44.     /**
  45.      * Processes the tokens that this sniff is interested in.
  46.      *
  47.      * @param PHP_CodeSniffer_File $phpcsFile The file where the token was found.
  48.      * @param int                  $stackPtr  The position in the stack where
  49.      *                                        the token was found.
  50.      *
  51.      * @return void
  52.      */
  53.     public function process(PHP_CodeSniffer_File $phpcsFile$stackPtr)
  54.     {
  55.         $tokens = $phpcsFile->getTokens();
  56.         if ($tokens[$stackPtr]['content']{0} === '#') {
  57.             $error = 'Hash comments are prohibited';
  58.             $phpcsFile->addError($error$stackPtr);
  59.         }

  60.     }//end process()


  61. }//end class

  62. ?>
Coding Standard类方法

   正如之前所提到的,每个编码标准都有一个Coding Standard类,
PHP_CodeSniffer 通过这个类获取关于这个编码标准的信息,同时这个类也向PHP_CodeSniffer标识了它亿在的这个文件目录中包含有sniff文件。我们可以通过重写这个类的两个方法来提供关于这个编码标准的额外信息。
  • getIncludedSniffs()
    这个方法可以告诉PHP_CodeSniffer除了这个编码对应的sniffs文件之外,你还要加载来自其它编码标准的sniff文件。它可以包含单个sniff文件,也可以包含整个目录或整个编码标准对应的sniff文件。
    看如下示例:
    1. <?php
    2. /**
    3.  * Return a list of external sniffs to include with this standard.
    4.  *
    5.  * The MyStandard coding standard uses some generic sniffs, and
    6.  * the entire PEAR coding standard.
    7.  *
    8.  * @return array
    9.  */
    10. public function getIncludedSniffs()
    11. {
    12.     return array(
    13.             'PEAR',
    14.             'Generic/Sniffs/Formatting/MultipleStatementAlignmentSniff.php',
    15.             'Generic/Sniffs/Functions',
    16.            );
    17. }//end getIncludedSniffs()
    18. ?>
    注:在用此方法包含另外一个编码标准的的sniff文件时,如果这个标准本身又有包含其它编码标准的sniff文件时,这些sniff文件也会被包含进来。所以,基于一个编码标准创建一个新的编码标准是非常方便的。

  • getExcludedSniffs()

    这个方法的作用和上面的方法相反。看下面的示例,先是包含了某个整个的编码标准的sniff文件,但是又不需要其中的某个sniff文件。
    1. <?php
    2. /**
    3.  * Return a list of external sniffs to include with this standard.
    4.  *
    5.  * The MyStandard coding standard uses all PEAR sniffs except one.
    6.  *
    7.  * @return array
    8.  */
    9. public function getIncludedSniffs()
    10. {
    11.     return array(
    12.             'PEAR',
    13.            );
    14. }//end getIncludedSniffs()
    15. /**
    16.  * Return a list of external sniffs to exclude from this standard.
    17.  *
    18.  * The MyStandard coding standard uses all PEAR sniffs except one.
    19.  *
    20.  * @return array
    21.  */
    22. public function getExcludedSniffs()
    23. {
    24.     return array(
    25.             'PEAR/Sniffs/ControlStructures/ControlSignatureSniff.php',
    26.            );
    27. }//end getExcludedSniffs()
    28. ?>
应用实例:定义自己的用于Seagull PHP Framework的编码标准
(待续)


你可能感兴趣的:(PHP,File,perl,token,Zend,Standards)