Skip to content

Commit

Permalink
Display target PHP version
Browse files Browse the repository at this point in the history
Historically it was often not quite clear to users what PHP version
Psalm assumes, and why. This PR addresses this issue by printing the
version and where we got it from right before scanning the files.
  • Loading branch information
weirdan committed Nov 27, 2021
1 parent 72de3b6 commit d19aad7
Show file tree
Hide file tree
Showing 31 changed files with 172 additions and 74 deletions.
3 changes: 3 additions & 0 deletions src/Psalm/Codebase.php
Expand Up @@ -278,6 +278,9 @@ class Codebase
*/
public $php_minor_version = PHP_MINOR_VERSION;

/** @var 'cli'|'config'|'composer'|'tests'|'runtime' */
public $php_version_source = 'runtime';

/**
* @var bool
*/
Expand Down
9 changes: 7 additions & 2 deletions src/Psalm/Config.php
Expand Up @@ -2225,7 +2225,12 @@ public function addPreloadedStubFile(string $stub_file): void

public function getPhpVersion(): ?string
{
return $this->configured_php_version ?? $this->getPHPVersionFromComposerJson();
return $this->getPhpVersionFromConfig() ?? $this->getPHPVersionFromComposerJson();
}

public function getPhpVersionFromConfig(): ?string
{
return $this->configured_php_version;
}

private function setBooleanAttribute(string $name, bool $value): void
Expand All @@ -2237,7 +2242,7 @@ private function setBooleanAttribute(string $name, bool $value): void
* @psalm-suppress MixedAssignment
* @psalm-suppress MixedArrayAccess
*/
private function getPHPVersionFromComposerJson(): ?string
public function getPHPVersionFromComposerJson(): ?string
{
$composer_json_path = Composer::getJsonFilePath($this->base_dir);

Expand Down
37 changes: 36 additions & 1 deletion src/Psalm/Internal/Analyzer/ProjectAnalyzer.php
Expand Up @@ -544,6 +544,33 @@ public function canReportIssues(string $file_path): bool
return isset($this->project_files[$file_path]);
}

private function generatePHPVersionMessage(): string
{
$codebase = $this->codebase;

$version = $codebase->php_major_version . '.' . $codebase->php_minor_version;

switch ($codebase->php_version_source) {
case 'cli':
$source = '(set by CLI argument)';
break;
case 'config':
$source = '(set by config file)';
break;
case 'composer':
$source = '(inferred from composer.json)';
break;
case 'tests':
$source = '(set by tests)';
break;
case 'runtime':
$source = '(inferred from current PHP version)';
break;
}

return "Target PHP version: $version $source\n";
}

public function check(string $base_dir, bool $is_diff = false): void
{
$start_checks = (int)microtime(true);
Expand Down Expand Up @@ -574,6 +601,7 @@ public function check(string $base_dir, bool $is_diff = false): void
}
}

$this->progress->write($this->generatePHPVersionMessage());
$this->progress->startScanningFiles();

$diff_no_files = false;
Expand Down Expand Up @@ -992,6 +1020,7 @@ public function checkDir(string $dir_name): void

$this->checkDirWithConfig($dir_name, $this->config, true);

$this->progress->write($this->generatePHPVersionMessage());
$this->progress->startScanningFiles();

$this->config->initializePlugins($this);
Expand Down Expand Up @@ -1123,6 +1152,7 @@ public function checkFile(string $file_path): void

$this->file_reference_provider->loadReferenceCache();

$this->progress->write($this->generatePHPVersionMessage());
$this->progress->startScanningFiles();

$this->config->initializePlugins($this);
Expand Down Expand Up @@ -1164,6 +1194,7 @@ public function checkPaths(array $paths_to_check): void

$this->file_reference_provider->loadReferenceCache();

$this->progress->write($this->generatePHPVersionMessage());
$this->progress->startScanningFiles();

$this->config->initializePlugins($this);
Expand Down Expand Up @@ -1262,7 +1293,10 @@ public function refactorCodeAfterCompletion(array $to_refactor): void
$this->show_issues = false;
}

public function setPhpVersion(string $version): void
/**
* @param 'cli'|'config'|'composer'|'tests' $source
*/
public function setPhpVersion(string $version, string $source): void
{
if (!preg_match('/^(5\.[456]|7\.[01234]|8\.[01])(\..*)?$/', $version)) {
throw new \UnexpectedValueException('Expecting a version number in the format x.y');
Expand All @@ -1283,6 +1317,7 @@ public function setPhpVersion(string $version): void

$this->codebase->php_major_version = $php_major_version;
$this->codebase->php_minor_version = $php_minor_version;
$this->codebase->php_version_source = $source;
}

/**
Expand Down
18 changes: 1 addition & 17 deletions src/Psalm/Internal/Cli/Psalm.php
Expand Up @@ -332,8 +332,7 @@ function () use ($current_dir, $options, $vendor_dir): ?\Composer\Autoload\Class
$progress
);

self::initPhpVersion($options, $config, $project_analyzer);

CliUtils::initPhpVersion($options, $config, $project_analyzer);

$start_time = microtime(true);

Expand Down Expand Up @@ -1071,21 +1070,6 @@ function (array $edges) {
}
}

private static function initPhpVersion(array $options, Config $config, ProjectAnalyzer $project_analyzer): void
{
if (!isset($options['php-version'])) {
$options['php-version'] = $config->getPhpVersion();
}

if (isset($options['php-version'])) {
if (!is_string($options['php-version'])) {
die('Expecting a version number in the format x.y' . PHP_EOL);
}

$project_analyzer->setPhpVersion($options['php-version']);
}
}

/** @return false|'always'|'auto' */
private static function shouldFindUnusedCode(array $options, Config $config)
{
Expand Down
12 changes: 1 addition & 11 deletions src/Psalm/Internal/Cli/Psalter.php
Expand Up @@ -281,17 +281,7 @@ function () use ($current_dir, $options, $vendor_dir): ?\Composer\Autoload\Class
$keyed_issues = [];
}

if (!isset($options['php-version'])) {
$options['php-version'] = $config->getPhpVersion();
}

if (isset($options['php-version'])) {
if (!is_string($options['php-version'])) {
die('Expecting a version number in the format x.y' . PHP_EOL);
}

$project_analyzer->setPhpVersion($options['php-version']);
}
CliUtils::initPhpVersion($options, $config, $project_analyzer);

if (isset($options['codeowner'])) {
$codeowner_files = self::loadCodeowners($providers);
Expand Down
22 changes: 22 additions & 0 deletions src/Psalm/Internal/CliUtils.php
Expand Up @@ -5,6 +5,7 @@
use Composer\Autoload\ClassLoader;
use Phar;
use Psalm\Config;
use Psalm\Internal\Analyzer\ProjectAnalyzer;
use Psalm\Internal\Composer;

use function assert;
Expand Down Expand Up @@ -622,4 +623,25 @@ public static function convertMemoryLimitToBytes(string $limit): int

return (int)$limit;
}

public static function initPhpVersion(array $options, Config $config, ProjectAnalyzer $project_analyzer): void
{
$source = null;

if (isset($options['php-version'])) {
if (!is_string($options['php-version'])) {
die('Expecting a version number in the format x.y' . PHP_EOL);
}
$version = $options['php-version'];
$source = 'cli';
} elseif ($version = $config->getPhpVersionFromConfig()) {
$source = 'config';
} elseif ($version = $config->getPHPVersionFromComposerJson()) {
$source = 'composer';
}

if ($version !== null && $source !== null) {
$project_analyzer->setPhpVersion($version, $source);
}
}
}
2 changes: 1 addition & 1 deletion tests/Config/ConfigTest.php
Expand Up @@ -67,7 +67,7 @@ private function getProjectAnalyzerWithConfig(Config $config): \Psalm\Internal\A
)
);

$p->setPhpVersion('7.3');
$p->setPhpVersion('7.3', 'tests');

return $p;
}
Expand Down
4 changes: 2 additions & 2 deletions tests/DocumentationTest.php
Expand Up @@ -136,7 +136,7 @@ public function setUp() : void
)
);

$this->project_analyzer->setPhpVersion('8.0');
$this->project_analyzer->setPhpVersion('8.0', 'tests');
}

public function testAllIssuesCoveredInConfigSchema(): void
Expand Down Expand Up @@ -204,7 +204,7 @@ public function testInvalidCode($code, $error_message, $error_levels = [], $chec
$this->markTestSkipped();
}

$this->project_analyzer->setPhpVersion($php_version);
$this->project_analyzer->setPhpVersion($php_version, 'tests');

if ($check_references) {
$this->project_analyzer->getCodebase()->reportUnusedCode();
Expand Down
30 changes: 28 additions & 2 deletions tests/EndToEnd/PsalmEndToEndTest.php
Expand Up @@ -115,13 +115,37 @@ public function testPsalm(): void
{
$this->runPsalmInit(1);
$result = $this->runPsalm([], self::$tmpDir, true);
$this->assertStringContainsString(
'Target PHP version: 7.1 (inferred from composer.json)',
$result['STDERR']
);
$this->assertStringContainsString('UnusedParam', $result['STDOUT']);
$this->assertStringContainsString('InvalidReturnType', $result['STDOUT']);
$this->assertStringContainsString('InvalidReturnStatement', $result['STDOUT']);
$this->assertStringContainsString('3 errors', $result['STDOUT']);
$this->assertSame(2, $result['CODE']);
}

public function testPsalmWithPHPVersionOverride(): void
{
$this->runPsalmInit(1);
$result = $this->runPsalm(['--php-version=8.0'], self::$tmpDir, true);
$this->assertStringContainsString(
'Target PHP version: 8.0 (set by CLI argument)',
$result['STDERR']
);
}

public function testPsalmWithPHPVersionFromConfig(): void
{
$this->runPsalmInit(1, '7.4');
$result = $this->runPsalm([], self::$tmpDir, true);
$this->assertStringContainsString(
'Target PHP version: 7.4 (set by config file)',
$result['STDERR']
);
}

public function testPsalmDiff(): void
{
if (PHP_VERSION_ID < 70400) {
Expand Down Expand Up @@ -212,7 +236,7 @@ public function testLegacyConfigWithoutresolveFromConfigFile(): void
/**
* @return array{STDOUT: string, STDERR: string, CODE: int|null}
*/
private function runPsalmInit(?int $level = null): array
private function runPsalmInit(?int $level = null, ?string $php_version = null): array
{
$args = ['--init'];

Expand All @@ -226,7 +250,9 @@ private function runPsalmInit(?int $level = null): array
$psalm_config_contents = file_get_contents(self::$tmpDir . '/psalm.xml');
$psalm_config_contents = \str_replace(
'errorLevel="1"',
'errorLevel="1" cacheDirectory="' . self::$tmpDir . '/cache"',
'errorLevel="1" '
. 'cacheDirectory="' . self::$tmpDir . '/cache" '
. ($php_version ? ('phpVersion="' . $php_version . '"') : ''),
$psalm_config_contents
);
file_put_contents(self::$tmpDir . '/psalm.xml', $psalm_config_contents);
Expand Down
2 changes: 1 addition & 1 deletion tests/FileManipulation/FileManipulationTestCase.php
Expand Up @@ -68,7 +68,7 @@ public function testValidCode(
$input_code
);

$this->project_analyzer->setPhpVersion($php_version);
$this->project_analyzer->setPhpVersion($php_version, 'tests');

$keyed_issues_to_fix = [];

Expand Down
2 changes: 1 addition & 1 deletion tests/FileReferenceTest.php
Expand Up @@ -29,7 +29,7 @@ public function setUp() : void
);

$this->project_analyzer->getCodebase()->collectLocations();
$this->project_analyzer->setPhpVersion('7.3');
$this->project_analyzer->setPhpVersion('7.3', 'tests');
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/FileUpdates/AnalyzedMethodTest.php
Expand Up @@ -36,7 +36,7 @@ public function setUp() : void
$config,
$providers
);
$this->project_analyzer->setPhpVersion('7.3');
$this->project_analyzer->setPhpVersion('7.3', 'tests');
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/FileUpdates/CachedStorageTest.php
Expand Up @@ -36,7 +36,7 @@ public function setUp() : void
$config,
$providers
);
$this->project_analyzer->setPhpVersion('7.3');
$this->project_analyzer->setPhpVersion('7.3', 'tests');
}

public function testValidInclude(): void
Expand Down
2 changes: 1 addition & 1 deletion tests/FileUpdates/ErrorAfterUpdateTest.php
Expand Up @@ -37,7 +37,7 @@ public function setUp() : void
$config,
$providers
);
$this->project_analyzer->setPhpVersion('7.3');
$this->project_analyzer->setPhpVersion('7.3', 'tests');
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/FileUpdates/ErrorFixTest.php
Expand Up @@ -37,7 +37,7 @@ public function setUp() : void
$config,
$providers
);
$this->project_analyzer->setPhpVersion('7.3');
$this->project_analyzer->setPhpVersion('7.3', 'tests');
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/FileUpdates/TemporaryUpdateTest.php
Expand Up @@ -39,7 +39,7 @@ public function setUp() : void
$config,
$providers
);
$this->project_analyzer->setPhpVersion('7.3');
$this->project_analyzer->setPhpVersion('7.3', 'tests');
}

/**
Expand Down
2 changes: 1 addition & 1 deletion tests/ForbiddenCodeTest.php
Expand Up @@ -361,7 +361,7 @@ private function getProjectAnalyzerWithConfig(Config $config): \Psalm\Internal\A
)
);

$p->setPhpVersion('7.4');
$p->setPhpVersion('7.4', 'tests');

return $p;
}
Expand Down
2 changes: 1 addition & 1 deletion tests/LanguageServer/CompletionTest.php
Expand Up @@ -35,7 +35,7 @@ public function setUp() : void
$config,
$providers
);
$this->project_analyzer->setPhpVersion('7.3');
$this->project_analyzer->setPhpVersion('7.3', 'tests');
$this->project_analyzer->getCodebase()->store_node_types = true;
}

Expand Down
2 changes: 1 addition & 1 deletion tests/LanguageServer/FileMapTest.php
Expand Up @@ -31,7 +31,7 @@ public function setUp() : void
$config,
$providers
);
$this->project_analyzer->setPhpVersion('7.3');
$this->project_analyzer->setPhpVersion('7.3', 'tests');
$this->project_analyzer->getCodebase()->store_node_types = true;
}

Expand Down
2 changes: 1 addition & 1 deletion tests/LanguageServer/SymbolLookupTest.php
Expand Up @@ -34,7 +34,7 @@ public function setUp() : void
$providers
);

$this->project_analyzer->setPhpVersion('7.3');
$this->project_analyzer->setPhpVersion('7.3', 'tests');
$this->project_analyzer->getCodebase()->store_node_types = true;
}

Expand Down

0 comments on commit d19aad7

Please sign in to comment.