phpDocInfoFactory = $phpDocInfoFactory; $this->staticTypeMapper = $staticTypeMapper; $this->phpDocTypeChanger = $phpDocTypeChanger; $this->varTagRemover = $varTagRemover; $this->phpDocInfoPrinter = $phpDocInfoPrinter; $this->docBlockUpdater = $docBlockUpdater; } public function mergePropertyAndParamDocBlocks(Property $property, Param $param, ?ParamTagValueNode $paramTagValueNode) : void { $paramComments = $param->getComments(); // already has @param tag → give it priority over @var and remove @var if ($paramTagValueNode instanceof ParamTagValueNode) { $propertyDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property); if ($propertyDocInfo->hasByType(VarTagValueNode::class)) { $propertyDocInfo->removeByType(VarTagValueNode::class); $propertyComments = $this->phpDocInfoPrinter->printToComments($propertyDocInfo); /** @var Comment[] $mergedComments */ $mergedComments = \array_merge($paramComments, $propertyComments); $mergedComments = $this->removeEmptyComments($mergedComments); $param->setAttribute(AttributeKey::COMMENTS, $mergedComments); } } $this->docBlockUpdater->updateRefactoredNodeWithPhpDocInfo($param); } public function decorateParamWithPropertyPhpDocInfo(ClassMethod $classMethod, Property $property, Param $param, string $paramName) : void { $propertyPhpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($property); $param->setAttribute(AttributeKey::PHP_DOC_INFO, $propertyPhpDocInfo); // make sure the docblock is useful if ($param->type === null) { $varTagValueNode = $propertyPhpDocInfo->getVarTagValueNode(); if (!$varTagValueNode instanceof VarTagValueNode) { return; } $paramType = $this->staticTypeMapper->mapPHPStanPhpDocTypeToPHPStanType($varTagValueNode, $property); $classMethodPhpDocInfo = $this->phpDocInfoFactory->createFromNodeOrEmpty($classMethod); $this->phpDocTypeChanger->changeParamType($classMethod, $classMethodPhpDocInfo, $paramType, $param, $paramName); } else { $paramType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($param->type); } $this->varTagRemover->removeVarPhpTagValueNodeIfNotComment($param, $paramType); } /** * @param Comment[] $mergedComments * @return Comment[] */ private function removeEmptyComments(array $mergedComments) : array { return \array_filter($mergedComments, static function (Comment $comment) : bool { return $comment->getText() !== ''; }); } }