Skip to content

Commit

Permalink
Merge pull request #10618 from weirdan/update-master
Browse files Browse the repository at this point in the history
  • Loading branch information
weirdan authored Jan 30, 2024
2 parents 9520223 + e87fd86 commit bf57d59
Show file tree
Hide file tree
Showing 17 changed files with 115 additions and 20 deletions.
1 change: 1 addition & 0 deletions dictionaries/ImpureFunctionsList.php
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@
'ob_end_clean' => true,
'ob_get_clean' => true,
'readfile' => true,
'readgzfile' => true,
'printf' => true,
'var_dump' => true,
'phpinfo' => true,
Expand Down
2 changes: 1 addition & 1 deletion src/Psalm/CodeLocation.php
Original file line number Diff line number Diff line change
Expand Up @@ -147,7 +147,7 @@ public function __construct(
$this->preview_start = $this->docblock_start ?: $this->file_start;

/** @psalm-suppress ImpureMethodCall Actually mutation-free just not marked */
$this->raw_line_number = $stmt->getLine();
$this->raw_line_number = $stmt->getStartLine();

$this->docblock_line_number = $comment_line;
}
Expand Down
9 changes: 6 additions & 3 deletions src/Psalm/Internal/Analyzer/ClassAnalyzer.php
Original file line number Diff line number Diff line change
Expand Up @@ -1091,8 +1091,11 @@ private function checkPropertyInitialization(
$uninitialized_variables[] = '$this->' . $property_name;
$uninitialized_properties[$property_class_name . '::$' . $property_name] = $property;

if ($property->type && !$property->type->isMixed()) {
$uninitialized_typed_properties[$property_class_name . '::$' . $property_name] = $property;
if ($property->type) {
// Complain about all natively typed properties and all non-mixed docblock typed properties
if (!$property->type->from_docblock || !$property->type->isMixed()) {
$uninitialized_typed_properties[$property_class_name . '::$' . $property_name] = $property;
}
}
}

Expand Down Expand Up @@ -1192,7 +1195,7 @@ static function (FunctionLikeParameter $param): PhpParser\Node\Arg {
$fake_stmt = new VirtualClassMethod(
new VirtualIdentifier('__construct'),
[
'type' => PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC,
'flags' => PhpParser\Node\Stmt\Class_::MODIFIER_PUBLIC,
'params' => $fake_constructor_params,
'stmts' => $fake_constructor_stmts,
],
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2042,7 +2042,9 @@ private static function hasNonEmptyCountCheck(PhpParser\Node\Expr\FuncCall $stmt

private static function hasArrayKeyExistsCheck(PhpParser\Node\Expr\FuncCall $stmt): bool
{
return $stmt->name instanceof PhpParser\Node\Name && strtolower($stmt->name->getFirst()) === 'array_key_exists';
return $stmt->name instanceof PhpParser\Node\Name
&& (strtolower($stmt->name->getFirst()) === 'array_key_exists'
|| strtolower($stmt->name->getFirst()) === 'key_exists');
}

/**
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1347,6 +1347,7 @@ private static function verifyExplicitParam(
} else {
if (!$param_type->hasString()
&& !$param_type->hasArray()
&& $context->check_functions
&& CallAnalyzer::checkFunctionExists(
$statements_analyzer,
$function_id,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,8 @@ private static function handleNonExistentClass(

$override_property_visibility = $interface_storage->override_property_visibility;

$intersects_with_enum = false;

foreach ($intersection_types as $intersection_type) {
if ($intersection_type instanceof TNamedObject
&& $codebase->classExists($intersection_type->value)
Expand All @@ -1141,12 +1143,19 @@ private static function handleNonExistentClass(
$class_exists = true;
return;
}
if ($intersection_type instanceof TNamedObject
&& (in_array($intersection_type->value, ['UnitEnum', 'BackedEnum'], true)
|| in_array('UnitEnum', $codebase->getParentInterfaces($intersection_type->value)))
) {
$intersects_with_enum = true;
}
}

if (!$class_exists &&
//interfaces can't have properties. Except when they do... In PHP Core, they can
!in_array($fq_class_name, ['UnitEnum', 'BackedEnum'], true) &&
!in_array('UnitEnum', $codebase->getParentInterfaces($fq_class_name))
!in_array('UnitEnum', $codebase->getParentInterfaces($fq_class_name)) &&
!$intersects_with_enum
) {
if (IssueBuffer::accepts(
new NoInterfaceProperties(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -67,7 +67,7 @@ public function findUnusedAssignment(
$traverser->addVisitor($visitor);
$traverser->traverse([$rhs_exp]);

$rhs_exp_trivial = (count($visitor->getNonTrivialExpr()) === 0);
$rhs_exp_trivial = !$visitor->hasNonTrivialExpr();

if ($rhs_exp_trivial) {
$treat_as_expr = false;
Expand Down
9 changes: 9 additions & 0 deletions src/Psalm/Internal/Fork/PsalmRestarter.php
Original file line number Diff line number Diff line change
Expand Up @@ -99,6 +99,11 @@ protected function requiresRestart($default): bool
}
}

// opcache.save_comments is required for json mapper (used in language server) to work
if ($opcache_loaded && in_array(ini_get('opcache.save_comments'), ['0', 'false', 0, false])) {
return true;
}

return $default || $this->required;
}

Expand Down Expand Up @@ -163,6 +168,10 @@ protected function restart($command): void
}
}

if ($opcache_loaded) {
$additional_options[] = '-dopcache.save_comments=1';
}

array_splice(
$command,
1,
Expand Down
2 changes: 1 addition & 1 deletion src/Psalm/Internal/LanguageServer/LanguageServer.php
Original file line number Diff line number Diff line change
Expand Up @@ -697,7 +697,7 @@ public function emitVersionedIssues(array $files, ?int $version = null): void
$diagnostics = array_map(
function (IssueData $issue_data): Diagnostic {
//$check_name = $issue->check_name;
$description = $issue_data->message;
$description = '[' . $issue_data->type . '] ' . $issue_data->message;
$severity = $issue_data->severity;

$start_line = max($issue_data->line_from, 1);
Expand Down
14 changes: 4 additions & 10 deletions src/Psalm/Internal/PhpVisitor/CheckTrivialExprVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,10 +11,7 @@
*/
final class CheckTrivialExprVisitor extends PhpParser\NodeVisitorAbstract
{
/**
* @var array<int, PhpParser\Node\Expr>
*/
private array $non_trivial_expr = [];
private bool $has_non_trivial_expr = false;

private function checkNonTrivialExpr(PhpParser\Node\Expr $node): bool
{
Expand Down Expand Up @@ -57,7 +54,7 @@ public function enterNode(PhpParser\Node $node): ?int
if ($node instanceof PhpParser\Node\Expr) {
// Check for Non-Trivial Expression first
if ($this->checkNonTrivialExpr($node)) {
$this->non_trivial_expr[] = $node;
$this->has_non_trivial_expr = true;
return PhpParser\NodeTraverser::STOP_TRAVERSAL;
}

Expand All @@ -72,11 +69,8 @@ public function enterNode(PhpParser\Node $node): ?int
return null;
}

/**
* @return array<int, PhpParser\Node\Expr>
*/
public function getNonTrivialExpr(): array
public function hasNonTrivialExpr(): bool
{
return $this->non_trivial_expr;
return $this->has_non_trivial_expr;
}
}
2 changes: 1 addition & 1 deletion src/Psalm/Internal/PhpVisitor/ReflectorVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -533,7 +533,7 @@ public function leaveNode(PhpParser\Node $node)
}

throw new UnexpectedValueException(
'There should be function storages for line ' . $this->file_path . ':' . $node->getLine(),
'There should be function storages for line ' . $this->file_path . ':' . $node->getStartLine(),
);
}

Expand Down
2 changes: 1 addition & 1 deletion src/Psalm/Internal/Type/TypeExpander.php
Original file line number Diff line number Diff line change
Expand Up @@ -278,7 +278,7 @@ public static function expandAtomic(
$declaring_fq_classlike_name = $self_class;
}

if (!($evaluate_class_constants && $codebase->classOrInterfaceExists($declaring_fq_classlike_name))) {
if (!($evaluate_class_constants && $codebase->classOrInterfaceOrEnumExists($declaring_fq_classlike_name))) {
return [$return_type];
}

Expand Down
27 changes: 27 additions & 0 deletions tests/EnumTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -679,6 +679,33 @@ enum Bar: int
'ignored_issues' => [],
'php_version' => '8.1',
],
'allowPropertiesOnIntersectionsWithEnumInterfaces' => [
'code' => <<<'PHP'
<?php
interface I {}
interface UE extends UnitEnum {}
interface BE extends BackedEnum {}
function f(I $i): void {
if ($i instanceof BackedEnum) {
echo $i->name;
}
if ($i instanceof UnitEnum) {
echo $i->name;
}
if ($i instanceof UE) {
echo $i->name;
}
if ($i instanceof BE) {
echo $i->name;
}
}
PHP,
'assertions' => [],
'ignored_issues' => [],
'php_version' => '8.1',
],
];
}

Expand Down
8 changes: 8 additions & 0 deletions tests/FunctionCallTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -1649,6 +1649,14 @@ function in_array($a, $b) {
}
}',
],
'callableArgumentWithFunctionExists' => [
'code' => <<<'PHP'
<?php
if (function_exists('foo')) {
register_shutdown_function('foo');
}
PHP,
],
'pregMatch' => [
'code' => '<?php
function takesInt(int $i) : void {}
Expand Down
9 changes: 9 additions & 0 deletions tests/PropertyTypeTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -3829,6 +3829,15 @@ class A {
',
'error_message' => 'UndefinedPropertyAssignment',
],
'nativeMixedPropertyWithNoConstructor' => [
'code' => <<< 'PHP'
<?php
class A {
public mixed $foo;
}
PHP,
'error_message' => 'MissingConstructor',
],
];
}
}
19 changes: 19 additions & 0 deletions tests/TypeAnnotationTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -889,6 +889,25 @@ public function doesNotWork($_doesNotWork): void {
}
}',
],
'importFromEnum' => [
'code' => <<<'PHP'
<?php
/** @psalm-type _Foo = array{foo: string} */
enum E {}
/**
* @psalm-import-type _Foo from E
*/
class C {
/** @param _Foo $foo */
public function f(array $foo): void {
echo $foo['foo'];
}
}
PHP,
'assertions' => [],
'ignored_issues' => [],
'php_version' => '8.1',
],
];
}

Expand Down
13 changes: 13 additions & 0 deletions tests/TypeReconciliation/ArrayKeyExistsTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -509,6 +509,19 @@ public function isCriticalError(int|string $key): bool {
'ignored_issues' => [],
'php_version' => '8.0',
],
'keyExistsAsAliasForArrayKeyExists' => [
'code' => <<<'PHP'
<?php
/**
* @param array<string, string> $arr
*/
function foo(array $arr): void {
if (key_exists("a", $arr)) {
echo $arr["a"];
}
}
PHP,
],
];
}

Expand Down

0 comments on commit bf57d59

Please sign in to comment.