addFile( 'somefile.php', ' 5, "b" => 12, "c" => null]); $e = array_filter(["a" => 5, "b" => 12, "c" => null], function(?int $i) : bool { return true; });' ); $file_checker = new FileChecker('somefile.php', $this->project_checker); $context = new Context(); $file_checker->visitAndAnalyzeMethods($context); $this->project_checker->checkClassReferences(); $this->assertSame('array', (string) $context->vars_in_scope['$d']); $this->assertSame('array', (string) $context->vars_in_scope['$e']); } /** * @return void */ public function testArrayFilterAdvanced() { if (version_compare((string)PHP_VERSION, '5.6.0', '>=')) { $this->addFile( 'somefile.php', ' 5, "b" => 12, "c" => null], function(?int $val, string $key) : bool { return true; }, ARRAY_FILTER_USE_BOTH); $g = array_filter(["a" => 5, "b" => 12, "c" => null], function(string $val) : bool { return true; }, ARRAY_FILTER_USE_KEY); $bar = "bar"; $foo = [ $bar => function () : string { return "baz"; }, ]; $foo = array_filter( $foo, function (string $key) : bool { return $key === "bar"; }, ARRAY_FILTER_USE_KEY );' ); $file_checker = new FileChecker('somefile.php', $this->project_checker); $context = new Context(); $file_checker->visitAndAnalyzeMethods($context); $this->project_checker->checkClassReferences(); $this->assertSame('array', (string) $context->vars_in_scope['$f']); $this->assertSame('array', (string) $context->vars_in_scope['$g']); } } /** * @return void */ public function testArrayFilterUseKey() { if (version_compare((string)PHP_VERSION, '5.6.0', '>=')) { $this->addFile( getcwd() . '/src/somefile.php', ' function () : string { return "baz"; }, ]; $foo = array_filter( $foo, function (string $key) : bool { return $key === "bar"; }, ARRAY_FILTER_USE_KEY );' ); $file_checker = new FileChecker(getcwd() . '/src/somefile.php', $this->project_checker); $context = new Context(); $file_checker->visitAndAnalyzeMethods($context); $this->project_checker->checkClassReferences(); } } /** * @return array */ public function providerFileCheckerValidCodeParse() { return [ 'typedArrayWithDefault' => [ ' $a */ function fooFoo(array $a = []) : void { }', ], 'typedArrayWithDefault' => [ ' [ '$a' => 'int', '$b' => 'int', ], ], 'validDocblockParamDefault' => [ ' [ ' [ ' [ ' [ ' [ ' 1, "b" => 2]);', 'assertions' => [ '$a' => 'array', ], ], 'arrayKeysMixed' => [ ' 5]; $a = array_keys($b);', 'assertions' => [ '$a' => 'array', ], 'error_levels' => ['MixedArgument'], ], 'arrayValues' => [ ' 1, "b" => 2]);', 'assertions' => [ '$b' => 'array', ], ], 'arrayCombine' => [ ' [ '$c' => 'array', ], ], 'arrayMerge' => [ ' [ '$d' => 'array', ], ], 'arrayDiff' => [ ' 5, "b" => 12], [5]);', 'assertions' => [ '$d' => 'array', ], ], 'byRefAfterCallable' => [ ' [], 'error_levels' => [ 'MixedAssignment', 'MixedArrayAccess', ], ], 'extractVarCheck' => [ ' "bar"]; extract($a); takesString($foo);', 'assertions' => [], 'error_levels' => [ 'MixedAssignment', 'MixedArrayAccess', ], ], 'arrayMergeObjectLike' => [ ' $a * @return array */ function foo($a) { return $a; } $a1 = ["hi" => 3]; $a2 = ["bye" => 5]; $a3 = array_merge($a1, $a2); foo($a3);', ], ]; } /** * @return array */ public function providerFileCheckerInvalidCodeParse() { return [ 'invalidScalarArgument' => [ ' 'InvalidScalarArgument', ], 'mixedArgument' => [ ' 'MixedArgument', 'error_levels' => ['MixedAssignment'], ], 'nullArgument' => [ ' 'NullArgument', ], 'tooFewArguments' => [ ' 'TooFewArguments', ], 'tooManyArguments' => [ ' 'TooManyArguments', ], 'tooManyArgumentsForConstructor' => [ ' 'TooManyArguments', ], 'typeCoercion' => [ ' 'TypeCoercion', ], 'arrayTypeCoercion' => [ ' 'TypeCoercion', ], 'duplicateParam' => [ ' 'DuplicateParam', ], 'invalidParamDefault' => [ ' 'InvalidParamDefault', ], 'invalidDocblockParamDefault' => [ ' 'InvalidParamDefault', ], // Skipped. Does not throw an error. 'SKIPPED-badByRef' => [ ' 'InvalidPassByReference', ], 'invalidArgAfterCallable' => [ ' 'InvalidScalarArgument', 'error_levels' => [ 'MixedAssignment', 'MixedArrayAccess', ], ], ]; } }