file_provider = new FakeFileProvider();
}
private function getProjectAnalyzerWithConfig(Config $config): ProjectAnalyzer
{
$config->setIncludeCollector(new IncludeCollector());
return new ProjectAnalyzer(
$config,
new Providers(
$this->file_provider,
new ParserInstanceCacheProvider(),
new FileStorageInstanceCacheProvider(),
new ClassLikeStorageInstanceCacheProvider(),
new FakeFileReferenceCacheProvider(),
new ProjectCacheProvider(),
),
new ReportOptions(),
);
}
public function testCheck(): void
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
Config::loadFromXML(
(string)getcwd(),
'
',
),
);
$this->project_analyzer->setPhpVersion('8.1', 'tests');
$this->project_analyzer->progress = new EchoProgress();
ob_start();
$this->project_analyzer->check('tests/fixtures/DummyProject');
$output = ob_get_clean();
$this->assertStringContainsString('Target PHP version: 8.1 (set by tests)', $output);
$this->assertStringContainsString('Scanning files...', $output);
$this->assertStringContainsString('Analyzing files...', $output);
$this->assertSame(0, IssueBuffer::getErrorCount());
$codebase = $this->project_analyzer->getCodebase();
$this->assertSame([0, 5], $codebase->analyzer->getTotalTypeCoverage($codebase));
$this->assertSame(
'Psalm was able to infer types for 100% of the codebase',
$codebase->analyzer->getTypeInferenceSummary(
$codebase,
),
);
}
public function testAfterCodebasePopulatedIsInvoked(): void
{
$hook = new class implements AfterCodebasePopulatedInterface {
public static bool $called = false;
/**
* @return void
* @phpcsSuppress SlevomatCodingStandard.TypeHints.ReturnTypeHint
*/
public static function afterCodebasePopulated(AfterCodebasePopulatedEvent $event)
{
self::$called = true;
}
};
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
Config::loadFromXML(
(string)getcwd(),
'
',
),
);
$hook_class = get_class($hook);
$this->project_analyzer->getCodebase()->config->eventDispatcher->after_codebase_populated[] = $hook_class;
ob_start();
$this->project_analyzer->check('tests/fixtures/DummyProject');
ob_end_clean();
$this->assertTrue($hook::$called);
}
public function testCheckAfterNoChange(): void
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
Config::loadFromXML(
(string)getcwd(),
'
',
),
);
$this->assertNotNull($this->project_analyzer->stdout_report_options);
$this->project_analyzer->stdout_report_options->format = Report::TYPE_JSON;
$this->project_analyzer->check('tests/fixtures/DummyProject', true);
ob_start();
IssueBuffer::finish($this->project_analyzer, true, microtime(true));
ob_end_clean();
$this->assertSame(
'Psalm was able to infer types for 100% of the codebase',
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary(
$this->project_analyzer->getCodebase(),
),
);
$this->project_analyzer->getCodebase()->reloadFiles($this->project_analyzer, []);
$this->project_analyzer->check('tests/fixtures/DummyProject', true);
$this->assertSame(0, IssueBuffer::getErrorCount());
$this->assertSame(
'Psalm was able to infer types for 100% of the codebase',
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary(
$this->project_analyzer->getCodebase(),
),
);
}
public function testCheckAfterFileChange(): void
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
Config::loadFromXML(
(string)getcwd(),
'
',
),
);
$this->assertNotNull($this->project_analyzer->stdout_report_options);
$this->project_analyzer->stdout_report_options->format = Report::TYPE_JSON;
$this->project_analyzer->check('tests/fixtures/DummyProject', true);
ob_start();
IssueBuffer::finish($this->project_analyzer, true, microtime(true));
ob_end_clean();
$this->assertSame(
'Psalm was able to infer types for 100% of the codebase',
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary(
$this->project_analyzer->getCodebase(),
),
);
$bat_file_path = getcwd()
. DIRECTORY_SEPARATOR . 'tests'
. DIRECTORY_SEPARATOR . 'fixtures'
. DIRECTORY_SEPARATOR . 'DummyProject'
. DIRECTORY_SEPARATOR . 'Bat.php';
$bat_replacement_contents = 'file_provider->registerFile($bat_file_path, $bat_replacement_contents);
$this->project_analyzer->getCodebase()->reloadFiles($this->project_analyzer, []);
$this->project_analyzer->check('tests/fixtures/DummyProject', true);
$this->assertSame(0, IssueBuffer::getErrorCount());
$this->assertSame(
'Psalm was able to infer types for 100% of the codebase',
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary(
$this->project_analyzer->getCodebase(),
),
);
}
public function testCheckDir(): void
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
Config::loadFromXML(
(string)getcwd(),
'
',
),
);
$this->project_analyzer->setPhpVersion('8.1', 'tests');
$this->project_analyzer->progress = new EchoProgress();
ob_start();
$this->project_analyzer->checkDir('tests/fixtures/DummyProject');
$output = ob_get_clean();
$this->assertStringContainsString('Target PHP version: 8.1 (set by tests)', $output);
$this->assertStringContainsString('Scanning files...', $output);
$this->assertStringContainsString('Analyzing files...', $output);
$this->assertSame(0, IssueBuffer::getErrorCount());
$this->assertSame(
'Psalm was able to infer types for 100% of the codebase',
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary(
$this->project_analyzer->getCodebase(),
),
);
}
public function testCheckPaths(): void
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
Config::loadFromXML(
(string)getcwd(),
'
',
),
);
$this->project_analyzer->setPhpVersion('8.1', 'tests');
$this->project_analyzer->progress = new EchoProgress();
ob_start();
// checkPaths expects absolute paths,
// otherwise it's unable to match them against configured folders
$this->project_analyzer->checkPaths([
realpath(getcwd() . '/tests/fixtures/DummyProject/Bar.php'),
realpath(getcwd() . '/tests/fixtures/DummyProject/SomeTrait.php'),
]);
$output = ob_get_clean();
$this->assertStringContainsString('Target PHP version: 8.1 (set by tests)', $output);
$this->assertStringContainsString('Scanning files...', $output);
$this->assertStringContainsString('Analyzing files...', $output);
$this->assertSame(0, IssueBuffer::getErrorCount());
$this->assertSame(
'Psalm was able to infer types for 100% of the codebase',
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary(
$this->project_analyzer->getCodebase(),
),
);
}
public function testCheckFile(): void
{
$this->project_analyzer = $this->getProjectAnalyzerWithConfig(
Config::loadFromXML(
(string)getcwd(),
'
',
),
);
$this->project_analyzer->setPhpVersion('8.1', 'tests');
$this->project_analyzer->progress = new EchoProgress();
ob_start();
// checkPaths expects absolute paths,
// otherwise it's unable to match them against configured folders
$this->project_analyzer->checkPaths([
realpath(getcwd() . '/tests/fixtures/DummyProject/Bar.php'),
realpath(getcwd() . '/tests/fixtures/DummyProject/SomeTrait.php'),
]);
$output = ob_get_clean();
$this->assertStringContainsString('Target PHP version: 8.1 (set by tests)', $output);
$this->assertStringContainsString('Scanning files...', $output);
$this->assertStringContainsString('Analyzing files...', $output);
$this->assertSame(0, IssueBuffer::getErrorCount());
$this->assertSame(
'Psalm was able to infer types for 100% of the codebase',
$this->project_analyzer->getCodebase()->analyzer->getTypeInferenceSummary(
$this->project_analyzer->getCodebase(),
),
);
}
}