Skip to content
Permalink
Browse files

Add a PossibleRawObjectIteration issue

  • Loading branch information...
muglug committed Aug 20, 2019
1 parent 14584d6 commit 95c61db5134569b9e5f315124cd444d89ec6cd95
@@ -89,5 +89,6 @@
<PossiblyUndefinedVariable errorLevel="info" />
<PossiblyUndefinedArrayOffset errorLevel="info" />
<PossiblyUndefinedMethod errorLevel="info" />
<PossibleRawObjectIteration errorLevel="info" />
</issueHandlers>
</psalm>
@@ -90,6 +90,7 @@
<PossiblyUndefinedVariable errorLevel="info" />
<PossiblyUndefinedArrayOffset errorLevel="info" />
<PossiblyUndefinedMethod errorLevel="info" />
<PossibleRawObjectIteration errorLevel="info" />

<!-- level 5 issues - should be avoided at mosts costs... -->

@@ -90,6 +90,7 @@
<PossiblyUndefinedVariable errorLevel="info" />
<PossiblyUndefinedArrayOffset errorLevel="info" />
<PossiblyUndefinedMethod errorLevel="info" />
<PossibleRawObjectIteration errorLevel="info" />

<!-- level 5 issues - should be avoided at mosts costs... -->

@@ -90,6 +90,7 @@
<PossiblyUndefinedVariable errorLevel="info" />
<PossiblyUndefinedArrayOffset errorLevel="info" />
<PossiblyUndefinedMethod errorLevel="info" />
<PossibleRawObjectIteration errorLevel="info" />

<!-- level 5 issues - should be avoided at mosts costs... -->

@@ -90,6 +90,7 @@
<PossiblyUndefinedVariable errorLevel="info" />
<PossiblyUndefinedArrayOffset errorLevel="info" />
<PossiblyUndefinedMethod errorLevel="info" />
<PossibleRawObjectIteration errorLevel="info" />

<!-- level 5 issues - should be avoided at mosts costs... -->

@@ -267,6 +267,7 @@
<xs:element name="OverriddenPropertyAccess" type="PropertyIssueHandlerType" minOccurs="0" />
<xs:element name="ParadoxicalCondition" type="IssueHandlerType" minOccurs="0" />
<xs:element name="ParentNotFound" type="IssueHandlerType" minOccurs="0" />
<xs:element name="PossibleRawObjectIteration" type="IssueHandlerType" minOccurs="0" />
<xs:element name="PossiblyFalseArgument" type="ArgumentIssueHandlerType" minOccurs="0" />
<xs:element name="PossiblyFalseIterator" type="IssueHandlerType" minOccurs="0" />
<xs:element name="PossiblyFalseOperand" type="IssueHandlerType" minOccurs="0" />
@@ -1518,6 +1518,28 @@ class A {

Can be emitted by plugins.

### PossibleRawObjectIteration

Emitted when possibly iterating over an object’s properties, the comparison to [RawObjectIteration](#rawobjectiteration).

```php
class A {
/** @var string|null */
public $foo;
/** @var string|null */
public $bar;
}
function takesA(A $a) {
if (rand(0, 1)) {
$a = [1, 2, 3];
}
foreach ($a as $property) {}
}
```

### PossiblyFalseArgument

Emitted when a function argument is possibly `false`, but the function doesn’t expect `false`. This is distinct from a function argument is possibly `bool`, which results in `PossiblyInvalidArgument`.
@@ -1270,6 +1270,10 @@ public static function getParentIssueType($issue_type)
return 'UndefinedMethod';
}
if ($issue_type === 'PossibleRawObjectIteration') {
return 'RawObjectIteration';
}
if ($issue_type === 'UninitializedProperty') {
return 'PropertyNotSetInConstructor';
}
@@ -19,6 +19,7 @@
use Psalm\Issue\PossiblyFalseIterator;
use Psalm\Issue\PossiblyInvalidIterator;
use Psalm\Issue\PossiblyNullIterator;
use Psalm\Issue\PossibleRawObjectIteration;
use Psalm\Issue\RawObjectIteration;
use Psalm\IssueBuffer;
use Psalm\Internal\Scope\LoopScope;
@@ -383,6 +384,7 @@ public static function checkIteratorType(
$has_valid_iterator = false;
$invalid_iterator_types = [];
$raw_object_types = [];
foreach ($iterator_type->getTypes() as $iterator_atomic_type) {
if ($iterator_atomic_type instanceof Type\Atomic\TTemplateParam) {
@@ -539,15 +541,31 @@ public static function checkIteratorType(
$has_valid_iterator
);
} else {
if (IssueBuffer::accepts(
new RawObjectIteration(
'Possibly undesired iteration over regular object ' . $iterator_atomic_type->value,
new CodeLocation($statements_analyzer->getSource(), $stmt->expr)
),
$statements_analyzer->getSuppressedIssues()
)) {
// fall through
}
$raw_object_types[] = $iterator_atomic_type->value;
}
}
}
if ($raw_object_types) {
if ($has_valid_iterator) {
if (IssueBuffer::accepts(
new PossibleRawObjectIteration(
'Possibly undesired iteration over regular object ' . \reset($raw_object_types),
new CodeLocation($statements_analyzer->getSource(), $stmt->expr)
),
$statements_analyzer->getSuppressedIssues()
)) {
// fall through
}
} else {
if (IssueBuffer::accepts(
new RawObjectIteration(
'Possibly undesired iteration over regular object ' . \reset($raw_object_types),
new CodeLocation($statements_analyzer->getSource(), $stmt->expr)
),
$statements_analyzer->getSuppressedIssues()
)) {
// fall through
}
}
}
@@ -0,0 +1,6 @@
<?php
namespace Psalm\Issue;
class PossibleRawObjectIteration extends CodeIssue
{
}
@@ -949,6 +949,18 @@ function foo(ValueCollection $v) : void {
foreach ($v as $value) {}
}',
],
'possibleRawObjectIterationFromIssetSuppressed' => [
'<?php
/**
* @psalm-suppress RawObjectIteration
* @psalm-suppress MixedAssignment
*/
function foo(array $a) : void {
if (isset($a["a"]["b"])) {
foreach ($a["a"] as $c) {}
}
}',
],
];
}
@@ -1112,6 +1124,18 @@ public function barBar() {
'error_message' => 'InvalidIterator',
],
'rawObjectIteration' => [
'<?php
class A {
/** @var ?string */
public $foo;
}
$arr = new A;
foreach ($arr as $a) {}',
'error_message' => 'RawObjectIteration',
],
'possibleRawObjectIteration' => [
'<?php
class A {
/** @var ?string */
@@ -1133,7 +1157,16 @@ function bar(A $a): void {}
foreach ($arr as $a) {
bar($a);
}',
'error_message' => 'RawObjectIteration',
'error_message' => 'PossibleRawObjectIteration',
],
'possibleRawObjectIterationFromIsset' => [
'<?php
function foo(array $a) : void {
if (isset($a["a"]["b"])) {
foreach ($a["a"] as $c) {}
}
}',
'error_message' => 'PossibleRawObjectIteration',
],
'ifSpecificNonEmptyValues' => [
'<?php

0 comments on commit 95c61db

Please sign in to comment.
You can’t perform that action at this time.