1
0
mirror of https://github.com/danog/psalm.git synced 2024-11-26 20:34:47 +01:00

Fix #522 - prevent interface instantiation

This commit is contained in:
Matthew Brown 2018-02-17 18:53:02 -05:00
parent 108ca54867
commit 59dc239c89
4 changed files with 32 additions and 1 deletions

View File

@ -107,6 +107,7 @@
<xs:element name="InaccessibleClassConstant" type="IssueHandlerType" minOccurs="0" /> <xs:element name="InaccessibleClassConstant" type="IssueHandlerType" minOccurs="0" />
<xs:element name="InaccessibleMethod" type="IssueHandlerType" minOccurs="0" /> <xs:element name="InaccessibleMethod" type="IssueHandlerType" minOccurs="0" />
<xs:element name="InaccessibleProperty" type="IssueHandlerType" minOccurs="0" /> <xs:element name="InaccessibleProperty" type="IssueHandlerType" minOccurs="0" />
<xs:element name="InterfaceInstantiation" type="IssueHandlerType" minOccurs="0" />
<xs:element name="InvalidArgument" type="IssueHandlerType" minOccurs="0" /> <xs:element name="InvalidArgument" type="IssueHandlerType" minOccurs="0" />
<xs:element name="InvalidArrayAccess" type="IssueHandlerType" minOccurs="0" /> <xs:element name="InvalidArrayAccess" type="IssueHandlerType" minOccurs="0" />
<xs:element name="InvalidArrayAssignment" type="IssueHandlerType" minOccurs="0" /> <xs:element name="InvalidArrayAssignment" type="IssueHandlerType" minOccurs="0" />

View File

@ -251,6 +251,15 @@ class A {
echo (new A)->foo(); echo (new A)->foo();
``` ```
### InterfaceInstantiation
Emitted when an attempt is made to instatiate an interface:
```php
interface I {}
new I();
```
### InaccessibleProperty ### InaccessibleProperty
Emitted when attempting to access a protected/private property from outside its available scope Emitted when attempting to access a protected/private property from outside its available scope

View File

@ -11,6 +11,7 @@ use Psalm\CodeLocation;
use Psalm\Context; use Psalm\Context;
use Psalm\Issue\AbstractInstantiation; use Psalm\Issue\AbstractInstantiation;
use Psalm\Issue\DeprecatedClass; use Psalm\Issue\DeprecatedClass;
use Psalm\Issue\InterfaceInstantiation;
use Psalm\Issue\TooManyArguments; use Psalm\Issue\TooManyArguments;
use Psalm\IssueBuffer; use Psalm\IssueBuffer;
use Psalm\Type; use Psalm\Type;
@ -59,6 +60,20 @@ class NewChecker extends \Psalm\Checker\Statements\Expression\CallChecker
) === false) { ) === false) {
return false; return false;
} }
if ($codebase->interfaceExists($fq_class_name)) {
if (IssueBuffer::accepts(
new InterfaceInstantiation(
'Interface ' . $fq_class_name . ' cannot be instantiated',
new CodeLocation($statements_checker->getSource(), $stmt->class)
),
$statements_checker->getSuppressedIssues()
)) {
return false;
}
return null;
}
} }
} else { } else {
switch ($stmt->class->parts[0]) { switch ($stmt->class->parts[0]) {
@ -106,7 +121,7 @@ class NewChecker extends \Psalm\Checker\Statements\Expression\CallChecker
if (strtolower($fq_class_name) !== 'stdclass' && if (strtolower($fq_class_name) !== 'stdclass' &&
$context->check_classes && $context->check_classes &&
$codebase->classExists($fq_class_name) $codebase->classlikes->classExists($fq_class_name)
) { ) {
$storage = $project_checker->classlike_storage_provider->get($fq_class_name); $storage = $project_checker->classlike_storage_provider->get($fq_class_name);

View File

@ -574,6 +574,12 @@ class InterfaceTest extends TestCase
}', }',
'error_message' => 'InvalidReturnType', 'error_message' => 'InvalidReturnType',
], ],
'interfaceInstantiation' => [
'<?php
interface myInterface{}
new myInterface();',
'error_message' => 'InterfaceInstantiation',
],
]; ];
} }
} }