Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Display target PHP version #7006

Merged
merged 1 commit into from Nov 27, 2021
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
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);
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This check can be dropped here, it seems to be checked again in project analyzer below

Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It is to avoid MixedAssignment to $version variable.

}
$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