public function InlineCommentSniff::process in Coder 8.2
Same name and namespace in other branches
- 8.3 coder_sniffer/Drupal/Sniffs/Commenting/InlineCommentSniff.php \Drupal\Sniffs\Commenting\InlineCommentSniff::process()
- 8.3.x coder_sniffer/Drupal/Sniffs/Commenting/InlineCommentSniff.php \Drupal\Sniffs\Commenting\InlineCommentSniff::process()
Processes this test, when one of its tokens is encountered.
Parameters
\PHP_CodeSniffer\Files\File $phpcsFile The file being scanned.:
int $stackPtr The position of the current token in the: stack passed in $tokens.
Return value
void
File
- coder_sniffer/
Drupal/ Sniffs/ Commenting/ InlineCommentSniff.php, line 66
Class
Namespace
Drupal\Sniffs\CommentingCode
public function process(File $phpcsFile, $stackPtr) {
$tokens = $phpcsFile
->getTokens();
// If this is a function/class/interface doc block comment, skip it.
// We are only interested in inline doc block comments, which are
// not allowed.
if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT_OPEN_TAG) {
$nextToken = $phpcsFile
->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true);
$ignore = array(
T_CLASS,
T_INTERFACE,
T_TRAIT,
T_FUNCTION,
T_CLOSURE,
T_PUBLIC,
T_PRIVATE,
T_PROTECTED,
T_FINAL,
T_STATIC,
T_ABSTRACT,
T_CONST,
T_PROPERTY,
T_VAR,
);
// Also ignore all doc blocks defined in the outer scope (no scope
// conditions are set).
if (in_array($tokens[$nextToken]['code'], $ignore) === true || empty($tokens[$stackPtr]['conditions']) === true) {
return;
}
if ($phpcsFile->tokenizerType === 'JS') {
// We allow block comments if a function or object
// is being assigned to a variable.
$ignore = Tokens::$emptyTokens;
$ignore[] = T_EQUAL;
$ignore[] = T_STRING;
$ignore[] = T_OBJECT_OPERATOR;
$nextToken = $phpcsFile
->findNext($ignore, $nextToken + 1, null, true);
if ($tokens[$nextToken]['code'] === T_FUNCTION || $tokens[$nextToken]['code'] === T_CLOSURE || $tokens[$nextToken]['code'] === T_OBJECT || $tokens[$nextToken]['code'] === T_PROTOTYPE) {
return;
}
}
$prevToken = $phpcsFile
->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true);
if ($tokens[$prevToken]['code'] === T_OPEN_TAG) {
return;
}
// Inline doc blocks are allowed in JSDoc.
if ($tokens[$stackPtr]['content'] === '/**' && $phpcsFile->tokenizerType !== 'JS') {
// The only exception to inline doc blocks is the /** @var */
// declaration.
$content = $phpcsFile
->getTokensAsString($stackPtr, $tokens[$stackPtr]['comment_closer'] - $stackPtr + 1);
if (preg_match('#^/\\*\\* @var [a-zA-Z0-9_\\\\\\[\\]|]+ \\$[a-zA-Z0-9_]+ \\*/$#', $content) !== 1) {
$error = 'Inline doc block comments are not allowed; use "/* Comment */" or "// Comment" instead';
$phpcsFile
->addError($error, $stackPtr, 'DocBlock');
}
}
}
//end if
if ($tokens[$stackPtr]['content'][0] === '#') {
$error = 'Perl-style comments are not allowed; use "// Comment" instead';
$fix = $phpcsFile
->addFixableError($error, $stackPtr, 'WrongStyle');
if ($fix === true) {
$comment = ltrim($tokens[$stackPtr]['content'], "# \t");
$phpcsFile->fixer
->replaceToken($stackPtr, "// {$comment}");
}
}
// We don't want end of block comments. If the last comment is a closing
// curly brace.
$previousContent = $phpcsFile
->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
if ($tokens[$previousContent]['line'] === $tokens[$stackPtr]['line']) {
if ($tokens[$previousContent]['code'] === T_CLOSE_CURLY_BRACKET) {
return;
}
// Special case for JS files.
if ($tokens[$previousContent]['code'] === T_COMMA || $tokens[$previousContent]['code'] === T_SEMICOLON) {
$lastContent = $phpcsFile
->findPrevious(T_WHITESPACE, $previousContent - 1, null, true);
if ($tokens[$lastContent]['code'] === T_CLOSE_CURLY_BRACKET) {
return;
}
}
}
$comment = rtrim($tokens[$stackPtr]['content']);
// Only want inline comments.
if (substr($comment, 0, 2) !== '//') {
return;
}
// Ignore code example lines.
if ($this
->isInCodeExample($phpcsFile, $stackPtr) === true) {
return;
}
// Verify the indentation of this comment line.
$this
->processIndentation($phpcsFile, $stackPtr);
// If the current line starts with a tag such as "@see" then the trailing dot
// rules and upper case start rules don't apply.
if (strpos(trim(substr($tokens[$stackPtr]['content'], 2)), '@') === 0) {
return;
}
// The below section determines if a comment block is correctly capitalised,
// and ends in a full-stop. It will find the last comment in a block, and
// work its way up.
$nextComment = $phpcsFile
->findNext(array(
T_COMMENT,
), $stackPtr + 1, null, false);
if ($nextComment !== false && $tokens[$nextComment]['line'] === $tokens[$stackPtr]['line'] + 1 && strpos(trim(substr($tokens[$nextComment]['content'], 2)), '@') !== 0) {
return;
}
$topComment = $stackPtr;
$lastComment = $stackPtr;
while (($topComment = $phpcsFile
->findPrevious(array(
T_COMMENT,
), $lastComment - 1, null, false)) !== false) {
if ($tokens[$topComment]['line'] !== $tokens[$lastComment]['line'] - 1) {
break;
}
$lastComment = $topComment;
}
$topComment = $lastComment;
$commentText = '';
for ($i = $topComment; $i <= $stackPtr; $i++) {
if ($tokens[$i]['code'] === T_COMMENT) {
$commentText .= trim(substr($tokens[$i]['content'], 2));
}
}
if ($commentText === '') {
$error = 'Blank comments are not allowed';
$fix = $phpcsFile
->addFixableError($error, $stackPtr, 'Empty');
if ($fix === true) {
$phpcsFile->fixer
->replaceToken($stackPtr, '');
}
return;
}
$words = preg_split('/\\s+/', $commentText);
if (preg_match('|\\p{Lu}|u', $commentText[0]) === 0 && $commentText[0] !== '@') {
// Allow special lower cased words that contain non-alpha characters
// (function references, machine names with underscores etc.).
$matches = array();
preg_match('/[a-z]+/', $words[0], $matches);
if (isset($matches[0]) === true && $matches[0] === $words[0]) {
$error = 'Inline comments must start with a capital letter';
$fix = $phpcsFile
->addFixableError($error, $topComment, 'NotCapital');
if ($fix === true) {
$newComment = preg_replace("/{$words[0]}/", ucfirst($words[0]), $tokens[$topComment]['content'], 1);
$phpcsFile->fixer
->replaceToken($topComment, $newComment);
}
}
}
$commentCloser = $commentText[strlen($commentText) - 1];
$acceptedClosers = array(
'full-stops' => '.',
'exclamation marks' => '!',
'colons' => ':',
'question marks' => '?',
'or closing parentheses' => ')',
);
// Allow @tag style comments without punctuation.
if (in_array($commentCloser, $acceptedClosers) === false && $commentText[0] !== '@') {
// Allow special last words like URLs or function references
// without punctuation.
$lastWord = $words[count($words) - 1];
$matches = array();
preg_match('/https?:\\/\\/.+/', $lastWord, $matches);
$isUrl = isset($matches[0]) === true;
preg_match('/[$a-zA-Z_]+\\([$a-zA-Z_]*\\)/', $lastWord, $matches);
$isFunction = isset($matches[0]) === true;
// Also allow closing tags like @endlink or @endcode.
$isEndTag = $lastWord[0] === '@';
if ($isUrl === false && $isFunction === false && $isEndTag === false) {
$error = 'Inline comments must end in %s';
$ender = '';
foreach ($acceptedClosers as $closerName => $symbol) {
$ender .= ' ' . $closerName . ',';
}
$ender = trim($ender, ' ,');
$data = array(
$ender,
);
$fix = $phpcsFile
->addFixableError($error, $stackPtr, 'InvalidEndChar', $data);
if ($fix === true) {
$newContent = preg_replace('/(\\s+)$/', '.$1', $tokens[$stackPtr]['content']);
$phpcsFile->fixer
->replaceToken($stackPtr, $newContent);
}
}
}
//end if
// Finally, the line below the last comment cannot be empty if this inline
// comment is on a line by itself.
if ($tokens[$previousContent]['line'] < $tokens[$stackPtr]['line'] && $stackPtr + 1 < $phpcsFile->numTokens) {
for ($i = $stackPtr + 1; $i < $phpcsFile->numTokens; $i++) {
if ($tokens[$i]['line'] === $tokens[$stackPtr]['line'] + 1) {
if ($tokens[$i]['code'] !== T_WHITESPACE || $i === $phpcsFile->numTokens - 1) {
return;
}
}
else {
if ($tokens[$i]['line'] > $tokens[$stackPtr]['line'] + 1) {
break;
}
}
}
$warning = 'There must be no blank line following an inline comment';
$fix = $phpcsFile
->addFixableWarning($warning, $stackPtr, 'SpacingAfter');
if ($fix === true) {
$next = $phpcsFile
->findNext(T_WHITESPACE, $stackPtr + 1, null, true);
if ($next === $phpcsFile->numTokens - 1) {
return;
}
$phpcsFile->fixer
->beginChangeset();
for ($i = $stackPtr + 1; $i < $next; $i++) {
if ($tokens[$i]['line'] === $tokens[$next]['line']) {
break;
}
$phpcsFile->fixer
->replaceToken($i, '');
}
$phpcsFile->fixer
->endChangeset();
}
}
//end if
}