@@ -754,18 +754,17 @@ private function getExpressionResolvers(): array
754754 )
755755 );
756756 },
757+ 'contains ' => static function (Scope $ scope , Arg $ value , Arg $ subString ): array {
758+ return self ::createContainsResolver ($ scope , $ value , $ subString );
759+ },
760+ 'startsWith ' => static function (Scope $ scope , Arg $ value , Arg $ subString ): array {
761+ return self ::createStartsWithResolver ($ scope , $ value , $ subString );
762+ },
763+ 'endsWith ' => static function (Scope $ scope , Arg $ value , Arg $ subString ): array {
764+ return self ::createEndsWithResolver ($ scope , $ value , $ subString );
765+ },
757766 ];
758767
759- foreach (['contains ' , 'startsWith ' , 'endsWith ' ] as $ name ) {
760- $ this ->resolvers [$ name ] = function (Scope $ scope , Arg $ value , Arg $ subString ) use ($ name ): array {
761- if ($ scope ->getType ($ subString ->value )->isNonEmptyString ()->yes ()) {
762- return self ::createIsNonEmptyStringAndSomethingExprPair ($ name , [$ value , $ subString ]);
763- }
764-
765- return [$ this ->resolvers ['string ' ]($ scope , $ value ), null ];
766- };
767- }
768-
769768 $ assertionsResultingAtLeastInNonEmptyString = [
770769 'startsWithLetter ' ,
771770 'unicodeLetters ' ,
@@ -1022,4 +1021,143 @@ private function specifyRootExprIfSet(?Expr $rootExpr, SpecifiedTypes $specified
10221021 );
10231022 }
10241023
1024+ /**
1025+ * @return array{Expr, Expr}
1026+ */
1027+ private static function createContainsResolver (Scope $ scope , Arg $ value , Arg $ subString ): array
1028+ {
1029+ $ stringExpr = $ scope ->getType ($ subString ->value )->isNonEmptyString ()->yes ()
1030+ ? new BooleanAnd (
1031+ new FuncCall (
1032+ new Name ('is_string ' ),
1033+ [$ value ]
1034+ ),
1035+ new NotIdentical (
1036+ $ value ->value ,
1037+ new String_ ('' )
1038+ )
1039+ )
1040+ : new FuncCall (
1041+ new Name ('is_string ' ),
1042+ [$ value ]
1043+ );
1044+
1045+ $ expr = new BooleanOr (
1046+ $ stringExpr ,
1047+ new BooleanAnd (
1048+ $ stringExpr ,
1049+ new GreaterOrEqual (
1050+ new FuncCall (
1051+ new Name ('strpos ' ),
1052+ [$ value ]
1053+ ),
1054+ new LNumber (0 )
1055+ )
1056+ )
1057+ );
1058+
1059+ $ rootExpr = new BooleanAnd (
1060+ $ expr ,
1061+ new FuncCall (new Name ('FAUX_FUNCTION_ contains ' ), [$ value , $ subString ])
1062+ );
1063+
1064+ return [$ expr , $ rootExpr ];
1065+ }
1066+
1067+ /**
1068+ * @return array{Expr, Expr}
1069+ */
1070+ private static function createStartsWithResolver (Scope $ scope , Arg $ value , Arg $ subString ): array
1071+ {
1072+ $ stringExpr = $ scope ->getType ($ subString ->value )->isNonEmptyString ()->yes ()
1073+ ? new BooleanAnd (
1074+ new FuncCall (
1075+ new Name ('is_string ' ),
1076+ [$ value ]
1077+ ),
1078+ new NotIdentical (
1079+ $ value ->value ,
1080+ new String_ ('' )
1081+ )
1082+ )
1083+ : new FuncCall (
1084+ new Name ('is_string ' ),
1085+ [$ value ]
1086+ );
1087+
1088+
1089+ $ expr = new BooleanOr (
1090+ $ stringExpr ,
1091+ new BooleanAnd (
1092+ $ stringExpr ,
1093+ new Identical (
1094+ new FuncCall (
1095+ new Name ('strpos ' ),
1096+ [$ value , $ subString ]
1097+ ),
1098+ new LNumber (0 )
1099+ )
1100+ )
1101+ );
1102+
1103+ $ rootExpr = new BooleanAnd (
1104+ $ expr ,
1105+ new FuncCall (new Name ('FAUX_FUNCTION_ startsWith ' ), [$ value , $ subString ])
1106+ );
1107+
1108+ return [$ expr , $ rootExpr ];
1109+ }
1110+
1111+ /**
1112+ * @return array{Expr, Expr}
1113+ */
1114+ private static function createEndsWithResolver (Scope $ scope , Arg $ value , Arg $ subString ): array
1115+ {
1116+ $ stringExpr = $ scope ->getType ($ subString ->value )->isNonEmptyString ()->yes ()
1117+ ? new BooleanAnd (
1118+ new FuncCall (
1119+ new Name ('is_string ' ),
1120+ [$ value ]
1121+ ),
1122+ new NotIdentical (
1123+ $ value ->value ,
1124+ new String_ ('' )
1125+ )
1126+ )
1127+ : new FuncCall (
1128+ new Name ('is_string ' ),
1129+ [$ value ]
1130+ );
1131+
1132+ $ expr = new BooleanOr (
1133+ $ stringExpr ,
1134+ new BooleanAnd (
1135+ $ stringExpr ,
1136+ new Identical (
1137+ new FuncCall (
1138+ new Name ('strpos ' ),
1139+ [$ value , $ subString ]
1140+ ),
1141+ new BinaryOp \Minus (
1142+ new FuncCall (
1143+ new Name ('strlen ' ),
1144+ [$ value ]
1145+ ),
1146+ new FuncCall (
1147+ new Name ('strlen ' ),
1148+ [$ subString ]
1149+ )
1150+ )
1151+ )
1152+ )
1153+ );
1154+
1155+ $ rootExpr = new BooleanAnd (
1156+ $ expr ,
1157+ new FuncCall (new Name ('FAUX_FUNCTION_ endsWith ' ), [$ value , $ subString ])
1158+ );
1159+
1160+ return [$ expr , $ rootExpr ];
1161+ }
1162+
10251163}
0 commit comments