-
Notifications
You must be signed in to change notification settings - Fork 5
Implement ParameterAttributeCollector #33
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
Conversation
6174bc8
to
342e40c
Compare
Hi @staabm, thank you for your contribution. What would the use case for this feature be? |
Hey, we use this implementation to make the lib work for PHPStan DI-Container configuration. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm considering the naming "methodAttributes". The class is ReflectionAttribute
, I think we should match the naming. Would it clash with other parameter types?
Also, please rebase you're branch. I've made some changes to decouple the collector from IOInterface
.
/** | ||
* @param array<TransientTargetMethod> $methodAttributes | ||
* @param array<array<TransientTargetMethodParameter>> $methodParameterAttributes | ||
* @return void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's remove this one, it's already in the signature.
* @param array<array<TransientTargetMethodParameter>> $methodParameterAttributes | ||
* @return void | ||
*/ | ||
private function collectMethodAndParameterAttributes(string $class, \ReflectionMethod $methodReflection, array &$methodAttributes, array &$methodParameterAttributes): void |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's split this over multiple lines.
private function collectMethodAndParameterAttributes(string $class, \ReflectionMethod $methodReflection, array &$methodAttributes, array &$methodParameterAttributes): void | |
private function collectMethodAndParameterAttributes( | |
string $class, | |
\ReflectionMethod $methodReflection, | |
array &$methodAttributes, | |
array &$methodParameterAttributes | |
): void { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Also, I'd like it better if we were not using references… but I can live with it.
} | ||
|
||
$parameterAttributes = $parameterAttributeCollector->collectAttributes($methodReflection); | ||
if ($parameterAttributes !== []) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
if ($parameterAttributes !== []) { | |
if ($parameterAttributes) { |
Simpler to read.
] = $classAttributeCollector->collectAttributes($class); | ||
} catch (Throwable $e) { | ||
$this->io->error( | ||
"Attribute collection failed for $class: {$e->getMessage()}", | ||
); | ||
} | ||
|
||
$this->state[$class] = [ time(), $classAttributes, $methodAttributes, $propertyAttributes ]; | ||
$this->state[$class] = [ time(), $classAttributes, $methodAttributes, $propertyAttributes, $methodParameterAttributes ]; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's split this one.
$this->state[$class] = [ time(), $classAttributes, $methodAttributes, $propertyAttributes, $methodParameterAttributes ]; | |
$this->state[$class] = [ | |
time(), | |
$classAttributes, | |
$methodAttributes, | |
$propertyAttributes, | |
$methodParameterAttributes, | |
]; |
use PhpParser\Node; | ||
use PhpParser\Node\Stmt\ClassLike; | ||
use PhpParser\NodeTraverser; | ||
use PhpParser\NodeVisitorAbstract; | ||
use PhpParser\Parser; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Unused imports.
use PhpParser\Node; | |
use PhpParser\Node\Stmt\ClassLike; | |
use PhpParser\NodeTraverser; | |
use PhpParser\NodeVisitorAbstract; | |
use PhpParser\Parser; |
{ | ||
$funcParameterAttributes = []; | ||
foreach ($reflectionFunctionAbstract->getParameters() as $parameter) { | ||
$attributes = $parameter->getAttributes(); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We initialize the variable here, but it's used much later. Besides, the variable is only used once, we could do without.
$attributes = $parameter->getAttributes(); |
$paramLabel = $functionName . '(' . $parameterName . ')'; | ||
} | ||
|
||
foreach ($attributes as $attribute) { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
foreach ($attributes as $attribute) { | |
foreach ($parameter->getAttributes() as $attribute) { |
{ | ||
public string $label; | ||
public function __construct( | ||
string $label = '' | ||
) { | ||
$this->label = $label; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use promoted properties here:
{ | |
public string $label; | |
public function __construct( | |
string $label = '' | |
) { | |
$this->label = $label; | |
} | |
public function __construct( | |
public string $label = '' | |
) { | |
} |
public string $label; | ||
public string $moreData; | ||
public function __construct( | ||
string $label = '', | ||
string $moreData = '' | ||
) { | ||
$this->label = $label; | ||
$this->moreData = $moreData; | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We can use promoted properties here:
public string $label; | |
public string $moreData; | |
public function __construct( | |
string $label = '', | |
string $moreData = '' | |
) { | |
$this->label = $label; | |
$this->moreData = $moreData; | |
} | |
public function __construct( | |
public string $label = '', | |
public string $moreData = '' | |
) { | |
} |
use Acme81\Attribute\ParameterA; | ||
|
||
function aFunc( | ||
#[ParameterA("my function parameter label")] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think we should make it more apparent in the tests that we don't want this attribute to be collected; for example, with a $this->assertNotExists()
.
By the way, I just wanted to show my appreciation for this package: it's awesome! It enabled me to use attributes in PHPStan to trim down the config files. I plan to publish a community update about this, but here's already an issue with some description and links to diffs what it allowed me to do: nette/di#324 I can also keep PHP 7.4 support because the attributes file is baked into the PHAR, so runtime inspection is not needed :) |
I opened another PR to complete the changes. I tested the branch on a few projects with success. @staabm @ondrejmirtes Could you test the changes with your project? Careful, I renamed a few things. You'll have to use the |
implemented via #37 |
implement the necessary plumbing which allows us to find targets for attributes on method parameters
ports the implementation from ondrejmirtes#2 into this upstream repo