Skip to content

Commit

Permalink
Add support for multiline annotations (#345)
Browse files Browse the repository at this point in the history
* Add support for multiline annotations

* Fix possibly wrong valueNode type

* Fix missing new line before break

---------

Co-authored-by: Adam Halfar <[email protected]>
  • Loading branch information
Harfusha and Adam Halfar authored Mar 5, 2024
1 parent 4d627ff commit 37887de
Show file tree
Hide file tree
Showing 4 changed files with 120 additions and 1 deletion.
24 changes: 23 additions & 1 deletion src/Annotator/AbstractAnnotator.php
Original file line number Diff line number Diff line change
Expand Up @@ -480,7 +480,29 @@ protected function parseExistingAnnotations(File $file, int $closeTagIndex, arra
/** @var \PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode|\PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode $valueNode */
$valueNode = static::getValueNode($tokens[$i]['content'], $content);
if ($valueNode instanceof InvalidTagValueNode) {
continue;
$multilineFixed = false;
for ($p = $i + 3; $p < $closeTagIndex; $p++) {
if ($tokens[$p]['type'] === 'T_DOC_COMMENT_TAG') {
break;
}

if ($tokens[$p]['type'] !== 'T_DOC_COMMENT_STRING') {
continue;
}

$content .= $tokens[$p]['content'];
/** @var \PHPStan\PhpDocParser\Ast\PhpDoc\InvalidTagValueNode|\PHPStan\PhpDocParser\Ast\PhpDoc\ReturnTagValueNode $valueNode */
$valueNode = static::getValueNode($tokens[$i]['content'], $content);
if (!($valueNode instanceof InvalidTagValueNode)) {
$multilineFixed = true;

break;
}
}

if (!$multilineFixed || $valueNode instanceof InvalidTagValueNode) {
continue;
}
}

$returnTypes = $this->valueNodeParts($valueNode);
Expand Down
27 changes: 27 additions & 0 deletions tests/TestCase/Annotator/TemplateAnnotatorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -438,6 +438,33 @@ public function testAnnotateWithShapedArray() {
$this->assertTextContains(' -> 1 annotation added.', $output);
}

/**
* Tests that a multiline array is parsed completly.
*
* @return void
*/
public function testAnnotateWithMultilineArray() {
$annotator = $this->_getAnnotatorMock([]);

$expectedContent = str_replace("\r\n", "\n", file_get_contents(TEST_FILES . 'templates/multiline.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/multiline.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
Expand Down
34 changes: 34 additions & 0 deletions tests/test_app/templates/Foos/multiline.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
<?php
/**
* @var \TestApp\View\AppView $this
* @var array $x
* @var array<int> $ints
* @var array{
* a: int,
* b: string|null
* }|null $shaped
* @var array{
* c: array{
* d: int|string,
* e: string|null
* }
* } $nested
*/
foreach ($x as $y) {
echo $y;
}
foreach ($foo as $int) {
echo $int;
}
?>
<div>
<?php foreach ($ints as $int) {
echo $int;
} ?>
<?php foreach ($shaped as $x) {
echo h($x);
} ?>
<?php foreach ($nested['c'] as $subArray) {
echo h($x);
} ?>
</div>
36 changes: 36 additions & 0 deletions tests/test_files/templates/multiline.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
<?php
/**
* @var \TestApp\View\AppView $this
* @var array $x
* @var array<int> $ints
* @var array{
* a: int,
* b: string|null
* }|null $shaped
* @var array{
* c: array{
* d: int|string,
* e: string|null
* }
* } $nested
*
* @var mixed $foo
*/
foreach ($x as $y) {
echo $y;
}
foreach ($foo as $int) {
echo $int;
}
?>
<div>
<?php foreach ($ints as $int) {
echo $int;
} ?>
<?php foreach ($shaped as $x) {
echo h($x);
} ?>
<?php foreach ($nested['c'] as $subArray) {
echo h($x);
} ?>
</div>

0 comments on commit 37887de

Please sign in to comment.