4040use function array_key_exists ;
4141use function array_keys ;
4242use function array_map ;
43+ use function array_merge ;
4344use function array_values ;
4445use function count ;
4546use function implode ;
@@ -1052,7 +1053,14 @@ public function changeSubtractedType(?Type $subtractedType): Type
10521053 $ cases [$ name ] = new EnumCaseObjectType ($ classReflection ->getName (), $ name );
10531054 }
10541055
1055- foreach (TypeUtils::flattenTypes ($ subtractedType ) as $ subType ) {
1056+ $ originalCases = $ cases ;
1057+
1058+ $ subtractedTypes = TypeUtils::flattenTypes ($ subtractedType );
1059+ if ($ this ->subtractedType !== null ) {
1060+ $ subtractedTypes = array_merge ($ subtractedTypes , TypeUtils::flattenTypes ($ this ->subtractedType ));
1061+ }
1062+ $ subtractedCases = [];
1063+ foreach ($ subtractedTypes as $ subType ) {
10561064 if (!$ subType instanceof EnumCaseObjectType) {
10571065 return new self ($ this ->className , $ subtractedType );
10581066 }
@@ -1061,19 +1069,33 @@ public function changeSubtractedType(?Type $subtractedType): Type
10611069 return new self ($ this ->className , $ subtractedType );
10621070 }
10631071
1064- unset($ cases [$ subType ->getEnumCaseName ()]);
1072+ if (!array_key_exists ($ subType ->getEnumCaseName (), $ cases )) {
1073+ return new self ($ this ->className , $ subtractedType );
1074+ }
1075+
1076+ $ subtractedCases [$ subType ->getEnumCaseName ()] = $ subType ;
1077+ unset($ originalCases [$ subType ->getEnumCaseName ()]);
10651078 }
10661079
1067- $ cases = array_values ($ cases );
1068- if (count ($ cases ) === 0 ) {
1080+ if (count ($ originalCases ) === 1 ) {
1081+ return array_values ($ originalCases )[0 ];
1082+ }
1083+
1084+ $ subtractedCases = array_values ($ subtractedCases );
1085+ $ subtractedCasesCount = count ($ subtractedCases );
1086+ if ($ subtractedCasesCount === count ($ cases )) {
10691087 return new NeverType ();
10701088 }
10711089
1072- if (count ($ cases ) === 1 ) {
1073- return $ cases [0 ];
1090+ if ($ subtractedCasesCount === 0 ) {
1091+ return new self ($ this ->className );
1092+ }
1093+
1094+ if (count ($ subtractedCases ) === 1 ) {
1095+ return new self ($ this ->className , $ subtractedCases [0 ]);
10741096 }
10751097
1076- return new UnionType (array_values ( $ cases ));
1098+ return new self ( $ this -> className , new UnionType ($ subtractedCases ));
10771099 }
10781100 }
10791101
0 commit comments