mirror of
https://github.com/danog/psalm.git
synced 2025-01-22 13:51:54 +01:00
Merge pull request #8693 from weirdan/fix-8267
Fixes https://github.com/vimeo/psalm/issues/8267
This commit is contained in:
commit
c613e47c55
@ -75,3 +75,28 @@ enum Status: string
|
|||||||
case Open = "open";
|
case Open = "open";
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Case with a type that cannot back an enum
|
||||||
|
|
||||||
|
Case type should be either `int` or `string`.
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
enum Status: int {
|
||||||
|
case Open = [];
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
### How to fix
|
||||||
|
|
||||||
|
Change the case value so that it's one of the allowed types (and matches the backing type)
|
||||||
|
|
||||||
|
```php
|
||||||
|
<?php
|
||||||
|
|
||||||
|
enum Status: int
|
||||||
|
{
|
||||||
|
case Open = 1;
|
||||||
|
}
|
||||||
|
```
|
||||||
|
@ -43,6 +43,7 @@ use Psalm\Issue\DuplicateConstant;
|
|||||||
use Psalm\Issue\DuplicateEnumCase;
|
use Psalm\Issue\DuplicateEnumCase;
|
||||||
use Psalm\Issue\InvalidDocblock;
|
use Psalm\Issue\InvalidDocblock;
|
||||||
use Psalm\Issue\InvalidEnumBackingType;
|
use Psalm\Issue\InvalidEnumBackingType;
|
||||||
|
use Psalm\Issue\InvalidEnumCaseValue;
|
||||||
use Psalm\Issue\InvalidTypeImport;
|
use Psalm\Issue\InvalidTypeImport;
|
||||||
use Psalm\Issue\MissingDocblockType;
|
use Psalm\Issue\MissingDocblockType;
|
||||||
use Psalm\Issue\ParseError;
|
use Psalm\Issue\ParseError;
|
||||||
@ -314,6 +315,17 @@ class ClassLikeNodeScanner
|
|||||||
if ($node->scalarType) {
|
if ($node->scalarType) {
|
||||||
if ($node->scalarType->name === 'string' || $node->scalarType->name === 'int') {
|
if ($node->scalarType->name === 'string' || $node->scalarType->name === 'int') {
|
||||||
$storage->enum_type = $node->scalarType->name;
|
$storage->enum_type = $node->scalarType->name;
|
||||||
|
$storage->class_implements['backedenum'] = 'BackedEnum';
|
||||||
|
$storage->direct_class_interfaces['backedenum'] = 'BackedEnum';
|
||||||
|
$this->file_storage->required_interfaces['backedenum'] = 'BackedEnum';
|
||||||
|
$this->codebase->scanner->queueClassLikeForScanning('BackedEnum');
|
||||||
|
$storage->declaring_method_ids['from'] = new MethodIdentifier('BackedEnum', 'from');
|
||||||
|
$storage->appearing_method_ids['from'] = $storage->declaring_method_ids['from'];
|
||||||
|
$storage->declaring_method_ids['tryfrom'] = new MethodIdentifier(
|
||||||
|
'BackedEnum',
|
||||||
|
'tryfrom'
|
||||||
|
);
|
||||||
|
$storage->appearing_method_ids['tryfrom'] = $storage->declaring_method_ids['tryfrom'];
|
||||||
} else {
|
} else {
|
||||||
IssueBuffer::maybeAdd(
|
IssueBuffer::maybeAdd(
|
||||||
new InvalidEnumBackingType(
|
new InvalidEnumBackingType(
|
||||||
@ -325,17 +337,6 @@ class ClassLikeNodeScanner
|
|||||||
$this->file_storage->has_visitor_issues = true;
|
$this->file_storage->has_visitor_issues = true;
|
||||||
$storage->has_visitor_issues = true;
|
$storage->has_visitor_issues = true;
|
||||||
}
|
}
|
||||||
$storage->class_implements['backedenum'] = 'BackedEnum';
|
|
||||||
$storage->direct_class_interfaces['backedenum'] = 'BackedEnum';
|
|
||||||
$this->file_storage->required_interfaces['backedenum'] = 'BackedEnum';
|
|
||||||
$this->codebase->scanner->queueClassLikeForScanning('BackedEnum');
|
|
||||||
$storage->declaring_method_ids['from'] = new MethodIdentifier('BackedEnum', 'from');
|
|
||||||
$storage->appearing_method_ids['from'] = $storage->declaring_method_ids['from'];
|
|
||||||
$storage->declaring_method_ids['tryfrom'] = new MethodIdentifier(
|
|
||||||
'BackedEnum',
|
|
||||||
'tryfrom'
|
|
||||||
);
|
|
||||||
$storage->appearing_method_ids['tryfrom'] = $storage->declaring_method_ids['tryfrom'];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->codebase->scanner->queueClassLikeForScanning('UnitEnum');
|
$this->codebase->scanner->queueClassLikeForScanning('UnitEnum');
|
||||||
@ -710,7 +711,11 @@ class ClassLikeNodeScanner
|
|||||||
} elseif ($node_stmt instanceof PhpParser\Node\Stmt\EnumCase
|
} elseif ($node_stmt instanceof PhpParser\Node\Stmt\EnumCase
|
||||||
&& $node instanceof PhpParser\Node\Stmt\Enum_
|
&& $node instanceof PhpParser\Node\Stmt\Enum_
|
||||||
) {
|
) {
|
||||||
$this->visitEnumDeclaration($node_stmt, $storage, $fq_classlike_name);
|
$this->visitEnumDeclaration(
|
||||||
|
$node_stmt,
|
||||||
|
$storage,
|
||||||
|
$fq_classlike_name
|
||||||
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1364,6 +1369,8 @@ class ClassLikeNodeScanner
|
|||||||
|
|
||||||
$enum_value = null;
|
$enum_value = null;
|
||||||
|
|
||||||
|
$case_location = new CodeLocation($this->file_scanner, $stmt);
|
||||||
|
|
||||||
if ($stmt->expr !== null) {
|
if ($stmt->expr !== null) {
|
||||||
$case_type = SimpleTypeInferer::infer(
|
$case_type = SimpleTypeInferer::infer(
|
||||||
$this->codebase,
|
$this->codebase,
|
||||||
@ -1381,8 +1388,12 @@ class ClassLikeNodeScanner
|
|||||||
} elseif ($case_type->isSingleStringLiteral()) {
|
} elseif ($case_type->isSingleStringLiteral()) {
|
||||||
$enum_value = $case_type->getSingleStringLiteral()->value;
|
$enum_value = $case_type->getSingleStringLiteral()->value;
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException(
|
IssueBuffer::maybeAdd(
|
||||||
'Unexpected: case value for ' . $stmt->name->name . ' is ' . $case_type->getId()
|
new InvalidEnumCaseValue(
|
||||||
|
'Case of a backed enum should have either string or int value',
|
||||||
|
$case_location,
|
||||||
|
$fq_classlike_name
|
||||||
|
)
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
@ -1390,7 +1401,6 @@ class ClassLikeNodeScanner
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
$case_location = new CodeLocation($this->file_scanner, $stmt);
|
|
||||||
|
|
||||||
if (!isset($storage->enum_cases[$stmt->name->name])) {
|
if (!isset($storage->enum_cases[$stmt->name->name])) {
|
||||||
$case = new EnumCaseStorage(
|
$case = new EnumCaseStorage(
|
||||||
|
@ -575,6 +575,16 @@ class EnumTest extends TestCase
|
|||||||
'ignored_issues' => [],
|
'ignored_issues' => [],
|
||||||
'php_version' => '8.1',
|
'php_version' => '8.1',
|
||||||
],
|
],
|
||||||
|
'invalidCaseTypeForBackedEnum' => [
|
||||||
|
'code' => '<?php
|
||||||
|
enum Status: int {
|
||||||
|
case Open = [];
|
||||||
|
}
|
||||||
|
',
|
||||||
|
'error_message' => 'InvalidEnumCaseValue',
|
||||||
|
'ignored_issues' => [],
|
||||||
|
'php_version' => '8.1',
|
||||||
|
],
|
||||||
'duplicateValues' => [
|
'duplicateValues' => [
|
||||||
'code' => '<?php
|
'code' => '<?php
|
||||||
enum Status: string
|
enum Status: string
|
||||||
|
Loading…
x
Reference in New Issue
Block a user