mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Fix #300 - add PossiblyInvalidPropertyFetch
This commit is contained in:
parent
c5faa2d06a
commit
a99135c4d0
@ -160,6 +160,7 @@
|
|||||||
<xs:element name="PossiblyInvalidArrayAccess" type="IssueHandlerType" minOccurs="0" />
|
<xs:element name="PossiblyInvalidArrayAccess" type="IssueHandlerType" minOccurs="0" />
|
||||||
<xs:element name="PossiblyInvalidMethodCall" type="IssueHandlerType" minOccurs="0" />
|
<xs:element name="PossiblyInvalidMethodCall" type="IssueHandlerType" minOccurs="0" />
|
||||||
<xs:element name="PossiblyInvalidPropertyAssignment" type="IssueHandlerType" minOccurs="0" />
|
<xs:element name="PossiblyInvalidPropertyAssignment" type="IssueHandlerType" minOccurs="0" />
|
||||||
|
<xs:element name="PossiblyInvalidPropertyFetch" type="IssueHandlerType" minOccurs="0" />
|
||||||
<xs:element name="PossiblyNullArgument" type="IssueHandlerType" minOccurs="0" />
|
<xs:element name="PossiblyNullArgument" type="IssueHandlerType" minOccurs="0" />
|
||||||
<xs:element name="PossiblyNullArrayAccess" type="IssueHandlerType" minOccurs="0" />
|
<xs:element name="PossiblyNullArrayAccess" type="IssueHandlerType" minOccurs="0" />
|
||||||
<xs:element name="PossiblyNullFunctionCall" type="IssueHandlerType" minOccurs="0" />
|
<xs:element name="PossiblyNullFunctionCall" type="IssueHandlerType" minOccurs="0" />
|
||||||
|
@ -27,6 +27,7 @@ use Psalm\Issue\NullPropertyFetch;
|
|||||||
use Psalm\Issue\NullReference;
|
use Psalm\Issue\NullReference;
|
||||||
use Psalm\Issue\ParentNotFound;
|
use Psalm\Issue\ParentNotFound;
|
||||||
use Psalm\Issue\PossiblyInvalidArrayAccess;
|
use Psalm\Issue\PossiblyInvalidArrayAccess;
|
||||||
|
use Psalm\Issue\PossiblyInvalidPropertyFetch;
|
||||||
use Psalm\Issue\PossiblyNullArrayAccess;
|
use Psalm\Issue\PossiblyNullArrayAccess;
|
||||||
use Psalm\Issue\PossiblyNullPropertyFetch;
|
use Psalm\Issue\PossiblyNullPropertyFetch;
|
||||||
use Psalm\Issue\PossiblyNullReference;
|
use Psalm\Issue\PossiblyNullReference;
|
||||||
@ -167,25 +168,22 @@ class FetchChecker
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$invalid_fetch_types = [];
|
||||||
|
$has_valid_fetch_type = false;
|
||||||
|
|
||||||
foreach ($stmt_var_type->types as $lhs_type_part) {
|
foreach ($stmt_var_type->types as $lhs_type_part) {
|
||||||
if ($lhs_type_part instanceof TNull) {
|
if ($lhs_type_part instanceof TNull) {
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!$lhs_type_part instanceof TNamedObject && !$lhs_type_part instanceof TObject) {
|
if (!$lhs_type_part instanceof TNamedObject && !$lhs_type_part instanceof TObject) {
|
||||||
if (IssueBuffer::accepts(
|
$invalid_fetch_types[] = (string)$lhs_type_part;
|
||||||
new InvalidPropertyFetch(
|
|
||||||
'Cannot fetch property on non-object ' . $stmt_var_id . ' of type ' . $lhs_type_part,
|
|
||||||
new CodeLocation($statements_checker->getSource(), $stmt)
|
|
||||||
),
|
|
||||||
$statements_checker->getSuppressedIssues()
|
|
||||||
)) {
|
|
||||||
// fall through
|
|
||||||
}
|
|
||||||
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
$has_valid_fetch_type = true;
|
||||||
|
|
||||||
// stdClass and SimpleXMLElement are special cases where we cannot infer the return types
|
// stdClass and SimpleXMLElement are special cases where we cannot infer the return types
|
||||||
// but we don't want to throw an error
|
// but we don't want to throw an error
|
||||||
// Hack has a similar issue: https://github.com/facebook/hhvm/issues/5164
|
// Hack has a similar issue: https://github.com/facebook/hhvm/issues/5164
|
||||||
@ -365,6 +363,32 @@ class FetchChecker
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($invalid_fetch_types) {
|
||||||
|
$lhs_type_part = $invalid_fetch_types[0];
|
||||||
|
|
||||||
|
if ($has_valid_fetch_type) {
|
||||||
|
if (IssueBuffer::accepts(
|
||||||
|
new PossiblyInvalidPropertyFetch(
|
||||||
|
'Cannot fetch property on possible non-object ' . $stmt_var_id . ' of type ' . $lhs_type_part,
|
||||||
|
new CodeLocation($statements_checker->getSource(), $stmt)
|
||||||
|
),
|
||||||
|
$statements_checker->getSuppressedIssues()
|
||||||
|
)) {
|
||||||
|
// fall through
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if (IssueBuffer::accepts(
|
||||||
|
new InvalidPropertyFetch(
|
||||||
|
'Cannot fetch property on non-object ' . $stmt_var_id . ' of type ' . $lhs_type_part,
|
||||||
|
new CodeLocation($statements_checker->getSource(), $stmt)
|
||||||
|
),
|
||||||
|
$statements_checker->getSuppressedIssues()
|
||||||
|
)) {
|
||||||
|
// fall through
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if ($var_id) {
|
if ($var_id) {
|
||||||
$context->vars_in_scope[$var_id] = isset($stmt->inferredType) ? $stmt->inferredType : Type::getMixed();
|
$context->vars_in_scope[$var_id] = isset($stmt->inferredType) ? $stmt->inferredType : Type::getMixed();
|
||||||
}
|
}
|
||||||
|
6
src/Psalm/Issue/PossiblyInvalidPropertyFetch.php
Normal file
6
src/Psalm/Issue/PossiblyInvalidPropertyFetch.php
Normal file
@ -0,0 +1,6 @@
|
|||||||
|
<?php
|
||||||
|
namespace Psalm\Issue;
|
||||||
|
|
||||||
|
class PossiblyInvalidPropertyFetch extends CodeError
|
||||||
|
{
|
||||||
|
}
|
@ -609,6 +609,12 @@ final class B extends A {}',
|
|||||||
echo $a->foo;',
|
echo $a->foo;',
|
||||||
'error_message' => 'InvalidPropertyFetch',
|
'error_message' => 'InvalidPropertyFetch',
|
||||||
],
|
],
|
||||||
|
'possiblyBadFetch' => [
|
||||||
|
'<?php
|
||||||
|
$a = rand(0, 5) > 3 ? "hello" : new stdClass;
|
||||||
|
echo $a->foo;',
|
||||||
|
'error_message' => 'PossiblyInvalidPropertyFetch',
|
||||||
|
],
|
||||||
'mixedPropertyFetch' => [
|
'mixedPropertyFetch' => [
|
||||||
'<?php
|
'<?php
|
||||||
class Foo {
|
class Foo {
|
||||||
|
Loading…
Reference in New Issue
Block a user