1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 12:24:49 +01:00

Emit specific issue when calling instance method with self::

This commit is contained in:
Matthew Brown 2016-12-31 09:20:10 -05:00
parent 393297786d
commit 49f7817a2a
5 changed files with 57 additions and 10 deletions

View File

@ -113,6 +113,7 @@
<xs:element name="MixedPropertyFetch" type="IssueHandlerType" minOccurs="0" />
<xs:element name="MixedStringOffsetAssignment" type="IssueHandlerType" minOccurs="0" />
<xs:element name="NoInterfaceProperties" type="IssueHandlerType" minOccurs="0" />
<xs:element name="NonStaticSelfCall" type="IssueHandlerType" minOccurs="0" />
<xs:element name="NullArgument" type="IssueHandlerType" minOccurs="0" />
<xs:element name="NullArrayAccess" type="IssueHandlerType" minOccurs="0" />
<xs:element name="NullOperand" type="IssueHandlerType" minOccurs="0" />

View File

@ -9,6 +9,7 @@ use Psalm\Issue\DeprecatedMethod;
use Psalm\Issue\InaccessibleMethod;
use Psalm\Issue\InvalidDocblock;
use Psalm\Issue\InvalidStaticInvocation;
use Psalm\Issue\NonStaticSelfCall;
use Psalm\Issue\UndefinedMethod;
use Psalm\IssueBuffer;
use Psalm\StatementsSource;
@ -213,12 +214,17 @@ class MethodChecker extends FunctionLikeChecker
* Determines whether a given method is static or not
*
* @param string $method_id
* @param bool $self_call
* @param CodeLocation $code_location
* @param array<string> $suppressed_issues
* @return bool
*/
public static function checkMethodStatic($method_id, CodeLocation $code_location, array $suppressed_issues)
{
public static function checkMethodStatic(
$method_id,
$self_call,
CodeLocation $code_location,
array $suppressed_issues
) {
self::registerClassMethod($method_id);
/** @var string */
@ -231,14 +237,26 @@ class MethodChecker extends FunctionLikeChecker
}
if (!$storage->is_static) {
if (IssueBuffer::accepts(
new InvalidStaticInvocation(
'Method ' . MethodChecker::getCasedMethodId($method_id) . ' is not static',
$code_location
),
$suppressed_issues
)) {
return false;
if ($self_call) {
if (IssueBuffer::accepts(
new NonStaticSelfCall(
'Method ' . MethodChecker::getCasedMethodId($method_id) . ' is not static, but is called using self::',
$code_location
),
$suppressed_issues
)) {
return false;
}
} else {
if (IssueBuffer::accepts(
new InvalidStaticInvocation(
'Method ' . MethodChecker::getCasedMethodId($method_id) . ' is not static, but is called statically',
$code_location
),
$suppressed_issues
)) {
return false;
}
}
}

View File

@ -696,6 +696,7 @@ class CallChecker
) {
if (MethodChecker::checkMethodStatic(
$method_id,
$stmt->class instanceof PhpParser\Node\Name && $stmt->class->parts[0] === 'self',
new CodeLocation($statements_checker->getSource(), $stmt),
$statements_checker->getSuppressedIssues()
) === false) {

View File

@ -0,0 +1,6 @@
<?php
namespace Psalm\Issue;
class NonStaticSelfCall extends CodeError
{
}

View File

@ -101,6 +101,27 @@ class MethodCallTest extends PHPUnit_Framework_TestCase
$file_checker->check(true, true, $context);
}
/**
* @expectedException \Psalm\Exception\CodeException
* @expectedExceptionMessage NonStaticSelfCall
*/
public function testSelfNonStaticInvocation()
{
$stmts = self::$parser->parse('<?php
class A {
public function fooFoo() : void {}
public function barBar() : void {
self::fooFoo();
}
}
');
$file_checker = new FileChecker('somefile.php', $stmts);
$context = new Context('somefile.php');
$file_checker->check(true, true, $context);
}
/**
* @expectedException \Psalm\Exception\CodeException
* @expectedExceptionMessage ParentNotFound