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__),
'
'
)
);
}
/**
* @return void
*/
public function testStubFileClass()
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
TestConfig::loadFromXML(
dirname(__DIR__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'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__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'analyzeFile($file_path, new Context());
}
/**
* @return void
*/
public function testPhpStormMetaParsingFile()
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
TestConfig::loadFromXML(
dirname(__DIR__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'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__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'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__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'analyzeFile($file_path, new Context());
}
/**
* @return void
*/
public function testStubVariadicFunction()
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
TestConfig::loadFromXML(
dirname(__DIR__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'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__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'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__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'analyzeFile($file_path, new Context());
}
/**
* @return void
*/
public function testPolyfilledFunction()
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
TestConfig::loadFromXML(
dirname(__DIR__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'analyzeFile($file_path, new Context());
}
/**
* @return void
*/
public function testClassAlias()
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
TestConfig::loadFromXML(
dirname(__DIR__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'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__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'analyzeFile($file_path, new Context());
}
/**
* @return void
*/
public function testNamespacedStubFunctionWithFunctionExists()
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
TestConfig::loadFromXML(
dirname(__DIR__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'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__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'analyzeFile($file_path, new Context());
}
/**
* @return void
*/
public function testNamespacedStubFunction()
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
TestConfig::loadFromXML(
dirname(__DIR__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'analyzeFile($file_path, new Context());
}
/**
* @return void
*/
public function testConditionalNamespacedStubFunction()
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
TestConfig::loadFromXML(
dirname(__DIR__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'analyzeFile($file_path, new Context());
}
/**
* @return void
*/
public function testConditionallyExtendingInterface()
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
TestConfig::loadFromXML(
dirname(__DIR__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'getMessage();
}
function bar(I6 $d) : void {
$d->getMessage();
}
function bat(I7 $d) : void {
$d->getMessage();
}
function baz(I8 $d) : void {
$d->getMessage();
}'
);
$this->analyzeFile($file_path, new Context());
}
/**
* @return void
*/
public function testStubFileWithExistingClassDefinition()
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
TestConfig::loadFromXML(
dirname(__DIR__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'analyzeFile($file_path, new Context());
}
/**
* @return void
*/
public function testStubFileWithPartialClassDefinitionWithMoreMethods()
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
TestConfig::loadFromXML(
dirname(__DIR__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'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__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'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__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'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__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'analyzeFile($file_path, new Context());
}
/**
* @return void
*/
public function testStubFileWithTemplatedClassDefinitionAndMagicMethodOverride()
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
TestConfig::loadFromXML(
dirname(__DIR__),
'
'
)
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'analyzeFile($file_path, new Context());
}
public function testInheritedMethodUsedInStub() : void
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
TestConfig::loadFromXML(
dirname(__DIR__),
'
'
)
);
$this->project_analyzer->getCodebase()->reportUnusedCode();
$vendor_file_path = getcwd() . '/vendor/vendor_class.php';
$this->addFile(
$vendor_file_path,
'foo();
}
}'
);
$file_path = getcwd() . '/src/somefile.php';
$this->addFile(
$file_path,
'collect_references = true;
$this->analyzeFile($file_path, $context, false);
$this->project_analyzer->consolidateAnalyzedData();
}
}