~ubuntu-branches/ubuntu/trusty/php-codesniffer/trusty

« back to all changes in this revision

Viewing changes to PHP_CodeSniffer-1.0.1/CodeSniffer/Standards/PEAR/Sniffs/NamingConventions/ValidFunctionNameSniff.php

  • Committer: Bazaar Package Importer
  • Author(s): Jan Wagner
  • Date: 2008-03-21 23:29:33 UTC
  • Revision ID: james.westby@ubuntu.com-20080321232933-za8kvi1bgvrvud6z
Tags: upstream-1.0.1
ImportĀ upstreamĀ versionĀ 1.0.1

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
<?php
 
2
/**
 
3
 * PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff.
 
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 Squiz Pty Ltd (ABN 77 084 670 600)
 
12
 * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
 
13
 * @version   CVS: $Id: ValidFunctionNameSniff.php,v 1.18 2008/01/22 23:50:23 squiz Exp $
 
14
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 
15
 */
 
16
 
 
17
if (class_exists('PHP_CodeSniffer_Standards_AbstractScopeSniff', true) === false) {
 
18
    throw new PHP_CodeSniffer_Exception('Class PHP_CodeSniffer_Standards_AbstractScopeSniff not found');
 
19
}
 
20
 
 
21
/**
 
22
 * PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff.
 
23
 *
 
24
 * Ensures method names are correct depending on whether they are public
 
25
 * or private, and that functions are named correctly.
 
26
 *
 
27
 * @category  PHP
 
28
 * @package   PHP_CodeSniffer
 
29
 * @author    Greg Sherwood <gsherwood@squiz.net>
 
30
 * @author    Marc McIntyre <mmcintyre@squiz.net>
 
31
 * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
 
32
 * @license   http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
 
33
 * @version   Release: 1.0.1
 
34
 * @link      http://pear.php.net/package/PHP_CodeSniffer
 
35
 */
 
36
class PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff extends PHP_CodeSniffer_Standards_AbstractScopeSniff
 
37
{
 
38
 
 
39
    /**
 
40
     * A list of all PHP magic methods.
 
41
     *
 
42
     * @var array
 
43
     */
 
44
    private $_magicMethods = array(
 
45
                              'construct',
 
46
                              'destruct',
 
47
                              'call',
 
48
                              'callStatic',
 
49
                              'get',
 
50
                              'set',
 
51
                              'isset',
 
52
                              'unset',
 
53
                              'sleep',
 
54
                              'wakeup',
 
55
                              'toString',
 
56
                              'set_state',
 
57
                              'clone',
 
58
                             );
 
59
 
 
60
    /**
 
61
     * A list of all PHP magic functions.
 
62
     *
 
63
     * @var array
 
64
     */
 
65
    private $_magicFunctions = array(
 
66
                                'autoload',
 
67
                               );
 
68
 
 
69
 
 
70
    /**
 
71
     * Constructs a PEAR_Sniffs_NamingConventions_ValidFunctionNameSniff.
 
72
     */
 
73
    public function __construct()
 
74
    {
 
75
        parent::__construct(array(T_CLASS, T_INTERFACE), array(T_FUNCTION), true);
 
76
 
 
77
    }//end __construct()
 
78
 
 
79
 
 
80
    /**
 
81
     * Processes the tokens within the scope.
 
82
     *
 
83
     * @param PHP_CodeSniffer_File $phpcsFile The file being processed.
 
84
     * @param int                  $stackPtr  The position where this token was
 
85
     *                                        found.
 
86
     * @param int                  $currScope The position of the current scope.
 
87
     *
 
88
     * @return void
 
89
     */
 
90
    protected function processTokenWithinScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $currScope)
 
91
    {
 
92
        $className  = $phpcsFile->getDeclarationName($currScope);
 
93
        $methodName = $phpcsFile->getDeclarationName($stackPtr);
 
94
 
 
95
        // Is this a magic method. IE. is prefixed with "__".
 
96
        if (preg_match('|^__|', $methodName) !== 0) {
 
97
            $magicPart = substr($methodName, 2);
 
98
            if (in_array($magicPart, $this->_magicMethods) === false) {
 
99
                 $error = "Method name \"$className::$methodName\" is invalid; only PHP magic methods should be prefixed with a double underscore";
 
100
                 $phpcsFile->addError($error, $stackPtr);
 
101
            }
 
102
 
 
103
            return;
 
104
        }
 
105
 
 
106
        // PHP4 constructors are allowed to break our rules.
 
107
        if ($methodName === $className) {
 
108
            return;
 
109
        }
 
110
 
 
111
        // PHP4 destructors are allowed to break our rules.
 
112
        if ($methodName === '_'.$className) {
 
113
            return;
 
114
        }
 
115
 
 
116
        $methodProps    = $phpcsFile->getMethodProperties($stackPtr);
 
117
        $isPublic       = ($methodProps['scope'] === 'private') ? false : true;
 
118
        $scope          = $methodProps['scope'];
 
119
        $scopeSpecified = $methodProps['scope_specified'];
 
120
 
 
121
        // If it's a private method, it must have an underscore on the front.
 
122
        if ($isPublic === false && $methodName{0} !== '_') {
 
123
            $error = "Private method name \"$className::$methodName\" must be prefixed with an underscore";
 
124
            $phpcsFile->addError($error, $stackPtr);
 
125
            return;
 
126
        }
 
127
 
 
128
        // If it's not a private method, it must not have an underscore on the front.
 
129
        if ($isPublic === true && $scopeSpecified === true && $methodName{0} === '_') {
 
130
            $error = ucfirst($scope)." method name \"$className::$methodName\" must not be prefixed with an underscore";
 
131
            $phpcsFile->addError($error, $stackPtr);
 
132
            return;
 
133
        }
 
134
 
 
135
        // If the scope was specified on the method, then the method must be
 
136
        // camel caps and an underscore should be checked for. If it wasn't
 
137
        // specified, treat it like a public method and remove the underscore
 
138
        // prefix if there is one because we cant determine if it is private or
 
139
        // public.
 
140
        $testMethodName = $methodName;
 
141
        if ($scopeSpecified === false && $methodName{0} === '_') {
 
142
            $testMethodName = substr($methodName, 1);
 
143
        }
 
144
 
 
145
        if (PHP_CodeSniffer::isCamelCaps($testMethodName, false, $isPublic, false) === false) {
 
146
            if ($scopeSpecified === true) {
 
147
                $error = ucfirst($scope)." method name \"$className::$methodName\" is not in camel caps format";
 
148
            } else {
 
149
                $error = "Method name \"$className::$methodName\" is not in camel caps format";
 
150
            }
 
151
 
 
152
            $phpcsFile->addError($error, $stackPtr);
 
153
            return;
 
154
        }
 
155
 
 
156
    }//end processTokenWithinScope()
 
157
 
 
158
 
 
159
    /**
 
160
     * Processes the tokens outside the scope.
 
161
     *
 
162
     * @param PHP_CodeSniffer_File $phpcsFile The file being processed.
 
163
     * @param int                  $stackPtr  The position where this token was
 
164
     *                                        found.
 
165
     *
 
166
     * @return void
 
167
     */
 
168
    protected function processTokenOutsideScope(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
 
169
    {
 
170
        $functionName = $phpcsFile->getDeclarationName($stackPtr);
 
171
 
 
172
        // Is this a magic function. IE. is prefixed with "__".
 
173
        if (preg_match('|^__|', $functionName) !== 0) {
 
174
            $magicPart = substr($functionName, 2);
 
175
            if (in_array($magicPart, $this->_magicFunctions) === false) {
 
176
                 $error = "Function name \"$functionName\" is invalid; only PHP magic methods should be prefixed with a double underscore";
 
177
                 $phpcsFile->addError($error, $stackPtr);
 
178
            }
 
179
 
 
180
            return;
 
181
        }
 
182
 
 
183
        // Function names can be in two parts; the package name and
 
184
        // the function name.
 
185
        $packagePart   = '';
 
186
        $camelCapsPart = '';
 
187
        $underscorePos = strrpos($functionName, '_');
 
188
        if ($underscorePos === false) {
 
189
            $camelCapsPart = $functionName;
 
190
        } else {
 
191
            $packagePart   = substr($functionName, 0, $underscorePos);
 
192
            $camelCapsPart = substr($functionName, ($underscorePos + 1));
 
193
 
 
194
            // We don't care about _'s on the front.
 
195
            $packagePart = ltrim($packagePart, '_');
 
196
        }
 
197
 
 
198
        // If it has a package part, make sure the first letter is a capital.
 
199
        if ($packagePart !== '') {
 
200
            if ($functionName{0} === '_') {
 
201
                $error = "Function name \"$functionName\" is invalid; only private methods should be prefixed with an underscore";
 
202
                $phpcsFile->addError($error, $stackPtr);
 
203
                return;
 
204
            }
 
205
 
 
206
            if ($functionName{0} !== strtoupper($functionName{0})) {
 
207
                $error = "Function name \"$functionName\" is prefixed with a package name but does not begin with a capital letter";
 
208
                $phpcsFile->addError($error, $stackPtr);
 
209
                return;
 
210
            }
 
211
        }
 
212
 
 
213
        // If it doesn't have a camel caps part, it's not valid.
 
214
        if (trim($camelCapsPart) === '') {
 
215
            $error = "Function name \"$functionName\" is not valid; name appears incomplete";
 
216
            $phpcsFile->addError($error, $stackPtr);
 
217
            return;
 
218
        }
 
219
 
 
220
        $validName        = true;
 
221
        $newPackagePart   = $packagePart;
 
222
        $newCamelCapsPart = $camelCapsPart;
 
223
 
 
224
        // Every function must have a camel caps part, so check that first.
 
225
        if (PHP_CodeSniffer::isCamelCaps($camelCapsPart, false, true, false) === false) {
 
226
            $validName        = false;
 
227
            $newCamelCapsPart = strtolower($camelCapsPart{0}).substr($camelCapsPart, 1);
 
228
        }
 
229
 
 
230
        if ($packagePart !== '') {
 
231
            // Check that each new word starts with a capital.
 
232
            $nameBits = explode('_', $packagePart);
 
233
            foreach ($nameBits as $bit) {
 
234
                if ($bit{0} !== strtoupper($bit{0})) {
 
235
                    $newPackagePart = '';
 
236
                    foreach ($nameBits as $bit) {
 
237
                        $newPackagePart .= strtoupper($bit{0}).substr($bit, 1).'_';
 
238
                    }
 
239
 
 
240
                    $validName = false;
 
241
                    break;
 
242
                }
 
243
            }
 
244
        }
 
245
 
 
246
        if ($validName === false) {
 
247
            $newName = rtrim($newPackagePart, '_').'_'.$newCamelCapsPart;
 
248
            if ($newPackagePart === '') {
 
249
                $newName = $newCamelCapsPart;
 
250
            } else {
 
251
                $newName = rtrim($newPackagePart, '_').'_'.$newCamelCapsPart;
 
252
            }
 
253
 
 
254
            $error = "Function name \"$functionName\" is invalid; consider \"$newName\" instead";
 
255
            $phpcsFile->addError($error, $stackPtr);
 
256
        }
 
257
 
 
258
    }//end processTokenOutsideScope()
 
259
 
 
260
 
 
261
}//end class
 
262
 
 
263
?>