typeFactory = $typeFactory; $this->reflectionResolver = $reflectionResolver; $this->classMethodReturnTypeOverrideGuard = $classMethodReturnTypeOverrideGuard; $this->betterNodeFinder = $betterNodeFinder; $this->staticTypeMapper = $staticTypeMapper; } public function getRuleDefinition() : RuleDefinition { return new RuleDefinition('Add return method return type based on strict typed property', [new CodeSample(<<<'CODE_SAMPLE' final class SomeClass { private int $age = 100; public function getAge() { return $this->age; } } CODE_SAMPLE , <<<'CODE_SAMPLE' final class SomeClass { private int $age = 100; public function getAge(): int { return $this->age; } } CODE_SAMPLE )]); } /** * @return array> */ public function getNodeTypes() : array { return [ClassMethod::class]; } /** * @param ClassMethod $node */ public function refactorWithScope(Node $node, Scope $scope) : ?Node { if ($node->returnType !== null) { return null; } if ($this->classMethodReturnTypeOverrideGuard->shouldSkipClassMethod($node, $scope)) { return null; } $propertyTypes = $this->resolveReturnPropertyType($node); if ($propertyTypes === []) { return null; } // add type to return type $propertyType = $this->typeFactory->createMixedPassedOrUnionType($propertyTypes); if ($propertyType instanceof MixedType) { return null; } $propertyTypeNode = $this->staticTypeMapper->mapPHPStanTypeToPhpParserNode($propertyType, TypeKind::RETURN); if (!$propertyTypeNode instanceof Node) { return null; } $node->returnType = $propertyTypeNode; return $node; } public function provideMinPhpVersion() : int { return PhpVersionFeature::TYPED_PROPERTIES; } /** * @return Type[] */ private function resolveReturnPropertyType(ClassMethod $classMethod) : array { /** @var Return_[] $returns */ $returns = $this->betterNodeFinder->findInstancesOfInFunctionLikeScoped($classMethod, Return_::class); $propertyTypes = []; foreach ($returns as $return) { if (!$return->expr instanceof Expr) { return []; } if (!$return->expr instanceof PropertyFetch && !$return->expr instanceof StaticPropertyFetch) { return []; } $phpPropertyReflection = $this->reflectionResolver->resolvePropertyReflectionFromPropertyFetch($return->expr); if (!$phpPropertyReflection instanceof PhpPropertyReflection) { return []; } // all property must have type declaration if ($phpPropertyReflection->getNativeType() instanceof MixedType) { return []; } $propertyTypes[] = $this->nodeTypeResolver->getNativeType($return->expr); } return $propertyTypes; } }