1<?php
2/**
3 * Verifies that class members are spaced correctly.
4 *
5 * PHP version 5
6 *
7 * @category  PHP
8 * @package   PHP_CodeSniffer
9 * @author    Greg Sherwood <gsherwood@squiz.net>
10 * @author    Marc McIntyre <mmcintyre@squiz.net>
11 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
12 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
13 * @link      http://pear.php.net/package/PHP_CodeSniffer
14 */
15
16if (class_exists('PHP_CodeSniffer_Standards_AbstractVariableSniff', true) === false) {
17    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractVariableSniff not found');
18}
19
20/**
21 * Verifies that class members are spaced correctly.
22 *
23 * @category  PHP
24 * @package   PHP_CodeSniffer
25 * @author    Greg Sherwood <gsherwood@squiz.net>
26 * @author    Marc McIntyre <mmcintyre@squiz.net>
27 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600)
28 * @license   https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence
29 * @version   Release: @package_version@
30 * @link      http://pear.php.net/package/PHP_CodeSniffer
31 */
32class Squiz_Sniffs_WhiteSpace_MemberVarSpacingSniff extends PHP_CodeSniffer_Standards_AbstractVariableSniff
33{
34
35
36    /**
37     * Processes the function tokens within the class.
38     *
39     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
40     * @param int                  $stackPtr  The position where the token was found.
41     *
42     * @return void
43     */
44    protected function processMemberVar(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
45    {
46        $tokens = $phpcsFile->getTokens();
47
48        $ignore   = PHP_CodeSniffer_Tokens::$methodPrefixes;
49        $ignore[] = T_VAR;
50        $ignore[] = T_WHITESPACE;
51
52        $start = $stackPtr;
53        $prev  = $phpcsFile->findPrevious($ignore, ($stackPtr - 1), null, true);
54        if (isset(PHP_CodeSniffer_Tokens::$commentTokens[$tokens[$prev]['code']]) === true) {
55            // Assume the comment belongs to the member var if it is on a line by itself.
56            $prevContent = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($prev - 1), null, true);
57            if ($tokens[$prevContent]['line'] !== $tokens[$prev]['line']) {
58                // Check the spacing, but then skip it.
59                $foundLines = ($tokens[$stackPtr]['line'] - $tokens[$prev]['line'] - 1);
60                if ($foundLines > 0) {
61                    $error = 'Expected 0 blank lines after member var comment; %s found';
62                    $data  = array($foundLines);
63                    $fix   = $phpcsFile->addFixableError($error, $prev, 'AfterComment', $data);
64                    if ($fix === true) {
65                        $phpcsFile->fixer->beginChangeset();
66                        // Inline comments have the newline included in the content but
67                        // docblock do not.
68                        if ($tokens[$prev]['code'] === T_COMMENT) {
69                            $phpcsFile->fixer->replaceToken($prev, rtrim($tokens[$prev]['content']));
70                        }
71
72                        for ($i = ($prev + 1); $i <= $stackPtr; $i++) {
73                            if ($tokens[$i]['line'] === $tokens[$stackPtr]['line']) {
74                                break;
75                            }
76
77                            $phpcsFile->fixer->replaceToken($i, '');
78                        }
79
80                        $phpcsFile->fixer->addNewline($prev);
81                        $phpcsFile->fixer->endChangeset();
82                    }
83                }//end if
84
85                $start = $prev;
86            }//end if
87        }//end if
88
89        // There needs to be 1 blank line before the var, not counting comments.
90        if ($start === $stackPtr) {
91            // No comment found.
92            $first = $phpcsFile->findFirstOnLine(PHP_CodeSniffer_Tokens::$emptyTokens, $start, true);
93            if ($first === false) {
94                $first = $start;
95            }
96        } else if ($tokens[$start]['code'] === T_DOC_COMMENT_CLOSE_TAG) {
97            $first = $tokens[$start]['comment_opener'];
98        } else {
99            $first = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($start - 1), null, true);
100            $first = $phpcsFile->findNext(PHP_CodeSniffer_Tokens::$commentTokens, ($first + 1));
101        }
102
103        $prev       = $phpcsFile->findPrevious(PHP_CodeSniffer_Tokens::$emptyTokens, ($first - 1), null, true);
104        $foundLines = ($tokens[$first]['line'] - $tokens[$prev]['line'] - 1);
105        if ($foundLines === 1) {
106            return;
107        }
108
109        $error = 'Expected 1 blank line before member var; %s found';
110        $data  = array($foundLines);
111        $fix   = $phpcsFile->addFixableError($error, $stackPtr, 'Incorrect', $data);
112        if ($fix === true) {
113            $phpcsFile->fixer->beginChangeset();
114            for ($i = ($prev + 1); $i < $first; $i++) {
115                if ($tokens[$i]['line'] === $tokens[$prev]['line']) {
116                    continue;
117                }
118
119                if ($tokens[$i]['line'] === $tokens[$first]['line']) {
120                    $phpcsFile->fixer->addNewline(($i - 1));
121                    break;
122                }
123
124                $phpcsFile->fixer->replaceToken($i, '');
125            }
126
127            $phpcsFile->fixer->endChangeset();
128        }//end if
129
130    }//end processMemberVar()
131
132
133    /**
134     * Processes normal variables.
135     *
136     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
137     * @param int                  $stackPtr  The position where the token was found.
138     *
139     * @return void
140     */
141    protected function processVariable(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
142    {
143        /*
144            We don't care about normal variables.
145        */
146
147    }//end processVariable()
148
149
150    /**
151     * Processes variables in double quoted strings.
152     *
153     * @param PHP_CodeSniffer_File $phpcsFile The file where this token was found.
154     * @param int                  $stackPtr  The position where the token was found.
155     *
156     * @return void
157     */
158    protected function processVariableInString(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
159    {
160        /*
161            We don't care about normal variables.
162        */
163
164    }//end processVariableInString()
165
166
167}//end class
168