@@ -74,6 +74,20 @@ zv::Val getParametersProcessor(zval *container)
7474 return service;
7575}
7676
77+ /* $this->container->getByType(AttributesHandler::class) */
78+ zv::Val getAttributesHandler (zval *container)
79+ {
80+ if (UNEXPECTED (Z_TYPE_P (container) != IS_OBJECT )) {
81+ zend_throw_error (NULL , " Call to a member function getByType() on %s" , zend_zval_value_name (container));
82+ return zv::Val ();
83+ }
84+ zval className;
85+ ZVAL_STRINGL (&className, " PHPStan\\ Analyser\\ AttributesHandler" , sizeof (" PHPStan\\ Analyser\\ AttributesHandler" ) - 1 );
86+ zv::Val service = pt_call_method_cached (pt_cp_get_by_type_site, Z_OBJ_P (container), PT_LC (" getbytype" ), 1 , &className);
87+ zval_ptr_dtor (&className);
88+ return service;
89+ }
90+
7791/* $invalidateExprNode->getExpr(): the final node's promoted $expr, the method
7892 * of anything else; UNDEF = pending exception */
7993zv::Val invalidateExprNodeExpr (zval *node)
@@ -636,7 +650,7 @@ class ClosureProcessor
636650 if (UNEXPECTED (contextHold.isUndef ())) return zv::Val ();
637651 context = contextHold.raw ();
638652 }
639- zv::Val parametersDependencies = processParams (nodeScopeResolver, stmt, expr, scopeArg, storage, nodeCallback);
653+ zv::Val parametersDependencies = processAttributeGroupsAndParams (nodeScopeResolver, stmt, expr, scopeArg, storage, nodeCallback);
640654 if (UNEXPECTED (parametersDependencies.isUndef ())) return zv::Val ();
641655 zv::Val scopeHold = zv::Val::copyOf (zv::Ref (scopeArg));
642656 bool observing;
@@ -847,6 +861,28 @@ class ClosureProcessor
847861 Z_PROP_FLAG_P (OBJ_PROP_NUM (self, index)) = 0 ;
848862 }
849863
864+ /* Mirrors processAttributeGroupsAndParams(): Dependencies::merge(
865+ * $this->getAttributesHandler()->processAttributeGroups(..., $expr->attrGroups, ...),
866+ * $this->getParametersProcessor()->processParams(..., $expr->params, ...));
867+ * UNDEF = pending exception */
868+ zv::Val processAttributeGroupsAndParams (zval *nodeScopeResolver, zval *stmt, zval *expr, zval *scope, zval *storage, zval *nodeCallback) const
869+ {
870+ zv::Val attributesHandler = getAttributesHandler (slot (slots::container));
871+ if (UNEXPECTED (attributesHandler.isUndef ())) return zv::Val ();
872+ if (UNEXPECTED (!attributesHandler.ref ().isObject ())) {
873+ zend_throw_error (NULL , " Call to a member function processAttributeGroups() on %s" , zend_zval_value_name (attributesHandler.raw ()));
874+ return zv::Val ();
875+ }
876+ zval *attrGroups = ptclosure::prop (ptclosure::attrGroupsSite, expr, PT_LC (" attrGroups" ));
877+ if (UNEXPECTED (attrGroups == NULL )) return zv::Val ();
878+ zv::Val attrGroupsHold = zv::Val::copyOf (zv::Ref (attrGroups));
879+ zv::Val attributesDependencies = pt_attributes_handler_process_attribute_groups (attributesHandler.raw (), nodeScopeResolver, stmt, attrGroupsHold.raw (), scope, storage, nodeCallback);
880+ if (UNEXPECTED (attributesDependencies.isUndef ())) return zv::Val ();
881+ zv::Val parametersDependencies = processParams (nodeScopeResolver, stmt, expr, scope, storage, nodeCallback);
882+ if (UNEXPECTED (parametersDependencies.isUndef ())) return zv::Val ();
883+ return pt_dependencies_merge ({attributesDependencies.raw (), parametersDependencies.raw ()});
884+ }
885+
850886 /* $this->getParametersProcessor()->processParams($nodeScopeResolver, $stmt,
851887 * $expr->params, $scope, $storage, $nodeCallback): what the parameters
852888 * depend on; UNDEF = pending exception */
@@ -940,7 +976,7 @@ class ClosureProcessor
940976 * gatherer; false = pending exception */
941977 [[nodiscard]] zend_never_inline bool enterClosure (ClosureWalk &w, zval *passedToType, zval *nativePassedToType) const
942978 {
943- w.parametersDependencies = processParams (w.nodeScopeResolver , w.stmt , w.expr , w.scope .raw (), w.storage , w.nodeCallback );
979+ w.parametersDependencies = processAttributeGroupsAndParams (w.nodeScopeResolver , w.stmt , w.expr , w.scope .raw (), w.storage , w.nodeCallback );
944980 if (UNEXPECTED (w.parametersDependencies .isUndef ())) return false ;
945981
946982 zval *closureCallArgs = ptclosure::attribute (w.expr , pt_cp_closure_call_args);
0 commit comments