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,
'= $unsafe . "safeString" ?>'
);
$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,
'= $unsafe ?>'
);
$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
= escapeHtml($unsafe) ?>'
);
$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());
}
}