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, false); return $project_analyzer; } /** * @expectedException \Psalm\Exception\ConfigException * @expectedExceptionMessage Cannot resolve stubfile path * * @return void */ public function testNonexistentStubFile() { $this->project_analyzer = $this->getProjectAnalyzerWithConfig( Config::loadFromXML( dirname(__DIR__), ' ' ) ); } /** * @return void */ public function testStubFile() { $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");' ); $this->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()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage InvalidScalarArgument * * @return void */ public function testStubVariadicFunctionWrongArgType() { $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__), ' ' ) ); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage TooManyArguments * * @return void */ public function testUserVariadicWithFalseVariadic() { $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()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage UndefinedFunction - /src/somefile.php:2:22 - Function barBar does not exist * * @return void */ public function testNoStubFunction() { $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 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()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage TypeCoercion * * @return void */ public function testStubFileWithPartialClassDefinitionWithCoercion() { $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()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage InvalidReturnStatement * * @return void */ public function testStubFileWithPartialClassDefinitionGeneralReturnType() { $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__), ' ' ) ); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } }