1010use PHPStan \Type \ArrayType ;
1111use PHPStan \Type \BitwiseFlagHelper ;
1212use PHPStan \Type \Constant \ConstantArrayType ;
13+ use PHPStan \Type \Constant \ConstantArrayTypeBuilder ;
1314use PHPStan \Type \Constant \ConstantBooleanType ;
1415use PHPStan \Type \Constant \ConstantIntegerType ;
16+ use PHPStan \Type \Constant \ConstantStringType ;
1517use PHPStan \Type \DynamicFunctionReturnTypeExtension ;
18+ use PHPStan \Type \ErrorType ;
1619use PHPStan \Type \IntegerRangeType ;
1720use PHPStan \Type \IntegerType ;
1821use PHPStan \Type \StringType ;
@@ -36,17 +39,79 @@ public function isFunctionSupported(FunctionReflection $functionReflection): boo
3639
3740 public function getTypeFromFunctionCall (FunctionReflection $ functionReflection , FuncCall $ functionCall , Scope $ scope ): ?Type
3841 {
39- $ flagsArg = $ functionCall ->getArgs ()[3 ] ?? null ;
42+ $ args = $ functionCall ->getArgs ();
43+ if (count ($ args ) < 2 ) {
44+ return null ;
45+ }
46+ $ patternArg = $ args [0 ];
47+ $ subjectArg = $ args [1 ];
48+ $ limitArg = $ args [2 ] ?? null ;
49+ $ flagArg = $ args [3 ] ?? null ;
50+ $ patternType = $ scope ->getType ($ patternArg ->value );
51+ $ patternConstantTypes = $ patternType ->getConstantStrings ();
52+ $ subjectType = $ scope ->getType ($ subjectArg ->value );
53+ $ subjectConstantTypes = $ subjectType ->getConstantStrings ();
54+
55+ if (
56+ count ($ patternConstantTypes ) > 0 &&
57+ @preg_match ($ patternConstantTypes [0 ]->getValue (), "" ) === false
58+ ) {
59+
60+ return new ErrorType ();
61+ }
4062
41- if ($ flagsArg !== null && $ this ->bitwiseFlagAnalyser ->bitwiseOrContainsConstant ($ flagsArg ->value , $ scope , 'PREG_SPLIT_OFFSET_CAPTURE ' )->yes ()) {
63+ if ($ subjectArg !== null && $ this ->bitwiseFlagAnalyser ->bitwiseOrContainsConstant ($ subjectArg ->value , $ scope , 'PREG_SPLIT_OFFSET_CAPTURE ' )->yes ()) {
4264 $ type = new ArrayType (
4365 new IntegerType (),
4466 new ConstantArrayType ([new ConstantIntegerType (0 ), new ConstantIntegerType (1 )], [new StringType (), IntegerRangeType::fromInterval (0 , null )], [2 ], [], TrinaryLogic::createYes ()),
4567 );
4668 return TypeCombinator::union (TypeCombinator::intersect ($ type , new AccessoryArrayListType ()), new ConstantBooleanType (false ));
4769 }
4870
49- return null ;
50- }
71+ if ($ limitArg === null ) {
72+ $ limits = [-1 ];
73+ } else {
74+ $ limitType = $ scope ->getType ($ limitArg ->value );
75+ $ limits = $ limitType ->getConstantScalarValues ();
76+ }
5177
78+ if ($ flagArg === null ) {
79+ $ flags = [0 ];
80+ } else {
81+ $ flagType = $ scope ->getType ($ flagArg ->value );
82+ $ flags = $ flagType ->getConstantScalarValues ();
83+ }
84+
85+ if (count ($ patternConstantTypes ) === 0 || count ($ subjectConstantTypes ) === 0 || count ($ flags ) === 0 ) {
86+ return null ;
87+ }
88+
89+ $ resultTypes = [];
90+ foreach ($ patternConstantTypes as $ patternConstantType ) {
91+ foreach ($ subjectConstantTypes as $ subjectConstantType ) {
92+ foreach ($ flags as $ flag ) {
93+ foreach ($ limits as $ limit ) {
94+ $ result = @preg_split ($ patternConstantType ->getValue (), $ subjectConstantType ->getValue (), $ limit , $ flag );
95+ if ($ result !== false ) {
96+ $ constantArray = ConstantArrayTypeBuilder::createEmpty ();
97+ foreach ($ result as $ key => $ value ) {
98+ assert (is_int ($ key ));
99+ if (is_array ($ value )) {
100+ $ valueConstantArray = ConstantArrayTypeBuilder::createEmpty ();
101+ $ valueConstantArray ->setOffsetValueType (new ConstantIntegerType (0 ), new ConstantStringType ($ value [0 ]));
102+ $ valueConstantArray ->setOffsetValueType (new ConstantIntegerType (1 ), new ConstantIntegerType ($ value [1 ]));
103+ $ valueType = $ valueConstantArray ->getArray ();
104+ } else {
105+ $ valueType = new ConstantStringType ($ value );
106+ }
107+ $ constantArray ->setOffsetValueType (new ConstantIntegerType ($ key ), $ valueType );
108+ }
109+ $ resultTypes [] = $ constantArray ->getArray ();
110+ }
111+ }
112+ }
113+ }
114+ }
115+ return TypeCombinator::union (...$ resultTypes );
116+ }
52117}
0 commit comments