1<?php 2/** 3 * Parses and verifies the doc comments for functions. 4 * 5 * PHP version 5 6 * 7 * @category PHP 8 * @package PHP_CodeSniffer 9 * @author Greg Sherwood <gsherwood@squiz.net> 10 * @author Marc McIntyre <mmcintyre@squiz.net> 11 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) 12 * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence 13 * @link http://pear.php.net/package/PHP_CodeSniffer 14 */ 15 16if (class_exists('PEAR_Sniffs_Commenting_FunctionCommentSniff', true) === false) { 17 throw new PHP_CodeSniffer_Exception('Class PEAR_Sniffs_Commenting_FunctionCommentSniff not found'); 18} 19 20/** 21 * Parses and verifies the doc comments for functions. 22 * 23 * @category PHP 24 * @package PHP_CodeSniffer 25 * @author Greg Sherwood <gsherwood@squiz.net> 26 * @author Marc McIntyre <mmcintyre@squiz.net> 27 * @copyright 2006-2014 Squiz Pty Ltd (ABN 77 084 670 600) 28 * @license https://github.com/squizlabs/PHP_CodeSniffer/blob/master/licence.txt BSD Licence 29 * @version Release: @package_version@ 30 * @link http://pear.php.net/package/PHP_CodeSniffer 31 */ 32class Squiz_Sniffs_Commenting_FunctionCommentSniff extends PEAR_Sniffs_Commenting_FunctionCommentSniff 33{ 34 35 /** 36 * The current PHP version. 37 * 38 * @var integer 39 */ 40 private $_phpVersion = null; 41 42 43 /** 44 * Process the return comment of this function comment. 45 * 46 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. 47 * @param int $stackPtr The position of the current token 48 * in the stack passed in $tokens. 49 * @param int $commentStart The position in the stack where the comment started. 50 * 51 * @return void 52 */ 53 protected function processReturn(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart) 54 { 55 $tokens = $phpcsFile->getTokens(); 56 57 // Skip constructor and destructor. 58 $methodName = $phpcsFile->getDeclarationName($stackPtr); 59 $isSpecialMethod = ($methodName === '__construct' || $methodName === '__destruct'); 60 61 $return = null; 62 foreach ($tokens[$commentStart]['comment_tags'] as $tag) { 63 if ($tokens[$tag]['content'] === '@return') { 64 if ($return !== null) { 65 $error = 'Only 1 @return tag is allowed in a function comment'; 66 $phpcsFile->addError($error, $tag, 'DuplicateReturn'); 67 return; 68 } 69 70 $return = $tag; 71 } 72 } 73 74 if ($isSpecialMethod === true) { 75 return; 76 } 77 78 if ($return !== null) { 79 $content = $tokens[($return + 2)]['content']; 80 if (empty($content) === true || $tokens[($return + 2)]['code'] !== T_DOC_COMMENT_STRING) { 81 $error = 'Return type missing for @return tag in function comment'; 82 $phpcsFile->addError($error, $return, 'MissingReturnType'); 83 } else { 84 // Support both a return type and a description. 85 $split = preg_match('`^((?:\|?(?:array\([^\)]*\)|[\\\\a-z0-9\[\]]+))*)( .*)?`i', $content, $returnParts); 86 if (isset($returnParts[1]) === false) { 87 return; 88 } 89 90 $returnType = $returnParts[1]; 91 92 // Check return type (can be multiple, separated by '|'). 93 $typeNames = explode('|', $returnType); 94 $suggestedNames = array(); 95 foreach ($typeNames as $i => $typeName) { 96 $suggestedName = PHP_CodeSniffer::suggestType($typeName); 97 if (in_array($suggestedName, $suggestedNames) === false) { 98 $suggestedNames[] = $suggestedName; 99 } 100 } 101 102 $suggestedType = implode('|', $suggestedNames); 103 if ($returnType !== $suggestedType) { 104 $error = 'Expected "%s" but found "%s" for function return type'; 105 $data = array( 106 $suggestedType, 107 $returnType, 108 ); 109 $fix = $phpcsFile->addFixableError($error, $return, 'InvalidReturn', $data); 110 if ($fix === true) { 111 $replacement = $suggestedType; 112 if (empty($returnParts[2]) === false) { 113 $replacement .= $returnParts[2]; 114 } 115 116 $phpcsFile->fixer->replaceToken(($return + 2), $replacement); 117 unset($replacement); 118 } 119 } 120 121 // If the return type is void, make sure there is 122 // no return statement in the function. 123 if ($returnType === 'void') { 124 if (isset($tokens[$stackPtr]['scope_closer']) === true) { 125 $endToken = $tokens[$stackPtr]['scope_closer']; 126 for ($returnToken = $stackPtr; $returnToken < $endToken; $returnToken++) { 127 if ($tokens[$returnToken]['code'] === T_CLOSURE 128 || $tokens[$returnToken]['code'] === T_ANON_CLASS 129 ) { 130 $returnToken = $tokens[$returnToken]['scope_closer']; 131 continue; 132 } 133 134 if ($tokens[$returnToken]['code'] === T_RETURN 135 || $tokens[$returnToken]['code'] === T_YIELD 136 || $tokens[$returnToken]['code'] === T_YIELD_FROM 137 ) { 138 break; 139 } 140 } 141 142 if ($returnToken !== $endToken) { 143 // If the function is not returning anything, just 144 // exiting, then there is no problem. 145 $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true); 146 if ($tokens[$semicolon]['code'] !== T_SEMICOLON) { 147 $error = 'Function return type is void, but function contains return statement'; 148 $phpcsFile->addError($error, $return, 'InvalidReturnVoid'); 149 } 150 } 151 }//end if 152 } else if ($returnType !== 'mixed' && in_array('void', $typeNames, true) === false) { 153 // If return type is not void, there needs to be a return statement 154 // somewhere in the function that returns something. 155 if (isset($tokens[$stackPtr]['scope_closer']) === true) { 156 $endToken = $tokens[$stackPtr]['scope_closer']; 157 $returnToken = $phpcsFile->findNext(array(T_RETURN, T_YIELD, T_YIELD_FROM), $stackPtr, $endToken); 158 if ($returnToken === false) { 159 $error = 'Function return type is not void, but function has no return statement'; 160 $phpcsFile->addError($error, $return, 'InvalidNoReturn'); 161 } else { 162 $semicolon = $phpcsFile->findNext(T_WHITESPACE, ($returnToken + 1), null, true); 163 if ($tokens[$semicolon]['code'] === T_SEMICOLON) { 164 $error = 'Function return type is not void, but function is returning void here'; 165 $phpcsFile->addError($error, $returnToken, 'InvalidReturnNotVoid'); 166 } 167 } 168 } 169 }//end if 170 }//end if 171 } else { 172 $error = 'Missing @return tag in function comment'; 173 $phpcsFile->addError($error, $tokens[$commentStart]['comment_closer'], 'MissingReturn'); 174 }//end if 175 176 }//end processReturn() 177 178 179 /** 180 * Process any throw tags that this function comment has. 181 * 182 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. 183 * @param int $stackPtr The position of the current token 184 * in the stack passed in $tokens. 185 * @param int $commentStart The position in the stack where the comment started. 186 * 187 * @return void 188 */ 189 protected function processThrows(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart) 190 { 191 $tokens = $phpcsFile->getTokens(); 192 193 $throws = array(); 194 foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { 195 if ($tokens[$tag]['content'] !== '@throws') { 196 continue; 197 } 198 199 $exception = null; 200 $comment = null; 201 if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { 202 $matches = array(); 203 preg_match('/([^\s]+)(?:\s+(.*))?/', $tokens[($tag + 2)]['content'], $matches); 204 $exception = $matches[1]; 205 if (isset($matches[2]) === true && trim($matches[2]) !== '') { 206 $comment = $matches[2]; 207 } 208 } 209 210 if ($exception === null) { 211 $error = 'Exception type and comment missing for @throws tag in function comment'; 212 $phpcsFile->addError($error, $tag, 'InvalidThrows'); 213 } else if ($comment === null) { 214 $error = 'Comment missing for @throws tag in function comment'; 215 $phpcsFile->addError($error, $tag, 'EmptyThrows'); 216 } else { 217 // Any strings until the next tag belong to this comment. 218 if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === true) { 219 $end = $tokens[$commentStart]['comment_tags'][($pos + 1)]; 220 } else { 221 $end = $tokens[$commentStart]['comment_closer']; 222 } 223 224 for ($i = ($tag + 3); $i < $end; $i++) { 225 if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { 226 $comment .= ' '.$tokens[$i]['content']; 227 } 228 } 229 230 // Starts with a capital letter and ends with a fullstop. 231 $firstChar = $comment{0}; 232 if (strtoupper($firstChar) !== $firstChar) { 233 $error = '@throws tag comment must start with a capital letter'; 234 $phpcsFile->addError($error, ($tag + 2), 'ThrowsNotCapital'); 235 } 236 237 $lastChar = substr($comment, -1); 238 if ($lastChar !== '.') { 239 $error = '@throws tag comment must end with a full stop'; 240 $phpcsFile->addError($error, ($tag + 2), 'ThrowsNoFullStop'); 241 } 242 }//end if 243 }//end foreach 244 245 }//end processThrows() 246 247 248 /** 249 * Process the function parameter comments. 250 * 251 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. 252 * @param int $stackPtr The position of the current token 253 * in the stack passed in $tokens. 254 * @param int $commentStart The position in the stack where the comment started. 255 * 256 * @return void 257 */ 258 protected function processParams(PHP_CodeSniffer_File $phpcsFile, $stackPtr, $commentStart) 259 { 260 if ($this->_phpVersion === null) { 261 $this->_phpVersion = PHP_CodeSniffer::getConfigData('php_version'); 262 if ($this->_phpVersion === null) { 263 $this->_phpVersion = PHP_VERSION_ID; 264 } 265 } 266 267 $tokens = $phpcsFile->getTokens(); 268 269 $params = array(); 270 $maxType = 0; 271 $maxVar = 0; 272 foreach ($tokens[$commentStart]['comment_tags'] as $pos => $tag) { 273 if ($tokens[$tag]['content'] !== '@param') { 274 continue; 275 } 276 277 $type = ''; 278 $typeSpace = 0; 279 $var = ''; 280 $varSpace = 0; 281 $comment = ''; 282 $commentLines = array(); 283 if ($tokens[($tag + 2)]['code'] === T_DOC_COMMENT_STRING) { 284 $matches = array(); 285 preg_match('/([^$&.]+)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/', $tokens[($tag + 2)]['content'], $matches); 286 287 if (empty($matches) === false) { 288 $typeLen = strlen($matches[1]); 289 $type = trim($matches[1]); 290 $typeSpace = ($typeLen - strlen($type)); 291 $typeLen = strlen($type); 292 if ($typeLen > $maxType) { 293 $maxType = $typeLen; 294 } 295 } 296 297 if (isset($matches[2]) === true) { 298 $var = $matches[2]; 299 $varLen = strlen($var); 300 if ($varLen > $maxVar) { 301 $maxVar = $varLen; 302 } 303 304 if (isset($matches[4]) === true) { 305 $varSpace = strlen($matches[3]); 306 $comment = $matches[4]; 307 $commentLines[] = array( 308 'comment' => $comment, 309 'token' => ($tag + 2), 310 'indent' => $varSpace, 311 ); 312 313 // Any strings until the next tag belong to this comment. 314 if (isset($tokens[$commentStart]['comment_tags'][($pos + 1)]) === true) { 315 $end = $tokens[$commentStart]['comment_tags'][($pos + 1)]; 316 } else { 317 $end = $tokens[$commentStart]['comment_closer']; 318 } 319 320 for ($i = ($tag + 3); $i < $end; $i++) { 321 if ($tokens[$i]['code'] === T_DOC_COMMENT_STRING) { 322 $indent = 0; 323 if ($tokens[($i - 1)]['code'] === T_DOC_COMMENT_WHITESPACE) { 324 $indent = strlen($tokens[($i - 1)]['content']); 325 } 326 327 $comment .= ' '.$tokens[$i]['content']; 328 $commentLines[] = array( 329 'comment' => $tokens[$i]['content'], 330 'token' => $i, 331 'indent' => $indent, 332 ); 333 } 334 } 335 } else { 336 $error = 'Missing parameter comment'; 337 $phpcsFile->addError($error, $tag, 'MissingParamComment'); 338 $commentLines[] = array('comment' => ''); 339 }//end if 340 } else { 341 $error = 'Missing parameter name'; 342 $phpcsFile->addError($error, $tag, 'MissingParamName'); 343 }//end if 344 } else { 345 $error = 'Missing parameter type'; 346 $phpcsFile->addError($error, $tag, 'MissingParamType'); 347 }//end if 348 349 $params[] = array( 350 'tag' => $tag, 351 'type' => $type, 352 'var' => $var, 353 'comment' => $comment, 354 'commentLines' => $commentLines, 355 'type_space' => $typeSpace, 356 'var_space' => $varSpace, 357 ); 358 }//end foreach 359 360 $realParams = $phpcsFile->getMethodParameters($stackPtr); 361 $foundParams = array(); 362 363 // We want to use ... for all variable length arguments, so added 364 // this prefix to the variable name so comparisons are easier. 365 foreach ($realParams as $pos => $param) { 366 if ($param['variable_length'] === true) { 367 $realParams[$pos]['name'] = '...'.$realParams[$pos]['name']; 368 } 369 } 370 371 foreach ($params as $pos => $param) { 372 // If the type is empty, the whole line is empty. 373 if ($param['type'] === '') { 374 continue; 375 } 376 377 // Check the param type value. 378 $typeNames = explode('|', $param['type']); 379 $suggestedTypeNames = array(); 380 381 foreach ($typeNames as $typeName) { 382 $suggestedName = PHP_CodeSniffer::suggestType($typeName); 383 $suggestedTypeNames[] = $suggestedName; 384 385 if (count($typeNames) > 1) { 386 continue; 387 } 388 389 // Check type hint for array and custom type. 390 $suggestedTypeHint = ''; 391 if (strpos($suggestedName, 'array') !== false || substr($suggestedName, -2) === '[]') { 392 $suggestedTypeHint = 'array'; 393 } else if (strpos($suggestedName, 'callable') !== false) { 394 $suggestedTypeHint = 'callable'; 395 } else if (strpos($suggestedName, 'callback') !== false) { 396 $suggestedTypeHint = 'callable'; 397 } else if (in_array($suggestedName, PHP_CodeSniffer::$allowedTypes) === false) { 398 $suggestedTypeHint = $suggestedName; 399 } 400 401 if ($this->_phpVersion >= 70000) { 402 if ($suggestedName === 'string') { 403 $suggestedTypeHint = 'string'; 404 } else if ($suggestedName === 'int' || $suggestedName === 'integer') { 405 $suggestedTypeHint = 'int'; 406 } else if ($suggestedName === 'float') { 407 $suggestedTypeHint = 'float'; 408 } else if ($suggestedName === 'bool' || $suggestedName === 'boolean') { 409 $suggestedTypeHint = 'bool'; 410 } 411 } 412 413 if ($suggestedTypeHint !== '' && isset($realParams[$pos]) === true) { 414 $typeHint = $realParams[$pos]['type_hint']; 415 if ($typeHint === '') { 416 $error = 'Type hint "%s" missing for %s'; 417 $data = array( 418 $suggestedTypeHint, 419 $param['var'], 420 ); 421 422 $errorCode = 'TypeHintMissing'; 423 if ($suggestedTypeHint === 'string' 424 || $suggestedTypeHint === 'int' 425 || $suggestedTypeHint === 'float' 426 || $suggestedTypeHint === 'bool' 427 ) { 428 $errorCode = 'Scalar'.$errorCode; 429 } 430 431 $phpcsFile->addError($error, $stackPtr, $errorCode, $data); 432 } else if ($typeHint !== substr($suggestedTypeHint, (strlen($typeHint) * -1))) { 433 $error = 'Expected type hint "%s"; found "%s" for %s'; 434 $data = array( 435 $suggestedTypeHint, 436 $typeHint, 437 $param['var'], 438 ); 439 $phpcsFile->addError($error, $stackPtr, 'IncorrectTypeHint', $data); 440 }//end if 441 } else if ($suggestedTypeHint === '' && isset($realParams[$pos]) === true) { 442 $typeHint = $realParams[$pos]['type_hint']; 443 if ($typeHint !== '') { 444 $error = 'Unknown type hint "%s" found for %s'; 445 $data = array( 446 $typeHint, 447 $param['var'], 448 ); 449 $phpcsFile->addError($error, $stackPtr, 'InvalidTypeHint', $data); 450 } 451 }//end if 452 }//end foreach 453 454 $suggestedType = implode($suggestedTypeNames, '|'); 455 if ($param['type'] !== $suggestedType) { 456 $error = 'Expected "%s" but found "%s" for parameter type'; 457 $data = array( 458 $suggestedType, 459 $param['type'], 460 ); 461 462 $fix = $phpcsFile->addFixableError($error, $param['tag'], 'IncorrectParamVarName', $data); 463 if ($fix === true) { 464 $phpcsFile->fixer->beginChangeset(); 465 466 $content = $suggestedType; 467 $content .= str_repeat(' ', $param['type_space']); 468 $content .= $param['var']; 469 $content .= str_repeat(' ', $param['var_space']); 470 if (isset($param['commentLines'][0]) === true) { 471 $content .= $param['commentLines'][0]['comment']; 472 } 473 474 $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); 475 476 // Fix up the indent of additional comment lines. 477 foreach ($param['commentLines'] as $lineNum => $line) { 478 if ($lineNum === 0 479 || $param['commentLines'][$lineNum]['indent'] === 0 480 ) { 481 continue; 482 } 483 484 $diff = (strlen($param['type']) - strlen($suggestedType)); 485 $newIndent = ($param['commentLines'][$lineNum]['indent'] - $diff); 486 $phpcsFile->fixer->replaceToken( 487 ($param['commentLines'][$lineNum]['token'] - 1), 488 str_repeat(' ', $newIndent) 489 ); 490 } 491 492 $phpcsFile->fixer->endChangeset(); 493 }//end if 494 }//end if 495 496 if ($param['var'] === '') { 497 continue; 498 } 499 500 $foundParams[] = $param['var']; 501 502 // Check number of spaces after the type. 503 $this->checkSpacingAfterParamType($phpcsFile, $param, $maxType); 504 505 // Make sure the param name is correct. 506 if (isset($realParams[$pos]) === true) { 507 $realName = $realParams[$pos]['name']; 508 if ($realName !== $param['var']) { 509 $code = 'ParamNameNoMatch'; 510 $data = array( 511 $param['var'], 512 $realName, 513 ); 514 515 $error = 'Doc comment for parameter %s does not match '; 516 if (strtolower($param['var']) === strtolower($realName)) { 517 $error .= 'case of '; 518 $code = 'ParamNameNoCaseMatch'; 519 } 520 521 $error .= 'actual variable name %s'; 522 523 $phpcsFile->addError($error, $param['tag'], $code, $data); 524 } 525 } else if (substr($param['var'], -4) !== ',...') { 526 // We must have an extra parameter comment. 527 $error = 'Superfluous parameter comment'; 528 $phpcsFile->addError($error, $param['tag'], 'ExtraParamComment'); 529 }//end if 530 531 if ($param['comment'] === '') { 532 continue; 533 } 534 535 // Check number of spaces after the var name. 536 $this->checkSpacingAfterParamName($phpcsFile, $param, $maxVar); 537 538 // Param comments must start with a capital letter and end with the full stop. 539 if (preg_match('/^(\p{Ll}|\P{L})/u', $param['comment']) === 1) { 540 $error = 'Parameter comment must start with a capital letter'; 541 $phpcsFile->addError($error, $param['tag'], 'ParamCommentNotCapital'); 542 } 543 544 $lastChar = substr($param['comment'], -1); 545 if ($lastChar !== '.') { 546 $error = 'Parameter comment must end with a full stop'; 547 $phpcsFile->addError($error, $param['tag'], 'ParamCommentFullStop'); 548 } 549 }//end foreach 550 551 $realNames = array(); 552 foreach ($realParams as $realParam) { 553 $realNames[] = $realParam['name']; 554 } 555 556 // Report missing comments. 557 $diff = array_diff($realNames, $foundParams); 558 foreach ($diff as $neededParam) { 559 $error = 'Doc comment for parameter "%s" missing'; 560 $data = array($neededParam); 561 $phpcsFile->addError($error, $commentStart, 'MissingParamTag', $data); 562 } 563 564 }//end processParams() 565 566 567 /** 568 * Check the spacing after the type of a parameter. 569 * 570 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. 571 * @param array $param The parameter to be checked. 572 * @param int $maxType The maxlength of the longest parameter type. 573 * @param int $spacing The number of spaces to add after the type. 574 * 575 * @return void 576 */ 577 protected function checkSpacingAfterParamType(PHP_CodeSniffer_File $phpcsFile, $param, $maxType, $spacing = 1) 578 { 579 // Check number of spaces after the type. 580 $spaces = ($maxType - strlen($param['type']) + $spacing); 581 if ($param['type_space'] !== $spaces) { 582 $error = 'Expected %s spaces after parameter type; %s found'; 583 $data = array( 584 $spaces, 585 $param['type_space'], 586 ); 587 588 $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamType', $data); 589 if ($fix === true) { 590 $phpcsFile->fixer->beginChangeset(); 591 592 $content = $param['type']; 593 $content .= str_repeat(' ', $spaces); 594 $content .= $param['var']; 595 $content .= str_repeat(' ', $param['var_space']); 596 $content .= $param['commentLines'][0]['comment']; 597 $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); 598 599 // Fix up the indent of additional comment lines. 600 foreach ($param['commentLines'] as $lineNum => $line) { 601 if ($lineNum === 0 602 || $param['commentLines'][$lineNum]['indent'] === 0 603 ) { 604 continue; 605 } 606 607 $diff = ($param['type_space'] - $spaces); 608 $newIndent = ($param['commentLines'][$lineNum]['indent'] - $diff); 609 $phpcsFile->fixer->replaceToken( 610 ($param['commentLines'][$lineNum]['token'] - 1), 611 str_repeat(' ', $newIndent) 612 ); 613 } 614 615 $phpcsFile->fixer->endChangeset(); 616 }//end if 617 }//end if 618 619 }//end checkSpacingAfterParamType() 620 621 622 /** 623 * Check the spacing after the name of a parameter. 624 * 625 * @param PHP_CodeSniffer_File $phpcsFile The file being scanned. 626 * @param array $param The parameter to be checked. 627 * @param int $maxVar The maxlength of the longest parameter name. 628 * @param int $spacing The number of spaces to add after the type. 629 * 630 * @return void 631 */ 632 protected function checkSpacingAfterParamName(PHP_CodeSniffer_File $phpcsFile, $param, $maxVar, $spacing = 1) 633 { 634 // Check number of spaces after the var name. 635 $spaces = ($maxVar - strlen($param['var']) + $spacing); 636 if ($param['var_space'] !== $spaces) { 637 $error = 'Expected %s spaces after parameter name; %s found'; 638 $data = array( 639 $spaces, 640 $param['var_space'], 641 ); 642 643 $fix = $phpcsFile->addFixableError($error, $param['tag'], 'SpacingAfterParamName', $data); 644 if ($fix === true) { 645 $phpcsFile->fixer->beginChangeset(); 646 647 $content = $param['type']; 648 $content .= str_repeat(' ', $param['type_space']); 649 $content .= $param['var']; 650 $content .= str_repeat(' ', $spaces); 651 $content .= $param['commentLines'][0]['comment']; 652 $phpcsFile->fixer->replaceToken(($param['tag'] + 2), $content); 653 654 // Fix up the indent of additional comment lines. 655 foreach ($param['commentLines'] as $lineNum => $line) { 656 if ($lineNum === 0 657 || $param['commentLines'][$lineNum]['indent'] === 0 658 ) { 659 continue; 660 } 661 662 $diff = ($param['var_space'] - $spaces); 663 $newIndent = ($param['commentLines'][$lineNum]['indent'] - $diff); 664 $phpcsFile->fixer->replaceToken( 665 ($param['commentLines'][$lineNum]['token'] - 1), 666 str_repeat(' ', $newIndent) 667 ); 668 } 669 670 $phpcsFile->fixer->endChangeset(); 671 }//end if 672 }//end if 673 674 }//end checkSpacingAfterParamName() 675 676 677}//end class 678