file_provider = new Provider\FakeFileProvider(); } /** * @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 !== 'MethodIssue' && $issue_name !== 'PropertyIssue' && $issue_name !== 'ClassIssue' && $issue_name !== 'CodeIssue'; } ); } /** * @param Config $config * * @return \Psalm\Checker\ProjectChecker */ private function getProjectCheckerWithConfig(Config $config) { return new \Psalm\Checker\ProjectChecker( $config, new \Psalm\Provider\Providers( $this->file_provider, new Provider\FakeParserCacheProvider() ) ); } /** * @return void */ public function testBarebonesConfig() { $this->project_checker = $this->getProjectCheckerWithConfig( Config::loadFromXML( (string)getcwd(), ' ' ) ); $config = $this->project_checker->getConfig(); $this->assertTrue($config->isInProjectDirs(realpath('src/Psalm/Type.php'))); $this->assertFalse($config->isInProjectDirs(realpath('examples/StringChecker.php'))); } /** * @return void */ public function testIgnoreProjectDirectory() { $this->project_checker = $this->getProjectCheckerWithConfig( Config::loadFromXML( dirname(__DIR__), ' ' ) ); $config = $this->project_checker->getConfig(); $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 testIgnoreWildcardProjectDirectory() { $this->project_checker = $this->getProjectCheckerWithConfig( Config::loadFromXML( dirname(__DIR__), ' ' ) ); $config = $this->project_checker->getConfig(); $this->assertTrue($config->isInProjectDirs(realpath('src/Psalm/Type.php'))); $this->assertFalse($config->isInProjectDirs(realpath('src/Psalm/Checker/FileChecker.php'))); $this->assertFalse($config->isInProjectDirs(realpath('src/Psalm/Checker/Statements/ReturnChecker.php'))); $this->assertFalse($config->isInProjectDirs(realpath('examples/StringChecker.php'))); } /** * @return void */ public function testIgnoreWildcardFiles() { $this->project_checker = $this->getProjectCheckerWithConfig( Config::loadFromXML( dirname(__DIR__), ' ' ) ); $config = $this->project_checker->getConfig(); $this->assertTrue($config->isInProjectDirs(realpath('src/Psalm/Type.php'))); $this->assertFalse($config->isInProjectDirs(realpath('src/Psalm/Checker/FileChecker.php'))); $this->assertTrue($config->isInProjectDirs(realpath('src/Psalm/Checker/Statements/ReturnChecker.php'))); $this->assertFalse($config->isInProjectDirs(realpath('examples/StringChecker.php'))); } /** * @return void */ public function testIgnoreWildcardFilesInWildcardFolder() { $this->project_checker = $this->getProjectCheckerWithConfig( Config::loadFromXML( dirname(__DIR__), ' ' ) ); $config = $this->project_checker->getConfig(); $this->assertTrue($config->isInProjectDirs(realpath('src/Psalm/Type.php'))); $this->assertTrue($config->isInProjectDirs(realpath('src/Psalm/Visitor/DependencyFinderVisitor.php'))); $this->assertFalse($config->isInProjectDirs(realpath('src/Psalm/Checker/FileChecker.php'))); $this->assertFalse($config->isInProjectDirs(realpath('src/Psalm/Checker/Statements/ReturnChecker.php'))); $this->assertTrue($config->isInProjectDirs(realpath('examples/StringChecker.php'))); } /** * @return void */ public function testIgnoreWildcardFilesInAllPossibleWildcardFolders() { $this->project_checker = $this->getProjectCheckerWithConfig( Config::loadFromXML( dirname(__DIR__), ' ' ) ); $config = $this->project_checker->getConfig(); $this->assertTrue($config->isInProjectDirs(realpath('src/Psalm/Type.php'))); $this->assertTrue($config->isInProjectDirs(realpath('src/Psalm/Visitor/DependencyFinderVisitor.php'))); $this->assertFalse($config->isInProjectDirs(realpath('src/Psalm/Checker/FileChecker.php'))); $this->assertFalse($config->isInProjectDirs(realpath('src/Psalm/Checker/Statements/ReturnChecker.php'))); $this->assertFalse($config->isInProjectDirs(realpath('examples/StringChecker.php'))); } /** * @return void */ public function testIssueHandler() { $this->project_checker = $this->getProjectCheckerWithConfig( Config::loadFromXML( dirname(__DIR__), ' ' ) ); $config = $this->project_checker->getConfig(); $this->assertFalse($config->reportIssueInFile('MissingReturnType', realpath('tests/ConfigTest.php'))); $this->assertFalse($config->reportIssueInFile('MissingReturnType', realpath('src/Psalm/Type.php'))); } /** * @return void */ public function testIssueHandlerWithCustomErrorLevels() { $this->project_checker = $this->getProjectCheckerWithConfig( Config::loadFromXML( dirname(__DIR__), ' ' ) ); $config = $this->project_checker->getConfig(); $this->assertSame( 'info', $config->getReportingLevelForFile( 'MissingReturnType', realpath('src/Psalm/Type.php') ) ); $this->assertSame( 'error', $config->getReportingLevelForFile( 'MissingReturnType', realpath('src/Psalm/Checker/FileChecker.php') ) ); $this->assertSame( 'suppress', $config->getReportingLevelForClass( 'UndefinedClass', 'Psalm\Badger' ) ); $this->assertSame( 'error', $config->getReportingLevelForClass( 'UndefinedClass', 'Psalm\Bodger' ) ); $this->assertSame( 'suppress', $config->getReportingLevelForMethod( 'UndefinedMethod', 'Psalm\Bodger::find1' ) ); $this->assertSame( 'error', $config->getReportingLevelForProperty( 'UndefinedMethod', 'Psalm\Bodger::$find3' ) ); $this->assertSame( 'error', $config->getReportingLevelForProperty( 'UndefinedMethod', 'Psalm\Bodger::$find4' ) ); } /** * @return void */ public function testAllPossibleIssues() { $all_possible_handlers = implode( ' ', array_map( /** * @param string $issue_name * * @return string */ function ($issue_name) { if ($issue_name === 'ParseError') { return ''; } return '<' . $issue_name . ' errorLevel="suppress" />' . "\n"; }, self::getAllIssues() ) ); $this->project_checker = $this->getProjectCheckerWithConfig( Config::loadFromXML( dirname(__DIR__), ' ' . $all_possible_handlers . ' ' ) ); } /** * @expectedException \Psalm\Exception\ConfigException * @expectedExceptionMessage This element is not expected * * @return void */ public function testImpossibleIssue() { $this->project_checker = $this->getProjectCheckerWithConfig( Config::loadFromXML( dirname(__DIR__), ' ' ) ); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage MissingReturnType * * @return void */ public function testRequireVoidReturnTypeExists() { $this->project_checker = $this->getProjectCheckerWithConfig( TestConfig::loadFromXML( dirname(__DIR__), ' ' ) ); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @return void */ public function testDoNotRequireVoidReturnTypeExists() { $this->project_checker = $this->getProjectCheckerWithConfig( TestConfig::loadFromXML( dirname(__DIR__), ' ' ) ); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @return void */ public function testMethodCallMemoize() { $this->project_checker = $this->getProjectCheckerWithConfig( TestConfig::loadFromXML( dirname(__DIR__), ' ' ) ); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'getFoo()) { if ($a->getFoo()->getBar()) { $a->getFoo()->getBar()->bat(); } }' ); $this->analyzeFile($file_path, new Context()); } /** * @return void */ public function testExitFunctions() { $this->project_checker = $this->getProjectCheckerWithConfig( TestConfig::loadFromXML( dirname(__DIR__), ' ' ) ); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @return void */ public function testAllowedEchoFunction() { $this->project_checker = $this->getProjectCheckerWithConfig( TestConfig::loadFromXML( dirname(__DIR__), ' ' ) ); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage ForbiddenCode * @return void */ public function testForbiddenEchoFunctionViaFunctions() { $this->project_checker = $this->getProjectCheckerWithConfig( TestConfig::loadFromXML( dirname(__DIR__), ' ' ) ); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage ForbiddenEcho * @return void */ public function testForbiddenEchoFunctionViaFlag() { $this->project_checker = $this->getProjectCheckerWithConfig( TestConfig::loadFromXML( dirname(__DIR__), ' ' ) ); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @return void */ public function testAllowedVarExportFunction() { $this->project_checker = $this->getProjectCheckerWithConfig( TestConfig::loadFromXML( dirname(__DIR__), ' ' ) ); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage ForbiddenCode * @return void */ public function testForbiddenVarExportFunction() { $this->project_checker = $this->getProjectCheckerWithConfig( TestConfig::loadFromXML( dirname(__DIR__), ' ' ) ); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage InvalidCatch * @return void */ public function testValidThrowInvalidCatch() { $this->project_checker = $this->getProjectCheckerWithConfig( TestConfig::loadFromXML( dirname(__DIR__), ' ' ) ); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage InvalidThrow * @return void */ public function testInvalidThrowValidCatch() { $this->project_checker = $this->getProjectCheckerWithConfig( TestConfig::loadFromXML( dirname(__DIR__), ' ' ) ); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @return void */ public function testValidThrowValidCatch() { $this->project_checker = $this->getProjectCheckerWithConfig( TestConfig::loadFromXML( dirname(__DIR__), ' ' ) ); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @return void */ public function testTemplatedFiles() { foreach (['1.xml', '2.xml', '3.xml', '4.xml', '5.xml', '6.xml', '7.xml', '8.xml'] as $file_name) { Config::loadFromXMLFile( realpath(dirname(__DIR__) . '/assets/config_levels/' . $file_name), dirname(__DIR__) ); } } }