@@ -324,14 +324,37 @@ private function addPropertyToClass(ClassLike $class, Node\Stmt\Property $node):
324
324
foreach ($ node ->props as $ item ) {
325
325
$ prop = $ class ->addProperty ($ item ->name ->toString ());
326
326
$ prop ->setStatic ($ node ->isStatic ());
327
- $ prop ->setVisibility ($ this ->toVisibility ($ node ->flags ));
327
+ $ prop ->setVisibility ($ this ->toVisibility ($ node ->flags ), $ this -> toSetterVisibility ( $ node -> flags ) );
328
328
$ prop ->setType ($ node ->type ? $ this ->toPhp ($ node ->type ) : null );
329
329
if ($ item ->default ) {
330
330
$ prop ->setValue ($ this ->toValue ($ item ->default ));
331
331
}
332
332
333
333
$ prop ->setReadOnly ((method_exists ($ node , 'isReadonly ' ) && $ node ->isReadonly ()) || ($ class instanceof ClassType && $ class ->isReadOnly ()));
334
334
$ this ->addCommentAndAttributes ($ prop , $ node );
335
+
336
+ $ prop ->setAbstract ((bool ) ($ node ->flags & Modifiers::ABSTRACT ));
337
+ $ prop ->setFinal ((bool ) ($ node ->flags & Modifiers::FINAL ));
338
+ $ this ->addHooksToProperty ($ prop , $ node );
339
+ }
340
+ }
341
+
342
+
343
+ private function addHooksToProperty (Property |PromotedParameter $ prop , Node \Stmt \Property |Node \Param $ node ): void
344
+ {
345
+ if (!class_exists (Node \PropertyHook::class)) {
346
+ return ;
347
+ }
348
+
349
+ foreach ($ node ->hooks as $ hookNode ) {
350
+ $ hook = $ prop ->addHook ($ hookNode ->name ->toString ());
351
+ $ hook ->setFinal ((bool ) ($ hookNode ->flags & Modifiers::FINAL ));
352
+ $ this ->setupFunction ($ hook , $ hookNode );
353
+ if ($ hookNode ->body === null ) {
354
+ $ hook ->setAbstract ();
355
+ } elseif (!is_array ($ hookNode ->body )) {
356
+ $ hook ->setBody ($ this ->getReformattedContents ([$ hookNode ->body ], 1 ), short: true );
357
+ }
335
358
}
336
359
}
337
360
@@ -381,7 +404,7 @@ private function addFunctionToFile(PhpFile $phpFile, Node\Stmt\Function_ $node):
381
404
382
405
383
406
private function addCommentAndAttributes (
384
- PhpFile |ClassLike |Constant |Property |GlobalFunction |Method |Parameter |EnumCase |TraitUse $ element ,
407
+ PhpFile |ClassLike |Constant |Property |GlobalFunction |Method |Parameter |EnumCase |TraitUse | PropertyHook $ element ,
385
408
Node $ node ,
386
409
): void
387
410
{
@@ -409,18 +432,29 @@ private function addCommentAndAttributes(
409
432
}
410
433
411
434
412
- private function setupFunction (GlobalFunction |Method $ function , Node \FunctionLike $ node ): void
435
+ private function setupFunction (GlobalFunction |Method | PropertyHook $ function , Node \FunctionLike $ node ): void
413
436
{
414
437
$ function ->setReturnReference ($ node ->returnsByRef ());
415
- $ function ->setReturnType ($ node ->getReturnType () ? $ this ->toPhp ($ node ->getReturnType ()) : null );
438
+ if (!$ function instanceof PropertyHook) {
439
+ $ function ->setReturnType ($ node ->getReturnType () ? $ this ->toPhp ($ node ->getReturnType ()) : null );
440
+ }
441
+
416
442
foreach ($ node ->getParams () as $ item ) {
417
- $ visibility = $ this ->toVisibility ($ item ->flags );
418
- $ param = $ visibility
419
- ? $ function ->addPromotedParameter ($ item ->var ->name )->setVisibility ($ visibility )->setReadonly ($ item ->isReadonly ())
420
- : $ function ->addParameter ($ item ->var ->name );
443
+ $ getVisibility = $ this ->toVisibility ($ item ->flags );
444
+ $ setVisibility = $ this ->toSetterVisibility ($ item ->flags );
445
+ if ($ getVisibility || $ setVisibility ) {
446
+ $ param = $ function ->addPromotedParameter ($ item ->var ->name )
447
+ ->setVisibility ($ getVisibility , $ setVisibility )
448
+ ->setReadonly ($ item ->isReadonly ());
449
+ $ this ->addHooksToProperty ($ param , $ item );
450
+ } else {
451
+ $ param = $ function ->addParameter ($ item ->var ->name );
452
+ }
421
453
$ param ->setType ($ item ->type ? $ this ->toPhp ($ item ->type ) : null );
422
454
$ param ->setReference ($ item ->byRef );
423
- $ function ->setVariadic ($ item ->variadic );
455
+ if (!$ function instanceof PropertyHook) {
456
+ $ function ->setVariadic ($ item ->variadic );
457
+ }
424
458
if ($ item ->default ) {
425
459
$ param ->setDefaultValue ($ this ->toValue ($ item ->default ));
426
460
}
@@ -491,6 +525,18 @@ private function toVisibility(int $flags): ?string
491
525
}
492
526
493
527
528
+ private function toSetterVisibility (int $ flags ): ?string
529
+ {
530
+ return match (true ) {
531
+ !class_exists (Node \PropertyHook::class) => null ,
532
+ (bool ) ($ flags & Modifiers::PUBLIC_SET ) => ClassType::VisibilityPublic,
533
+ (bool ) ($ flags & Modifiers::PROTECTED_SET ) => ClassType::VisibilityProtected,
534
+ (bool ) ($ flags & Modifiers::PRIVATE_SET ) => ClassType::VisibilityPrivate,
535
+ default => null ,
536
+ };
537
+ }
538
+
539
+
494
540
private function toPhp (Node $ value ): string
495
541
{
496
542
$ dolly = clone $ value ;
0 commit comments