mirror of
https://github.com/danog/psalm.git
synced 2024-11-26 20:34:47 +01:00
Fix failure to warn when class does not implement all interface methods
This commit is contained in:
parent
d012510a41
commit
972e3b5c6e
@ -426,7 +426,7 @@ abstract class ClassLikeChecker extends SourceChecker implements StatementsSourc
|
||||
$implemented_method_id = $this->fq_class_name . '::' . $method_name;
|
||||
MethodChecker::setOverriddenMethodId($implemented_method_id, $mentioned_method_id);
|
||||
|
||||
if (!isset(self::$public_class_methods[$this->fq_class_name])) {
|
||||
if (!isset(self::$public_class_methods[$this->fq_class_name][$method_name])) {
|
||||
if (IssueBuffer::accepts(
|
||||
new UnimplementedInterfaceMethod(
|
||||
'Method ' . $method_name . ' is not defined on class ' . $this->fq_class_name,
|
||||
|
@ -158,4 +158,46 @@ class InterfaceTest extends PHPUnit_Framework_TestCase
|
||||
$context = new Context('somefile.php');
|
||||
$file_checker->check(true, true, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Psalm\Exception\CodeException
|
||||
* @expectedExceptionMessage NoInterfaceProperties
|
||||
*/
|
||||
public function testNoInterfaceProperties()
|
||||
{
|
||||
$stmts = self::$parser->parse('<?php
|
||||
interface A { }
|
||||
|
||||
function foo(A $a) : void {
|
||||
if ($a->bar) {
|
||||
|
||||
}
|
||||
}
|
||||
?>
|
||||
');
|
||||
|
||||
$file_checker = new FileChecker('somefile.php', $stmts);
|
||||
$context = new Context('somefile.php');
|
||||
$file_checker->check(true, true, $context);
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Psalm\Exception\CodeException
|
||||
* @expectedExceptionMessage UnimplementedInterfaceMethod
|
||||
*/
|
||||
public function testUnimplementedInterfaceMethod()
|
||||
{
|
||||
$stmts = self::$parser->parse('<?php
|
||||
interface A {
|
||||
public function foo();
|
||||
}
|
||||
|
||||
class B implements A { }
|
||||
?>
|
||||
');
|
||||
|
||||
$file_checker = new FileChecker('somefile.php', $stmts);
|
||||
$context = new Context('somefile.php');
|
||||
$file_checker->check(true, true, $context);
|
||||
}
|
||||
}
|
||||
|
@ -617,142 +617,6 @@ class ScopeTest extends PHPUnit_Framework_TestCase
|
||||
$file_checker->check();
|
||||
}
|
||||
|
||||
public function testAccessiblePrivateMethodFromTrait()
|
||||
{
|
||||
$stmts = self::$parser->parse('<?php
|
||||
trait A {
|
||||
private function foo() : void {
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
use A;
|
||||
|
||||
public function doFoo() : void {
|
||||
$this->foo();
|
||||
}
|
||||
}
|
||||
');
|
||||
|
||||
$file_checker = new FileChecker('somefile.php', $stmts);
|
||||
$file_checker->check();
|
||||
}
|
||||
|
||||
public function testAccessibleProtectedMethodFromTrait()
|
||||
{
|
||||
$stmts = self::$parser->parse('<?php
|
||||
trait A {
|
||||
protected function foo() : void {
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
use A;
|
||||
|
||||
public function doFoo() : void {
|
||||
$this->foo();
|
||||
}
|
||||
}
|
||||
');
|
||||
|
||||
$file_checker = new FileChecker('somefile.php', $stmts);
|
||||
$file_checker->check();
|
||||
}
|
||||
|
||||
public function testAccessiblePublicMethodFromTrait()
|
||||
{
|
||||
$stmts = self::$parser->parse('<?php
|
||||
trait A {
|
||||
public function foo() : void {
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
use A;
|
||||
|
||||
public function doFoo() : void {
|
||||
$this->foo();
|
||||
}
|
||||
}
|
||||
');
|
||||
|
||||
$file_checker = new FileChecker('somefile.php', $stmts);
|
||||
$file_checker->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Psalm\Exception\CodeException
|
||||
* @expectedExceptionMessage UndefinedMethod
|
||||
*/
|
||||
public function testInccessiblePrivateMethodFromInheritedTrait()
|
||||
{
|
||||
$stmts = self::$parser->parse('<?php
|
||||
trait A {
|
||||
private function foo() : void {
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
use A;
|
||||
}
|
||||
|
||||
class C extends B {
|
||||
public function doFoo() : void {
|
||||
$this->foo();
|
||||
}
|
||||
}
|
||||
');
|
||||
|
||||
$file_checker = new FileChecker('somefile.php', $stmts);
|
||||
$file_checker->check();
|
||||
}
|
||||
|
||||
public function testAccessibleProtectedMethodFromInheritedTrait()
|
||||
{
|
||||
$stmts = self::$parser->parse('<?php
|
||||
trait A {
|
||||
protected function foo() : void {
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
use A;
|
||||
}
|
||||
|
||||
class C extends B {
|
||||
public function doFoo() : void {
|
||||
$this->foo();
|
||||
}
|
||||
}
|
||||
');
|
||||
|
||||
$file_checker = new FileChecker('somefile.php', $stmts);
|
||||
$file_checker->check();
|
||||
}
|
||||
|
||||
public function testAccessiblePublicMethodFromInheritedTrait()
|
||||
{
|
||||
$stmts = self::$parser->parse('<?php
|
||||
trait A {
|
||||
public function foo() : void {
|
||||
}
|
||||
}
|
||||
|
||||
class B {
|
||||
use A;
|
||||
}
|
||||
|
||||
class C extends B {
|
||||
public function doFoo() : void {
|
||||
$this->foo();
|
||||
}
|
||||
}
|
||||
');
|
||||
|
||||
$file_checker = new FileChecker('somefile.php', $stmts);
|
||||
$file_checker->check();
|
||||
}
|
||||
|
||||
/**
|
||||
* @expectedException \Psalm\Exception\CodeException
|
||||
* @expectedExceptionMessage InaccessibleProperty
|
||||
|
Loading…
Reference in New Issue
Block a user