mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Fix #2 - suppress errors for single lines
This commit is contained in:
parent
d06e844748
commit
8b7d82ddf6
@ -33,7 +33,7 @@ class FileChecker extends SourceChecker implements StatementsSource
|
||||
protected $actual_file_path;
|
||||
|
||||
/**
|
||||
* @var array<string, string>
|
||||
* @var array<int, string>
|
||||
*/
|
||||
protected $suppressed_issues = [];
|
||||
|
||||
@ -497,6 +497,26 @@ class FileChecker extends SourceChecker implements StatementsSource
|
||||
return $this->suppressed_issues;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $new_issues
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addSuppressedIssues(array $new_issues)
|
||||
{
|
||||
$this->suppressed_issues = array_merge($new_issues, $this->suppressed_issues);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $new_issues
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeSuppressedIssues(array $new_issues)
|
||||
{
|
||||
$this->suppressed_issues = array_diff($this->suppressed_issues, $new_issues);
|
||||
}
|
||||
|
||||
public function getFQCLN()
|
||||
{
|
||||
return null;
|
||||
|
@ -1321,6 +1321,26 @@ abstract class FunctionLikeChecker extends SourceChecker implements StatementsSo
|
||||
return $this->suppressed_issues;
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $new_issues
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addSuppressedIssues(array $new_issues)
|
||||
{
|
||||
$this->suppressed_issues = array_merge($new_issues, $this->suppressed_issues);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $new_issues
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeSuppressedIssues(array $new_issues)
|
||||
{
|
||||
$this->suppressed_issues = array_diff($this->suppressed_issues, $new_issues);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds a suppressed issue, useful when creating a method checker from scratch
|
||||
*
|
||||
|
@ -161,6 +161,34 @@ abstract class SourceChecker implements StatementsSource
|
||||
return $this->source->getSuppressedIssues();
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $new_issues
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addSuppressedIssues(array $new_issues)
|
||||
{
|
||||
if ($this->source === null) {
|
||||
throw new \UnexpectedValueException('$source cannot be null');
|
||||
}
|
||||
|
||||
return $this->source->addSuppressedIssues($new_issues);
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $new_issues
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeSuppressedIssues(array $new_issues)
|
||||
{
|
||||
if ($this->source === null) {
|
||||
throw new \UnexpectedValueException('$source cannot be null');
|
||||
}
|
||||
|
||||
return $this->source->removeSuppressedIssues($new_issues);
|
||||
}
|
||||
|
||||
/**
|
||||
* @return string
|
||||
*/
|
||||
|
@ -129,6 +129,33 @@ class StatementsChecker extends SourceChecker implements StatementsSource
|
||||
}
|
||||
*/
|
||||
|
||||
$new_issues = null;
|
||||
|
||||
if ($docblock = $stmt->getDocComment()) {
|
||||
$comments = CommentChecker::parseDocComment((string)$docblock);
|
||||
if (isset($comments['specials']['psalm-suppress'])) {
|
||||
$suppressed = array_filter(
|
||||
array_map(
|
||||
/**
|
||||
* @param string $line
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
function ($line) {
|
||||
return explode(' ', trim($line))[0];
|
||||
},
|
||||
$comments['specials']['psalm-suppress']
|
||||
)
|
||||
);
|
||||
|
||||
if ($suppressed) {
|
||||
$new_issues = array_diff($suppressed, $this->source->getSuppressedIssues());
|
||||
/** @psalm-suppress TypeCoercion */
|
||||
$this->addSuppressedIssues($new_issues);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($stmt instanceof PhpParser\Node\Stmt\If_) {
|
||||
IfChecker::analyze($this, $stmt, $context, $loop_context);
|
||||
} elseif ($stmt instanceof PhpParser\Node\Stmt\TryCatch) {
|
||||
@ -348,6 +375,11 @@ class StatementsChecker extends SourceChecker implements StatementsSource
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
if ($new_issues) {
|
||||
/** @psalm-suppress TypeCoercion */
|
||||
$this->removeSuppressedIssues($new_issues);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
|
@ -82,4 +82,18 @@ interface StatementsSource
|
||||
* @return array<int, string>
|
||||
*/
|
||||
public function getSuppressedIssues();
|
||||
|
||||
/**
|
||||
* @param array<int, string> $new_issues
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addSuppressedIssues(array $new_issues);
|
||||
|
||||
/**
|
||||
* @param array<int, string> $new_issues
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeSuppressedIssues(array $new_issues);
|
||||
}
|
||||
|
@ -140,4 +140,22 @@ class TraitSource implements StatementsSource
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $new_issues
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function addSuppressedIssues(array $new_issues)
|
||||
{
|
||||
}
|
||||
|
||||
/**
|
||||
* @param array<int, string> $new_issues
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function removeSuppressedIssues(array $new_issues)
|
||||
{
|
||||
}
|
||||
}
|
||||
|
54
tests/AssertTest.php
Normal file
54
tests/AssertTest.php
Normal file
@ -0,0 +1,54 @@
|
||||
<?php
|
||||
namespace Psalm\Tests;
|
||||
|
||||
class AssertTest extends TestCase
|
||||
{
|
||||
use Traits\FileCheckerInvalidCodeParseTestTrait;
|
||||
use Traits\FileCheckerValidCodeParseTestTrait;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function providerFileCheckerValidCodeParse()
|
||||
{
|
||||
return [
|
||||
'assertInstanceOfB' => [
|
||||
'<?php
|
||||
class A {}
|
||||
class B extends A {
|
||||
public function foo() : void {}
|
||||
}
|
||||
|
||||
function assertInstanceOfB(A $var) : void {
|
||||
if (!$var instanceof B) {
|
||||
throw new \Exception();
|
||||
}
|
||||
}
|
||||
|
||||
function assertInstanceOfClass(A $var, string $class) : void {
|
||||
if (!$var instanceof $class) {
|
||||
throw new \Exception();
|
||||
}
|
||||
}
|
||||
|
||||
function takesA(A $a) : void {
|
||||
assertInstanceOfB($a);
|
||||
$a->foo();
|
||||
}
|
||||
|
||||
function takesA(A $a) : void {
|
||||
assertInstanceOfB($a);
|
||||
$a->foo();
|
||||
}',
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function providerFileCheckerInvalidCodeParse()
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
@ -4,6 +4,7 @@ namespace Psalm\Tests;
|
||||
class IssueSuppressionTest extends TestCase
|
||||
{
|
||||
use Traits\FileCheckerValidCodeParseTestTrait;
|
||||
use Traits\FileCheckerInvalidCodeParseTestTrait;
|
||||
|
||||
/**
|
||||
* @return array
|
||||
@ -24,6 +25,24 @@ class IssueSuppressionTest extends TestCase
|
||||
}
|
||||
}',
|
||||
],
|
||||
'undefinedClassOneLine' => [
|
||||
'<?php
|
||||
class A {
|
||||
public function b() : void {
|
||||
/**
|
||||
* @psalm-suppress UndefinedClass
|
||||
*/
|
||||
new B();
|
||||
}
|
||||
}',
|
||||
],
|
||||
'undefinedClassOneLineInFile' => [
|
||||
'<?php
|
||||
/**
|
||||
* @psalm-suppress UndefinedClass
|
||||
*/
|
||||
new B();',
|
||||
],
|
||||
'excludeIssue' => [
|
||||
'<?php
|
||||
fooFoo();',
|
||||
@ -32,4 +51,35 @@ class IssueSuppressionTest extends TestCase
|
||||
],
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* @return array
|
||||
*/
|
||||
public function providerFileCheckerInvalidCodeParse()
|
||||
{
|
||||
return [
|
||||
'undefinedClassOneLineWithLineAfter' => [
|
||||
'<?php
|
||||
class A {
|
||||
public function b() {
|
||||
/**
|
||||
* @psalm-suppress UndefinedClass
|
||||
*/
|
||||
new B();
|
||||
new C();
|
||||
}
|
||||
}',
|
||||
'error_message' => 'UndefinedClass - src/somefile.php:8 - Class or interface C',
|
||||
],
|
||||
'undefinedClassOneLineInFileAfter' => [
|
||||
'<?php
|
||||
/**
|
||||
* @psalm-suppress UndefinedClass
|
||||
*/
|
||||
new B();
|
||||
new C();',
|
||||
'error_message' => 'UndefinedClass - src/somefile.php:6 - Class or interface C',
|
||||
],
|
||||
];
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user