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

Fix extension capitalization issue, add extensions to version message. #7574

Merged
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
26 changes: 23 additions & 3 deletions src/Psalm/Config.php
Expand Up @@ -72,6 +72,7 @@
use function implode;
use function in_array;
use function is_a;
use function is_array;
use function is_dir;
use function is_file;
use function is_string;
Expand Down Expand Up @@ -595,6 +596,13 @@ class Config
"xdebug" => false,
];

/**
* A list of php extensions required by the project that aren't fully supported by Psalm.
*
* @var array<string, true>
*/
public $php_extensions_not_supported = [];

/**
* @var array<class-string, PluginInterface>
*/
Expand Down Expand Up @@ -995,12 +1003,24 @@ private static function fromXmlAndPaths(

$composer_json = null;
if (file_exists($composer_json_path)) {
if (!$composer_json = json_decode(file_get_contents($composer_json_path), true)) {
$composer_json = json_decode(file_get_contents($composer_json_path), true);
if (!is_array($composer_json)) {
throw new UnexpectedValueException('Invalid composer.json at ' . $composer_json_path);
}
}
foreach ($config->php_extensions as $ext => $_) {
$config->php_extensions[$ext] = isset($composer_json["require"]["ext-$ext"]);
$required_extensions = [];
foreach (($composer_json["require"] ?? []) as $required => $_) {
if (strpos($required, "ext-") === 0) {
$required_extensions[strtolower(substr($required, 4))] = true;
}
}
foreach ($required_extensions as $required_ext => $_) {
if (isset($config->php_extensions[$required_ext])) {
/** @psalm-suppress PropertyTypeCoercion isset doesn't narrow $required_ext like it should */
$config->php_extensions[$required_ext] = true;
} else {
$config->php_extensions_not_supported[$required_ext] = true;
}
}

if (isset($config_xml->enableExtensions) && isset($config_xml->enableExtensions->extension)) {
Expand Down
5 changes: 4 additions & 1 deletion src/Psalm/Internal/Analyzer/ProjectAnalyzer.php
Expand Up @@ -59,6 +59,7 @@
use function array_combine;
use function array_diff;
use function array_fill_keys;
use function array_filter;
use function array_keys;
use function array_map;
use function array_merge;
Expand Down Expand Up @@ -590,7 +591,9 @@ private function generatePHPVersionMessage(): string
break;
}

return "Target PHP version: $version $source\n";
return "Target PHP version: $version $source Extensions enabled: "
. implode(", ", array_keys(array_filter($codebase->config->php_extensions))) . " (unsupported extensions: "
. implode(", ", array_keys($codebase->config->php_extensions_not_supported)) . ")\n";
}

public function check(string $base_dir, bool $is_diff = false): void
Expand Down
3 changes: 2 additions & 1 deletion tests/EndToEnd/PsalmEndToEndTest.php
Expand Up @@ -20,6 +20,7 @@
use function readdir;
use function rmdir;
use function str_replace;
use function substr_count;
use function sys_get_temp_dir;
use function tempnam;
use function unlink;
Expand Down Expand Up @@ -168,7 +169,7 @@ public function testPsalmDiff(): void
$this->assertStringContainsString('InvalidReturnType', $result['STDOUT']);
$this->assertStringContainsString('InvalidReturnStatement', $result['STDOUT']);
$this->assertStringContainsString('3 errors', $result['STDOUT']);
$this->assertStringNotContainsString('E', $result['STDERR']);
$this->assertEquals(1, substr_count($result['STDERR'], 'E')); // Should only have 'E' from 'Extensions' in version message

$this->assertSame(2, $result['CODE']);

Expand Down
39 changes: 11 additions & 28 deletions tests/ProjectCheckerTest.php
Expand Up @@ -40,6 +40,13 @@ class ProjectCheckerTest extends TestCase
/** @var ProjectAnalyzer */
protected $project_analyzer;

private const EXPECTED_OUTPUT = "Target PHP version: 8.1 (set by tests) Extensions enabled: dom (unsupported "
. "extensions: simplexml, ctype, json, libxml, mbstring, tokenizer)\n"
. "Scanning files...\n"
. "Analyzing files...\n"
. "\n"
;

public static function setUpBeforeClass(): void
{
self::$config = new TestConfig();
Expand Down Expand Up @@ -97,13 +104,7 @@ public function testCheck(): void
$this->project_analyzer->check('tests/fixtures/DummyProject');
$output = ob_get_clean();

$this->assertSame(
'Target PHP version: 8.1 (set by tests)' . "\n"
. 'Scanning files...' . "\n"
. 'Analyzing files...' . "\n"
. "\n",
$output
);
$this->assertSame(self::EXPECTED_OUTPUT, $output);

$this->assertSame(0, IssueBuffer::getErrorCount());

Expand Down Expand Up @@ -289,13 +290,7 @@ public function testCheckDir(): void
$this->project_analyzer->checkDir('tests/fixtures/DummyProject');
$output = ob_get_clean();

$this->assertSame(
'Target PHP version: 8.1 (set by tests)' . "\n"
. 'Scanning files...' . "\n"
. 'Analyzing files...' . "\n"
. "\n",
$output
);
$this->assertSame(self::EXPECTED_OUTPUT, $output);

$this->assertSame(0, IssueBuffer::getErrorCount());

Expand Down Expand Up @@ -334,13 +329,7 @@ public function testCheckPaths(): void
]);
$output = ob_get_clean();

$this->assertSame(
'Target PHP version: 8.1 (set by tests)' . "\n"
. 'Scanning files...' . "\n"
. 'Analyzing files...' . "\n"
. "\n",
$output
);
$this->assertSame(self::EXPECTED_OUTPUT, $output);

$this->assertSame(0, IssueBuffer::getErrorCount());

Expand Down Expand Up @@ -379,13 +368,7 @@ public function testCheckFile(): void
]);
$output = ob_get_clean();

$this->assertSame(
'Target PHP version: 8.1 (set by tests)' . "\n"
. 'Scanning files...' . "\n"
. 'Analyzing files...' . "\n"
. "\n",
$output
);
$this->assertSame(self::EXPECTED_OUTPUT, $output);

$this->assertSame(0, IssueBuffer::getErrorCount());

Expand Down