From f5f4b00998abc24af898373dda73861b047e6a19 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?David=20N=C3=A9grier?= Date: Fri, 22 Sep 2017 12:00:54 +0200 Subject: [PATCH] Adding difference in detection between mixed[] and array --- .../TypeHints/AbstractMissingTypeHintRule.php | 30 ++++++++++++++++--- .../MissingTypeHintRuleInFunctionTest.php | 8 +++++ tests/Rules/TypeHints/data/typehints.php | 18 +++++++++++ 3 files changed, 52 insertions(+), 4 deletions(-) diff --git a/src/Rules/TypeHints/AbstractMissingTypeHintRule.php b/src/Rules/TypeHints/AbstractMissingTypeHintRule.php index 6f3dd48..03a89ac 100644 --- a/src/Rules/TypeHints/AbstractMissingTypeHintRule.php +++ b/src/Rules/TypeHints/AbstractMissingTypeHintRule.php @@ -4,6 +4,7 @@ namespace TheCodingMachine\PHPStan\Rules\TypeHints; +use phpDocumentor\Reflection\DocBlockFactory; use phpDocumentor\Reflection\Type; use phpDocumentor\Reflection\Types\Array_; use phpDocumentor\Reflection\Types\Boolean; @@ -24,6 +25,8 @@ use Roave\BetterReflection\Reflection\ReflectionFunction; use Roave\BetterReflection\Reflection\ReflectionMethod; use Roave\BetterReflection\Reflection\ReflectionParameter; +use Roave\BetterReflection\TypesFinder\PhpDocumentor\NamespaceNodeToReflectionTypeContext; +use Roave\BetterReflection\TypesFinder\ResolveTypes; abstract class AbstractMissingTypeHintRule implements Rule { @@ -181,10 +184,12 @@ private function analyzeWithTypehint($context, Type $phpTypeHint, array $docBloc } if ($docblockTypehint->getValueType() instanceof Mixed_) { - if ($context instanceof ReflectionParameter) { - return sprintf('%s, parameter $%s type is "array". Please provide a more specific @param annotation. For instance: @param int[] $%s', $this->getContext($context), $context->getName(), $context->getName()); - } else { - return sprintf('%s, return type is "array". Please provide a more specific @return annotation. For instance: @return int[]', $this->getContext($context)); + if (!$this->findExplicitMixedArray($context)) { + if ($context instanceof ReflectionParameter) { + return sprintf('%s, parameter $%s type is "array". Please provide a more specific @param annotation in the docblock. For instance: @param int[] $%s. Use @param mixed[] $%s if this is really an array of mixed values.', $this->getContext($context), $context->getName(), $context->getName(), $context->getName()); + } else { + return sprintf('%s, return type is "array". Please provide a more specific @return annotation. For instance: @return int[]. Use @return mixed[] if this is really an array of mixed values.', $this->getContext($context)); + } } } } @@ -193,6 +198,23 @@ private function analyzeWithTypehint($context, Type $phpTypeHint, array $docBloc return null; } + /** + * @param ReflectionParameter|ReflectionMethod|ReflectionFunction $context + * @return bool + */ + private function findExplicitMixedArray($context) : bool + { + if ($context instanceof ReflectionParameter) { + $context = $context->getDeclaringFunction(); + } + + $docComment = $context->getDocComment(); + + // Very approximate solution: let's find in the whole docblock whether there is a mixed[] value or not. + // TODO: improve this to target precisely the parameter or return type. + return strpos($docComment, 'mixed[]') !== false; + } + /** * @param ReflectionParameter|ReflectionMethod|ReflectionFunction $context * @param Type[] $docBlockTypeHints diff --git a/tests/Rules/TypeHints/MissingTypeHintRuleInFunctionTest.php b/tests/Rules/TypeHints/MissingTypeHintRuleInFunctionTest.php index a116a3b..159d9bc 100644 --- a/tests/Rules/TypeHints/MissingTypeHintRuleInFunctionTest.php +++ b/tests/Rules/TypeHints/MissingTypeHintRuleInFunctionTest.php @@ -64,6 +64,14 @@ public function testCheckCatchedException() [ 'In function "mismatch", return type is type-hinted to "string" but the @return annotation says it is a "int". Please fix the @return annotation.', 52, + ], + [ + 'In function "test8", parameter $any_array type is "array". Please provide a more specific @param annotation in the docblock. For instance: @param int[] $any_array. Use @param mixed[] $any_array if this is really an array of mixed values.', + 70, + ], + [ + 'In function "test8", return type is "array". Please provide a more specific @return annotation. For instance: @return int[]. Use @return mixed[] if this is really an array of mixed values.', + 70, ], ]); } diff --git a/tests/Rules/TypeHints/data/typehints.php b/tests/Rules/TypeHints/data/typehints.php index 7160e4b..093165f 100644 --- a/tests/Rules/TypeHints/data/typehints.php +++ b/tests/Rules/TypeHints/data/typehints.php @@ -53,3 +53,21 @@ function mismatch(?string $param): string { } + +/** + * @param mixed[] $any_array + * @return mixed[] + */ +function test7(array $any_array): array +{ + +} + +/** + * @param array $any_array + * @return array + */ +function test8(array $any_array): array +{ + +} \ No newline at end of file