file_provider = new Provider\FakeFileProvider(); } /** * @param Config $config * * @return \Psalm\Internal\Analyzer\ProjectAnalyzer */ private function getProjectAnalyzerWithConfig(Config $config) { return new \Psalm\Internal\Analyzer\ProjectAnalyzer( $config, new \Psalm\Internal\Provider\Providers( $this->file_provider, new Provider\FakeParserCacheProvider() ) ); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage InvalidClass * * @return void */ public function testStringAnalyzerPlugin() { $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage InvalidClass * * @return void */ public function testStringAnalyzerPluginWithClassConstant() { $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, ' "Psalm\Internal\Analyzer\ProjectAnalyzer", ]; }' ); $this->analyzeFile($file_path, new Context()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage UndefinedMethod * * @return void */ public function testStringAnalyzerPluginWithClassConstantConcat() { $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, ' \Psalm\Internal\Analyzer\ProjectAnalyzer::class . "::foo", ]; }' ); $this->analyzeFile($file_path, new Context()); } /** * @return void */ public function testEchoAnalyzerPluginWithJustHtml() { $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, '

This is a header

' ); $this->analyzeFile($file_path, new Context()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage TypeCoercion * * @return void */ public function testEchoAnalyzerPluginWithUnescapedConcatenatedString() { $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, '' ); $this->analyzeFile($file_path, new Context()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage TypeCoercion * * @return void */ public function testEchoAnalyzerPluginWithUnescapedString() { $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, '' ); $this->analyzeFile($file_path, new Context()); } /** * @return void */ public function testEchoAnalyzerPluginWithEscapedString() { $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, ' Some text ' ); $this->analyzeFile($file_path, new Context()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage NoFloatAssignment * * @return void */ public function testFloatCheckerPlugin() { $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @return void */ public function testFloatCheckerPluginIssueSuppressionByConfig() { $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @return void */ public function testFloatCheckerPluginIssueSuppressionByDocblock() { $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** @return void */ public function testInheritedHookHandlersAreCalled() { require_once __DIR__ . '/stubs/extending_plugin_entrypoint.php'; $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $this->assertContains( 'ExtendingPlugin', $this->project_analyzer->getCodebase()->config->after_function_checks ); } /** @return void */ public function testAfterCodebasePopulatedHookIsLoaded() { $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $hook = new class implements AfterCodebasePopulatedInterface { /** @return void */ public static function afterCodebasePopulated(Codebase $codebase) { } }; $codebase = $this->project_analyzer->getCodebase(); $config = $codebase->config; (new PluginRegistrationSocket($config, $codebase))->registerHooksFromClass(get_class($hook)); $this->assertContains( get_class($hook), $this->project_analyzer->getCodebase()->config->after_codebase_populated ); } /** @return void */ public function testPropertyProviderHooks() { require_once __DIR__ . '/Plugin/PropertyPlugin.php'; $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'magic_property;' ); $this->analyzeFile($file_path, new Context()); } /** @return void */ public function testMethodProviderHooks() { require_once __DIR__ . '/Plugin/MethodPlugin.php'; $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'magicMethod("hello"); echo $foo::magicMethod("hello");' ); $this->analyzeFile($file_path, new Context()); } /** @return void */ public function testFunctionProviderHooks() { require_once __DIR__ . '/Plugin/FunctionPlugin.php'; $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage InvalidPropertyAssignmentValue * * @return void */ public function testPropertyProviderHooksInvalidAssignment() { require_once __DIR__ . '/Plugin/PropertyPlugin.php'; $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'magic_property = 5;' ); $this->analyzeFile($file_path, new Context()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage InvalidScalarArgument * * @return void */ public function testMethodProviderHooksInvalidArg() { require_once __DIR__ . '/Plugin/MethodPlugin.php'; $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'magicMethod(5);' ); $this->analyzeFile($file_path, new Context()); } /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage InvalidScalarArgument * * @return void */ public function testFunctionProviderHooksInvalidArg() { require_once __DIR__ . '/Plugin/FunctionPlugin.php'; $this->project_analyzer = $this->getProjectAnalyzerWithConfig( TestConfig::loadFromXML( dirname(__DIR__) . DIRECTORY_SEPARATOR, ' ' ) ); $this->project_analyzer->getCodebase()->config->initializePlugins($this->project_analyzer); $file_path = getcwd() . '/src/somefile.php'; $this->addFile( $file_path, 'analyzeFile($file_path, new Context()); } }