From 14a69b1efc2c16bb8e82aa9793eb9d4c0146c571 Mon Sep 17 00:00:00 2001 From: Jaapio Date: Mon, 13 May 2024 21:51:06 +0200 Subject: [PATCH] Hack to work around parser issue --- .../Tags/Factory/AbstractPHPStanFactory.php | 1 - src/DocBlock/Tags/Factory/TokenIterator.php | 55 ++++++++++++++ .../integration/InterpretingDocBlocksTest.php | 71 ++++++++++++++++++- 3 files changed, 125 insertions(+), 2 deletions(-) create mode 100644 src/DocBlock/Tags/Factory/TokenIterator.php diff --git a/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php b/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php index 2c3b43f7..a7f5b87d 100644 --- a/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php +++ b/src/DocBlock/Tags/Factory/AbstractPHPStanFactory.php @@ -19,7 +19,6 @@ use PHPStan\PhpDocParser\Lexer\Lexer; use PHPStan\PhpDocParser\Parser\ConstExprParser; use PHPStan\PhpDocParser\Parser\PhpDocParser; -use PHPStan\PhpDocParser\Parser\TokenIterator; use PHPStan\PhpDocParser\Parser\TypeParser; use RuntimeException; diff --git a/src/DocBlock/Tags/Factory/TokenIterator.php b/src/DocBlock/Tags/Factory/TokenIterator.php new file mode 100644 index 00000000..48535007 --- /dev/null +++ b/src/DocBlock/Tags/Factory/TokenIterator.php @@ -0,0 +1,55 @@ +indexProperty = $r->getParentClass()->getProperty('index'); + $this->indexProperty->setAccessible(true); + $this->tokensProperty = $r->getParentClass()->getProperty('tokens'); + $this->tokensProperty->setAccessible(true); + } + + public function getSkippedHorizontalWhiteSpaceIfAny(): string + { + $index = $this->indexProperty->getValue($this); + $tokens = $this->tokensProperty->getValue($this); + + if ( + $index > 0 && ( + $tokens[$index - 1][Lexer::TYPE_OFFSET] === Lexer::TOKEN_HORIZONTAL_WS || + $tokens[$index - 1][Lexer::TYPE_OFFSET] === Lexer::TOKEN_PHPDOC_EOL) + ) { + return $tokens[$index - 1][Lexer::VALUE_OFFSET]; + } + + return ''; + } + } +} else { + class_alias(PhpStanTokenIterator::class, '\phpDocumentor\Reflection\DocBlock\Tags\Factory\TokenIterator'); +} diff --git a/tests/integration/InterpretingDocBlocksTest.php b/tests/integration/InterpretingDocBlocksTest.php index e9685e97..13eff38a 100644 --- a/tests/integration/InterpretingDocBlocksTest.php +++ b/tests/integration/InterpretingDocBlocksTest.php @@ -338,7 +338,8 @@ public function testRegressionWordpressDocblocks(): void false, new Description( '{' . "\n" . - 'Optional. Array or string of arguments for installing a package. Default empty array.' . "\n" . + "\n" . + ' Optional. Array or string of arguments for installing a package. Default empty array.' . "\n" . "\n" . ' @type string $source Required path to the package source. Default empty.' . "\n" . ' @type string $destination Required path to a folder to install the package in.' . "\n" . @@ -364,4 +365,72 @@ public function testRegressionWordpressDocblocks(): void $docblock ); } + + public function testIndentationIsKept(): void + { + $docComment = <<create($docComment); + + self::assertEquals( + new DocBlock( + 'Registers the script module if no script module with that script module +identifier has already been registered.', + new Description( + '' + ), + [ + new Since('6.5.0', new Description('')), + new Param( + 'deps', + new Array_(new Mixed_()), + false, + new Description("{ + + Optional. List of dependencies. + + @type string|array ...$0 { + An array of script module identifiers of the dependencies of this script + module. The dependencies can be strings or arrays. If they are arrays, + they need an `id` key with the script module identifier, and can contain + an `import` key with either `static` or `dynamic`. By default, + dependencies that don't contain an `import` key are considered static. + + @type string \$id The script module identifier. + @type string \$import Optional. Import type. May be either `static` or + `dynamic`. Defaults to `static`. + } +}" + ) + ), + ], + new Context('\\') + ), + $docblock + ); + } }