jenkins-bot has submitted this change and it was merged. ( 
https://gerrit.wikimedia.org/r/383004 )

Change subject: Validate doc syntax
......................................................................


Validate doc syntax

Check for /**, *, */, aligned * and spacing around all of them

Added the following checks:
- SyntaxOpenTag: Comment open tag must be '/**'
- SyntaxDocStar: Comment star must be '*'
- SyntaxMultiDocStar: Comment star must be a single '*'
- SpacingDocStar: Expected at least %s spaces after doc star; %s found
- SpacingDocStarSingleLine: Expected %s spaces after doc star on single
line; %s found
- SpacingDocTag: Expected %s spaces before %s; %s found
- SyntaxAlignedDocStar: Comment star tag not aligned with open tag
- SyntaxAlignedDocClose: Comment close tag not aligned with open tag
- SyntaxCloseTag: Comment close tag must be '*/'
- CloseTagOwnLine: Comment close tag should have own line
- SpacingSingleLineCloseTag: Expected %s spaces before close comment tag
on single line; %s found

Change-Id: I8fe953c1f83b75c9b4f024173c46bc02e6bcc8d4
---
M MediaWiki/Sniffs/Commenting/FunctionCommentSniff.php
M MediaWiki/Tests/files/Commenting/commenting_function.php
M MediaWiki/Tests/files/Commenting/commenting_function.php.expect
M MediaWiki/Tests/files/Commenting/commenting_function.php.fixed
4 files changed, 409 insertions(+), 3 deletions(-)

Approvals:
  Legoktm: Looks good to me, approved
  jenkins-bot: Verified



diff --git a/MediaWiki/Sniffs/Commenting/FunctionCommentSniff.php 
b/MediaWiki/Sniffs/Commenting/FunctionCommentSniff.php
index 8bd2db2..0debd9e 100644
--- a/MediaWiki/Sniffs/Commenting/FunctionCommentSniff.php
+++ b/MediaWiki/Sniffs/Commenting/FunctionCommentSniff.php
@@ -159,6 +159,9 @@
                                $skipDoc = true;
                        }
                }
+
+               $this->validateDocSyntax( $phpcsFile, $stackPtr, $commentStart, 
$commentEnd );
+
                if ( $skipDoc ) {
                        // Don't need to validate anything else
                        return;
@@ -665,5 +668,251 @@
                $content .= $fixParam['comment_first'];
                $phpcsFile->fixer->replaceToken( ( $fixParam['tag'] + 2 ), 
$content );
        }
+
+       /**
+        * Check the doc syntax like start or end tags
+        *
+        * @param File $phpcsFile The file being scanned.
+        * @param int $stackPtr The position of the current token in the stack 
passed in $tokens.
+        * @param int $commentStart The position in the stack where the comment 
started.
+        * @param int $commentEnd The position in the stack where the comment 
ended.
+        *
+        * @return void
+        */
+       protected function validateDocSyntax( File $phpcsFile, $stackPtr, 
$commentStart, $commentEnd ) {
+               $tokens = $phpcsFile->getTokens();
+               $isMultiLineDoc = ( $tokens[$commentStart]['line'] !== 
$tokens[$commentEnd]['line'] );
+
+               // Start token should exact /**
+               if ( $tokens[$commentStart]['code'] === T_DOC_COMMENT_OPEN_TAG 
&&
+                       $tokens[$commentStart]['content'] !== '/**'
+               ) {
+                       $error = 'Comment open tag must be \'/**\'';
+                       $fix = $phpcsFile->addFixableError( $error, 
$commentStart, 'SyntaxOpenTag' );
+                       if ( $fix === true ) {
+                               $phpcsFile->fixer->replaceToken( $commentStart, 
'/**' );
+                       }
+               }
+               // Calculate the column to align all doc stars. Use column of 
/**, add 1 to skip char /
+               $columnDocStar = $tokens[$commentStart]['column'] + 1;
+               $prevLineDocStar = $tokens[$commentStart]['line'];
+
+               for ( $i = $commentStart; $i <= $commentEnd; $i++ ) {
+                       $initialStarChars = 0;
+
+                       // Star token should exact *
+                       if ( $tokens[$i]['code'] === T_DOC_COMMENT_STAR ) {
+                               if ( $tokens[$i]['content'] !== '*' ) {
+                                       $error = 'Comment star must be \'*\'';
+                                       $fix = $phpcsFile->addFixableError( 
$error, $i, 'SyntaxDocStar' );
+                                       if ( $fix === true ) {
+                                               
$phpcsFile->fixer->replaceToken( $i, '*' );
+                                       }
+                               }
+                               // Multi stars in a line are parsed as a new 
token
+                               $initialStarChars = strspn( $tokens[$i + 
1]['content'], '*' );
+                               if ( $initialStarChars > 0 ) {
+                                       $error = 'Comment star must be a single 
\'*\'';
+                                       $fix = $phpcsFile->addFixableError( 
$error, $i, 'SyntaxMultiDocStar' );
+                                       if ( $fix === true ) {
+                                               $phpcsFile->fixer->replaceToken(
+                                                       $i + 1,
+                                                       substr( $tokens[$i + 
1]['content'], $initialStarChars )
+                                               );
+                                       }
+                               }
+                       }
+
+                       // Ensure whitespace after /** or *
+                       if ( ( $tokens[$i]['code'] === T_DOC_COMMENT_OPEN_TAG ||
+                               $tokens[$i]['code'] === T_DOC_COMMENT_STAR ) &&
+                               $tokens[$i + 1]['length'] > 0
+                       ) {
+                               $commentStarSpacing = $i + 1;
+                               $expectedSpaces = 1;
+                               $currentSpaces = 0;
+                               // ignore * removed by SyntaxMultiDocStar and 
count spaces after that
+                               $currentSpaces = strspn(
+                                       
$tokens[$commentStarSpacing]['content'], ' ', $initialStarChars
+                               );
+                               $error = null;
+                               $code = null;
+                               if ( $isMultiLineDoc && $currentSpaces < 
$expectedSpaces ) {
+                                       // be relax for multiline docs, because 
some line breaks in @param can
+                                       // have more than one space after a doc 
star
+                                       $error = 'Expected at least %s spaces 
after doc star; %s found';
+                                       $code = 'SpacingDocStar';
+                               } elseif ( !$isMultiLineDoc && $currentSpaces 
!== $expectedSpaces ) {
+                                       $error = 'Expected %s spaces after doc 
star on single line; %s found';
+                                       $code = 'SpacingDocStarSingleLine';
+                               }
+                               if ( $error !== null && $code !== null ) {
+                                       $data = [
+                                               $expectedSpaces,
+                                               $currentSpaces,
+                                       ];
+                                       $fix = $phpcsFile->addFixableError(
+                                               $error,
+                                               $commentStarSpacing,
+                                               $code,
+                                               $data
+                                       );
+                                       if ( $fix ) {
+                                               if ( $currentSpaces > 
$expectedSpaces ) {
+                                                       // Remove whitespace
+                                                       $content = 
$tokens[$commentStarSpacing]['content'];
+                                                       
$phpcsFile->fixer->replaceToken(
+                                                               
$commentStarSpacing,
+                                                               substr( 
$content, 0, $expectedSpaces - $currentSpaces )
+                                                       );
+                                               } else {
+                                                       // Add whitespace
+                                                       
$phpcsFile->fixer->addContent(
+                                                               $i, str_repeat( 
' ', $expectedSpaces )
+                                                       );
+                                               }
+                                       }
+                               }
+                       }
+
+                       // Ensure one whitespace before @param/@return
+                       if ( $isMultiLineDoc && $tokens[$i]['code'] === 
T_DOC_COMMENT_TAG &&
+                               $tokens[$i]['line'] === $tokens[$i - 1]['line']
+                       ) {
+                               $commentTagSpacing = $i - 1;
+                               $expectedSpaces = 1;
+                               $currentSpaces = strspn( strrev( 
$tokens[$commentTagSpacing]['content'] ), ' ' );
+                               if ( $expectedSpaces !== $currentSpaces ) {
+                                       $data = [
+                                               $expectedSpaces,
+                                               $tokens[$i]['content'],
+                                               $currentSpaces,
+                                       ];
+                                       $fix = $phpcsFile->addFixableError(
+                                               'Expected %s spaces before %s; 
%s found',
+                                               $commentTagSpacing,
+                                               'SpacingDocTag',
+                                               $data
+                                       );
+                                       if ( $fix ) {
+                                               if ( $currentSpaces > 
$expectedSpaces ) {
+                                                       // Remove whitespace
+                                                       $content = 
$tokens[$commentTagSpacing]['content'];
+                                                       
$phpcsFile->fixer->replaceToken(
+                                                               
$commentTagSpacing,
+                                                               substr( 
$content, 0, $expectedSpaces - $currentSpaces )
+                                                       );
+                                               } else {
+                                                       // Add whitespace
+                                                       
$phpcsFile->fixer->addContentBefore(
+                                                               $i, str_repeat( 
' ', $expectedSpaces )
+                                                       );
+                                               }
+                                       }
+                               }
+                       }
+
+                       // Ensure aligned * or */ for multiline comments
+                       if ( $isMultiLineDoc && ( $tokens[$i]['code'] === 
T_DOC_COMMENT_STAR ||
+                               $tokens[$i]['code'] === T_DOC_COMMENT_CLOSE_TAG 
) &&
+                               $tokens[$i]['column'] !== $columnDocStar &&
+                               $tokens[$i]['line'] !== $prevLineDocStar
+                       ) {
+                               if ( $tokens[$i]['code'] === T_DOC_COMMENT_STAR 
) {
+                                       $error = 'Comment star tag not aligned 
with open tag';
+                                       $code = 'SyntaxAlignedDocStar';
+                               } else {
+                                       $error = 'Comment close tag not aligned 
with open tag';
+                                       $code = 'SyntaxAlignedDocClose';
+                               }
+                               $fix = $phpcsFile->addFixableError( $error, $i, 
$code );
+                               if ( $fix === true ) {
+                                       $columnOff = $columnDocStar - 
$tokens[$i]['column'];
+                                       if ( $columnOff < 0 ) {
+                                               $tokenBefore = $i - 1;
+                                               // Ensure to remove only 
whitespaces
+                                               if ( 
$tokens[$tokenBefore]['code'] === T_DOC_COMMENT_WHITESPACE ) {
+                                                       $columnOff = max( 
$columnOff, $tokens[$tokenBefore]['length'] * -1 );
+                                                       // remove whitespaces
+                                                       
$phpcsFile->fixer->replaceToken(
+                                                               $tokenBefore,
+                                                               substr( 
$tokens[$tokenBefore]['content'], 0, $columnOff )
+                                                       );
+                                               }
+                                       } else {
+                                               // Add whitespaces
+                                               
$phpcsFile->fixer->addContentBefore( $i, str_repeat( ' ', $columnOff ) );
+                                       }
+                               }
+                               $prevLineDocStar = $tokens[$i]['line'];
+                       }
+               }
+
+               // End token should exact */
+               if ( $tokens[$commentEnd]['code'] === T_DOC_COMMENT_CLOSE_TAG &&
+                       $tokens[$commentEnd]['content'] !== '*/'
+               ) {
+                       $error = 'Comment close tag must be \'*/\'';
+                       $fix = $phpcsFile->addFixableError( $error, 
$commentEnd, 'SyntaxCloseTag' );
+                       if ( $fix === true ) {
+                               $phpcsFile->fixer->replaceToken( $commentEnd, 
'*/' );
+                       }
+               }
+
+               // For multi line comments the closing tag must have it own line
+               if ( $isMultiLineDoc ) {
+                       $prev = $commentEnd - 1;
+                       $prevNonWhitespace = $phpcsFile->findPrevious(
+                               [ T_DOC_COMMENT_WHITESPACE ], $prev, null, true
+                       );
+                       if ( $tokens[$prevNonWhitespace]['line'] === 
$tokens[$commentEnd]['line'] ) {
+                               $firstWhitespaceOnLine = 
$phpcsFile->findFirstOnLine(
+                                       [ T_DOC_COMMENT_WHITESPACE ], 
$prevNonWhitespace
+                               );
+                               $error = 'Comment close tag should have own 
line';
+                               $fix = $phpcsFile->addFixableError( $error, 
$commentEnd, 'CloseTagOwnLine' );
+                               if ( $fix === true ) {
+                                       $phpcsFile->fixer->beginChangeset();
+                                       $phpcsFile->fixer->addNewline( $prev );
+                                       // Copy the indent of the previous line 
to the new line
+                                       $phpcsFile->fixer->addContent(
+                                               $prev, 
$tokens[$firstWhitespaceOnLine]['content']
+                                       );
+                                       $phpcsFile->fixer->endChangeset();
+                               }
+                       }
+               } else {
+                       // Ensure a whitespace before the token
+                       $commentCloseSpacing = $commentEnd - 1;
+                       $expectedSpaces = 1;
+                       $currentSpaces = strspn( strrev( 
$tokens[$commentCloseSpacing]['content'] ), ' ' );
+                       if ( $currentSpaces !== $expectedSpaces ) {
+                               $data = [
+                                       $expectedSpaces,
+                                       $currentSpaces,
+                               ];
+                               $fix = $phpcsFile->addFixableError(
+                                       'Expected %s spaces before close 
comment tag on single line; %s found',
+                                       $commentCloseSpacing,
+                                       'SpacingSingleLineCloseTag',
+                                       $data
+                               );
+                               if ( $fix ) {
+                                       if ( $currentSpaces > $expectedSpaces ) 
{
+                                               // Remove whitespace
+                                               $content = 
$tokens[$commentCloseSpacing]['content'];
+                                               $phpcsFile->fixer->replaceToken(
+                                                       $commentCloseSpacing, 
substr( $content, 0, $expectedSpaces - $currentSpaces )
+                                               );
+                                       } else {
+                                               // Add whitespace
+                                               
$phpcsFile->fixer->addContentBefore(
+                                                       $commentEnd, 
str_repeat( ' ', $expectedSpaces )
+                                               );
+                                       }
+                               }
+                       }
+               }
+       }
 }
 // end class
diff --git a/MediaWiki/Tests/files/Commenting/commenting_function.php 
b/MediaWiki/Tests/files/Commenting/commenting_function.php
index ffa889a..a09fd43 100644
--- a/MediaWiki/Tests/files/Commenting/commenting_function.php
+++ b/MediaWiki/Tests/files/Commenting/commenting_function.php
@@ -125,6 +125,49 @@
        public function testDeprecated( $stuff, $more, $blah ) {
                $blah = $more . $stuff . $blah;
        }
+
+       /**
+       * Some text
+         *
+       * And other test
+       */
+       public function testStarAlignedDoc() {
+       }
+
+       /***SomeTextWithoutSpaces
+       ***
+       ***AndNoSpacesHere
+       ***/
+       public function testSyntaxDoc() {
+       }
+
+       /***  NoSpaceHere
+        ***
+        ***  AndHere
+        ***/
+       public function testVerySpacyDoc() {
+       }
+
+       /***SingleLineNoSpaceHere***/
+       public function testSpacingDocSingleLine() {
+       }
+
+       /**   SingleLineSpacy  */
+       public function testSpacingDocSingleLineSpacy() {
+       }
+
+       /***
+       *NewLineNoSpaceHere***/
+       public function testCloseTagOwnLine() {
+       }
+
+       /** Comment
+        *@param string $a A comment
+        *  @return string A comment
+        */
+       public function testSyntaxDocTag( $a ) {
+               return $a;
+       }
 }
 
 class TestPassedExamples {
diff --git a/MediaWiki/Tests/files/Commenting/commenting_function.php.expect 
b/MediaWiki/Tests/files/Commenting/commenting_function.php.expect
index a140814..94b65e6 100644
--- a/MediaWiki/Tests/files/Commenting/commenting_function.php.expect
+++ b/MediaWiki/Tests/files/Commenting/commenting_function.php.expect
@@ -83,8 +83,78 @@
      |       |     (MediaWiki.Commenting.FunctionComment.NotPunctuationReturn)
  116 | ERROR | [x] Incorrect capitalization of @inheritDoc
      |       |     (MediaWiki.Commenting.FunctionComment.LowercaseInheritDoc)
- 130 | ERROR | [ ] Only one class is allowed in a file
+ 130 | ERROR | [x] Comment star tag not aligned with open tag
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxAlignedDocStar)
+ 131 | ERROR | [x] Comment star tag not aligned with open tag
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxAlignedDocStar)
+ 132 | ERROR | [x] Comment star tag not aligned with open tag
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxAlignedDocStar)
+ 133 | ERROR | [x] Comment close tag not aligned with open tag
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxAlignedDocClose)
+ 137 | ERROR | [x] Comment open tag must be '/**'
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxOpenTag)
+ 137 | ERROR | [x] Expected at least 1 spaces after doc star; 0 found
+     |       |     (MediaWiki.Commenting.FunctionComment.SpacingDocStar)
+ 138 | ERROR | [x] Comment star must be a single '*'
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxMultiDocStar)
+ 138 | ERROR | [x] Comment star tag not aligned with open tag
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxAlignedDocStar)
+ 138 | ERROR | [x] Expected at least 1 spaces after doc star; 0 found
+     |       |     (MediaWiki.Commenting.FunctionComment.SpacingDocStar)
+ 139 | ERROR | [x] Comment star must be a single '*'
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxMultiDocStar)
+ 139 | ERROR | [x] Comment star tag not aligned with open tag
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxAlignedDocStar)
+ 139 | ERROR | [x] Expected at least 1 spaces after doc star; 0 found
+     |       |     (MediaWiki.Commenting.FunctionComment.SpacingDocStar)
+ 140 | ERROR | [x] Comment close tag not aligned with open tag
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxAlignedDocClose)
+ 140 | ERROR | [x] Comment close tag must be '*/'
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxCloseTag)
+ 144 | ERROR | [x] Comment open tag must be '/**'
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxOpenTag)
+ 145 | ERROR | [x] Comment star must be a single '*'
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxMultiDocStar)
+ 145 | ERROR | [x] Expected at least 1 spaces after doc star; 0 found
+     |       |     (MediaWiki.Commenting.FunctionComment.SpacingDocStar)
+ 146 | ERROR | [x] Comment star must be a single '*'
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxMultiDocStar)
+ 147 | ERROR | [x] Comment close tag must be '*/'
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxCloseTag)
+ 151 | ERROR | [x] Comment open tag must be '/**'
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxOpenTag)
+ 151 | ERROR | [x] Expected 1 spaces after doc star on single line; 0
+     |       |     found
+     |       |     
(MediaWiki.Commenting.FunctionComment.SpacingDocStarSingleLine)
+ 151 | ERROR | [x] Expected 1 spaces before close comment tag on single
+     |       |     line; 0 found
+     |       |     
(MediaWiki.Commenting.FunctionComment.SpacingSingleLineCloseTag)
+ 151 | ERROR | [x] Comment close tag must be '*/'
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxCloseTag)
+ 155 | ERROR | [x] Expected 1 spaces after doc star on single line; 3
+     |       |     found
+     |       |     
(MediaWiki.Commenting.FunctionComment.SpacingDocStarSingleLine)
+ 155 | ERROR | [x] Expected 1 spaces before close comment tag on single
+     |       |     line; 2 found
+     |       |     
(MediaWiki.Commenting.FunctionComment.SpacingSingleLineCloseTag)
+ 159 | ERROR | [x] Comment open tag must be '/**'
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxOpenTag)
+ 160 | ERROR | [x] Comment star tag not aligned with open tag
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxAlignedDocStar)
+ 160 | ERROR | [x] Expected at least 1 spaces after doc star; 0 found
+     |       |     (MediaWiki.Commenting.FunctionComment.SpacingDocStar)
+ 160 | ERROR | [x] Comment close tag must be '*/'
+     |       |     (MediaWiki.Commenting.FunctionComment.SyntaxCloseTag)
+ 160 | ERROR | [x] Comment close tag should have own line
+     |       |     (MediaWiki.Commenting.FunctionComment.CloseTagOwnLine)
+ 165 | ERROR | [x] Expected 1 spaces before @param; 0 found
+     |       |     (MediaWiki.Commenting.FunctionComment.SpacingDocTag)
+ 165 | ERROR | [x] Expected at least 1 spaces after doc star; 0 found
+     |       |     (MediaWiki.Commenting.FunctionComment.SpacingDocStar)
+ 166 | ERROR | [x] Expected 1 spaces before @return; 2 found
+     |       |     (MediaWiki.Commenting.FunctionComment.SpacingDocTag)
+ 173 | ERROR | [ ] Only one class is allowed in a file
      |       |     (MediaWiki.Files.OneClassPerFile.MultipleFound)
- 197 | ERROR | [ ] Only one class is allowed in a file
+ 240 | ERROR | [ ] Only one class is allowed in a file
      |       |     (MediaWiki.Files.OneClassPerFile.MultipleFound)
-PHPCBF CAN FIX THE 32 MARKED SNIFF VIOLATIONS AUTOMATICALLY
+PHPCBF CAN FIX THE 65 MARKED SNIFF VIOLATIONS AUTOMATICALLY
diff --git a/MediaWiki/Tests/files/Commenting/commenting_function.php.fixed 
b/MediaWiki/Tests/files/Commenting/commenting_function.php.fixed
index cdd105c..2f4a517 100644
--- a/MediaWiki/Tests/files/Commenting/commenting_function.php.fixed
+++ b/MediaWiki/Tests/files/Commenting/commenting_function.php.fixed
@@ -125,6 +125,50 @@
        public function testDeprecated( $stuff, $more, $blah ) {
                $blah = $more . $stuff . $blah;
        }
+
+       /**
+        * Some text
+        *
+        * And other test
+        */
+       public function testStarAlignedDoc() {
+       }
+
+       /** SomeTextWithoutSpaces
+        *
+        * AndNoSpacesHere
+        */
+       public function testSyntaxDoc() {
+       }
+
+       /**  NoSpaceHere
+        *
+        *  AndHere
+        */
+       public function testVerySpacyDoc() {
+       }
+
+       /** SingleLineNoSpaceHere */
+       public function testSpacingDocSingleLine() {
+       }
+
+       /** SingleLineSpacy */
+       public function testSpacingDocSingleLineSpacy() {
+       }
+
+       /**
+        * NewLineNoSpaceHere
+        */
+       public function testCloseTagOwnLine() {
+       }
+
+       /** Comment
+        * @param string $a A comment
+        * @return string A comment
+        */
+       public function testSyntaxDocTag( $a ) {
+               return $a;
+       }
 }
 
 class TestPassedExamples {

-- 
To view, visit https://gerrit.wikimedia.org/r/383004
To unsubscribe, visit https://gerrit.wikimedia.org/r/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I8fe953c1f83b75c9b4f024173c46bc02e6bcc8d4
Gerrit-PatchSet: 1
Gerrit-Project: mediawiki/tools/codesniffer
Gerrit-Branch: master
Gerrit-Owner: Umherirrender <umherirrender_de...@web.de>
Gerrit-Reviewer: Addshore <addshorew...@gmail.com>
Gerrit-Reviewer: Legoktm <lego...@member.fsf.org>
Gerrit-Reviewer: jenkins-bot <>

_______________________________________________
MediaWiki-commits mailing list
MediaWiki-commits@lists.wikimedia.org
https://lists.wikimedia.org/mailman/listinfo/mediawiki-commits

Reply via email to