PageRenderTime 53ms CodeModel.GetById 26ms RepoModel.GetById 1ms app.codeStats 0ms

/libs/php/pear/PHP/CodeSniffer/Standards/Squiz/Sniffs/Classes/ClassDeclarationSniff.php

https://github.com/KaRLsM/SIFO
PHP | 281 lines | 179 code | 34 blank | 68 comment | 33 complexity | a48e00fe037dfdc43d5d31b514132a7d MD5 | raw file
  1. <?php
  2. /**
  3. * Class Declaration Test.
  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: ClassDeclarationSniff.php 301641 2010-07-28 05:20:22Z squiz $
  14. * @link http://pear.php.net/package/PHP_CodeSniffer
  15. */
  16. if (class_exists('PEAR_Sniffs_Classes_ClassDeclarationSniff', true) === false) {
  17. $error = 'Class PEAR_Sniffs_Classes_ClassDeclarationSniff not found';
  18. throw new PHP_CodeSniffer_Exception($error);
  19. }
  20. /**
  21. * Class Declaration Test.
  22. *
  23. * Checks the declaration of the class and its inheritance is correct.
  24. *
  25. * @category PHP
  26. * @package PHP_CodeSniffer
  27. * @author Greg Sherwood <gsherwood@squiz.net>
  28. * @author Marc McIntyre <mmcintyre@squiz.net>
  29. * @copyright 2006 Squiz Pty Ltd (ABN 77 084 670 600)
  30. * @license http://matrix.squiz.net/developer/tools/php_cs/licence BSD Licence
  31. * @version Release: 1.3.0
  32. * @link http://pear.php.net/package/PHP_CodeSniffer
  33. */
  34. class Squiz_Sniffs_Classes_ClassDeclarationSniff extends PEAR_Sniffs_Classes_ClassDeclarationSniff
  35. {
  36. /**
  37. * Returns an array of tokens this test wants to listen for.
  38. *
  39. * @return array
  40. */
  41. public function register()
  42. {
  43. return array(
  44. T_CLASS,
  45. T_INTERFACE,
  46. );
  47. }//end register()
  48. /**
  49. * Processes this test, when one of its tokens is encountered.
  50. *
  51. * @param PHP_CodeSniffer_File $phpcsFile The file being scanned.
  52. * @param int $stackPtr The position of the current token
  53. * in the stack passed in $tokens.
  54. *
  55. * @return void
  56. */
  57. public function process(PHP_CodeSniffer_File $phpcsFile, $stackPtr)
  58. {
  59. // We want all the errors from the PEAR standard, plus some of our own.
  60. parent::process($phpcsFile, $stackPtr);
  61. $tokens = $phpcsFile->getTokens();
  62. /*
  63. Check that this is the only class or interface in the file.
  64. */
  65. $nextClass = $phpcsFile->findNext(array(T_CLASS, T_INTERFACE), ($stackPtr + 1));
  66. if ($nextClass !== false) {
  67. // We have another, so an error is thrown.
  68. $error = 'Only one interface or class is allowed in a file';
  69. $phpcsFile->addError($error, $nextClass, 'MultipleClasses');
  70. }
  71. /*
  72. Check alignment of the keyword and braces.
  73. */
  74. if ($tokens[($stackPtr - 1)]['code'] === T_WHITESPACE) {
  75. $prevContent = $tokens[($stackPtr - 1)]['content'];
  76. if ($prevContent !== $phpcsFile->eolChar) {
  77. $blankSpace = substr($prevContent, strpos($prevContent, $phpcsFile->eolChar));
  78. $spaces = strlen($blankSpace);
  79. if (in_array($tokens[($stackPtr - 2)]['code'], array(T_ABSTRACT, T_FINAL)) === false) {
  80. if ($spaces !== 0) {
  81. $type = strtolower($tokens[$stackPtr]['content']);
  82. $error = 'Expected 0 spaces before %s keyword; %s found';
  83. $data = array(
  84. $type,
  85. $spaces,
  86. );
  87. $phpcsFile->addError($error, $stackPtr, 'SpaceBeforeKeyword', $data);
  88. }
  89. } else {
  90. if ($spaces !== 1) {
  91. $type = strtolower($tokens[$stackPtr]['content']);
  92. $prevContent = strtolower($tokens[($stackPtr - 2)]['content']);
  93. $error = 'Expected 1 space between %s and %s keywords; %s found';
  94. $data = array(
  95. $prevContent,
  96. $type,
  97. $spaces,
  98. );
  99. $phpcsFile->addError($error, $stackPtr, 'SpacesBeforeKeyword', $data);
  100. }
  101. }
  102. }
  103. }//end if
  104. if (isset($tokens[$stackPtr]['scope_opener']) === false) {
  105. $error = 'Possible parse error: %s missing opening or closing brace';
  106. $data = array($tokens[$stackPtr]['content']);
  107. $phpcsFile->addWarning($error, $stackPtr, 'MissingBrace', $data);
  108. return;
  109. }
  110. $closeBrace = $tokens[$stackPtr]['scope_closer'];
  111. if ($tokens[($closeBrace - 1)]['code'] === T_WHITESPACE) {
  112. $prevContent = $tokens[($closeBrace - 1)]['content'];
  113. if ($prevContent !== $phpcsFile->eolChar) {
  114. $blankSpace = substr($prevContent, strpos($prevContent, $phpcsFile->eolChar));
  115. $spaces = strlen($blankSpace);
  116. if ($spaces !== 0) {
  117. if ($tokens[($closeBrace - 1)]['line'] !== $tokens[$closeBrace]['line']) {
  118. $error = 'Expected 0 spaces before closing brace; newline found';
  119. $phpcsFile->addError($error, $closeBrace, 'NewLineBeforeCloseBrace');
  120. } else {
  121. $error = 'Expected 0 spaces before closing brace; %s found';
  122. $data = array($spaces);
  123. $phpcsFile->addError($error, $closeBrace, 'SpaceBeforeCloseBrace', $data);
  124. }
  125. }
  126. }
  127. }
  128. // Check that the closing brace has one blank line after it.
  129. $nextContent = $phpcsFile->findNext(array(T_WHITESPACE, T_COMMENT), ($closeBrace + 1), null, true);
  130. if ($nextContent === false) {
  131. // No content found, so we reached the end of the file.
  132. // That means there was no closing tag either.
  133. $error = 'Closing brace of a %s must be followed by a blank line and then a closing PHP tag';
  134. $data = array($tokens[$stackPtr]['content']);
  135. $phpcsFile->addError($error, $closeBrace, 'EndFileAfterCloseBrace', $data);
  136. } else {
  137. $nextLine = $tokens[$nextContent]['line'];
  138. $braceLine = $tokens[$closeBrace]['line'];
  139. if ($braceLine === $nextLine) {
  140. $error = 'Closing brace of a %s must be followed by a single blank line';
  141. $data = array($tokens[$stackPtr]['content']);
  142. $phpcsFile->addError($error, $closeBrace, 'NoNewlineAfterCloseBrace', $data);
  143. } else if ($nextLine !== ($braceLine + 2)) {
  144. $difference = ($nextLine - $braceLine - 1);
  145. $error = 'Closing brace of a %s must be followed by a single blank line; found %s';
  146. $data = array(
  147. $tokens[$stackPtr]['content'],
  148. $difference,
  149. );
  150. $phpcsFile->addError($error, $closeBrace, 'NewlinesAfterCloseBrace', $data);
  151. }
  152. }//end if
  153. // Check the closing brace is on it's own line, but allow
  154. // for comments like "//end class".
  155. $nextContent = $phpcsFile->findNext(T_COMMENT, ($closeBrace + 1), null, true);
  156. if ($tokens[$nextContent]['content'] !== $phpcsFile->eolChar && $tokens[$nextContent]['line'] === $tokens[$closeBrace]['line']) {
  157. $type = strtolower($tokens[$stackPtr]['content']);
  158. $error = 'Closing %s brace must be on a line by itself';
  159. $data = array($tokens[$stackPtr]['content']);
  160. $phpcsFile->addError($error, $closeBrace, 'CloseBraceSameLine', $data);
  161. }
  162. /*
  163. Check that each of the parent classes or interfaces specified
  164. are spaced correctly.
  165. */
  166. // We need to map out each of the possible tokens in the declaration.
  167. $keyword = $stackPtr;
  168. $openingBrace = $tokens[$stackPtr]['scope_opener'];
  169. $className = $phpcsFile->findNext(T_STRING, $stackPtr);
  170. /*
  171. Now check the spacing of each token.
  172. */
  173. $name = strtolower($tokens[$keyword]['content']);
  174. // Spacing of the keyword.
  175. $gap = $tokens[($stackPtr + 1)]['content'];
  176. if (strlen($gap) !== 1) {
  177. $found = strlen($gap);
  178. $error = 'Expected 1 space between %s keyword and %s name; %s found';
  179. $data = array(
  180. $name,
  181. $name,
  182. $found,
  183. );
  184. $phpcsFile->addError($error, $stackPtr, 'SpaceAfterKeyword', $data);
  185. }
  186. // Check after the name.
  187. $gap = $tokens[($className + 1)]['content'];
  188. if (strlen($gap) !== 1) {
  189. $found = strlen($gap);
  190. $error = 'Expected 1 space after %s name; %s found';
  191. $data = array(
  192. $name,
  193. $found,
  194. );
  195. $phpcsFile->addError($error, $stackPtr, 'SpaceAfterName', $data);
  196. }
  197. // Now check each of the parents.
  198. $parents = array();
  199. $nextParent = ($className + 1);
  200. while (($nextParent = $phpcsFile->findNext(array(T_STRING, T_IMPLEMENTS), ($nextParent + 1), ($openingBrace - 1))) !== false) {
  201. $parents[] = $nextParent;
  202. }
  203. $parentCount = count($parents);
  204. for ($i = 0; $i < $parentCount; $i++) {
  205. if ($tokens[$parents[$i]]['code'] === T_IMPLEMENTS) {
  206. continue;
  207. }
  208. if ($tokens[($parents[$i] - 1)]['code'] !== T_WHITESPACE) {
  209. $name = $tokens[$parents[$i]]['content'];
  210. $error = 'Expected 1 space before "%s"; 0 found';
  211. $data = array($name);
  212. $phpcsFile->addError($error, ($nextComma + 1), 'NoSpaceBeforeName', $data);
  213. } else {
  214. $spaceBefore = strlen($tokens[($parents[$i] - 1)]['content']);
  215. if ($spaceBefore !== 1) {
  216. $name = $tokens[$parents[$i]]['content'];
  217. $error = 'Expected 1 space before "%s"; %s found';
  218. $data = array(
  219. $name,
  220. $spaceBefore,
  221. );
  222. $phpcsFile->addError($error, $stackPtr, 'SpaceBeforeName', $data);
  223. }
  224. }
  225. if ($tokens[($parents[$i] + 1)]['code'] !== T_COMMA) {
  226. if ($i !== ($parentCount - 1)) {
  227. // This is not the last parent, and the comma
  228. // is not where we expect it to be.
  229. if ($tokens[($parents[$i] + 2)]['code'] !== T_IMPLEMENTS) {
  230. $found = strlen($tokens[($parents[$i] + 1)]['content']);
  231. $name = $tokens[$parents[$i]]['content'];
  232. $error = 'Expected 0 spaces between "%s" and comma; $%s found';
  233. $data = array(
  234. $name,
  235. $found,
  236. );
  237. $phpcsFile->addError($error, $stackPtr, 'SpaceBeforeComma', $data);
  238. }
  239. }
  240. $nextComma = $phpcsFile->findNext(T_COMMA, $parents[$i]);
  241. } else {
  242. $nextComma = ($parents[$i] + 1);
  243. }
  244. }//end for
  245. }//end process()
  246. }//end class
  247. ?>