Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

ExportedNodeResolver - Add support for attributes #1427

Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
85 changes: 85 additions & 0 deletions src/Dependency/ExportedNode/ExportedAttributeNode.php
@@ -0,0 +1,85 @@
<?php declare(strict_types = 1);

namespace PHPStan\Dependency\ExportedNode;

use JsonSerializable;
use PHPStan\Dependency\ExportedNode;
use ReturnTypeWillChange;
use function count;

class ExportedAttributeNode implements ExportedNode, JsonSerializable
{

/**
* @param array<int|string, string> $args argument name or index(string|int) => value expression (string)
*/
public function __construct(
private string $name,
private array $args,
)
{
}

public function equals(ExportedNode $node): bool
{
if (!$node instanceof self) {
return false;
}

if ($this->name !== $node->name) {
return false;
}

if (count($this->args) !== count($node->args)) {
return false;
}

foreach ($this->args as $argName => $argValue) {
if (!isset($node->args[$argName]) || $argValue !== $node->args[$argName]) {
return false;
}
}

return true;
}

/**
* @param mixed[] $properties
* @return self
*/
public static function __set_state(array $properties): ExportedNode
{
return new self(
$properties['name'],
$properties['args'],
);
}

/**
* @return mixed
*/
#[ReturnTypeWillChange]
public function jsonSerialize()
{
return [
'type' => self::class,
'data' => [
'name' => $this->name,
'args' => $this->args,
],
];
}

/**
* @param mixed[] $data
* @return self
*/
public static function decode(array $data): ExportedNode
{
return new self(
$data['name'],
$data['args'],
);
}

}
30 changes: 29 additions & 1 deletion src/Dependency/ExportedNode/ExportedClassConstantNode.php
Expand Up @@ -4,12 +4,22 @@

use JsonSerializable;
use PHPStan\Dependency\ExportedNode;
use PHPStan\ShouldNotHappenException;
use ReturnTypeWillChange;
use function array_map;
use function count;

class ExportedClassConstantNode implements ExportedNode, JsonSerializable
{

public function __construct(private string $name, private string $value)
/**
* @param ExportedAttributeNode[] $attributes
*/
public function __construct(
private string $name,
private string $value,
private array $attributes,
)
{
}

Expand All @@ -19,6 +29,16 @@ public function equals(ExportedNode $node): bool
return false;
}

if (count($this->attributes) !== count($node->attributes)) {
return false;
}

foreach ($this->attributes as $i => $attribute) {
if (!$attribute->equals($node->attributes[$i])) {
return false;
}
}

return $this->name === $node->name
&& $this->value === $node->value;
}
Expand All @@ -32,6 +52,7 @@ public static function __set_state(array $properties): ExportedNode
return new self(
$properties['name'],
$properties['value'],
$properties['attributes'],
);
}

Expand All @@ -44,6 +65,12 @@ public static function decode(array $data): ExportedNode
return new self(
$data['name'],
$data['value'],
array_map(static function (array $attributeData): ExportedAttributeNode {
if ($attributeData['type'] !== ExportedAttributeNode::class) {
throw new ShouldNotHappenException();
}
return ExportedAttributeNode::decode($attributeData['data']);
}, $data['attributes']),
);
}

Expand All @@ -58,6 +85,7 @@ public function jsonSerialize()
'data' => [
'name' => $this->name,
'value' => $this->value,
'attributes' => $this->attributes,
],
];
}
Expand Down
20 changes: 20 additions & 0 deletions src/Dependency/ExportedNode/ExportedClassNode.php
Expand Up @@ -17,6 +17,7 @@ class ExportedClassNode implements ExportedNode, JsonSerializable
* @param string[] $usedTraits
* @param ExportedTraitUseAdaptation[] $traitUseAdaptations
* @param ExportedNode[] $statements
* @param ExportedAttributeNode[] $attributes
*/
public function __construct(
private string $name,
Expand All @@ -28,6 +29,7 @@ public function __construct(
private array $usedTraits,
private array $traitUseAdaptations,
private array $statements,
private array $attributes,
)
{
}
Expand All @@ -50,6 +52,16 @@ public function equals(ExportedNode $node): bool
return false;
}

if (count($this->attributes) !== count($node->attributes)) {
return false;
}

foreach ($this->attributes as $i => $attribute) {
if (!$attribute->equals($node->attributes[$i])) {
return false;
}
}

if (count($this->traitUseAdaptations) !== count($node->traitUseAdaptations)) {
return false;
}
Expand Down Expand Up @@ -97,6 +109,7 @@ public static function __set_state(array $properties): ExportedNode
$properties['usedTraits'],
$properties['traitUseAdaptations'],
$properties['statements'],
$properties['attributes'],
);
}

Expand All @@ -118,6 +131,7 @@ public function jsonSerialize()
'usedTraits' => $this->usedTraits,
'traitUseAdaptations' => $this->traitUseAdaptations,
'statements' => $this->statements,
'attributes' => $this->attributes,
],
];
}
Expand Down Expand Up @@ -147,6 +161,12 @@ public static function decode(array $data): ExportedNode

return $nodeType::decode($node['data']);
}, $data['statements']),
array_map(static function (array $attributeData): ExportedAttributeNode {
if ($attributeData['type'] !== ExportedAttributeNode::class) {
throw new ShouldNotHappenException();
}
return ExportedAttributeNode::decode($attributeData['data']);
}, $data['attributes']),
);
}

Expand Down
29 changes: 28 additions & 1 deletion src/Dependency/ExportedNode/ExportedEnumNode.php
Expand Up @@ -4,6 +4,7 @@

use JsonSerializable;
use PHPStan\Dependency\ExportedNode;
use PHPStan\ShouldNotHappenException;
use ReturnTypeWillChange;
use function array_map;
use function count;
Expand All @@ -14,8 +15,16 @@ class ExportedEnumNode implements ExportedNode, JsonSerializable
/**
* @param string[] $implements
* @param ExportedNode[] $statements
* @param ExportedAttributeNode[] $attributes
*/
public function __construct(private string $name, private ?string $scalarType, private ?ExportedPhpDocNode $phpDoc, private array $implements, private array $statements)
public function __construct(
private string $name,
private ?string $scalarType,
private ?ExportedPhpDocNode $phpDoc,
private array $implements,
private array $statements,
private array $attributes,
)
{
}

Expand Down Expand Up @@ -49,6 +58,16 @@ public function equals(ExportedNode $node): bool
return false;
}

if (count($this->attributes) !== count($node->attributes)) {
return false;
}

foreach ($this->attributes as $i => $attribute) {
if (!$attribute->equals($node->attributes[$i])) {
return false;
}
}

return $this->name === $node->name
&& $this->scalarType === $node->scalarType
&& $this->implements === $node->implements;
Expand All @@ -66,6 +85,7 @@ public static function __set_state(array $properties): ExportedNode
$properties['phpDoc'],
$properties['implements'],
$properties['statements'],
$properties['attributes'],
);
}

Expand All @@ -83,6 +103,7 @@ public function jsonSerialize()
'phpDoc' => $this->phpDoc,
'implements' => $this->implements,
'statements' => $this->statements,
'attributes' => $this->attributes,
],
];
}
Expand All @@ -103,6 +124,12 @@ public static function decode(array $data): ExportedNode

return $nodeType::decode($node['data']);
}, $data['statements']),
array_map(static function (array $attributeData): ExportedAttributeNode {
if ($attributeData['type'] !== ExportedAttributeNode::class) {
throw new ShouldNotHappenException();
}
return ExportedAttributeNode::decode($attributeData['data']);
}, $data['attributes']),
);
}

Expand Down
20 changes: 20 additions & 0 deletions src/Dependency/ExportedNode/ExportedFunctionNode.php
Expand Up @@ -14,13 +14,15 @@ class ExportedFunctionNode implements ExportedNode, JsonSerializable

/**
* @param ExportedParameterNode[] $parameters
* @param ExportedAttributeNode[] $attributes
*/
public function __construct(
private string $name,
private ?ExportedPhpDocNode $phpDoc,
private bool $byRef,
private ?string $returnType,
private array $parameters,
private array $attributes,
)
{
}
Expand Down Expand Up @@ -54,6 +56,16 @@ public function equals(ExportedNode $node): bool
return false;
}

if (count($this->attributes) !== count($node->attributes)) {
return false;
}

foreach ($this->attributes as $i => $attribute) {
if (!$attribute->equals($node->attributes[$i])) {
return false;
}
}

return $this->name === $node->name
&& $this->byRef === $node->byRef
&& $this->returnType === $node->returnType;
Expand All @@ -71,6 +83,7 @@ public static function __set_state(array $properties): ExportedNode
$properties['byRef'],
$properties['returnType'],
$properties['parameters'],
$properties['attributes'],
);
}

Expand All @@ -88,6 +101,7 @@ public function jsonSerialize()
'byRef' => $this->byRef,
'returnType' => $this->returnType,
'parameters' => $this->parameters,
'attributes' => $this->attributes,
],
];
}
Expand All @@ -109,6 +123,12 @@ public static function decode(array $data): ExportedNode
}
return ExportedParameterNode::decode($parameterData['data']);
}, $data['parameters']),
array_map(static function (array $attributeData): ExportedAttributeNode {
if ($attributeData['type'] !== ExportedAttributeNode::class) {
throw new ShouldNotHappenException();
}
return ExportedAttributeNode::decode($attributeData['data']);
}, $data['attributes']),
);
}

Expand Down