Skip to content

Commit

Permalink
bug: PhpdocAlignFixer - fix static @method (#6366)
Browse files Browse the repository at this point in the history
  • Loading branch information
HypeMC authored Aug 13, 2022
1 parent 304ee4d commit 3b471b4
Show file tree
Hide file tree
Showing 2 changed files with 170 additions and 3 deletions.
41 changes: 38 additions & 3 deletions src/Fixer/Phpdoc/PhpdocAlignFixer.php
Original file line number Diff line number Diff line change
Expand Up @@ -113,7 +113,7 @@ public function configure(array $configuration): void

// e.g. @method <hint> <signature>
if ([] !== $tagsWithMethodSignatureToAlign) {
$types[] = '(?P<tag3>'.implode('|', $tagsWithMethodSignatureToAlign).')(\s+(?P<hint3>[^\s(]+)|)\s+(?P<signature>.+\))';
$types[] = '(?P<tag3>'.implode('|', $tagsWithMethodSignatureToAlign).')(\s+(?P<static>static))?(\s+(?P<hint3>[^\s(]+)|)\s+(?P<signature>.+\))';
}

// optional <desc>
Expand Down Expand Up @@ -255,6 +255,7 @@ private function fixDocBlock(DocBlock $docBlock): void
}

// compute the max length of the tag, hint and variables
$hasStatic = false;
$tagMax = 0;
$hintMax = 0;
$varMax = 0;
Expand All @@ -264,6 +265,7 @@ private function fixDocBlock(DocBlock $docBlock): void
continue;
}

$hasStatic = $hasStatic || $item['static'];
$tagMax = max($tagMax, \strlen($item['tag']));
$hintMax = max($hintMax, \strlen($item['hint']));
$varMax = max($varMax, \strlen($item['var']));
Expand All @@ -286,6 +288,10 @@ private function fixDocBlock(DocBlock $docBlock): void
$extraIndent = 3;
}

if ($hasStatic) {
$extraIndent += 7; // \strlen('static ');
}

$line =
$item['indent']
.' * '
Expand All @@ -307,8 +313,24 @@ private function fixDocBlock(DocBlock $docBlock): void
$item['indent']
.' * @'
.$item['tag']
.$this->getIndent(
$tagMax - \strlen($item['tag']) + 1,
;

if ($hasStatic) {
$line .=
$this->getIndent(
$tagMax - \strlen($item['tag']) + 1,
$item['static'] ? 1 : 0
)
.($item['static'] ?: $this->getIndent(6 /* \strlen('static') */, 0))
;
$hintVerticalAlignIndent = 1;
} else {
$hintVerticalAlignIndent = $tagMax - \strlen($item['tag']) + 1;
}

$line .=
$this->getIndent(
$hintVerticalAlignIndent,
$item['hint'] ? 1 : 0
)
.$item['hint']
Expand Down Expand Up @@ -351,19 +373,31 @@ private function getMatches(string $line, bool $matchCommentOnly = false): ?arra
$matches['tag'] = $matches['tag3'];
$matches['hint'] = $matches['hint3'];
$matches['var'] = $matches['signature'];

// Since static can be both a return type declaration & a keyword that defines static methods
// we assume it's a type declaration when only one value is present
if ('' === $matches['hint'] && '' !== $matches['static']) {
$matches['hint'] = $matches['static'];
$matches['static'] = '';
}
}

if (isset($matches['hint'])) {
$matches['hint'] = trim($matches['hint']);
}

if (!isset($matches['static'])) {
$matches['static'] = '';
}

return $matches;
}

if ($matchCommentOnly && Preg::match($this->regexCommentLine, $line, $matches)) {
$matches['tag'] = null;
$matches['var'] = '';
$matches['hint'] = '';
$matches['static'] = '';

return $matches;
}
Expand Down Expand Up @@ -403,6 +437,7 @@ private function getLeftAlignedDescriptionIndent(array $items, int $index): int

// Indent according to existing values:
return
$this->getSentenceIndent($item['static']) +
$this->getSentenceIndent($item['tag']) +
$this->getSentenceIndent($item['hint']) +
$this->getSentenceIndent($item['var']);
Expand Down
132 changes: 132 additions & 0 deletions tests/Fixer/Phpdoc/PhpdocAlignFixerTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1103,6 +1103,138 @@ public function testAlignsMethodsWithoutReturnType(): void
$this->doTest($expected, $input);
}

public function testAlignsStaticAndNonStaticMethods(): void
{
$this->fixer->configure(['tags' => ['method', 'property']]);

$expected = <<<'EOF'
<?php
/**
* @property string $foo Desc1
* @property int $bar Desc2
* @method foo(string $foo) DescriptionFoo
* @method static bar(string $foo) DescriptionBar
* @method string|null baz(bool $baz) DescriptionBaz
* @method static int|false qux(float $qux) DescriptionQux
* @method static static quux(int $quux) DescriptionQuux
* @method static $this quuz(bool $quuz) DescriptionQuuz
*/
EOF;

$input = <<<'EOF'
<?php
/**
* @property string $foo Desc1
* @property int $bar Desc2
* @method foo(string $foo) DescriptionFoo
* @method static bar(string $foo) DescriptionBar
* @method string|null baz(bool $baz) DescriptionBaz
* @method static int|false qux(float $qux) DescriptionQux
* @method static static quux(int $quux) DescriptionQuux
* @method static $this quuz(bool $quuz) DescriptionQuuz
*/
EOF;

$this->doTest($expected, $input);
}

public function testAlignsStaticAndNonStaticMethodsLeftAlign(): void
{
$this->fixer->configure(['tags' => ['method', 'property'], 'align' => PhpdocAlignFixer::ALIGN_LEFT]);

$expected = <<<'EOF'
<?php
/**
* @property string $foo Desc1
* @property int $bar Desc2
* @method foo(string $foo) DescriptionFoo
* @method static bar(string $foo) DescriptionBar
* @method string|null baz(bool $baz) DescriptionBaz
* @method static int|false qux(float $qux) DescriptionQux
* @method static static quux(int $quux) DescriptionQuux
* @method static $this quuz(bool $quuz) DescriptionQuuz
*/
EOF;

$input = <<<'EOF'
<?php
/**
* @property string $foo Desc1
* @property int $bar Desc2
* @method foo(string $foo) DescriptionFoo
* @method static bar(string $foo) DescriptionBar
* @method string|null baz(bool $baz) DescriptionBaz
* @method static int|false qux(float $qux) DescriptionQux
* @method static static quux(int $quux) DescriptionQuux
* @method static $this quuz(bool $quuz) DescriptionQuuz
*/
EOF;

$this->doTest($expected, $input);
}

public function testAlignsReturnStatic(): void
{
$this->fixer->configure(['tags' => ['param', 'return', 'throws']]);

$expected = <<<'EOF'
<?php
/**
* @param string $foobar Desc1
* @param int &$baz Desc2
* @param ?Qux $qux Desc3
* @param int|float $quux Desc4
* @return static DescriptionReturn
* @throws Exception DescriptionException
*/
EOF;

$input = <<<'EOF'
<?php
/**
* @param string $foobar Desc1
* @param int &$baz Desc2
* @param ?Qux $qux Desc3
* @param int|float $quux Desc4
* @return static DescriptionReturn
* @throws Exception DescriptionException
*/
EOF;

$this->doTest($expected, $input);
}

public function testAlignsReturnStaticLeftAlign(): void
{
$this->fixer->configure(['tags' => ['param', 'return', 'throws'], 'align' => PhpdocAlignFixer::ALIGN_LEFT]);

$expected = <<<'EOF'
<?php
/**
* @param string $foobar Desc1
* @param int &$baz Desc2
* @param ?Qux $qux Desc3
* @param int|float $quux Desc4
* @return static DescriptionReturn
* @throws Exception DescriptionException
*/
EOF;

$input = <<<'EOF'
<?php
/**
* @param string $foobar Desc1
* @param int &$baz Desc2
* @param ?Qux $qux Desc3
* @param int|float $quux Desc4
* @return static DescriptionReturn
* @throws Exception DescriptionException
*/
EOF;

$this->doTest($expected, $input);
}

public function testDoesNotAlignWithEmptyConfig(): void
{
$this->fixer->configure(['tags' => []]);
Expand Down

0 comments on commit 3b471b4

Please sign in to comment.