diff --git a/BigBite/Sniffs/Commenting/DocCommentLineLengthSniff.php b/BigBite/Sniffs/Commenting/DocCommentLineLengthSniff.php index e2b5566..522eee9 100644 --- a/BigBite/Sniffs/Commenting/DocCommentLineLengthSniff.php +++ b/BigBite/Sniffs/Commenting/DocCommentLineLengthSniff.php @@ -49,6 +49,16 @@ final class DocCommentLineLengthSniff implements Sniff { */ public $includeIndentation = false; + /** + * Specific comment prefixes to ignore. + * + * @var array + */ + public $descriptorsToIgnore = array( + 'Plugin Name:', + 'Theme Name:', + ); + /** * Returns an array of tokens this test wants to listen for. * @@ -92,21 +102,53 @@ public function process( File $phpcsFile, $stackPtr ) { return; } - if ( 1 === preg_match( '/^(Plugin|Theme)\s+Name:/i', $tokens[ $short ]['content'] ) ) { - // It's a WordPress plugin or theme, so disregard line length. - return; + foreach ( $this->descriptorsToIgnore as $descriptor ) { + // It's an ignored comment, so disregard line length. + if ( 0 === strpos( $tokens[ $short ]['content'], $descriptor ) ) { + return; + } } for ( $i = ( $commentStart + 1 ); $i < $commentEnd; $i++ ) { + if ( in_array( $tokens[ $i ]['type'], array( 'T_DOC_COMMENT_WHITESPACE', 'T_DOC_COMMENT_STAR' ), true ) ) { + continue; + } + if ( \T_DOC_COMMENT_STRING !== $tokens[ $i ]['code'] ) { continue; } + $isAParameterDescription = false; + $lineLength = $tokens[ $i ]['length']; if ( true === $this->includeIndentation ) { $lineLength = ( $tokens[ $i ]['column'] + $tokens[ $i ]['length'] - 1 ); } + // The line is over the limit, but it's a param comment. + // See if it's reasonable to split - most of the length could be the type hint, which we should allow. + if ( $lineLength > $this->lineLimit ) { + $parameterToken = $phpcsFile->findPrevious( \T_DOC_COMMENT_TAG, $i ); + $itIsAParameter = false !== $parameterToken && $tokens[ $parameterToken ]['line'] === $tokens[ $i ]['line']; + $itMatchesRegex = 1 === preg_match( '/^(.+)\s+(\$[a-zA-Z_]+)\s+(.+)$/', $tokens[ $i ]['content'], $lineContent ); + + // Split the content into parts. + if ( $itIsAParameter && $itMatchesRegex ) { + list( /* $fullMatch */, /* $typehint */, /* $paramName */, $description ) = $lineContent; + + $descriptionLength = strlen( $description ); + // We only need to flag it if the description alone is greater than the line limit. + if ( $descriptionLength <= $this->lineLimit ) { + $phpcsFile->recordMetric( $i, 'Line length', "{$this->lineLimit} or less" ); + continue; + } + + $lineLength = $descriptionLength; + + $isAParameterDescription = true; + } + } + // Record metrics. if ( $lineLength <= $this->lineLimit ) { $phpcsFile->recordMetric( $i, 'Line length', "{$this->lineLimit} or less" ); @@ -144,6 +186,11 @@ public function process( File $phpcsFile, $stackPtr ) { ); $error = 'Line exceeds maximum limit of %s characters; contains %s characters'; + + if ( $isAParameterDescription ) { + $error = 'Parameter description exceeds maximum limit of %s characters; contains %s characters'; + } + $phpcsFile->addError( $error, $i, 'MaxExceeded', $data ); } elseif ( $lineLength > $this->lineLimit ) { $data = array( @@ -152,6 +199,11 @@ public function process( File $phpcsFile, $stackPtr ) { ); $warning = 'Line exceeds %s characters; contains %s characters'; + + if ( $isAParameterDescription ) { + $warning = 'Parameter description exceeds %s characters; contains %s characters'; + } + $phpcsFile->addWarning( $warning, $i, 'TooLong', $data ); } } diff --git a/BigBite/Tests/Commenting/DocCommentLineLengthUnitTest.1.inc b/BigBite/Tests/Commenting/DocCommentLineLengthUnitTest.1.inc index a000a8c..3f1700e 100644 --- a/BigBite/Tests/Commenting/DocCommentLineLengthUnitTest.1.inc +++ b/BigBite/Tests/Commenting/DocCommentLineLengthUnitTest.1.inc @@ -33,3 +33,16 @@ /** * This is a comment line that should not trigger a warning, nor an error. */ + +/** + * This is a function docblock, and the first line of it is really long, so it should trigger an error. + * + * However, it also includes a really long parameter type hint, + * which should not trigger an error, despite its line length. + * Sometimes type hints are just really long. + * + * @param array>>> $reallyLongParamName This is a description of the param. + * @param array $anotherParamName This is a description of the param that exceeds the minimum line length even when disregarding the type hint and parameter name from the length calculation. + * + * @return void + */ diff --git a/BigBite/Tests/Commenting/DocCommentLineLengthUnitTest.1.inc.fixed b/BigBite/Tests/Commenting/DocCommentLineLengthUnitTest.1.inc.fixed index 7ed3985..0da500e 100644 --- a/BigBite/Tests/Commenting/DocCommentLineLengthUnitTest.1.inc.fixed +++ b/BigBite/Tests/Commenting/DocCommentLineLengthUnitTest.1.inc.fixed @@ -35,3 +35,17 @@ /** * This is a comment line that should not trigger a warning, nor an error. */ + +/** + * This is a function docblock, and the first line of it is really long, so it should trigger an error. + * + * However, it also includes a really long parameter type hint, + * which should not trigger an error, despite its line length. + * Sometimes type hints are just really long. + * + * @param array>>> $reallyLongParamName This is a description of the param. + * @param array $anotherParamName This is a description of the param that exceeds the minimum line length even when disregarding the + * type hint and parameter name from the length calculation. + * + * @return void + */ diff --git a/BigBite/Tests/Commenting/DocCommentLineLengthUnitTest.php b/BigBite/Tests/Commenting/DocCommentLineLengthUnitTest.php index 1ea8765..5f80be0 100644 --- a/BigBite/Tests/Commenting/DocCommentLineLengthUnitTest.php +++ b/BigBite/Tests/Commenting/DocCommentLineLengthUnitTest.php @@ -44,7 +44,8 @@ public function getErrorList( $testFile = '' ) { switch ( $testFile ) { case 'DocCommentLineLengthUnitTest.1.inc': return array( - 8 => 1, + 8 => 1, + 45 => 1, ); case 'DocCommentLineLengthUnitTest.2.inc': return array( @@ -73,7 +74,8 @@ public function getWarningList( $testFile = '' ) { switch ( $testFile ) { case 'DocCommentLineLengthUnitTest.1.inc': return array( - 4 => 1, + 4 => 1, + 38 => 1, ); case 'DocCommentLineLengthUnitTest.2.inc': return array(