Chris@18: getTokens(); Chris@18: Chris@18: // Only process @deprecated tags. Chris@18: if (strcasecmp($tokens[$stackPtr]['content'], '@deprecated') !== 0) { Chris@18: return; Chris@18: } Chris@18: Chris@18: // Get the end point of the comment block which has the deprecated tag. Chris@18: $commentEnd = $phpcsFile->findNext(T_DOC_COMMENT_CLOSE_TAG, ($stackPtr + 1)); Chris@18: Chris@18: // Get the full @deprecated text which may cover multiple lines. Chris@18: $depText = ''; Chris@18: $depEnd = ($stackPtr + 1); Chris@18: for ($i = ($stackPtr + 1); $i < $commentEnd; $i++) { Chris@18: if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { Chris@18: if ($tokens[$i]['line'] <= ($tokens[$depEnd]['line'] + 1)) { Chris@18: $depText .= ' '.$tokens[$i]['content']; Chris@18: $depEnd = $i; Chris@18: } else { Chris@18: break; Chris@18: } Chris@18: } Chris@18: Chris@18: // Found another tag, so we have all the deprecation text. Chris@18: if ($tokens[$i]['code'] === T_DOC_COMMENT_TAG) { Chris@18: break; Chris@18: } Chris@18: } Chris@18: Chris@18: $depText = trim($depText); Chris@18: Chris@18: // The standard format for the deprecation text is: Chris@18: // @deprecated in %in-version% and will be removed from %removal-version%. %extra-info%. Chris@18: // Use (?U) 'ungreedy' before the version so that only the text up to Chris@18: // the first '. ' is matched, as there may be more than one sentence in Chris@18: // the extra-info part. Chris@18: $matches = array(); Chris@18: preg_match('/in (.+) and will be removed from (?U)(.+)\. (.+)$/', $depText, $matches); Chris@18: // There should be 4 items in $matches: 0 is full text, 1 = in-version, Chris@18: // 2 = removal-version, 3 = extra-info. Chris@18: if (count($matches) !== 4) { Chris@18: $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: $phpcsFile->addError($error, $stackPtr, 'IncorrectTextLayout', array($depText)); Chris@18: } else { Chris@18: // The text follows the basic layout. Now check that the versions Chris@18: // match drupal:n.n.n or project:n.x-n.n. The text must be all lower Chris@18: // case and numbers can be one or two digits. Chris@18: foreach (array('in-version' => $matches[1], 'removal-version' => $matches[2]) as $name => $version) { Chris@18: if (preg_match('/^drupal:\d{1,2}\.\d{1,2}\.\d{1,2}$/', $version) === 0 Chris@18: && preg_match('/^[a-z\d_]:\d{1,2}\.x\-\d{1,2}\.\d{1,2}$/', $version) === 0 Chris@18: ) { Chris@18: $error = "The deprecation %s '%s' does not match the standard: drupal:n.n.n or project:n.x-n.n"; Chris@18: $phpcsFile->addWarning($error, $stackPtr, 'DeprecatedVersionFormat', array($name, $version)); Chris@18: } Chris@18: } Chris@18: } Chris@18: Chris@18: // The next tag in this comment block after @deprecated must be @see. Chris@18: $seeTag = $phpcsFile->findNext(T_DOC_COMMENT_TAG, ($stackPtr + 1), $commentEnd, false, '@see'); Chris@18: if ($seeTag === false) { Chris@18: $error = 'Each @deprecated tag must have a @see tag immediately following it.'; Chris@18: $phpcsFile->addError($error, $stackPtr, 'DeprecatedMissingSeeTag'); Chris@18: return; Chris@18: } Chris@18: Chris@18: // Check the format of the @see url. Chris@18: $string = $phpcsFile->findNext(T_DOC_COMMENT_STRING, ($seeTag + 1), $commentEnd); Chris@18: $cr_link = $tokens[$string]['content']; Chris@18: // Allow for the alternative 'node' or 'project/aaa/issues' format. Chris@18: preg_match('[^http(s*)://www.drupal.org/(node|project/\w+/issues)/(\d+)(\.*)$]', $cr_link, $matches); Chris@18: // If matches[4] is not blank it means that the url is correct but it Chris@18: // ends with a period. As this can be a common mistake give a specific Chris@18: // message to assist in fixing. Chris@18: if (isset($matches[4]) === true && empty($matches[4]) === false) { Chris@18: $error = "The @see url '%s' should not end with a period."; Chris@18: $phpcsFile->addWarning($error, $seeTag, 'DeprecatedPeriodAfterSeeUrl', array($cr_link)); Chris@18: } else if (empty($matches) === true) { Chris@18: $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: $phpcsFile->addWarning($error, $seeTag, 'DeprecatedWrongSeeUrlFormat', array($cr_link)); Chris@18: } Chris@18: Chris@18: }//end process() Chris@18: Chris@18: Chris@18: }//end class