propertyNaming = $propertyNaming; $this->phpDocInfoFactory = $phpDocInfoFactory; $this->nodeNameResolver = $nodeNameResolver; $this->propertyManipulator = $propertyManipulator; $this->reflectionResolver = $reflectionResolver; $this->staticTypeMapper = $staticTypeMapper; } public function resolve(Property $property, ClassLike $classLike) : ?string { if (!$classLike instanceof Class_) { return null; } $classReflection = $this->reflectionResolver->resolveClassReflection($property); if (!$classReflection instanceof ClassReflection) { return null; } $propertyName = $this->nodeNameResolver->getName($property); if ($this->propertyManipulator->isUsedByTrait($classReflection, $propertyName)) { return null; } $expectedName = $this->resolveExpectedName($property); if (!$expectedName instanceof ExpectedName) { return null; } $propertyName = $this->nodeNameResolver->getName($property); // skip if already has suffix if (\substr_compare($propertyName, $expectedName->getName(), -\strlen($expectedName->getName())) === 0 || \substr_compare($propertyName, \ucfirst($expectedName->getName()), -\strlen(\ucfirst($expectedName->getName()))) === 0) { return null; } return $expectedName->getName(); } private function resolveExpectedName(Property $property) : ?ExpectedName { $phpDocInfo = $this->phpDocInfoFactory->createFromNode($property); $isPhpDocInfo = $phpDocInfo instanceof PhpDocInfo; // property type first if ($property->type instanceof Node) { $propertyType = $this->staticTypeMapper->mapPhpParserNodePHPStanType($property->type); // not has docblock, use property type if (!$isPhpDocInfo) { return $this->propertyNaming->getExpectedNameFromType($propertyType); } // @var type is ObjectType, use property type $varType = $phpDocInfo->getVarType(); if ($varType instanceof ObjectType) { return $this->propertyNaming->getExpectedNameFromType($propertyType); } } // fallback to docblock if ($isPhpDocInfo) { return $this->propertyNaming->getExpectedNameFromType($phpDocInfo->getVarType()); } return null; } }