-
Notifications
You must be signed in to change notification settings - Fork 542
NodeCallbackInvoker #4429
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
NodeCallbackInvoker #4429
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,65 @@ | ||
| <?php declare(strict_types = 1); | ||
|
|
||
| namespace PHPStan\Analyser; | ||
|
|
||
| use PhpParser\Node; | ||
| use PHPStan\DependencyInjection\Type\DynamicReturnTypeExtensionRegistryProvider; | ||
| use PHPStan\DependencyInjection\Type\ExpressionTypeResolverExtensionRegistryProvider; | ||
| use PHPStan\Node\Printer\ExprPrinter; | ||
| use PHPStan\Parser\Parser; | ||
| use PHPStan\Php\PhpVersion; | ||
| use PHPStan\Reflection\AttributeReflectionFactory; | ||
| use PHPStan\Reflection\InitializerExprTypeResolver; | ||
| use PHPStan\Reflection\ReflectionProvider; | ||
| use PHPStan\Rules\Properties\PropertyReflectionFinder; | ||
|
|
||
| final class DirectInternalScopeFactoryFactory implements InternalScopeFactoryFactory | ||
| { | ||
|
|
||
| /** | ||
| * @param int|array{min: int, max: int}|null $configPhpVersion | ||
| */ | ||
| public function __construct( | ||
| private ReflectionProvider $reflectionProvider, | ||
| private InitializerExprTypeResolver $initializerExprTypeResolver, | ||
| private DynamicReturnTypeExtensionRegistryProvider $dynamicReturnTypeExtensionRegistryProvider, | ||
| private ExpressionTypeResolverExtensionRegistryProvider $expressionTypeResolverExtensionRegistryProvider, | ||
| private ExprPrinter $exprPrinter, | ||
| private TypeSpecifier $typeSpecifier, | ||
| private PropertyReflectionFinder $propertyReflectionFinder, | ||
| private Parser $parser, | ||
| private NodeScopeResolver $nodeScopeResolver, | ||
| private RicherScopeGetTypeHelper $richerScopeGetTypeHelper, | ||
| private PhpVersion $phpVersion, | ||
| private AttributeReflectionFactory $attributeReflectionFactory, | ||
| private int|array|null $configPhpVersion, | ||
| private ConstantResolver $constantResolver, | ||
| ) | ||
| { | ||
| } | ||
|
|
||
| /** | ||
| * @param callable(Node $node, Scope $scope): void|null $nodeCallback | ||
| */ | ||
| public function create(?callable $nodeCallback): DirectInternalScopeFactory | ||
| { | ||
| return new DirectInternalScopeFactory( | ||
| $this->reflectionProvider, | ||
| $this->initializerExprTypeResolver, | ||
| $this->dynamicReturnTypeExtensionRegistryProvider, | ||
| $this->expressionTypeResolverExtensionRegistryProvider, | ||
| $this->exprPrinter, | ||
| $this->typeSpecifier, | ||
| $this->propertyReflectionFinder, | ||
| $this->parser, | ||
| $this->nodeScopeResolver, | ||
| $this->richerScopeGetTypeHelper, | ||
| $this->phpVersion, | ||
| $this->attributeReflectionFactory, | ||
| $this->configPhpVersion, | ||
| $nodeCallback, | ||
| $this->constantResolver, | ||
| ); | ||
| } | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,17 @@ | ||
| <?php declare(strict_types = 1); | ||
|
|
||
| namespace PHPStan\Analyser; | ||
|
|
||
| use PhpParser\Node; | ||
|
|
||
| interface InternalScopeFactoryFactory | ||
| { | ||
|
|
||
| /** | ||
| * @param callable(Node $node, Scope $scope): void $nodeCallback | ||
| */ | ||
| public function create( | ||
| ?callable $nodeCallback, | ||
| ): InternalScopeFactory; | ||
|
|
||
| } |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,37 @@ | ||
| <?php declare(strict_types = 1); | ||
|
|
||
| namespace PHPStan\Analyser; | ||
|
|
||
| use PhpParser\Node; | ||
|
|
||
| /** | ||
| * The interface NodeCallbackInvoker can be typehinted in 2nd parameter of Rule::processNode(): | ||
| * | ||
| * ```php | ||
| * public function processNode(Node $node, Scope&NodeCallbackInvoker $scope): array | ||
| * ``` | ||
| * | ||
| * It can be used to invoke rules for virtual made-up nodes. | ||
| * | ||
| * For example: You're writing a rule for a method with declaration like: | ||
| * | ||
| * ```php | ||
| * public static create(string $class, mixed ...$args) | ||
| * ``` | ||
| * | ||
| * And you'd like to check `Factory::create(Foo::class, 1, 2, 3)` as if it were | ||
| * `new Foo(1, 2, 3)`. | ||
| * | ||
| * You can call `$scope->invokeNodeCallback(new New_(new Name($className), $args))` | ||
| * | ||
| * And PHPStan will call all the registered rules for New_, checking as if the instantiation | ||
| * is actually in the code. | ||
|
Comment on lines
+7
to
+28
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. oh wow, this is awesome! 🚀 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yeah, I vaguely remember you're using FunctionCallParametersCheck somewhere, which is not part of BC promise. This would allow you to write simple and clean code instead 😊 There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Please note that this PHPDoc is lying a little bit. You don't need to change your processNode signature to take advantage of this. phpstan-src uses native intersection type which is downgraded to PHPDoc because of PHP 7.4+ support. Which means that unless you have your own PHPDoc in your custom rule, PHPStan will implicitly inherit the Rule interface PHPDoc and you can call |
||
| * | ||
| * @api | ||
| */ | ||
| interface NodeCallbackInvoker | ||
| { | ||
|
|
||
| public function invokeNodeCallback(Node $node): void; | ||
|
|
||
| } | ||
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -3,6 +3,7 @@ | |
| namespace PHPStan\Rules\Playground; | ||
|
|
||
| use PhpParser\Node; | ||
| use PHPStan\Analyser\NodeCallbackInvoker; | ||
| use PHPStan\Analyser\Scope; | ||
| use PHPStan\DependencyInjection\Container; | ||
| use PHPStan\DependencyInjection\MissingServiceException; | ||
|
|
@@ -87,7 +88,7 @@ private function getOriginalRule(): ?Rule | |
| return $this->originalRule = $originalRule; | ||
| } | ||
|
|
||
| public function processNode(Node $node, Scope $scope): array | ||
| public function processNode(Node $node, Scope&NodeCallbackInvoker $scope): array | ||
|
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. is this a testing-only change which we need to be cleaned up? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. No, we're calling another rule, which might need it. If you revert it, you get PHPStan error. |
||
| { | ||
| if ($this->parameterValue) { | ||
| return []; | ||
|
|
||
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 am getting java vibes.. where is the FactoryFactoryFactory :-)