@@ -435,14 +435,21 @@ private function compareStatementsInNamespace(array $oldStmts, array $newStmts,
435435 throw new \LogicException ('Classname changed ' );
436436 }
437437 $ newMethods = array_filter ($ new ->stmts , fn (Node \Stmt $ stmt ) => $ stmt instanceof Node \Stmt \ClassMethod);
438- [$ untouchedStmts , $ oldMethodsStmt ] = $ this ->filterStatementsByVersion ($ old ->stmts , $ updateFrom );
438+ $ newConstants = array_filter ($ new ->stmts , fn (Node \Stmt $ stmt ) => $ stmt instanceof Node \Stmt \ClassConst);
439+ [$ untouchedStmts , $ oldStmts ] = $ this ->filterStatementsByVersion ($ old ->stmts , $ updateFrom );
439440 $ oldMethods = [];
440- foreach ($ oldMethodsStmt as $ stmt ) {
441- if (!$ stmt instanceof Node \Stmt \ClassMethod) {
441+ $ oldConstants = [];
442+ foreach ($ oldStmts as $ stmt ) {
443+ if ($ stmt instanceof Node \Stmt \ClassMethod) {
444+ $ oldMethods [$ stmt ->name ->toLowerString ()] = $ stmt ;
442445 continue ;
443446 }
444447
445- $ oldMethods [$ stmt ->name ->toLowerString ()] = $ stmt ;
448+ if ($ stmt instanceof Node \Stmt \ClassConst) {
449+ $ names = array_map (static fn (Node \Const_ $ const ) => $ const ->name ->toString (), $ stmt ->consts );
450+ $ oldConstants [implode (', ' , $ names )] = $ stmt ;
451+ continue ;
452+ }
446453 }
447454
448455 if ($ old ->stmts !== null ) {
@@ -467,6 +474,26 @@ private function compareStatementsInNamespace(array $oldStmts, array $newStmts,
467474
468475 // todo has a method been removed?
469476
477+ foreach ($ newConstants as $ stmt ) {
478+ $ namesKey = implode (', ' , array_map (static fn (Node \Const_ $ const ) => $ const ->name ->toString (), $ stmt ->consts ));
479+ if (!array_key_exists ($ namesKey , $ oldConstants )) {
480+ $ stmt ->attrGroups [] = new Node \AttributeGroup ([
481+ new Node \Attribute (
482+ new Node \Name \FullyQualified ('Since ' ),
483+ [new Node \Arg (new Node \Scalar \String_ ($ updateTo ))],
484+ ),
485+ ]);
486+ $ newStmtsToSet [] = $ stmt ;
487+ continue ;
488+ }
489+
490+ foreach ($ this ->compareConstants ($ oldConstants [$ namesKey ], $ stmt , $ updateTo ) as $ constantStmt ) {
491+ $ newStmtsToSet [] = $ constantStmt ;
492+ }
493+ }
494+
495+ // todo has a constant been removed?
496+
470497 $ old ->stmts = $ newStmtsToSet ;
471498 }
472499
@@ -508,49 +535,49 @@ private function compareFunctions(Node\FunctionLike $old, Node\FunctionLike $new
508535 }
509536 }
510537 if ($ this ->printType ($ old ->getReturnType ()) !== $ this ->printType ($ new ->getReturnType ())) {
511- return $ this ->functionDiff ($ old , $ new , $ updateTo );
538+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
512539 }
513540 if ($ old ->returnsByRef () !== $ new ->returnsByRef ()) {
514- return $ this ->functionDiff ($ old , $ new , $ updateTo );
541+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
515542 }
516543 if (count ($ old ->getParams ()) !== count ($ new ->getParams ())) {
517- return $ this ->functionDiff ($ old , $ new , $ updateTo );
544+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
518545 }
519546
520547 foreach ($ old ->getParams () as $ i => $ oldParam ) {
521548 $ newParam = $ new ->getParams ()[$ i ];
522549 if ($ this ->printType ($ oldParam ->type ) !== $ this ->printType ($ newParam ->type )) {
523- return $ this ->functionDiff ($ old , $ new , $ updateTo );
550+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
524551 }
525552 if ($ oldParam ->byRef !== $ newParam ->byRef ) {
526- return $ this ->functionDiff ($ old , $ new , $ updateTo );
553+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
527554 }
528555 if ($ oldParam ->variadic !== $ newParam ->variadic ) {
529- return $ this ->functionDiff ($ old , $ new , $ updateTo );
556+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
530557 }
531558 assert ($ oldParam ->var instanceof Node \Expr \Variable);
532559 assert (is_string ($ oldParam ->var ->name ));
533560 assert ($ newParam ->var instanceof Node \Expr \Variable);
534561 assert (is_string ($ newParam ->var ->name ));
535562 if ($ oldParam ->var ->name !== $ newParam ->var ->name ) {
536- return $ this ->functionDiff ($ old , $ new , $ updateTo );
563+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
537564 }
538565 if (is_null ($ oldParam ->default ) !== is_null ($ newParam ->default )) {
539- return $ this ->functionDiff ($ old , $ new , $ updateTo );
566+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
540567 }
541568 if ($ oldParam ->default !== null && $ newParam ->default !== null ) {
542569 if ($ this ->printer ->prettyPrintExpr ($ oldParam ->default ) !== $ this ->printer ->prettyPrintExpr ($ newParam ->default )) {
543- return $ this ->functionDiff ($ old , $ new , $ updateTo );
570+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
544571 }
545572 }
546573 if ($ oldParam ->flags !== $ newParam ->flags ) {
547- return $ this ->functionDiff ($ old , $ new , $ updateTo );
574+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
548575 }
549576 }
550577
551578 if ($ old instanceof Node \Stmt \ClassMethod && $ new instanceof Node \Stmt \ClassMethod) {
552579 if ($ old ->flags !== $ new ->flags ) {
553- return $ this ->functionDiff ($ old , $ new , $ updateTo );
580+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
554581 }
555582 }
556583
@@ -596,19 +623,19 @@ private function compareFunctions(Node\FunctionLike $old, Node\FunctionLike $new
596623 }
597624
598625 if ($ oldPhpDocParameters !== $ newPhpDocParameters ) {
599- return $ this ->functionDiff ($ old , $ new , $ updateTo );
626+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
600627 }
601628
602629 return [$ old ];
603630 }
604631
605632 /**
606- * @template T of Node\FunctionLike
633+ * @template T of Node
607634 * @param T $old
608635 * @param T $new
609636 * @return T[]
610637 */
611- private function functionDiff (Node \ FunctionLike $ old , Node \ FunctionLike $ new , string $ updateTo ): array
638+ private function stmtDiff (Node $ old , Node $ new , string $ updateTo ): array
612639 {
613640 $ args = [new Node \Arg (new Node \Scalar \String_ ($ updateTo ))];
614641 $ old = clone $ old ;
@@ -632,6 +659,52 @@ private function functionDiff(Node\FunctionLike $old, Node\FunctionLike $new, st
632659 return [$ old , $ new ];
633660 }
634661
662+ /**
663+ * @return Node\Stmt\ClassConst[]
664+ */
665+ private function compareConstants (Node \Stmt \ClassConst $ old , Node \Stmt \ClassConst $ new , string $ updateTo ): array
666+ {
667+ if ($ old ->getDocComment () !== $ new ->getDocComment ()) {
668+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
669+ }
670+ if ($ old ->flags !== $ new ->flags ) {
671+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
672+ }
673+
674+ if (count ($ old ->consts ) !== count ($ new ->consts )) {
675+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
676+ }
677+
678+ foreach ($ new ->consts as $ i => $ newConst ) {
679+ $ oldConst = $ old ->consts [$ i ];
680+ if ($ oldConst ->name ->toString () !== $ newConst ->name ->toString ()) {
681+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
682+ }
683+
684+ $ oldValue = $ this ->printer ->prettyPrintExpr ($ oldConst ->value );
685+ $ newValue = $ this ->printer ->prettyPrintExpr ($ newConst ->value );
686+ if ($ oldValue !== $ newValue ) {
687+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
688+ }
689+ }
690+
691+ $ oldType = $ old ->type ;
692+ $ newType = $ new ->type ;
693+ if ($ oldType !== null ) {
694+ if ($ newType === null ) {
695+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
696+ }
697+
698+ if ($ this ->printType ($ oldType ) !== $ this ->printType ($ newType )) {
699+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
700+ }
701+ } elseif ($ newType !== null ) {
702+ return $ this ->stmtDiff ($ old , $ new , $ updateTo );
703+ }
704+
705+ return [$ old ];
706+ }
707+
635708 /**
636709 * @param Node\Identifier|Node\Name|Node\ComplexType|null $type
637710 */
0 commit comments