Process the function parameter comments.
246 if ($this->phpVersion ===
null) {
247 $this->phpVersion = Config::getConfigData(
'php_version');
248 if ($this->phpVersion ===
null) {
249 $this->phpVersion = PHP_VERSION_ID;
253 $tokens = $phpcsFile->getTokens();
258 foreach (
$tokens[$commentStart][
'comment_tags'] as
$pos => $tag) {
259 if (
$tokens[$tag][
'content'] !==
'@param') {
268 $commentLines = array();
269 if (
$tokens[($tag + 2)][
'code'] === T_DOC_COMMENT_STRING) {
271 preg_match(
'/([^$&.]+)(?:((?:\.\.\.)?(?:\$|&)[^\s]+)(?:(\s+)(.*))?)?/',
$tokens[($tag + 2)][
'content'], $matches);
273 if (empty($matches) ===
false) {
274 $typeLen = strlen($matches[1]);
275 $type = trim($matches[1]);
276 $typeSpace = ($typeLen - strlen(
$type));
277 $typeLen = strlen(
$type);
278 if ($typeLen > $maxType) {
283 if (isset($matches[2]) ===
true) {
285 $varLen = strlen($var);
286 if ($varLen > $maxVar) {
290 if (isset($matches[4]) ===
true) {
291 $varSpace = strlen($matches[3]);
292 $comment = $matches[4];
293 $commentLines[] = array(
294 'comment' => $comment,
295 'token' => ($tag + 2),
296 'indent' => $varSpace,
300 if (isset(
$tokens[$commentStart][
'comment_tags'][(
$pos + 1)]) ===
true) {
301 $end =
$tokens[$commentStart][
'comment_tags'][(
$pos + 1)];
303 $end =
$tokens[$commentStart][
'comment_closer'];
306 for (
$i = ($tag + 3);
$i < $end;
$i++) {
307 if (
$tokens[
$i][
'code'] === T_DOC_COMMENT_STRING) {
309 if (
$tokens[(
$i - 1)][
'code'] === T_DOC_COMMENT_WHITESPACE) {
310 $indent = strlen(
$tokens[(
$i - 1)][
'content']);
313 $comment .=
' '.$tokens[
$i][
'content'];
314 $commentLines[] = array(
322 $error =
'Missing parameter comment';
324 $commentLines[] = array(
'comment' =>
'');
327 $error =
'Missing parameter name';
328 $phpcsFile->addError($error, $tag,
'MissingParamName');
331 $error =
'Missing parameter type';
332 $phpcsFile->addError($error, $tag,
'MissingParamType');
339 'comment' => $comment,
340 'commentLines' => $commentLines,
341 'type_space' => $typeSpace,
342 'var_space' => $varSpace,
346 $realParams = $phpcsFile->getMethodParameters($stackPtr);
347 $foundParams = array();
351 foreach ($realParams as
$pos => $param) {
352 if ($param[
'variable_length'] ===
true) {
353 $realParams[
$pos][
'name'] =
'...'.$realParams[
$pos][
'name'];
359 if ($param[
'type'] ===
'') {
364 $typeNames = explode(
'|', $param[
'type']);
365 $suggestedTypeNames = array();
367 foreach ($typeNames as $typeName) {
368 $suggestedName = Common::suggestType($typeName);
369 $suggestedTypeNames[] = $suggestedName;
371 if (count($typeNames) > 1) {
376 $suggestedTypeHint =
'';
377 if (strpos($suggestedName,
'array') !==
false || substr($suggestedName, -2) ===
'[]') {
378 $suggestedTypeHint =
'array';
379 }
else if (strpos($suggestedName,
'callable') !==
false) {
380 $suggestedTypeHint =
'callable';
381 }
else if (strpos($suggestedName,
'callback') !==
false) {
382 $suggestedTypeHint =
'callable';
383 }
else if (in_array($suggestedName, Common::$allowedTypes) ===
false) {
384 $suggestedTypeHint = $suggestedName;
387 if ($this->phpVersion >= 70000) {
388 if ($suggestedName ===
'string') {
389 $suggestedTypeHint =
'string';
390 }
else if ($suggestedName ===
'int' || $suggestedName ===
'integer') {
391 $suggestedTypeHint =
'int';
392 }
else if ($suggestedName ===
'float') {
393 $suggestedTypeHint =
'float';
394 }
else if ($suggestedName ===
'bool' || $suggestedName ===
'boolean') {
395 $suggestedTypeHint =
'bool';
399 if ($suggestedTypeHint !==
'' && isset($realParams[
$pos]) ===
true) {
400 $typeHint = $realParams[
$pos][
'type_hint'];
401 if ($typeHint ===
'') {
402 $error =
'Type hint "%s" missing for %s';
408 $errorCode =
'TypeHintMissing';
409 if ($suggestedTypeHint ===
'string' 410 || $suggestedTypeHint ===
'int' 411 || $suggestedTypeHint ===
'float' 412 || $suggestedTypeHint ===
'bool' 414 $errorCode =
'Scalar'.$errorCode;
418 }
else if ($typeHint !== substr($suggestedTypeHint, (strlen($typeHint) * -1))) {
419 $error =
'Expected type hint "%s"; found "%s" for %s';
425 $phpcsFile->addError($error, $stackPtr,
'IncorrectTypeHint',
$data);
427 }
else if ($suggestedTypeHint ===
'' && isset($realParams[
$pos]) ===
true) {
428 $typeHint = $realParams[
$pos][
'type_hint'];
429 if ($typeHint !==
'') {
430 $error =
'Unknown type hint "%s" found for %s';
435 $phpcsFile->addError($error, $stackPtr,
'InvalidTypeHint',
$data);
440 $suggestedType = implode($suggestedTypeNames,
'|');
441 if ($param[
'type'] !== $suggestedType) {
442 $error =
'Expected "%s" but found "%s" for parameter type';
448 $fix = $phpcsFile->addFixableError($error, $param[
'tag'],
'IncorrectParamVarName',
$data);
450 $phpcsFile->fixer->beginChangeset();
453 $content .= str_repeat(
' ', $param[
'type_space']);
455 $content .= str_repeat(
' ', $param[
'var_space']);
456 if (isset($param[
'commentLines'][0]) ===
true) {
457 $content .= $param[
'commentLines'][0][
'comment'];
460 $phpcsFile->fixer->replaceToken(($param[
'tag'] + 2),
$content);
463 foreach ($param[
'commentLines'] as $lineNum => $line) {
465 || $param[
'commentLines'][$lineNum][
'indent'] === 0
470 $diff = (strlen($param[
'type']) - strlen($suggestedType));
471 $newIndent = ($param[
'commentLines'][$lineNum][
'indent'] - $diff);
472 $phpcsFile->fixer->replaceToken(
473 ($param[
'commentLines'][$lineNum][
'token'] - 1),
474 str_repeat(
' ', $newIndent)
478 $phpcsFile->fixer->endChangeset();
482 if ($param[
'var'] ===
'') {
486 $foundParams[] = $param[
'var'];
492 if (isset($realParams[
$pos]) ===
true) {
493 $realName = $realParams[
$pos][
'name'];
494 if ($realName !== $param[
'var']) {
495 $code =
'ParamNameNoMatch';
501 $error =
'Doc comment for parameter %s does not match ';
502 if (strtolower($param[
'var']) === strtolower($realName)) {
503 $error .=
'case of ';
504 $code =
'ParamNameNoCaseMatch';
507 $error .=
'actual variable name %s';
509 $phpcsFile->addError($error, $param[
'tag'],
$code,
$data);
511 }
else if (substr($param[
'var'], -4) !==
',...') {
513 $error =
'Superfluous parameter comment';
514 $phpcsFile->addError($error, $param[
'tag'],
'ExtraParamComment');
517 if ($param[
'comment'] ===
'') {
525 if (preg_match(
'/^(\p{Ll}|\P{L})/u', $param[
'comment']) === 1) {
526 $error =
'Parameter comment must start with a capital letter';
527 $phpcsFile->addError($error, $param[
'tag'],
'ParamCommentNotCapital');
530 $lastChar = substr($param[
'comment'], -1);
531 if ($lastChar !==
'.') {
532 $error =
'Parameter comment must end with a full stop';
533 $phpcsFile->addError($error, $param[
'tag'],
'ParamCommentFullStop');
537 $realNames = array();
538 foreach ($realParams as $realParam) {
539 $realNames[] = $realParam[
'name'];
543 $diff = array_diff($realNames, $foundParams);
544 foreach ($diff as $neededParam) {
545 $error =
'Doc comment for parameter "%s" missing';
546 $data = array($neededParam);
$params[\Magento\Store\Model\StoreManager::PARAM_RUN_CODE]