annotate vendor/drupal/coder/coder_sniffer/Drupal/Sniffs/WhiteSpace/ScopeClosingBraceSniff.php @ 12:7a779792577d

Update Drupal core to v8.4.5 (via Composer)
author Chris Cannam
date Fri, 23 Feb 2018 15:52:07 +0000
parents 4c8ae668cc8c
children 129ea1e6d783
rev   line source
Chris@0 1 <?php
Chris@0 2 /**
Chris@0 3 * Drupal_Sniffs_Whitespace_ScopeClosingBraceSniff.
Chris@0 4 *
Chris@0 5 * @category PHP
Chris@0 6 * @package PHP_CodeSniffer
Chris@0 7 * @link http://Drupal.php.net/package/PHP_CodeSniffer
Chris@0 8 */
Chris@0 9
Chris@0 10 /**
Chris@0 11 * Copied from PEAR_Sniffs_WhiteSpace_ScopeClosingBraceSniff to allow empty methods
Chris@0 12 * and classes.
Chris@0 13 *
Chris@0 14 * Checks that the closing braces of scopes are aligned correctly.
Chris@0 15 *
Chris@0 16 * @category PHP
Chris@0 17 * @package PHP_CodeSniffer
Chris@0 18 * @link http://pear.php.net/package/PHP_CodeSniffer
Chris@0 19 */
Chris@0 20 class Drupal_Sniffs_WhiteSpace_ScopeClosingBraceSniff implements PHP_CodeSniffer_Sniff
Chris@0 21 {
Chris@0 22
Chris@0 23 /**
Chris@0 24 * The number of spaces code should be indented.
Chris@0 25 *
Chris@0 26 * @var int
Chris@0 27 */
Chris@0 28 public $indent = 2;
Chris@0 29
Chris@0 30
Chris@0 31 /**
Chris@0 32 * Returns an array of tokens this test wants to listen for.
Chris@0 33 *
Chris@0 34 * @return array
Chris@0 35 */
Chris@0 36 public function register()
Chris@0 37 {
Chris@0 38 return PHP_CodeSniffer_Tokens::$scopeOpeners;
Chris@0 39
Chris@0 40 }//end register()
Chris@0 41
Chris@0 42
Chris@0 43 /**
Chris@0 44 * Processes this test, when one of its tokens is encountered.
Chris@0 45 *
Chris@0 46 * @param PHP_CodeSniffer_File $phpcsFile All the tokens found in the document.
Chris@0 47 * @param int $stackPtr The position of the current token
Chris@0 48 * in the stack passed in $tokens.
Chris@0 49 *
Chris@0 50 * @return void
Chris@0 51 */
Chris@0 52 public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
Chris@0 53 {
Chris@0 54 $tokens = $phpcsFile->getTokens();
Chris@0 55
Chris@0 56 // If this is an inline condition (ie. there is no scope opener), then
Chris@0 57 // return, as this is not a new scope.
Chris@0 58 if (isset($tokens[$stackPtr]['scope_closer']) === false) {
Chris@0 59 return;
Chris@0 60 }
Chris@0 61
Chris@0 62 $scopeStart = $tokens[$stackPtr]['scope_opener'];
Chris@0 63 $scopeEnd = $tokens[$stackPtr]['scope_closer'];
Chris@0 64
Chris@0 65 // If the scope closer doesn't think it belongs to this scope opener
Chris@0 66 // then the opener is sharing its closer with other tokens. We only
Chris@0 67 // want to process the closer once, so skip this one.
Chris@0 68 if (isset($tokens[$scopeEnd]['scope_condition']) === false
Chris@0 69 || $tokens[$scopeEnd]['scope_condition'] !== $stackPtr
Chris@0 70 ) {
Chris@0 71 return;
Chris@0 72 }
Chris@0 73
Chris@0 74 // We need to actually find the first piece of content on this line,
Chris@0 75 // because if this is a method with tokens before it (public, static etc)
Chris@0 76 // or an if with an else before it, then we need to start the scope
Chris@0 77 // checking from there, rather than the current token.
Chris@0 78 $lineStart = ($stackPtr - 1);
Chris@0 79 for ($lineStart; $lineStart > 0; $lineStart--) {
Chris@0 80 if (strpos($tokens[$lineStart]['content'], $phpcsFile->eolChar) !== false) {
Chris@0 81 break;
Chris@0 82 }
Chris@0 83 }
Chris@0 84
Chris@0 85 $lineStart++;
Chris@0 86
Chris@0 87 $startColumn = 1;
Chris@0 88 if ($tokens[$lineStart]['code'] === T_WHITESPACE) {
Chris@0 89 $startColumn = $tokens[($lineStart + 1)]['column'];
Chris@0 90 } else if ($tokens[$lineStart]['code'] === T_INLINE_HTML) {
Chris@0 91 $trimmed = ltrim($tokens[$lineStart]['content']);
Chris@0 92 if ($trimmed === '') {
Chris@0 93 $startColumn = $tokens[($lineStart + 1)]['column'];
Chris@0 94 } else {
Chris@0 95 $startColumn = (strlen($tokens[$lineStart]['content']) - strlen($trimmed));
Chris@0 96 }
Chris@0 97 }
Chris@0 98
Chris@0 99 // Check that the closing brace is on it's own line.
Chris@0 100 $lastContent = $phpcsFile->findPrevious(
Chris@0 101 array(
Chris@0 102 T_WHITESPACE,
Chris@0 103 T_INLINE_HTML,
Chris@0 104 T_OPEN_TAG,
Chris@0 105 ),
Chris@0 106 ($scopeEnd - 1),
Chris@0 107 $scopeStart,
Chris@0 108 true
Chris@0 109 );
Chris@0 110
Chris@0 111 if ($tokens[$lastContent]['line'] === $tokens[$scopeEnd]['line']) {
Chris@0 112 // Only allow empty classes and methods.
Chris@0 113 if (($tokens[$tokens[$scopeEnd]['scope_condition']]['code'] !== T_CLASS
Chris@0 114 && $tokens[$tokens[$scopeEnd]['scope_condition']]['code'] !== T_INTERFACE
Chris@0 115 && in_array(T_CLASS, $tokens[$scopeEnd]['conditions']) === false
Chris@0 116 && in_array(T_INTERFACE, $tokens[$scopeEnd]['conditions']) === false)
Chris@0 117 || $tokens[$lastContent]['code'] !== T_OPEN_CURLY_BRACKET
Chris@0 118 ) {
Chris@0 119 $error = 'Closing brace must be on a line by itself';
Chris@0 120 $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'Line');
Chris@0 121 if ($fix === true) {
Chris@0 122 $phpcsFile->fixer->addNewlineBefore($scopeEnd);
Chris@0 123 }
Chris@0 124 }
Chris@0 125
Chris@0 126 return;
Chris@0 127 }
Chris@0 128
Chris@0 129 // Check now that the closing brace is lined up correctly.
Chris@0 130 $lineStart = ($scopeEnd - 1);
Chris@0 131 for ($lineStart; $lineStart > 0; $lineStart--) {
Chris@0 132 if (strpos($tokens[$lineStart]['content'], $phpcsFile->eolChar) !== false) {
Chris@0 133 break;
Chris@0 134 }
Chris@0 135 }
Chris@0 136
Chris@0 137 $lineStart++;
Chris@0 138
Chris@0 139 $braceIndent = 0;
Chris@0 140 if ($tokens[$lineStart]['code'] === T_WHITESPACE) {
Chris@0 141 $braceIndent = ($tokens[($lineStart + 1)]['column'] - 1);
Chris@0 142 } else if ($tokens[$lineStart]['code'] === T_INLINE_HTML) {
Chris@0 143 $trimmed = ltrim($tokens[$lineStart]['content']);
Chris@0 144 if ($trimmed === '') {
Chris@0 145 $braceIndent = ($tokens[($lineStart + 1)]['column'] - 1);
Chris@0 146 } else {
Chris@0 147 $braceIndent = (strlen($tokens[$lineStart]['content']) - strlen($trimmed) - 1);
Chris@0 148 }
Chris@0 149 }
Chris@0 150
Chris@0 151 $fix = false;
Chris@0 152 if ($tokens[$stackPtr]['code'] === T_CASE
Chris@0 153 || $tokens[$stackPtr]['code'] === T_DEFAULT
Chris@0 154 ) {
Chris@0 155 // BREAK statements should be indented n spaces from the
Chris@0 156 // CASE or DEFAULT statement.
Chris@0 157 $expectedIndent = ($startColumn + $this->indent - 1);
Chris@0 158 if ($braceIndent !== $expectedIndent) {
Chris@0 159 $error = 'Case breaking statement indented incorrectly; expected %s spaces, found %s';
Chris@0 160 $data = array(
Chris@0 161 $expectedIndent,
Chris@0 162 $braceIndent,
Chris@0 163 );
Chris@0 164 $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'BreakIndent', $data);
Chris@0 165 }
Chris@0 166 } else {
Chris@0 167 $expectedIndent = ($startColumn - 1);
Chris@0 168 if ($braceIndent !== $expectedIndent) {
Chris@0 169 $error = 'Closing brace indented incorrectly; expected %s spaces, found %s';
Chris@0 170 $data = array(
Chris@0 171 $expectedIndent,
Chris@0 172 $braceIndent,
Chris@0 173 );
Chris@0 174 $fix = $phpcsFile->addFixableError($error, $scopeEnd, 'Indent', $data);
Chris@0 175 }
Chris@0 176 }//end if
Chris@0 177
Chris@0 178 if ($fix === true) {
Chris@0 179 $spaces = str_repeat(' ', $expectedIndent);
Chris@0 180 if ($braceIndent === 0) {
Chris@0 181 $phpcsFile->fixer->addContentBefore($lineStart, $spaces);
Chris@0 182 } else {
Chris@0 183 $phpcsFile->fixer->replaceToken($lineStart, ltrim($tokens[$lineStart]['content']));
Chris@0 184 $phpcsFile->fixer->addContentBefore($lineStart, $spaces);
Chris@0 185 }
Chris@0 186 }
Chris@0 187
Chris@0 188 }//end process()
Chris@0 189
Chris@0 190
Chris@0 191 }//end class