1<?php
2/**
3 * This file is part of the CodeAnalysis add-on for PHP_CodeSniffer.
4 *
5 * PHP version 5
6 *
7 * @category  PHP
8 * @package   PHP_CodeSniffer
9 * @author    Greg Sherwood <gsherwood@squiz.net>
10 * @author    Manuel Pichler <mapi@manuel-pichler.de>
11 * @copyright 2007-2014 Manuel Pichler. All rights reserved.
12 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
13 * @link      http://pear.php.net/package/PHP_CodeSniffer
14 */
15
16/**
17 * Detects unnecessary final modifiers inside of final classes.
18 *
19 * This rule is based on the PMD rule catalog. The Unnecessary Final Modifier
20 * sniff detects the use of the final modifier inside of a final class which
21 * is unnecessary.
22 *
23 * <code>
24 * final class Foo
25 * {
26 *     public final function bar()
27 *     {
28 *     }
29 * }
30 * </code>
31 *
32 * @category  PHP
33 * @package   PHP_CodeSniffer
34 * @author    Manuel Pichler <mapi@manuel-pichler.de>
35 * @copyright 2007-2014 Manuel Pichler. All rights reserved.
36 * @license   http://www.opensource.org/licenses/bsd-license.php BSD License
37 * @version   Release: @package_version@
38 * @link      http://pear.php.net/package/PHP_CodeSniffer
39 */
40class Generic_Sniffs_CodeAnalysis_UnnecessaryFinalModifierSniff implements PHP_CodeSniffer_Sniff
41{
42
43
44    /**
45     * Registers the tokens that this sniff wants to listen for.
46     *
47     * @return int[]
48     */
49    public function register()
50    {
51        return array(T_CLASS);
52
53    }//end register()
54
55
56    /**
57     * Processes this test, when one of its tokens is encountered.
58     *
59     * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
60     * @param int                  $stackPtr  The position of the current token
61     *                                        in the stack passed in $tokens.
62     *
63     * @return void
64     */
65    public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
66    {
67        $tokens = $phpcsFile->getTokens();
68        $token  = $tokens[$stackPtr];
69
70        // Skip for-statements without body.
71        if (isset($token['scope_opener']) === false) {
72            return;
73        }
74
75        // Fetch previous token.
76        $prev = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($stackPtr - 1), null, true);
77
78        // Skip for non final class.
79        if ($prev === false || $tokens[$prev]['code'] !== T_FINAL) {
80            return;
81        }
82
83        $next = ++$token['scope_opener'];
84        $end  = --$token['scope_closer'];
85
86        for (; $next <= $end; ++$next) {
87            if ($tokens[$next]['code'] === T_FINAL) {
88                $error = 'Unnecessary FINAL modifier in FINAL class';
89                $phpcsFile->addWarning($error, $next, 'Found');
90            }
91        }
92
93    }//end process()
94
95
96}//end class
97