2016-12-12 05:41:11 +01:00
|
|
|
<?php
|
|
|
|
namespace Psalm\Tests;
|
|
|
|
|
2017-04-25 05:45:02 +02:00
|
|
|
class MethodCallTest extends TestCase
|
2016-12-12 05:41:11 +01:00
|
|
|
{
|
2017-04-25 05:45:02 +02:00
|
|
|
use Traits\FileCheckerInvalidCodeParseTestTrait;
|
|
|
|
use Traits\FileCheckerValidCodeParseTestTrait;
|
2016-12-31 15:20:10 +01:00
|
|
|
|
2016-12-17 04:16:29 +01:00
|
|
|
/**
|
2017-04-25 05:45:02 +02:00
|
|
|
* @return array
|
2016-12-17 04:16:29 +01:00
|
|
|
*/
|
2017-04-25 05:45:02 +02:00
|
|
|
public function providerFileCheckerValidCodeParse()
|
2016-12-17 04:16:29 +01:00
|
|
|
{
|
2017-04-25 05:45:02 +02:00
|
|
|
return [
|
2017-07-09 20:36:06 +02:00
|
|
|
'notInCallMapTest' => [
|
|
|
|
'<?php
|
2017-07-25 22:11:02 +02:00
|
|
|
new DOMImplementation();',
|
2017-07-09 20:36:06 +02:00
|
|
|
],
|
2017-04-25 05:45:02 +02:00
|
|
|
'parentStaticCall' => [
|
|
|
|
'<?php
|
|
|
|
class A {
|
|
|
|
/** @return void */
|
|
|
|
public static function foo(){}
|
|
|
|
}
|
2017-07-09 20:36:06 +02:00
|
|
|
|
2017-04-25 05:45:02 +02:00
|
|
|
class B extends A {
|
|
|
|
/** @return void */
|
|
|
|
public static function bar(){
|
|
|
|
parent::foo();
|
|
|
|
}
|
2017-05-27 02:05:57 +02:00
|
|
|
}',
|
2017-04-25 05:45:02 +02:00
|
|
|
],
|
|
|
|
'nonStaticInvocation' => [
|
|
|
|
'<?php
|
|
|
|
class Foo {
|
|
|
|
public static function barBar() : void {}
|
|
|
|
}
|
2017-07-09 20:36:06 +02:00
|
|
|
|
2017-05-27 02:05:57 +02:00
|
|
|
(new Foo())->barBar();',
|
2017-04-25 05:45:02 +02:00
|
|
|
],
|
|
|
|
'staticInvocation' => [
|
|
|
|
'<?php
|
|
|
|
class A {
|
|
|
|
public static function fooFoo() : void {}
|
|
|
|
}
|
2017-07-09 20:36:06 +02:00
|
|
|
|
2017-04-25 05:45:02 +02:00
|
|
|
class B extends A {
|
2017-07-09 20:36:06 +02:00
|
|
|
|
2017-04-25 05:45:02 +02:00
|
|
|
}
|
2017-07-09 20:36:06 +02:00
|
|
|
|
2017-05-27 02:05:57 +02:00
|
|
|
B::fooFoo();',
|
|
|
|
],
|
2017-11-06 21:37:49 +01:00
|
|
|
'staticCallOnVar' => [
|
|
|
|
'<?php
|
|
|
|
class A {
|
|
|
|
public static function bar() : int {
|
|
|
|
return 5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$foo = new A;
|
|
|
|
$b = $foo::bar();',
|
|
|
|
],
|
2017-04-25 05:45:02 +02:00
|
|
|
];
|
2016-12-17 04:16:29 +01:00
|
|
|
}
|
2017-02-12 06:50:37 +01:00
|
|
|
|
|
|
|
/**
|
2017-04-25 05:45:02 +02:00
|
|
|
* @return array
|
2017-02-12 06:50:37 +01:00
|
|
|
*/
|
2017-04-25 05:45:02 +02:00
|
|
|
public function providerFileCheckerInvalidCodeParse()
|
2017-02-12 06:50:37 +01:00
|
|
|
{
|
2017-04-25 05:45:02 +02:00
|
|
|
return [
|
|
|
|
'staticInvocation' => [
|
|
|
|
'<?php
|
|
|
|
class Foo {
|
|
|
|
public function barBar() : void {}
|
|
|
|
}
|
2017-07-09 20:36:06 +02:00
|
|
|
|
2017-04-25 05:45:02 +02:00
|
|
|
Foo::barBar();',
|
2017-05-27 02:05:57 +02:00
|
|
|
'error_message' => 'InvalidStaticInvocation',
|
2017-04-25 05:45:02 +02:00
|
|
|
],
|
|
|
|
'parentStaticCall' => [
|
|
|
|
'<?php
|
|
|
|
class A {
|
|
|
|
/** @return void */
|
|
|
|
public function foo(){}
|
|
|
|
}
|
2017-07-09 20:36:06 +02:00
|
|
|
|
2017-04-25 05:45:02 +02:00
|
|
|
class B extends A {
|
|
|
|
/** @return void */
|
|
|
|
public static function bar(){
|
|
|
|
parent::foo();
|
|
|
|
}
|
|
|
|
}',
|
2017-05-27 02:05:57 +02:00
|
|
|
'error_message' => 'InvalidStaticInvocation',
|
2017-04-25 05:45:02 +02:00
|
|
|
],
|
|
|
|
'mixedMethodCall' => [
|
|
|
|
'<?php
|
|
|
|
class Foo {
|
|
|
|
public static function barBar() : void {}
|
|
|
|
}
|
2017-07-09 20:36:06 +02:00
|
|
|
|
2017-04-25 05:45:02 +02:00
|
|
|
/** @var mixed */
|
|
|
|
$a = (new Foo());
|
2017-07-09 20:36:06 +02:00
|
|
|
|
2017-04-25 05:45:02 +02:00
|
|
|
$a->barBar();',
|
|
|
|
'error_message' => 'MixedMethodCall',
|
|
|
|
'error_levels' => [
|
|
|
|
'MissingPropertyType',
|
2017-05-27 02:05:57 +02:00
|
|
|
'MixedAssignment',
|
|
|
|
],
|
2017-04-25 05:45:02 +02:00
|
|
|
],
|
|
|
|
'selfNonStaticInvocation' => [
|
|
|
|
'<?php
|
|
|
|
class A {
|
|
|
|
public function fooFoo() : void {}
|
2017-07-09 20:36:06 +02:00
|
|
|
|
2017-04-25 05:45:02 +02:00
|
|
|
public function barBar() : void {
|
|
|
|
self::fooFoo();
|
|
|
|
}
|
|
|
|
}',
|
2017-05-27 02:05:57 +02:00
|
|
|
'error_message' => 'NonStaticSelfCall',
|
2017-04-25 05:45:02 +02:00
|
|
|
],
|
|
|
|
'noParent' => [
|
|
|
|
'<?php
|
|
|
|
class Foo {
|
|
|
|
public function barBar() : void {
|
|
|
|
parent::barBar();
|
|
|
|
}
|
|
|
|
}',
|
2017-05-27 02:05:57 +02:00
|
|
|
'error_message' => 'ParentNotFound',
|
2017-04-25 05:45:02 +02:00
|
|
|
],
|
|
|
|
'coercedClass' => [
|
|
|
|
'<?php
|
|
|
|
class NullableClass {
|
|
|
|
}
|
2017-07-09 20:36:06 +02:00
|
|
|
|
2017-04-25 05:45:02 +02:00
|
|
|
class NullableBug {
|
|
|
|
/**
|
|
|
|
* @param string $className
|
|
|
|
* @return object|null
|
|
|
|
*/
|
|
|
|
public static function mock($className) {
|
|
|
|
if (!$className) { return null; }
|
|
|
|
return new $className();
|
|
|
|
}
|
2017-07-09 20:36:06 +02:00
|
|
|
|
2017-04-25 05:45:02 +02:00
|
|
|
/**
|
|
|
|
* @return NullableClass
|
|
|
|
*/
|
|
|
|
public function returns_nullable_class() {
|
|
|
|
return self::mock("NullableClass");
|
|
|
|
}
|
|
|
|
}',
|
|
|
|
'error_message' => 'MoreSpecificReturnType',
|
2017-05-27 02:05:57 +02:00
|
|
|
'error_levels' => ['MixedInferredReturnType'],
|
|
|
|
],
|
2017-11-06 21:37:49 +01:00
|
|
|
'undefinedVariableStaticCall' => [
|
|
|
|
'<?php
|
|
|
|
$foo::bar();',
|
|
|
|
'error_message' => 'UndefinedVariable',
|
|
|
|
],
|
|
|
|
'staticCallOnString' => [
|
|
|
|
'<?php
|
|
|
|
class A {
|
|
|
|
public static function bar() : int {
|
|
|
|
return 5;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
$foo = "A";
|
|
|
|
$b = $foo::bar();',
|
|
|
|
'error_message' => 'MixedAssignment',
|
|
|
|
],
|
2017-04-25 05:45:02 +02:00
|
|
|
];
|
2017-02-12 06:50:37 +01:00
|
|
|
}
|
2016-12-12 05:41:11 +01:00
|
|
|
}
|