annotate vendor/drupal/coder/coder_sniffer/Drupal/Sniffs/Commenting/DeprecatedSniff.php @ 19:fa3358dc1485 tip

Add ndrum files
author Chris Cannam
date Wed, 28 Aug 2019 13:14:47 +0100
parents af1871eacc83
children
rev   line source
Chris@18 1 <?php
Chris@18 2 /**
Chris@18 3 * \Drupal\Sniffs\Commenting\DeprecatedSniff.
Chris@18 4 *
Chris@18 5 * @category PHP
Chris@18 6 * @package PHP_CodeSniffer
Chris@18 7 * @link http://pear.php.net/package/PHP_CodeSniffer
Chris@18 8 */
Chris@18 9
Chris@18 10 namespace Drupal\Sniffs\Commenting;
Chris@18 11
Chris@18 12 use PHP_CodeSniffer\Files\File;
Chris@18 13 use PHP_CodeSniffer\Sniffs\Sniff;
Chris@18 14
Chris@18 15 /**
Chris@18 16 * Ensures standard format of a @deprecated text.
Chris@18 17 *
Chris@18 18 * @category PHP
Chris@18 19 * @package PHP_CodeSniffer
Chris@18 20 * @link http://pear.php.net/package/PHP_CodeSniffer
Chris@18 21 */
Chris@18 22 class DeprecatedSniff implements Sniff
Chris@18 23 {
Chris@18 24
Chris@18 25
Chris@18 26 /**
Chris@18 27 * Returns an array of tokens this test wants to listen for.
Chris@18 28 *
Chris@18 29 * @return array
Chris@18 30 */
Chris@18 31 public function register()
Chris@18 32 {
Chris@18 33 return array(T_DOC_COMMENT_TAG);
Chris@18 34
Chris@18 35 }//end register()
Chris@18 36
Chris@18 37
Chris@18 38 /**
Chris@18 39 * Processes this test, when one of its tokens is encountered.
Chris@18 40 *
Chris@18 41 * @param \PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.
Chris@18 42 * @param int $stackPtr The position of the current token
Chris@18 43 * in the stack passed in $tokens.
Chris@18 44 *
Chris@18 45 * @return void
Chris@18 46 */
Chris@18 47 public function process(File $phpcsFile, $stackPtr)
Chris@18 48 {
Chris@18 49 $tokens = $phpcsFile->getTokens();
Chris@18 50
Chris@18 51 // Only process @deprecated tags.
Chris@18 52 if (strcasecmp($tokens[$stackPtr]['content'], '@deprecated') !== 0) {
Chris@18 53 return;
Chris@18 54 }
Chris@18 55
Chris@18 56 // Get the end point of the comment block which has the deprecated tag.
Chris@18 57 $commentEnd = $phpcsFile->findNext(T_DOC_COMMENT_CLOSE_TAG, ($stackPtr + 1));
Chris@18 58
Chris@18 59 // Get the full @deprecated text which may cover multiple lines.
Chris@18 60 $depText = '';
Chris@18 61 $depEnd = ($stackPtr + 1);
Chris@18 62 for ($i = ($stackPtr + 1); $i < $commentEnd; $i++) {
Chris@18 63 if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) {
Chris@18 64 if ($tokens[$i]['line'] <= ($tokens[$depEnd]['line'] + 1)) {
Chris@18 65 $depText .= ' '.$tokens[$i]['content'];
Chris@18 66 $depEnd = $i;
Chris@18 67 } else {
Chris@18 68 break;
Chris@18 69 }
Chris@18 70 }
Chris@18 71
Chris@18 72 // Found another tag, so we have all the deprecation text.
Chris@18 73 if ($tokens[$i]['code'] === T_DOC_COMMENT_TAG) {
Chris@18 74 break;
Chris@18 75 }
Chris@18 76 }
Chris@18 77
Chris@18 78 $depText = trim($depText);
Chris@18 79
Chris@18 80 // The standard format for the deprecation text is:
Chris@18 81 // @deprecated in %in-version% and will be removed from %removal-version%. %extra-info%.
Chris@18 82 // Use (?U) 'ungreedy' before the version so that only the text up to
Chris@18 83 // the first '. ' is matched, as there may be more than one sentence in
Chris@18 84 // the extra-info part.
Chris@18 85 $matches = array();
Chris@18 86 preg_match('/in (.+) and will be removed from (?U)(.+)\. (.+)$/', $depText, $matches);
Chris@18 87 // There should be 4 items in $matches: 0 is full text, 1 = in-version,
Chris@18 88 // 2 = removal-version, 3 = extra-info.
Chris@18 89 if (count($matches) !== 4) {
Chris@18 90 $error = "The deprecation text '@deprecated %s' does not match the standard format: @deprecated in %%in-version%% and will be removed from %%removal-version%%. %%extra-info%%.";
Chris@18 91 $phpcsFile->addError($error, $stackPtr, 'IncorrectTextLayout', array($depText));
Chris@18 92 } else {
Chris@18 93 // The text follows the basic layout. Now check that the versions
Chris@18 94 // match drupal:n.n.n or project:n.x-n.n. The text must be all lower
Chris@18 95 // case and numbers can be one or two digits.
Chris@18 96 foreach (array('in-version' => $matches[1], 'removal-version' => $matches[2]) as $name => $version) {
Chris@18 97 if (preg_match('/^drupal:\d{1,2}\.\d{1,2}\.\d{1,2}$/', $version) === 0
Chris@18 98 && preg_match('/^[a-z\d_]:\d{1,2}\.x\-\d{1,2}\.\d{1,2}$/', $version) === 0
Chris@18 99 ) {
Chris@18 100 $error = "The deprecation %s '%s' does not match the standard: drupal:n.n.n or project:n.x-n.n";
Chris@18 101 $phpcsFile->addWarning($error, $stackPtr, 'DeprecatedVersionFormat', array($name, $version));
Chris@18 102 }
Chris@18 103 }
Chris@18 104 }
Chris@18 105
Chris@18 106 // The next tag in this comment block after @deprecated must be @see.
Chris@18 107 $seeTag = $phpcsFile->findNext(T_DOC_COMMENT_TAG, ($stackPtr + 1), $commentEnd, false, '@see');
Chris@18 108 if ($seeTag === false) {
Chris@18 109 $error = 'Each @deprecated tag must have a @see tag immediately following it.';
Chris@18 110 $phpcsFile->addError($error, $stackPtr, 'DeprecatedMissingSeeTag');
Chris@18 111 return;
Chris@18 112 }
Chris@18 113
Chris@18 114 // Check the format of the @see url.
Chris@18 115 $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, ($seeTag + 1), $commentEnd);
Chris@18 116 $cr_link = $tokens[$string]['content'];
Chris@18 117 // Allow for the alternative 'node' or 'project/aaa/issues' format.
Chris@18 118 preg_match('[^http(s*)://www.drupal.org/(node|project/\w+/issues)/(\d+)(\.*)$]', $cr_link, $matches);
Chris@18 119 // If matches[4] is not blank it means that the url is correct but it
Chris@18 120 // ends with a period. As this can be a common mistake give a specific
Chris@18 121 // message to assist in fixing.
Chris@18 122 if (isset($matches[4]) === true && empty($matches[4]) === false) {
Chris@18 123 $error = "The @see url '%s' should not end with a period.";
Chris@18 124 $phpcsFile->addWarning($error, $seeTag, 'DeprecatedPeriodAfterSeeUrl', array($cr_link));
Chris@18 125 } else if (empty($matches) === true) {
Chris@18 126 $error = "The @see url '%s' does not match the standard: http(s)://www.drupal.org/node/n or http(s)://www.drupal.org/project/aaa/issues/n";
Chris@18 127 $phpcsFile->addWarning($error, $seeTag, 'DeprecatedWrongSeeUrlFormat', array($cr_link));
Chris@18 128 }
Chris@18 129
Chris@18 130 }//end process()
Chris@18 131
Chris@18 132
Chris@18 133 }//end class