Skip to content

Commit

Permalink
Unified deciding type based on reflection and phpDoc
Browse files Browse the repository at this point in the history
  • Loading branch information
ondrejmirtes committed Nov 12, 2016
1 parent e32a958 commit f649596
Show file tree
Hide file tree
Showing 5 changed files with 46 additions and 78 deletions.
34 changes: 5 additions & 29 deletions src/Reflection/Php/PhpMethodReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,7 @@
use PHPStan\Parser\Parser;
use PHPStan\Reflection\ClassReflection;
use PHPStan\Reflection\MethodReflection;
use PHPStan\Type\ArrayType;
use PHPStan\Type\IntegerType;
use PHPStan\Type\MixedType;
use PHPStan\Type\StringType;
use PHPStan\Type\Type;
use PHPStan\Type\TypehintHelper;
Expand Down Expand Up @@ -179,33 +177,11 @@ public function isPublic(): bool
public function getReturnType(): Type
{
if ($this->returnType === null) {
$phpTypeReflection = $this->reflection->getReturnType();
if ($phpTypeReflection === null) {
if ($this->phpDocReturnType !== null) {
$this->returnType = $this->phpDocReturnType;
} else {
$this->returnType = new MixedType(true);
}
} else {
$returnType = TypehintHelper::getTypeObjectFromTypehint(
(string) $phpTypeReflection,
$phpTypeReflection->allowsNull(),
$this->declaringClass->getName()
);
if ($this->phpDocReturnType !== null) {
if ($returnType instanceof ArrayType && $this->phpDocReturnType instanceof ArrayType) {
$returnType = new ArrayType(
$this->phpDocReturnType->getItemType(),
$returnType->isNullable() || $this->phpDocReturnType->isNullable()
);
}
if ($returnType->accepts($this->phpDocReturnType)) {
return $this->phpDocReturnType;
}
}

$this->returnType = $returnType;
}
$this->returnType = TypehintHelper::decideType(
$this->reflection->getReturnType(),
$this->phpDocReturnType,
$this->declaringClass->getName()
);
}

return $this->returnType;
Expand Down
54 changes: 8 additions & 46 deletions src/Reflection/Php/PhpParameterReflection.php
Original file line number Diff line number Diff line change
Expand Up @@ -3,8 +3,6 @@
namespace PHPStan\Reflection\Php;

use PHPStan\Reflection\ParameterReflection;
use PHPStan\Type\ArrayType;
use PHPStan\Type\MixedType;
use PHPStan\Type\Type;
use PHPStan\Type\TypehintHelper;

Expand Down Expand Up @@ -39,51 +37,15 @@ public function getName(): string
public function getType(): Type
{
if ($this->type === null) {
$phpTypeReflection = $this->reflection->getType();
if ($phpTypeReflection === null) {
if ($this->phpDocType !== null) {
$type = $this->phpDocType;
if ($this->reflection->isDefaultValueAvailable() && $this->reflection->getDefaultValue() === null) {
$type = $type->makeNullable();
}

$this->type = $type;
} else {
$this->type = new MixedType(true);
}
} else {
$typehintType = TypehintHelper::getTypeObjectFromTypehint(
(string) $phpTypeReflection,
$phpTypeReflection->allowsNull(),
$this->reflection->getDeclaringClass() !== null ? $this->reflection->getDeclaringClass()->getName() : null
);
if ($this->phpDocType !== null) {
$phpDocType = $this->phpDocType;
if ($this->reflection->isDefaultValueAvailable() && $this->reflection->getDefaultValue() === null) {
$phpDocType = $phpDocType->makeNullable();
}

if (
$typehintType->getClass() !== null
&& $phpDocType->getClass() !== $typehintType->getClass()
&& $this->phpDocType->getClass() !== null
) {
$phpDocTypeClassReflection = new \ReflectionClass($phpDocType->getClass());
if ($phpDocTypeClassReflection->isSubclassOf($typehintType->getClass())) {
return $this->type = $phpDocType;
} else {
return new MixedType($typehintType->isNullable() || $phpDocType->isNullable());
}
} elseif (
$typehintType instanceof ArrayType
&& $phpDocType instanceof ArrayType
) {
return $this->type = $phpDocType;
}
}

return $this->type = $typehintType;
$phpDocType = $this->phpDocType;
if ($phpDocType !== null && $this->reflection->isDefaultValueAvailable() && $this->reflection->getDefaultValue() === null) {
$phpDocType = $phpDocType->makeNullable();
}
$this->type = TypehintHelper::decideType(
$this->reflection->getType(),
$phpDocType,
$this->reflection->getDeclaringClass() !== null ? $this->reflection->getDeclaringClass()->getName() : null
);
}

return $this->type;
Expand Down
2 changes: 1 addition & 1 deletion src/Type/FileTypeMapper.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function __construct(

public function getTypeMap(string $fileName): array
{
$cacheKey = sprintf('%s-%d-v4', $fileName, filemtime($fileName));
$cacheKey = sprintf('%s-%d-v5', $fileName, filemtime($fileName));
$cachedResult = $this->cache->load($cacheKey);
if ($cachedResult === null) {
$typeMap = $this->createTypeMap($fileName);
Expand Down
30 changes: 30 additions & 0 deletions src/Type/TypehintHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -58,4 +58,34 @@ public static function getTypeObjectFromTypehint(
}
}

public static function decideType(
\ReflectionType $reflectionType = null,
Type $phpDocType = null,
string $selfClass = null
): Type
{
if ($reflectionType === null) {
return $phpDocType !== null ? $phpDocType : new MixedType(true);
}

$type = self::getTypeObjectFromTypehint(
(string) $reflectionType,
$reflectionType->allowsNull(),
$selfClass
);
if ($phpDocType !== null) {
if ($type instanceof ArrayType && $phpDocType instanceof ArrayType) {
$type = new ArrayType(
$phpDocType->getItemType(),
$type->isNullable() || $phpDocType->isNullable()
);
}
if ($type->accepts($phpDocType)) {
return $phpDocType;
}
}

return $type;
}

}
4 changes: 2 additions & 2 deletions tests/PHPStan/Analyser/NodeScopeResolverTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1369,9 +1369,9 @@ public function dataTypeFromMethodPhpDocs(): array
'$barObject->doBar()',
],
[
MixedType::class,
ObjectType::class,
false,
null,
'MethodPhpDocsNamespace\Bar',
'$conflictedObject',
],
[
Expand Down

0 comments on commit f649596

Please sign in to comment.