From 5d7912b9631144566aa32b84a1f60cb5570b633b Mon Sep 17 00:00:00 2001 From: Mark Scherer Date: Wed, 14 Feb 2024 14:42:38 +0100 Subject: [PATCH] Allow support for more complex array annotations (#344) * Test that all different array annotations work. * Adding more complex type * Fix up template variable parsing. * Fix tests. * Fix tests. --- src/Annotator/AbstractAnnotator.php | 7 ++++- .../Annotator/TemplateAnnotatorTest.php | 27 +++++++++++++++++++ tests/test_app/templates/Foos/array.php | 22 +++++++++++++++ tests/test_files/templates/array.php | 23 ++++++++++++++++ 4 files changed, 78 insertions(+), 1 deletion(-) create mode 100644 tests/test_app/templates/Foos/array.php create mode 100644 tests/test_files/templates/array.php diff --git a/src/Annotator/AbstractAnnotator.php b/src/Annotator/AbstractAnnotator.php index 95ff0d9b..8e50efcc 100644 --- a/src/Annotator/AbstractAnnotator.php +++ b/src/Annotator/AbstractAnnotator.php @@ -487,7 +487,12 @@ protected function parseExistingAnnotations(File $file, int $closeTagIndex, arra $typeString = $this->renderUnionTypes($returnTypes); $tag = $tokens[$i]['content']; - $content = mb_substr($content, mb_strlen($typeString) + 1); + $variablePos = strpos($content, ' $'); + if ($tag === VariableAnnotation::TAG && $variablePos) { + $content = mb_substr($content, $variablePos + 1); + } else { + $content = mb_substr($content, mb_strlen($typeString) + 1); + } $annotation = AnnotationFactory::createOrFail($tag, $typeString, $content, $classNameIndex); if ($this->getConfig(static::CONFIG_REMOVE) && $tag === VariableAnnotation::TAG && $this->varInUse($tokens, $closeTagIndex, $content)) { diff --git a/tests/TestCase/Annotator/TemplateAnnotatorTest.php b/tests/TestCase/Annotator/TemplateAnnotatorTest.php index 336e9aef..f7e9272c 100644 --- a/tests/TestCase/Annotator/TemplateAnnotatorTest.php +++ b/tests/TestCase/Annotator/TemplateAnnotatorTest.php @@ -411,6 +411,33 @@ public function testAnnotateWithFollowingInline() { $this->assertTextContains(' -> 1 annotation added.', $output); } + /** + * Tests that a docblock with arrays in different types, e.g. shape. + * + * @return void + */ + public function testAnnotateWithShapedArray() { + $annotator = $this->_getAnnotatorMock([]); + + $expectedContent = str_replace("\r\n", "\n", file_get_contents(TEST_FILES . 'templates/array.php')); + $callback = function($value) use ($expectedContent) { + $value = str_replace(["\r\n", "\r"], "\n", $value); + if ($value !== $expectedContent) { + $this->_displayDiff($expectedContent, $value); + } + + return $value === $expectedContent; + }; + $annotator->expects($this->once())->method('storeFile')->with($this->anything(), $this->callback($callback)); + + $path = TEST_ROOT . 'templates/Foos/array.php'; + $annotator->annotate($path); + + $output = $this->out->output(); + + $this->assertTextContains(' -> 1 annotation added.', $output); + } + /** * @param array $params * @return \IdeHelper\Annotator\TemplateAnnotator|\PHPUnit\Framework\MockObject\MockObject diff --git a/tests/test_app/templates/Foos/array.php b/tests/test_app/templates/Foos/array.php new file mode 100644 index 00000000..27decc7a --- /dev/null +++ b/tests/test_app/templates/Foos/array.php @@ -0,0 +1,22 @@ + $ints + * @var array{a: int, b: string|null}|null $shaped + */ + foreach ($x as $y) { + echo $y; + } + foreach ($foo as $int) { + echo $int; + } +?> +
+ + +
diff --git a/tests/test_files/templates/array.php b/tests/test_files/templates/array.php new file mode 100644 index 00000000..3e739997 --- /dev/null +++ b/tests/test_files/templates/array.php @@ -0,0 +1,23 @@ + $ints + * @var array{a: int, b: string|null}|null $shaped + * @var mixed $foo + */ + foreach ($x as $y) { + echo $y; + } + foreach ($foo as $int) { + echo $int; + } +?> +
+ + +