From 49f7817a2a0f111b8a5317adf27b9f303fef11c8 Mon Sep 17 00:00:00 2001 From: Matthew Brown Date: Sat, 31 Dec 2016 09:20:10 -0500 Subject: [PATCH] Emit specific issue when calling instance method with self:: --- config.xsd | 1 + src/Psalm/Checker/MethodChecker.php | 38 ++++++++++++++----- .../Statements/Expression/CallChecker.php | 1 + src/Psalm/Issue/NonStaticSelfCall.php | 6 +++ tests/MethodCallTest.php | 21 ++++++++++ 5 files changed, 57 insertions(+), 10 deletions(-) create mode 100644 src/Psalm/Issue/NonStaticSelfCall.php diff --git a/config.xsd b/config.xsd index c8e0e661c..6868c4ee3 100644 --- a/config.xsd +++ b/config.xsd @@ -113,6 +113,7 @@ + diff --git a/src/Psalm/Checker/MethodChecker.php b/src/Psalm/Checker/MethodChecker.php index 757a0bf30..fbd65d472 100644 --- a/src/Psalm/Checker/MethodChecker.php +++ b/src/Psalm/Checker/MethodChecker.php @@ -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 $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; + } } } diff --git a/src/Psalm/Checker/Statements/Expression/CallChecker.php b/src/Psalm/Checker/Statements/Expression/CallChecker.php index a252d39a5..0dab8bb6f 100644 --- a/src/Psalm/Checker/Statements/Expression/CallChecker.php +++ b/src/Psalm/Checker/Statements/Expression/CallChecker.php @@ -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) { diff --git a/src/Psalm/Issue/NonStaticSelfCall.php b/src/Psalm/Issue/NonStaticSelfCall.php new file mode 100644 index 000000000..faf4bd8d4 --- /dev/null +++ b/src/Psalm/Issue/NonStaticSelfCall.php @@ -0,0 +1,6 @@ +check(true, true, $context); } + /** + * @expectedException \Psalm\Exception\CodeException + * @expectedExceptionMessage NonStaticSelfCall + */ + public function testSelfNonStaticInvocation() + { + $stmts = self::$parser->parse('check(true, true, $context); + } + /** * @expectedException \Psalm\Exception\CodeException * @expectedExceptionMessage ParentNotFound