mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 20:34:47 +01:00
5a14e4b1cf
* Revert "Revert "Implement better progress"" This reverts commit4302596654
. * Revert "Revert "Implement dots progress bar"" This reverts commite41733d789
. * Revert "Revert "Switch to VoidProgress by default"" This reverts commit304ffeb0a3
. * Revert "Revert "Pass success flag to progress"" This reverts commit62a690ee4e
. * Improve socket communication * Use an underscore * Add means to disable progress * Add extra newline before progress bar
879 lines
23 KiB
PHP
879 lines
23 KiB
PHP
<?php
|
|
namespace Psalm\Tests;
|
|
|
|
use Psalm\Config;
|
|
use Psalm\Context;
|
|
use Psalm\Internal\Analyzer\FileAnalyzer;
|
|
use Psalm\Tests\Internal\Provider;
|
|
|
|
class StubTest extends TestCase
|
|
{
|
|
/** @var TestConfig */
|
|
protected static $config;
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public static function setUpBeforeClass() : void
|
|
{
|
|
self::$config = new TestConfig();
|
|
|
|
if (!defined('PSALM_VERSION')) {
|
|
define('PSALM_VERSION', '2.0.0');
|
|
}
|
|
|
|
if (!defined('PHP_PARSER_VERSION')) {
|
|
define('PHP_PARSER_VERSION', '4.0.0');
|
|
}
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function setUp() : void
|
|
{
|
|
FileAnalyzer::clearCache();
|
|
$this->file_provider = new Provider\FakeFileProvider();
|
|
}
|
|
|
|
/**
|
|
* @param Config $config
|
|
*
|
|
* @return \Psalm\Internal\Analyzer\ProjectAnalyzer
|
|
*/
|
|
private function getProjectAnalyzerWithConfig(Config $config)
|
|
{
|
|
$project_analyzer = new \Psalm\Internal\Analyzer\ProjectAnalyzer(
|
|
$config,
|
|
new \Psalm\Internal\Provider\Providers(
|
|
$this->file_provider,
|
|
new Provider\FakeParserCacheProvider()
|
|
)
|
|
);
|
|
$project_analyzer->setPhpVersion('7.3');
|
|
|
|
$config->visitComposerAutoloadFiles($project_analyzer, null);
|
|
|
|
return $project_analyzer;
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testNonexistentStubFile()
|
|
{
|
|
$this->expectException(\Psalm\Exception\ConfigException::class);
|
|
$this->expectExceptionMessage('Cannot resolve stubfile path');
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
Config::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="stubs/invalidfile.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testStubFileClass()
|
|
{
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/systemclass.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
namespace A\B\C;
|
|
|
|
$a = new \SystemClass();
|
|
$b = $a->foo(5, "hello");
|
|
$c = \SystemClass::bar(5, "hello");
|
|
echo \SystemClass::HELLO;'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testStubFileConstant()
|
|
{
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/systemclass.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
namespace A\B\C;
|
|
|
|
$d = ROOT_CONST_CONSTANT;
|
|
$e = \ROOT_CONST_CONSTANT;
|
|
$f = ROOT_DEFINE_CONSTANT;
|
|
$g = \ROOT_DEFINE_CONSTANT;'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testPhpStormMetaParsingFile()
|
|
{
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/phpstorm.meta.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
namespace Ns {
|
|
class MyClass {
|
|
/**
|
|
* @return mixed
|
|
* @psalm-suppress InvalidReturnType
|
|
*/
|
|
public function create(string $s) {}
|
|
|
|
/**
|
|
* @param mixed $s
|
|
* @return mixed
|
|
* @psalm-suppress InvalidReturnType
|
|
*/
|
|
public function foo($s) {}
|
|
|
|
/**
|
|
* @return mixed
|
|
* @psalm-suppress InvalidReturnType
|
|
*/
|
|
public function bar(array $a) {}
|
|
}
|
|
}
|
|
namespace {
|
|
/**
|
|
* @return mixed
|
|
* @psalm-suppress InvalidReturnType
|
|
*/
|
|
function create(string $s) {}
|
|
|
|
/**
|
|
* @param mixed $s
|
|
* @return mixed
|
|
* @psalm-suppress InvalidReturnType
|
|
*/
|
|
function foo($s) {}
|
|
|
|
/**
|
|
* @return mixed
|
|
* @psalm-suppress InvalidReturnType
|
|
*/
|
|
function bar(array $a) {}
|
|
|
|
$a1 = (new \Ns\MyClass)->create("object");
|
|
$a2 = (new \Ns\MyClass)->create("exception");
|
|
|
|
$b1 = \create("object");
|
|
$b2 = \create("exception");
|
|
|
|
$e2 = \create(\LogicException::class);
|
|
|
|
$c1 = (new \Ns\MyClass)->foo(5);
|
|
$c2 = (new \Ns\MyClass)->bar(["hello"]);
|
|
|
|
$d1 = \foo(5);
|
|
$d2 = \bar(["hello"]);
|
|
}'
|
|
);
|
|
|
|
$context = new Context();
|
|
$this->analyzeFile($file_path, $context);
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testNamespacedStubClass()
|
|
{
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/namespaced_class.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
$a = new Foo\SystemClass();
|
|
echo Foo\SystemClass::HELLO;
|
|
|
|
$b = $a->foo(5, "hello");
|
|
$c = Foo\SystemClass::bar(5, "hello");
|
|
|
|
echo Foo\BAR;'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testStubRegularFunction()
|
|
{
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/custom_functions.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
echo barBar("hello");'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testStubVariadicFunction()
|
|
{
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/custom_functions.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
variadic("bat", "bam");'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testStubVariadicFunctionWrongArgType()
|
|
{
|
|
$this->expectExceptionMessage('InvalidScalarArgument');
|
|
$this->expectException(\Psalm\Exception\CodeException::class);
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/custom_functions.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
variadic("bat", 5);'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testUserVariadicWithFalseVariadic()
|
|
{
|
|
$this->expectExceptionMessage('TooManyArguments');
|
|
$this->expectException(\Psalm\Exception\CodeException::class);
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
/**
|
|
* @param string ...$bar
|
|
*/
|
|
function variadic() : void {}
|
|
variadic("hello");'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testPolyfilledFunction()
|
|
{
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm
|
|
autoloader="tests/fixtures/stubs/polyfill.php"
|
|
>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
$a = random_bytes(16);
|
|
$b = new_random_bytes(16);'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testClassAlias()
|
|
{
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm
|
|
autoloader="tests/fixtures/stubs/class_alias.php"
|
|
>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
namespace ClassAliasStubTest;
|
|
|
|
function foo(A $a) : void {}
|
|
|
|
foo(new B());
|
|
foo(new C());
|
|
|
|
function bar(B $b) : void {}
|
|
|
|
bar(new A());
|
|
|
|
$a = new B();
|
|
|
|
echo $a->foo;
|
|
|
|
echo $a->bar("hello");
|
|
|
|
function f(): A {
|
|
return new A;
|
|
}
|
|
|
|
function getAliased(): B {
|
|
return f();
|
|
}
|
|
|
|
$d = new D();
|
|
|
|
D::bat();
|
|
$d::bat();
|
|
|
|
class E implements IAlias {}'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testStubFunctionWithFunctionExists()
|
|
{
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/custom_functions.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
function_exists("fooBar");
|
|
echo barBar("hello");'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testNamespacedStubFunctionWithFunctionExists()
|
|
{
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/custom_functions.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
namespace A;
|
|
function_exists("fooBar");
|
|
echo barBar("hello");'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testNoStubFunction()
|
|
{
|
|
$this->expectExceptionMessage('UndefinedFunction - /src/somefile.php:2:22 - Function barBar does not exist');
|
|
$this->expectException(\Psalm\Exception\CodeException::class);
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
echo barBar("hello");'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testNamespacedStubFunction()
|
|
{
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/namespaced_functions.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
echo Foo\barBar("hello");'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testConditionalNamespacedStubFunction()
|
|
{
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/conditional_namespaced_functions.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
echo Foo\barBar("hello");'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testStubFileWithExistingClassDefinition()
|
|
{
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/DomainException.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
$a = new DomainException(5);'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testStubFileWithPartialClassDefinitionWithMoreMethods()
|
|
{
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/partial_class.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
namespace Foo;
|
|
|
|
class PartiallyStubbedClass {
|
|
/**
|
|
* @param string $a
|
|
* @return object
|
|
*/
|
|
public function foo(string $a) {
|
|
return new self;
|
|
}
|
|
|
|
public function bar(int $i) : void {}
|
|
}
|
|
|
|
class A {}
|
|
|
|
(new PartiallyStubbedClass())->foo(A::class);
|
|
(new PartiallyStubbedClass())->bar(5);'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testStubFileWithExtendedStubbedClass()
|
|
{
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/partial_class.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
namespace Foo;
|
|
|
|
class Bar extends PartiallyStubbedClass {}
|
|
|
|
new Bar();'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
* @return void
|
|
*/
|
|
public function testStubFileWithPartialClassDefinitionWithCoercion()
|
|
{
|
|
$this->expectExceptionMessage('TypeCoercion');
|
|
$this->expectException(\Psalm\Exception\CodeException::class);
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/partial_class.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
namespace Foo;
|
|
|
|
class PartiallyStubbedClass {
|
|
/**
|
|
* @param string $a
|
|
* @return object
|
|
*/
|
|
public function foo(string $a) {
|
|
return new self;
|
|
}
|
|
}
|
|
|
|
(new PartiallyStubbedClass())->foo("dasda");'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
|
|
/**
|
|
*
|
|
* @return void
|
|
*/
|
|
public function testStubFileWithPartialClassDefinitionGeneralReturnType()
|
|
{
|
|
$this->expectExceptionMessage('InvalidReturnStatement');
|
|
$this->expectException(\Psalm\Exception\CodeException::class);
|
|
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
|
|
TestConfig::loadFromXML(
|
|
dirname(__DIR__),
|
|
'<?xml version="1.0"?>
|
|
<psalm>
|
|
<projectFiles>
|
|
<directory name="src" />
|
|
</projectFiles>
|
|
|
|
<stubs>
|
|
<file name="tests/fixtures/stubs/partial_class.php" />
|
|
</stubs>
|
|
</psalm>'
|
|
)
|
|
);
|
|
|
|
$file_path = getcwd() . '/src/somefile.php';
|
|
|
|
$this->addFile(
|
|
$file_path,
|
|
'<?php
|
|
namespace Foo;
|
|
|
|
class PartiallyStubbedClass {
|
|
/**
|
|
* @param string $a
|
|
* @return object
|
|
*/
|
|
public function foo(string $a) {
|
|
return new \stdClass;
|
|
}
|
|
}'
|
|
);
|
|
|
|
$this->analyzeFile($file_path, new Context());
|
|
}
|
|
}
|