|
10 | 10 | namespace Drupal\Sniffs\Semantics;
|
11 | 11 |
|
12 | 12 | use PHP_CodeSniffer\Files\File;
|
| 13 | +use PHP_CodeSniffer\Sniffs\Sniff; |
| 14 | +use PHP_CodeSniffer\Util\Tokens; |
13 | 15 |
|
14 | 16 | /**
|
15 | 17 | * Checks that constants introduced with define() in module or install files start
|
16 | 18 | * with the module's name.
|
17 | 19 | *
|
| 20 | + * Largely copied from |
| 21 | + * \PHP_CodeSniffer\Standards\Generic\Sniffs\NamingConventions\UpperCaseConstantNameSniff. |
| 22 | + * |
18 | 23 | * @category PHP
|
19 | 24 | * @package PHP_CodeSniffer
|
20 | 25 | * @link http://pear.php.net/package/PHP_CodeSniffer
|
21 | 26 | */
|
22 |
| -class ConstantNameSniff extends FunctionCall |
| 27 | +class ConstantNameSniff implements Sniff |
23 | 28 | {
|
24 | 29 |
|
25 | 30 |
|
26 | 31 | /**
|
27 |
| - * Returns an array of function names this test wants to listen for. |
| 32 | + * Returns an array of tokens this test wants to listen for. |
28 | 33 | *
|
29 |
| - * @return array<string> |
| 34 | + * @return array<int|string> |
30 | 35 | */
|
31 |
| - public function registerFunctionNames() |
| 36 | + public function register() |
32 | 37 | {
|
33 |
| - return ['define']; |
| 38 | + return [ |
| 39 | + T_STRING, |
| 40 | + T_CONST, |
| 41 | + ]; |
34 | 42 |
|
35 |
| - }//end registerFunctionNames() |
| 43 | + }//end register() |
36 | 44 |
|
37 | 45 |
|
38 | 46 | /**
|
39 |
| - * Processes this function call. |
| 47 | + * Processes this test, when one of its tokens is encountered. |
40 | 48 | *
|
41 |
| - * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. |
42 |
| - * @param int $stackPtr The position of the function call in |
43 |
| - * the stack. |
44 |
| - * @param int $openBracket The position of the opening |
45 |
| - * parenthesis in the stack. |
46 |
| - * @param int $closeBracket The position of the closing |
47 |
| - * parenthesis in the stack. |
| 49 | + * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned. |
| 50 | + * @param int $stackPtr The position of the current token in the |
| 51 | + * stack passed in $tokens. |
48 | 52 | *
|
49 |
| - * @return void |
| 53 | + * @return void|int |
50 | 54 | */
|
51 |
| - public function processFunctionCall( |
52 |
| - File $phpcsFile, |
53 |
| - $stackPtr, |
54 |
| - $openBracket, |
55 |
| - $closeBracket |
56 |
| - ) { |
| 55 | + public function process(File $phpcsFile, $stackPtr) |
| 56 | + { |
57 | 57 | $nameParts = explode('.', basename($phpcsFile->getFilename()));
|
58 | 58 | $fileExtension = end($nameParts);
|
59 | 59 | // Only check in *.module files.
|
60 | 60 | if ($fileExtension !== 'module' && $fileExtension !== 'install') {
|
61 |
| - return; |
| 61 | + return ($phpcsFile->numTokens + 1); |
62 | 62 | }
|
63 | 63 |
|
64 |
| - $tokens = $phpcsFile->getTokens(); |
65 |
| - $argument = $this->getArgument(1); |
66 |
| - if ($tokens[$argument['start']]['code'] !== T_CONSTANT_ENCAPSED_STRING) { |
67 |
| - // Not a string literal, so this is some obscure constant that we ignore. |
| 64 | + $tokens = $phpcsFile->getTokens(); |
| 65 | + // Only check in the outer scope, not within classes. |
| 66 | + if (empty($tokens[$stackPtr]['conditions']) === false) { |
68 | 67 | return;
|
69 | 68 | }
|
70 | 69 |
|
71 | 70 | $moduleName = reset($nameParts);
|
72 | 71 | $expectedStart = strtoupper($moduleName);
|
73 |
| - // Remove the quotes around the string litral. |
74 |
| - $constant = substr($tokens[$argument['start']]['content'], 1, -1); |
75 |
| - if (strpos($constant, $expectedStart) !== 0) { |
| 72 | + |
| 73 | + if ($tokens[$stackPtr]['code'] === T_CONST) { |
| 74 | + // This is a class constant. |
| 75 | + $constant = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); |
| 76 | + if ($constant === false) { |
| 77 | + return; |
| 78 | + } |
| 79 | + |
| 80 | + $constName = $tokens[$constant]['content']; |
| 81 | + |
| 82 | + if (strpos($constName, $expectedStart) !== 0) { |
| 83 | + $warning = 'All constants defined by a module must be prefixed with the module\'s name, expected "%s" but found "%s"'; |
| 84 | + $data = [ |
| 85 | + $expectedStart."_$constName", |
| 86 | + $constName, |
| 87 | + ]; |
| 88 | + $phpcsFile->addWarning($warning, $stackPtr, 'ConstConstantStart', $data); |
| 89 | + return; |
| 90 | + }//end if |
| 91 | + } |
| 92 | + |
| 93 | + // Only interested in define statements now. |
| 94 | + if (strtolower($tokens[$stackPtr]['content']) !== 'define') { |
| 95 | + return; |
| 96 | + } |
| 97 | + |
| 98 | + // Make sure this is not a method call. |
| 99 | + $prev = $phpcsFile->findPrevious(T_WHITESPACE, ($stackPtr - 1), null, true); |
| 100 | + if ($tokens[$prev]['code'] === T_OBJECT_OPERATOR |
| 101 | + || $tokens[$prev]['code'] === T_DOUBLE_COLON |
| 102 | + || $tokens[$prev]['code'] === T_NULLSAFE_OBJECT_OPERATOR |
| 103 | + ) { |
| 104 | + return; |
| 105 | + } |
| 106 | + |
| 107 | + // If the next non-whitespace token after this token |
| 108 | + // is not an opening parenthesis then it is not a function call. |
| 109 | + $openBracket = $phpcsFile->findNext(Tokens::$emptyTokens, ($stackPtr + 1), null, true); |
| 110 | + if ($openBracket === false) { |
| 111 | + return; |
| 112 | + } |
| 113 | + |
| 114 | + // The next non-whitespace token must be the constant name. |
| 115 | + $constPtr = $phpcsFile->findNext(T_WHITESPACE, ($openBracket + 1), null, true); |
| 116 | + if ($tokens[$constPtr]['code'] !== T_CONSTANT_ENCAPSED_STRING) { |
| 117 | + return; |
| 118 | + } |
| 119 | + |
| 120 | + $constName = $tokens[$constPtr]['content']; |
| 121 | + |
| 122 | + if (strpos($constName, $expectedStart) !== 0) { |
76 | 123 | $warning = 'All constants defined by a module must be prefixed with the module\'s name, expected "%s" but found "%s"';
|
77 | 124 | $data = [
|
78 |
| - $expectedStart."_$constant", |
79 |
| - $constant, |
| 125 | + $expectedStart."_$constName", |
| 126 | + $constName, |
80 | 127 | ];
|
81 | 128 | $phpcsFile->addWarning($warning, $stackPtr, 'ConstantStart', $data);
|
82 |
| - } |
| 129 | + }//end if |
83 | 130 |
|
84 |
| - }//end processFunctionCall() |
| 131 | + }//end process() |
85 | 132 |
|
86 | 133 |
|
87 | 134 | }//end class
|
0 commit comments