Skip to content

Commit

Permalink
Add Method attribute
Browse files Browse the repository at this point in the history
  • Loading branch information
carlos-granados committed Feb 19, 2024
1 parent 00b5edf commit 6d83ed9
Show file tree
Hide file tree
Showing 3 changed files with 85 additions and 14 deletions.
2 changes: 1 addition & 1 deletion composer.json
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@
"require": {
"php": ">=8.0",
"nikic/php-parser": "^4 || ^5",
"php-static-analysis/attributes": "^0.1.5 || dev-main"
"php-static-analysis/attributes": "^0.1.6 || dev-main"
},
"require-dev": {
"php-static-analysis/phpstan-extension": "dev-main",
Expand Down
44 changes: 31 additions & 13 deletions src/AttributeNodeVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@
use PhpParser\Node\Stmt;
use PhpParser\NodeVisitorAbstract;
use PhpStaticAnalysis\Attributes\IsReadOnly;
use PhpStaticAnalysis\Attributes\Method;
use PhpStaticAnalysis\Attributes\Param;
use PhpStaticAnalysis\Attributes\Property;
use PhpStaticAnalysis\Attributes\PropertyRead;
Expand All @@ -28,6 +29,7 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
private const ARGS_ONE = 'one';
private const ARGS_TWO_WITH_TYPE = 'two with type';
private const ARGS_MANY_WITH_NAME = "many with name";
private const ARGS_MANY_WITHOUT_NAME = "many without name";

private const ALLOWED_NODE_TYPES = [
Stmt\Class_::class,
Expand All @@ -41,6 +43,7 @@ class AttributeNodeVisitor extends NodeVisitorAbstract

private const ALLOWED_ATTRIBUTES_PER_NODE_TYPE = [
Stmt\Class_::class => [
Method::class,
Property::class,
PropertyRead::class,
PropertyWrite::class,
Expand All @@ -64,6 +67,7 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
Type::class,
],
Stmt\Interface_::class => [
Method::class,
Property::class,
PropertyRead::class,
PropertyWrite::class,
Expand All @@ -77,6 +81,7 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
Type::class,
],
Stmt\Trait_::class => [
Method::class,
Property::class,
PropertyRead::class,
PropertyWrite::class,
Expand All @@ -88,6 +93,7 @@ class AttributeNodeVisitor extends NodeVisitorAbstract

private const SHORT_NAME_TO_FQN = [
'IsReadOnly' => IsReadOnly::class,
'Method' => Method::class,
'Param' => Param::class,
'Property' => Property::class,
'PropertyRead' => PropertyRead::class,
Expand All @@ -101,11 +107,14 @@ class AttributeNodeVisitor extends NodeVisitorAbstract

private const ANNOTATION_PER_ATTRIBUTE = [
IsReadOnly::class => [
'all' => 'readonly',
],
'all' => 'readonly',
],
Method::class => [
'all' => 'method',
],
Param::class => [
'all' => 'param',
],
'all' => 'param',
],
Property::class => [
Stmt\Class_::class => 'property',
Stmt\Property::class => 'var',
Expand All @@ -117,29 +126,32 @@ class AttributeNodeVisitor extends NodeVisitorAbstract
'all' => 'property-write',
],
Returns::class => [
'all' => 'return',
],
'all' => 'return',
],
Template::class => [
'all' => 'template',
],
'all' => 'template',
],
TemplateContravariant::class => [
'all' => 'template-contravariant',
],
TemplateCovariant::class => [
'all' => 'template-covariant',
],
Type::class => [
Stmt\ClassConst::class => 'var',
Stmt\ClassMethod::class => 'return',
Stmt\Function_::class => 'return',
Stmt\Property::class => 'var',
],
Stmt\ClassConst::class => 'var',
Stmt\ClassMethod::class => 'return',
Stmt\Function_::class => 'return',
Stmt\Property::class => 'var',
],
];

private const ARGUMENTS_PER_ATTRIBUTE = [
IsReadOnly::class => [
'all' => self::ARGS_NONE,
],
Method::class => [
'all' => self::ARGS_MANY_WITHOUT_NAME,
],
Param::class => [
'all' => self::ARGS_MANY_WITH_NAME,
],
Expand Down Expand Up @@ -236,6 +248,12 @@ public function enterNode(Node $node)
$tagCreated = true;
}
break;
case self::ARGS_MANY_WITHOUT_NAME:
foreach ($args as $arg) {
$tagsToAdd[] = $this->createTag($nodeType, $attributeName, $arg, useName: false);
$tagCreated = true;
}
break;
}
if ($tagCreated) {
$this->updatePositions($attribute);
Expand Down
53 changes: 53 additions & 0 deletions tests/MethodAttributeNodeVisitorTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
<?php

namespace test\PhpStaticAnalysis\NodeVisitor;

use PhpParser\Node;
use PhpParser\Node\Attribute;
use PhpParser\Node\AttributeGroup;
use PhpParser\Node\Identifier;
use PhpParser\Node\Name\FullyQualified;
use PhpStaticAnalysis\Attributes\Method;

class MethodAttributeNodeVisitorTest extends AttributeNodeVisitorTestBase
{
public function testAddsMethodPHPDoc(): void
{
$node = new Node\Stmt\Class_('Test');
$this->addMethodAttributesToNode($node);
$this->nodeVisitor->enterNode($node);
$docText = $this->getDocText($node);
$this->assertEquals("/**\n * @method void setString(string \$text)\n */", $docText);
}

public function testAddsSeveralMethodPHPDocs(): void
{
$node = new Node\Stmt\Class_('Test');
$this->addMethodAttributesToNode($node, 2);
$this->nodeVisitor->enterNode($node);
$docText = $this->getDocText($node);
$this->assertEquals("/**\n * @method void setString(string \$text)\n * @method void setString(string \$text)\n */", $docText);
}

public function testAddsMultipleMethodPHPDocs(): void
{
$node = new Node\Stmt\Class_('Test');
$this->addMethodAttributesToNode($node);
$this->addMethodAttributesToNode($node);
$this->nodeVisitor->enterNode($node);
$docText = $this->getDocText($node);
$this->assertEquals("/**\n * @method void setString(string \$text)\n * @method void setString(string \$text)\n */", $docText);
}

private function addMethodAttributesToNode(Node\Stmt\Class_ $node, int $num = 1): void
{
$value = new Node\Scalar\String_('void setString(string $text)');
$args = [];
for ($i = 0; $i < $num; $i++) {
$args[] = new Node\Arg($value);
}
$attributeName = new FullyQualified(Method::class);
$attribute = new Attribute($attributeName, $args);
$node->attrGroups = array_merge($node->attrGroups, [new AttributeGroup([$attribute])]);
}
}

0 comments on commit 6d83ed9

Please sign in to comment.