1
0
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:
Matthew Brown 2016-12-16 22:15:31 -05:00
parent d012510a41
commit 972e3b5c6e
3 changed files with 43 additions and 137 deletions

View File

@ -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,

View File

@ -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);
}
}

View File

@ -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