function BlockCommentSniff::process
Processes this test, when one of its tokens is encountered.
Parameters
\PHP_CodeSniffer\Files\File $phpcsFile The current file being scanned.:
int $stackPtr The position of the current token in the: stack passed in $tokens.
Return value
void
Overrides Sniff::process
File
-
vendor/
squizlabs/ php_codesniffer/ src/ Standards/ Squiz/ Sniffs/ Commenting/ BlockCommentSniff.php, line 51
Class
Namespace
PHP_CodeSniffer\Standards\Squiz\Sniffs\CommentingCode
public function process(File $phpcsFile, $stackPtr) {
if ($this->tabWidth === null) {
if (isset($phpcsFile->config->tabWidth) === false || $phpcsFile->config->tabWidth === 0) {
// We have no idea how wide tabs are, so assume 4 spaces for fixing.
$this->tabWidth = 4;
}
else {
$this->tabWidth = $phpcsFile->config->tabWidth;
}
}
$tokens = $phpcsFile->getTokens();
// If it's an inline comment, return.
if (substr($tokens[$stackPtr]['content'], 0, 2) !== '/*') {
return;
}
// If this is a function/class/interface doc block comment, skip it.
// We are only interested in inline doc block comments.
if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT_OPEN_TAG) {
$nextToken = $stackPtr;
do {
$nextToken = $phpcsFile->findNext(Tokens::$emptyTokens, $nextToken + 1, null, true);
if ($tokens[$nextToken]['code'] === T_ATTRIBUTE) {
$nextToken = $tokens[$nextToken]['attribute_closer'];
continue;
}
break;
} while (true);
$ignore = [
T_CLASS => true,
T_INTERFACE => true,
T_TRAIT => true,
T_ENUM => true,
T_FUNCTION => true,
T_PUBLIC => true,
T_PRIVATE => true,
T_FINAL => true,
T_PROTECTED => true,
T_STATIC => true,
T_ABSTRACT => true,
T_CONST => true,
T_VAR => true,
T_READONLY => true,
];
if (isset($ignore[$tokens[$nextToken]['code']]) === true) {
return;
}
$prevToken = $phpcsFile->findPrevious(Tokens::$emptyTokens, $stackPtr - 1, null, true);
if ($tokens[$prevToken]['code'] === T_OPEN_TAG) {
return;
}
$error = 'Block comments must be started with /*';
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'WrongStart');
if ($fix === true) {
$phpcsFile->fixer
->replaceToken($stackPtr, '/*');
}
$end = $tokens[$stackPtr]['comment_closer'];
if ($tokens[$end]['content'] !== '*/') {
$error = 'Block comments must be ended with */';
$fix = $phpcsFile->addFixableError($error, $end, 'WrongEnd');
if ($fix === true) {
$phpcsFile->fixer
->replaceToken($end, '*/');
}
}
return;
}
//end if
$commentLines = [
$stackPtr,
];
$nextComment = $stackPtr;
$lastLine = $tokens[$stackPtr]['line'];
$commentString = $tokens[$stackPtr]['content'];
// Construct the comment into an array.
while (($nextComment = $phpcsFile->findNext(T_WHITESPACE, $nextComment + 1, null, true)) !== false) {
if ($tokens[$nextComment]['code'] !== $tokens[$stackPtr]['code'] && isset(Tokens::$phpcsCommentTokens[$tokens[$nextComment]['code']]) === false) {
// Found the next bit of code.
break;
}
if ($tokens[$nextComment]['line'] - 1 !== $lastLine) {
// Not part of the block.
break;
}
$lastLine = $tokens[$nextComment]['line'];
$commentLines[] = $nextComment;
$commentString .= $tokens[$nextComment]['content'];
if ($tokens[$nextComment]['code'] === T_DOC_COMMENT_CLOSE_TAG || substr($tokens[$nextComment]['content'], -2) === '*/') {
break;
}
}
//end while
$commentText = str_replace($phpcsFile->eolChar, '', $commentString);
$commentText = trim($commentText, "/* \t");
if ($commentText === '') {
$error = 'Empty block comment not allowed';
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'Empty');
if ($fix === true) {
$phpcsFile->fixer
->beginChangeset();
$phpcsFile->fixer
->replaceToken($stackPtr, '');
$lastToken = array_pop($commentLines);
for ($i = $stackPtr + 1; $i <= $lastToken; $i++) {
$phpcsFile->fixer
->replaceToken($i, '');
}
$phpcsFile->fixer
->endChangeset();
}
return;
}
if (count($commentLines) === 1) {
$error = 'Single line block comment not allowed; use inline ("// text") comment instead';
// Only fix comments when they are the last token on a line.
$nextNonEmpty = $phpcsFile->findNext(Tokens::$emptyTokens, $stackPtr + 1, null, true);
if ($tokens[$stackPtr]['line'] !== $tokens[$nextNonEmpty]['line']) {
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'SingleLine');
if ($fix === true) {
$comment = '// ' . $commentText . $phpcsFile->eolChar;
$phpcsFile->fixer
->replaceToken($stackPtr, $comment);
}
}
else {
$phpcsFile->addError($error, $stackPtr, 'SingleLine');
}
return;
}
$content = trim($tokens[$stackPtr]['content']);
if ($content !== '/*' && $content !== '/**') {
$error = 'Block comment text must start on a new line';
$fix = $phpcsFile->addFixableError($error, $stackPtr, 'NoNewLine');
if ($fix === true) {
$indent = '';
if ($tokens[$stackPtr - 1]['code'] === T_WHITESPACE) {
if (isset($tokens[$stackPtr - 1]['orig_content']) === true) {
$indent = $tokens[$stackPtr - 1]['orig_content'];
}
else {
$indent = $tokens[$stackPtr - 1]['content'];
}
}
$comment = preg_replace('/^(\\s*\\/\\*\\*?)/', '$1' . $phpcsFile->eolChar . $indent, $tokens[$stackPtr]['content'], 1);
$phpcsFile->fixer
->replaceToken($stackPtr, $comment);
}
return;
}
//end if
$starColumn = $tokens[$stackPtr]['column'];
$hasStars = false;
// Make sure first line isn't blank.
if (trim($tokens[$commentLines[1]]['content']) === '') {
$error = 'Empty line not allowed at start of comment';
$fix = $phpcsFile->addFixableError($error, $commentLines[1], 'HasEmptyLine');
if ($fix === true) {
$phpcsFile->fixer
->replaceToken($commentLines[1], '');
}
}
else {
// Check indentation of first line.
$content = $tokens[$commentLines[1]]['content'];
$commentText = ltrim($content);
$leadingSpace = strlen($content) - strlen($commentText);
$expected = $starColumn + 3;
if ($commentText[0] === '*') {
$expected = $starColumn;
$hasStars = true;
}
if ($leadingSpace !== $expected) {
$expectedTxt = $expected . ' space';
if ($expected !== 1) {
$expectedTxt .= 's';
}
$data = [
$expectedTxt,
$leadingSpace,
];
$error = 'First line of comment not aligned correctly; expected %s but found %s';
$fix = $phpcsFile->addFixableError($error, $commentLines[1], 'FirstLineIndent', $data);
if ($fix === true) {
if (isset($tokens[$commentLines[1]]['orig_content']) === true && $tokens[$commentLines[1]]['orig_content'][0] === "\t") {
// Line is indented using tabs.
$padding = str_repeat("\t", floor($expected / $this->tabWidth));
$padding .= str_repeat(' ', $expected % $this->tabWidth);
}
else {
$padding = str_repeat(' ', $expected);
}
$phpcsFile->fixer
->replaceToken($commentLines[1], $padding . $commentText);
}
}
//end if
if (preg_match('/^\\p{Ll}/u', $commentText) === 1) {
$error = 'Block comments must start with a capital letter';
$phpcsFile->addError($error, $commentLines[1], 'NoCapital');
}
}
//end if
// Check that each line of the comment is indented past the star.
foreach ($commentLines as $line) {
// First and last lines (comment opener and closer) are handled separately.
if ($line === $commentLines[count($commentLines) - 1] || $line === $commentLines[0]) {
continue;
}
// First comment line was handled above.
if ($line === $commentLines[1]) {
continue;
}
// If it's empty, continue.
if (trim($tokens[$line]['content']) === '') {
continue;
}
$commentText = ltrim($tokens[$line]['content']);
$leadingSpace = strlen($tokens[$line]['content']) - strlen($commentText);
$expected = $starColumn + 3;
if ($commentText[0] === '*') {
$expected = $starColumn;
$hasStars = true;
}
if ($leadingSpace < $expected) {
$expectedTxt = $expected . ' space';
if ($expected !== 1) {
$expectedTxt .= 's';
}
$data = [
$expectedTxt,
$leadingSpace,
];
$error = 'Comment line indented incorrectly; expected at least %s but found %s';
$fix = $phpcsFile->addFixableError($error, $line, 'LineIndent', $data);
if ($fix === true) {
if (isset($tokens[$line]['orig_content']) === true && $tokens[$line]['orig_content'][0] === "\t") {
// Line is indented using tabs.
$padding = str_repeat("\t", floor($expected / $this->tabWidth));
$padding .= str_repeat(' ', $expected % $this->tabWidth);
}
else {
$padding = str_repeat(' ', $expected);
}
$phpcsFile->fixer
->replaceToken($line, $padding . $commentText);
}
}
//end if
}
//end foreach
// Finally, test the last line is correct.
$lastIndex = count($commentLines) - 1;
$content = $tokens[$commentLines[$lastIndex]]['content'];
$commentText = ltrim($content);
if ($commentText !== '*/' && $commentText !== '**/') {
$error = 'Comment closer must be on a new line';
$phpcsFile->addError($error, $commentLines[$lastIndex], 'CloserSameLine');
}
else {
$leadingSpace = strlen($content) - strlen($commentText);
$expected = $starColumn - 1;
if ($hasStars === true) {
$expected = $starColumn;
}
if ($leadingSpace !== $expected) {
$expectedTxt = $expected . ' space';
if ($expected !== 1) {
$expectedTxt .= 's';
}
$data = [
$expectedTxt,
$leadingSpace,
];
$error = 'Last line of comment aligned incorrectly; expected %s but found %s';
$fix = $phpcsFile->addFixableError($error, $commentLines[$lastIndex], 'LastLineIndent', $data);
if ($fix === true) {
if (isset($tokens[$line]['orig_content']) === true && $tokens[$line]['orig_content'][0] === "\t") {
// Line is indented using tabs.
$padding = str_repeat("\t", floor($expected / $this->tabWidth));
$padding .= str_repeat(' ', $expected % $this->tabWidth);
}
else {
$padding = str_repeat(' ', $expected);
}
$phpcsFile->fixer
->replaceToken($commentLines[$lastIndex], $padding . $commentText);
}
}
//end if
}
//end if
// Check that the lines before and after this comment are blank.
$contentBefore = $phpcsFile->findPrevious(T_WHITESPACE, $stackPtr - 1, null, true);
if (isset($tokens[$contentBefore]['scope_closer']) === true && $tokens[$contentBefore]['scope_opener'] === $contentBefore || $tokens[$contentBefore]['code'] === T_OPEN_TAG || $tokens[$contentBefore]['code'] === T_OPEN_TAG_WITH_ECHO) {
if ($tokens[$stackPtr]['line'] - $tokens[$contentBefore]['line'] !== 1) {
$error = 'Empty line not required before block comment';
$phpcsFile->addError($error, $stackPtr, 'HasEmptyLineBefore');
}
}
else {
if ($tokens[$stackPtr]['line'] - $tokens[$contentBefore]['line'] < 2) {
$error = 'Empty line required before block comment';
$phpcsFile->addError($error, $stackPtr, 'NoEmptyLineBefore');
}
}
$commentCloser = $commentLines[$lastIndex];
$contentAfter = $phpcsFile->findNext(T_WHITESPACE, $commentCloser + 1, null, true);
if ($contentAfter !== false && $tokens[$contentAfter]['line'] - $tokens[$commentCloser]['line'] < 2) {
$error = 'Empty line required after block comment';
$phpcsFile->addError($error, $commentCloser, 'NoEmptyLineAfter');
}
}