Skip to content
Snippets Groups Projects
Unverified Commit 1617b8e2 authored by Adam Zimmermann's avatar Adam Zimmermann Committed by GitHub
Browse files

feat(Todo): Add fixer for todo comments (#3177471 by adamzimmermann)

parent 8066395d
Branches
Tags 8.3.12
No related merge requests found
......@@ -83,7 +83,7 @@ class TodoCommentSniff implements Sniff
echo "Getting \$comment from \$tokens[$stackPtr]['content']\n";
}
$this->checkTodoFormat($phpcsFile, $stackPtr, $comment);
$this->checkTodoFormat($phpcsFile, $stackPtr, $comment, $tokens);
} else if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT_TAG) {
// Document comment tag (i.e. comments that begin with "@").
// Determine if this is related at all and build the full comment line
......@@ -105,7 +105,7 @@ class TodoCommentSniff implements Sniff
echo "Result comment = $comment\n";
}
$this->checkTodoFormat($phpcsFile, $stackPtr, $comment);
$this->checkTodoFormat($phpcsFile, $stackPtr, $comment, $tokens);
}//end if
}//end if
......@@ -119,37 +119,71 @@ class TodoCommentSniff implements Sniff
* @param int $stackPtr The position of the current token
* in the stack passed in $tokens.
* @param string $comment The comment text.
* @param array<array> $tokens The token data.
*
* @return void
*/
private function checkTodoFormat(File $phpcsFile, $stackPtr, string $comment)
private function checkTodoFormat(File $phpcsFile, int $stackPtr, string $comment, array $tokens)
{
if ($this->debug === true) {
echo "Checking \$comment = '$comment'\n";
}
$expression = '/(?x) # Set free-space mode to allow this commenting
$expression = '/(?x) # Set free-space mode to allow this commenting.
^(\/|\s)* # At the start optionally match any forward slashes and spaces
(?i) # set case-insensitive mode
(?=( # start a positive non-consuming look-ahead to find all possible todos
@+to(-|\s|)+do # if one or more @ allow spaces and - between the to and do
(?i) # set case-insensitive mode.
(?=( # Start a positive non-consuming look-ahead to find all possible todos
@+to(-|\s|)+do # if one or more @ allow spaces and - between the to and do.
\h*(-|:)* # Also match the trailing "-" or ":" so they can be replaced.
| # or
to(-)*do # if no @ then only accept todo or to-do or to--do, etc, no spaces
to(-)*do # If no @ then only accept todo or to-do or to--do, etc, no spaces.
(\s-|:)* # Also match the trailing "-" or ":" so they can be replaced.
))
(?-i) # Reset to case-sensitive
(?! # Start another non-consuming look-ahead, this time negative
@todo\s # It has to match lower-case @todo followed by one space
(?!-|:)\S # and then any non-space except - or :
(?!-|:)\S # and then any non-space except "-" or ":".
)/m';
if ((bool) preg_match($expression, $comment) === true) {
if ((bool) preg_match($expression, $comment, $matches) === true) {
if ($this->debug === true) {
echo "Failed regex - give message\n";
}
$comment = trim($comment, " /\r\n");
$phpcsFile->addWarning("'%s' should match the format '@todo Fix problem X here.'", $stackPtr, 'TodoFormat', [$comment]);
}
$commentTrimmed = trim($comment, " /\r\n");
if ($commentTrimmed === '@todo') {
// We can't fix a comment that doesn't have any text.
$phpcsFile->addWarning("'%s' should match the format '@todo Fix problem X here.'", $stackPtr, 'TodoFormat', [$commentTrimmed]);
$fix = false;
} else {
// Comments with description text are fixable.
$fix = $phpcsFile->addFixableWarning("'%s' should match the format '@todo Fix problem X here.'", $stackPtr, 'TodoFormat', [$commentTrimmed]);
}
if ($fix === true) {
if ($tokens[$stackPtr]['code'] === T_DOC_COMMENT_TAG) {
// Rewrite the comment past the token content to an empty
// string as part of it may be part of the match, but not in
// the token content. Then replace the token content with
// the fixed comment from the matched content.
$phpcsFile->fixer->beginChangeset();
$index = ($stackPtr + 1);
while ($tokens[$index]['line'] === $tokens[$stackPtr]['line']) {
$phpcsFile->fixer->replaceToken($index, '');
$index++;
}
$fixedTodo = str_replace($matches[2], '@todo ', $comment);
$phpcsFile->fixer->replaceToken($stackPtr, $fixedTodo);
$phpcsFile->fixer->endChangeset();
} else {
// The full comment line text is available here, so the
// replacement is fairly straightforward.
$fixedTodo = str_replace($matches[2], '@todo ', $tokens[$stackPtr]['content']);
$phpcsFile->fixer->replaceToken($stackPtr, $fixedTodo);
}//end if
}//end if
}//end if
}//end checkTodoFormat()
......
<?php
/**
* @file
* Test file for the todo standard.
*
* These are valid examples.
*
* @todo Valid.
* @todo valid with lower-case first letter
* @todo $can start with a $
* @todo \also with backslash
*
* These are all incorrect.
* These are all incorrect but can be fixed automatically.
*
* @TODO Error
* @ToDo Error
* @TODo Error
......@@ -29,19 +32,26 @@
* TODO Error
* ToDo Error
* to-do Error
*
* These are all incorrect but cannot be fully fixed automatically.
*
* @todo
* @to-do
* @TODO
*/
/**
* Example function.
*/
function foo() {
// These are valid examples.
// @todo Valid.
// @todo valid with lower-case first letter
// @todo $can start with a $
// @todo \also with backslash
// This is not a todo tag. It is a general comment and we do not want
// to do the standards checking here.
// These are all incorrect.
// These are all incorrect but can be fixed automatically.
// @TODO Error
// @ToDo Error
// @TODo Error
......@@ -61,4 +71,8 @@ function foo() {
// TODO Error
// ToDo Error
// to-do Error
// These are all incorrect but cannot be fully fixed automatically.
// @todo
// @to-do
// @TODO
}
<?php
/**
* @file
* Test file for the todo standard.
*
* These are valid examples.
*
* @todo Valid.
* @todo valid with lower-case first letter
* @todo $can start with a $
* @todo \also with backslash
*
* These are all incorrect but can be fixed automatically.
*
* @todo Error
* @todo Error
* @todo Error
* @todo Error
* @todo Error
* @todo Error
* @todo Error
* @todo Error
* @todo Error
* @todo Error
* @todo Error
* @todo Error
* @todo Error
* @todo Error
* @todo Error
* @todo Error
* @todo Error
* @todo Error
* @todo Error
*
* These are all incorrect but cannot be fully fixed automatically.
*
* @todo
* @todo
* @todo
*/
/**
* Example function.
*/
function foo() {
// These are valid examples.
// @todo Valid.
// @todo valid with lower-case first letter
// @todo $can start with a $
// @todo \also with backslash
// This is not a todo tag. It is a general comment and we do not want
// to do the standards checking here.
// These are all incorrect but can be fixed automatically.
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// @todo Error
// These are all incorrect but cannot be fully fixed automatically.
// @todo
// @todo
// @todo
}
......@@ -37,7 +37,7 @@ class TodoCommentUnitTest extends CoderSniffUnitTest
*/
protected function getWarningList(string $testFile): array
{
$warningList = (array_fill_keys(range(13, 31), 1) + array_fill_keys(range(45, 63), 1));
$warningList = (array_fill_keys(range(16, 34), 1) + array_fill_keys(range(38, 40), 1) + array_fill_keys(range(55, 73), 1) + array_fill_keys(range(75, 77), 1));
return $warningList;
}//end getWarningList()
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment