file_provider = new Provider\FakeFileProvider(); $this->project_checker = new \Psalm\Checker\ProjectChecker( $this->file_provider, new Provider\FakeParserCacheProvider() ); } /** * @return string[] * @psalm-return array */ public static function getAllIssues() { return array_filter( array_map( /** * @param string $file_name * * @return string */ function ($file_name) { return substr($file_name, 0, -4); }, scandir(dirname(__DIR__) . '/src/Psalm/Issue') ), /** * @param string $issue_name * * @return bool */ function ($issue_name) { return !empty($issue_name) && $issue_name !== 'CodeError' && $issue_name !== 'CodeIssue'; } ); } /** * @return void */ public function testBarebonesConfig() { $config = Config::loadFromXML( 'psalm.xml', (string)getcwd(), ' ' ); $this->assertTrue($config->isInProjectDirs(realpath('src/Psalm/Type.php'))); $this->assertFalse($config->isInProjectDirs(realpath('examples/StringChecker.php'))); } /** * @return void */ public function testIgnoreProjectDirectory() { $config = Config::loadFromXML( 'psalm.xml', dirname(__DIR__), ' ' ); $this->assertTrue($config->isInProjectDirs(realpath('src/Psalm/Type.php'))); $this->assertFalse($config->isInProjectDirs(realpath('src/Psalm/Checker/FileChecker.php'))); $this->assertFalse($config->isInProjectDirs(realpath('examples/StringChecker.php'))); } /** * @return void */ public function testIssueHandler() { $config = Config::loadFromXML( 'psalm.xml', dirname(__DIR__), ' ' ); $this->assertFalse($config->reportIssueInFile('MissingReturnType', realpath('tests/ConfigTest.php'))); $this->assertFalse($config->reportIssueInFile('MissingReturnType', realpath('src/Psalm/Type.php'))); } /** * @return void */ public function testIssueHandlerWithCustomErrorLevels() { $config = Config::loadFromXML( 'psalm.xml', dirname(__DIR__), ' ' ); $this->assertSame( 'info', $config->getReportingLevelForFile( 'MissingReturnType', realpath('src/Psalm/Type.php') ) ); $this->assertSame( 'error', $config->getReportingLevelForFile( 'MissingReturnType', realpath('src/Psalm/Checker/FileChecker.php') ) ); } /** * @return void */ public function testAllPossibleIssues() { $all_possible_handlers = implode( ' ', array_map( /** * @param string $issue_name * * @return string */ function ($issue_name) { return '<' . $issue_name . ' errorLevel="suppress" />' . PHP_EOL; }, self::getAllIssues() ) ); Config::loadFromXML( 'psalm.xml', dirname(__DIR__), ' ' . $all_possible_handlers . ' ' ); } /** * @expectedException \Psalm\Exception\ConfigException * @expectedExceptionMessage This element is not expected * * @return void */ public function testImpossibleIssue() { Config::loadFromXML( 'psalm.xml', dirname(__DIR__), ' ' ); } /** * @expectedException \Psalm\Exception\ConfigException * @expectedExceptionMessage Cannot resolve stubfile path * * @return void */ public function testNonexistentStubFile() { Config::loadFromXML( 'psalm.xml', dirname(__DIR__), ' ' ); } /** * @return void */ public function testStubFile() { $this->project_checker->setConfig( TestConfig::loadFromXML( 'psalm.xml', dirname(__DIR__), ' ' ) ); $this->addFile( getcwd() . '/src/somefile.php', 'foo(5, "hello"); $c = SystemClass::bar(5, "hello");' ); $file_checker = new FileChecker(getcwd() . '/src/somefile.php', $this->project_checker); $file_checker->visitAndAnalyzeMethods(); $this->project_checker->checkClassReferences(); } /** * @return void */ public function testNamespacedStubClass() { $this->project_checker->setConfig( TestConfig::loadFromXML( 'psalm.xml', dirname(__DIR__), ' ' ) ); $this->addFile( getcwd() . '/src/somefile.php', 'foo(5, "hello"); $c = Foo\SystemClass::bar(5, "hello");' ); $file_checker = new FileChecker(getcwd() . '/src/somefile.php', $this->project_checker); $file_checker->visitAndAnalyzeMethods(); $this->project_checker->checkClassReferences(); } /** * @return void */ public function testStubFunction() { $this->project_checker->setConfig( TestConfig::loadFromXML( 'psalm.xml', dirname(__DIR__), ' ' ) ); $this->addFile( getcwd() . '/src/somefile.php', 'project_checker); $file_checker->visitAndAnalyzeMethods(); $this->project_checker->checkClassReferences(); } /** * @return void */ public function testNamespacedStubFunction() { $this->project_checker->setConfig( TestConfig::loadFromXML( 'psalm.xml', dirname(__DIR__), ' ' ) ); $this->addFile( getcwd() . '/src/somefile.php', 'project_checker); $file_checker->visitAndAnalyzeMethods(); $this->project_checker->checkClassReferences(); } /** * @return void */ public function testConditionalNamespacedStubFunction() { $this->project_checker->setConfig( TestConfig::loadFromXML( 'psalm.xml', dirname(__DIR__), ' ' ) ); $this->addFile( getcwd() . '/src/somefile.php', 'project_checker); $file_checker->visitAndAnalyzeMethods(); $this->project_checker->checkClassReferences(); } /** * @return void */ public function testStubFileWithExistingClassDefinition() { $this->project_checker->setConfig( TestConfig::loadFromXML( 'psalm.xml', dirname(__DIR__), ' ' ) ); $this->addFile( getcwd() . '/src/somefile.php', 'project_checker); $file_checker->visitAndAnalyzeMethods(); $this->project_checker->checkClassReferences(); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage MissingReturnType * * @return void */ public function testRequireVoidReturnTypeExists() { $this->project_checker->setConfig( TestConfig::loadFromXML( 'psalm.xml', dirname(__DIR__), ' ' ) ); $this->addFile( getcwd() . '/src/somefile.php', 'project_checker); $file_checker->visitAndAnalyzeMethods(); $this->project_checker->checkClassReferences(); } /** * @return void */ public function testDoNotRequireVoidReturnTypeExists() { $this->project_checker->setConfig( TestConfig::loadFromXML( 'psalm.xml', dirname(__DIR__), ' ' ) ); $this->addFile( getcwd() . '/src/somefile.php', 'project_checker); $file_checker->visitAndAnalyzeMethods(); $this->project_checker->checkClassReferences(); } /** * @return void */ public function testTemplatedFiles() { foreach (['1.xml', '2.xml', '3.xml', '4.xml', '5.xml'] as $file_name) { Config::loadFromXMLFile( realpath(dirname(__DIR__) . '/assets/config_levels/' . $file_name), dirname(__DIR__) ); } } }