mirror of
https://github.com/danog/psalm.git
synced 2024-11-30 04:39:00 +01:00
Support multiple issue types in @psalm-suppress
(#4179)
* Accept multiple issue names in `@psalm-suppress` Fixes vimeo/psalm#1575 * Accept multiple issue types on statement docblocks as well * Proper highlighting of individual issues in compound suppressions
This commit is contained in:
parent
4319132057
commit
b27a233cdd
@ -197,4 +197,41 @@ class DocComment
|
|||||||
|
|
||||||
return $parsed_docblock;
|
return $parsed_docblock;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @psalm-pure
|
||||||
|
* @return array<int,string>
|
||||||
|
*/
|
||||||
|
public static function parseSuppressList(string $suppress_entry): array
|
||||||
|
{
|
||||||
|
preg_match(
|
||||||
|
'/
|
||||||
|
(?(DEFINE)
|
||||||
|
# either a single issue or comma separated list of issues
|
||||||
|
(?<issue_list> (?&issue) \s* , \s* (?&issue_list) | (?&issue) )
|
||||||
|
|
||||||
|
# definition of a single issue
|
||||||
|
(?<issue> [A-Za-z0-9_-]+ )
|
||||||
|
)
|
||||||
|
^ (?P<issues> (?&issue_list) ) (?P<description> .* ) $
|
||||||
|
/xm',
|
||||||
|
$suppress_entry,
|
||||||
|
$matches
|
||||||
|
);
|
||||||
|
|
||||||
|
if (!isset($matches['issues'])) {
|
||||||
|
return [];
|
||||||
|
}
|
||||||
|
|
||||||
|
$issue_offset = 0;
|
||||||
|
$ret = [];
|
||||||
|
|
||||||
|
foreach (explode(',', $matches['issues']) as $suppressed_issue) {
|
||||||
|
$issue_offset += strspn($suppressed_issue, "\t\n\f\r ");
|
||||||
|
$ret[$issue_offset] = trim($suppressed_issue);
|
||||||
|
$issue_offset += strlen($suppressed_issue) + 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
return $ret;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -357,10 +357,7 @@ class CommentAnalyzer
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param int $line_number
|
|
||||||
*
|
|
||||||
* @throws DocblockParseException if there was a problem parsing the docblock
|
* @throws DocblockParseException if there was a problem parsing the docblock
|
||||||
*
|
|
||||||
*/
|
*/
|
||||||
public static function extractFunctionDocblockInfo(PhpParser\Comment\Doc $comment): FunctionDocblockComment
|
public static function extractFunctionDocblockInfo(PhpParser\Comment\Doc $comment): FunctionDocblockComment
|
||||||
{
|
{
|
||||||
@ -644,7 +641,9 @@ class CommentAnalyzer
|
|||||||
|
|
||||||
if (isset($parsed_docblock->tags['psalm-suppress'])) {
|
if (isset($parsed_docblock->tags['psalm-suppress'])) {
|
||||||
foreach ($parsed_docblock->tags['psalm-suppress'] as $offset => $suppress_entry) {
|
foreach ($parsed_docblock->tags['psalm-suppress'] as $offset => $suppress_entry) {
|
||||||
$info->suppressed_issues[$offset + $comment->getFilePos()] = preg_split('/[\s]+/', $suppress_entry)[0];
|
foreach (DocComment::parseSuppressList($suppress_entry) as $issue_offset => $suppressed_issue) {
|
||||||
|
$info->suppressed_issues[$issue_offset + $offset + $comment->getFilePos()] = $suppressed_issue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -985,7 +984,9 @@ class CommentAnalyzer
|
|||||||
|
|
||||||
if (isset($parsed_docblock->tags['psalm-suppress'])) {
|
if (isset($parsed_docblock->tags['psalm-suppress'])) {
|
||||||
foreach ($parsed_docblock->tags['psalm-suppress'] as $offset => $suppress_entry) {
|
foreach ($parsed_docblock->tags['psalm-suppress'] as $offset => $suppress_entry) {
|
||||||
$info->suppressed_issues[$offset + $comment->getFilePos()] = preg_split('/[\s]+/', $suppress_entry)[0];
|
foreach (DocComment::parseSuppressList($suppress_entry) as $issue_offset => $suppressed_issue) {
|
||||||
|
$info->suppressed_issues[$issue_offset + $offset + $comment->getFilePos()] = $suppressed_issue;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -342,26 +342,13 @@ class StatementsAnalyzer extends SourceAnalyzer implements StatementsSource
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isset($statements_analyzer->parsed_docblock->tags['psalm-suppress'])) {
|
if (isset($statements_analyzer->parsed_docblock->tags['psalm-suppress'])) {
|
||||||
$suppressed = array_filter(
|
$suppressed = $statements_analyzer->parsed_docblock->tags['psalm-suppress'];
|
||||||
array_map(
|
|
||||||
/**
|
|
||||||
* @param string $line
|
|
||||||
*
|
|
||||||
* @return string
|
|
||||||
*/
|
|
||||||
function ($line): string {
|
|
||||||
return preg_split('/[\s]+/', $line)[0];
|
|
||||||
},
|
|
||||||
$statements_analyzer->parsed_docblock->tags['psalm-suppress']
|
|
||||||
)
|
|
||||||
);
|
|
||||||
|
|
||||||
if ($suppressed) {
|
if ($suppressed) {
|
||||||
$new_issues = [];
|
$new_issues = [];
|
||||||
|
|
||||||
foreach ($suppressed as $offset => $issue_type) {
|
foreach ($suppressed as $offset => $suppress_entry) {
|
||||||
$offset += $docblock->getFilePos();
|
foreach (DocComment::parseSuppressList($suppress_entry) as $issue_offset => $issue_type) {
|
||||||
$new_issues[$offset] = $issue_type;
|
$new_issues[$issue_offset + $offset + $docblock->getFilePos()] = $issue_type;
|
||||||
|
|
||||||
if ($issue_type === 'InaccessibleMethod') {
|
if ($issue_type === 'InaccessibleMethod') {
|
||||||
continue;
|
continue;
|
||||||
@ -370,11 +357,12 @@ class StatementsAnalyzer extends SourceAnalyzer implements StatementsSource
|
|||||||
if ($codebase->track_unused_suppressions) {
|
if ($codebase->track_unused_suppressions) {
|
||||||
IssueBuffer::addUnusedSuppression(
|
IssueBuffer::addUnusedSuppression(
|
||||||
$statements_analyzer->getFilePath(),
|
$statements_analyzer->getFilePath(),
|
||||||
$offset,
|
$issue_offset + $offset + $docblock->getFilePos(),
|
||||||
$issue_type
|
$issue_type
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$statements_analyzer->addSuppressedIssues($new_issues);
|
$statements_analyzer->addSuppressedIssues($new_issues);
|
||||||
}
|
}
|
||||||
|
@ -210,6 +210,17 @@ class IssueSuppressionTest extends TestCase
|
|||||||
}
|
}
|
||||||
}',
|
}',
|
||||||
],
|
],
|
||||||
|
'multipleIssues' => [
|
||||||
|
'<?php
|
||||||
|
class A {
|
||||||
|
/**
|
||||||
|
* @psalm-suppress UndefinedClass, MixedMethodCall,MissingReturnType because reasons
|
||||||
|
*/
|
||||||
|
public function b() {
|
||||||
|
B::fooFoo()->barBar()->bat()->baz()->bam()->bas()->bee()->bet()->bes()->bis();
|
||||||
|
}
|
||||||
|
}',
|
||||||
|
],
|
||||||
'undefinedClassOneLine' => [
|
'undefinedClassOneLine' => [
|
||||||
'<?php
|
'<?php
|
||||||
class A {
|
class A {
|
||||||
|
Loading…
Reference in New Issue
Block a user