diff --git a/config.xsd b/config.xsd index 046547eee..4f4b7f82a 100644 --- a/config.xsd +++ b/config.xsd @@ -44,6 +44,8 @@ + + @@ -476,6 +478,7 @@ + diff --git a/docs/running_psalm/configuration.md b/docs/running_psalm/configuration.md index 8b8d5a385..c642eb3f0 100644 --- a/docs/running_psalm/configuration.md +++ b/docs/running_psalm/configuration.md @@ -491,6 +491,10 @@ class PremiumCar extends StandardCar { ``` `ImplementedReturnTypeMismatch - The inherited return type 'list{'motor', 'brakes', 'wheels'}' for StandardCar::getSystems is different to the implemented return type for PremiumCar::getsystems 'list{'motor', 'brakes', 'wheels', 'rear parking sensor'}'` +#### findUnusedBaselineEntry + +Emits [UnusedBaselineEntry](issues/UnusedBaselineEntry.md) when a baseline entry +is not being used to suppress an issue. ## Project settings diff --git a/docs/running_psalm/issues.md b/docs/running_psalm/issues.md index 615dd2d97..b232476a3 100644 --- a/docs/running_psalm/issues.md +++ b/docs/running_psalm/issues.md @@ -282,6 +282,7 @@ - [UnsafeGenericInstantiation](issues/UnsafeGenericInstantiation.md) - [UnsafeInstantiation](issues/UnsafeInstantiation.md) - [UnsupportedReferenceUsage](issues/UnsupportedReferenceUsage.md) + - [UnusedBaselineEntry](issues/UnusedBaselineEntry.md) - [UnusedClass](issues/UnusedClass.md) - [UnusedClosureParam](issues/UnusedClosureParam.md) - [UnusedConstructor](issues/UnusedConstructor.md) diff --git a/docs/running_psalm/issues/UnusedBaselineEntry.md b/docs/running_psalm/issues/UnusedBaselineEntry.md new file mode 100644 index 000000000..16e238eb4 --- /dev/null +++ b/docs/running_psalm/issues/UnusedBaselineEntry.md @@ -0,0 +1,22 @@ +# UnusedBaselineEntry + +Emitted when a baseline entry is not being used to suppress an issue. + +Enabled by [findUnusedBaselineEntry](../configuration.md#findunusedbaselineentry) + +```php + + + + + + $a + + + +``` diff --git a/psalm-baseline.xml b/psalm-baseline.xml index 590089a84..516695fa2 100644 --- a/psalm-baseline.xml +++ b/psalm-baseline.xml @@ -701,11 +701,6 @@ hasLowercaseString - - - UndefinedMethod - - $subNodes['expr'] diff --git a/psalm.xml.dist b/psalm.xml.dist index f81ee56d4..6cee5a64b 100644 --- a/psalm.xml.dist +++ b/psalm.xml.dist @@ -12,6 +12,7 @@ limitMethodComplexity="true" errorBaseline="psalm-baseline.xml" findUnusedPsalmSuppress="true" + findUnusedBaselineEntry="true" > diff --git a/src/Psalm/Config.php b/src/Psalm/Config.php index 5efbf8c27..faee01d9f 100644 --- a/src/Psalm/Config.php +++ b/src/Psalm/Config.php @@ -460,6 +460,11 @@ class Config */ public $find_unused_psalm_suppress = false; + /** + * TODO: Psalm 6: Update default to be true and remove warning. + */ + public bool $find_unused_baseline_entry = false; + /** * @var bool */ @@ -1061,6 +1066,7 @@ class Config 'allowInternalNamedArgumentsCalls' => 'allow_internal_named_arg_calls', 'allowNamedArgumentCalls' => 'allow_named_arg_calls', 'findUnusedPsalmSuppress' => 'find_unused_psalm_suppress', + 'findUnusedBaselineEntry' => 'find_unused_baseline_entry', 'reportInfo' => 'report_info', 'restrictReturnTypes' => 'restrict_return_types', 'limitMethodComplexity' => 'limit_method_complexity', @@ -1164,6 +1170,10 @@ class Config $config->use_igbinary = version_compare($igbinary_version, '2.0.5') >= 0; } + if (!isset($config_xml['findUnusedBaselineEntry']) && !defined('__IS_TEST_ENV__')) { + fwrite(STDERR, 'Warning: "findUnusedBaselineEntry" will be defaulted to "true" in Psalm 6. You should' + . ' explicitly enable or disable this setting.' . PHP_EOL); + } if (isset($config_xml['findUnusedCode'])) { $attribute_text = (string) $config_xml['findUnusedCode']; diff --git a/src/Psalm/Config/Creator.php b/src/Psalm/Config/Creator.php index 8b3f102a8..2ce9f3c5c 100644 --- a/src/Psalm/Config/Creator.php +++ b/src/Psalm/Config/Creator.php @@ -45,6 +45,7 @@ final class Creator xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://getpsalm.org/schema/config" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" + findUnusedBaselineEntry="true" > diff --git a/src/Psalm/Issue/UnusedBaselineEntry.php b/src/Psalm/Issue/UnusedBaselineEntry.php new file mode 100644 index 000000000..7397a33d3 --- /dev/null +++ b/src/Psalm/Issue/UnusedBaselineEntry.php @@ -0,0 +1,11 @@ +config->find_unused_baseline_entry) { + foreach ($issue_baseline as $file_path => $issues) { + foreach ($issues as $issue_name => $issue) { + if ($issue['o'] !== 0) { + $issues_data[$file_path][] = new IssueData( + Config::REPORT_ERROR, + 0, + 0, + UnusedBaselineEntry::getIssueType(), + sprintf( + 'Baseline for issue "%s" has %d extra %s.', + $issue_name, + $issue['o'], + $issue['o'] === 1 ? 'entry' : 'entries', + ), + $file_path, + '', + '', + '', + 0, + 0, + 0, + 0, + 0, + 0, + UnusedBaselineEntry::SHORTCODE, + UnusedBaselineEntry::ERROR_LEVEL, + ); + } + } + } + } } } diff --git a/tests/Config/CreatorTest.php b/tests/Config/CreatorTest.php index 23bd7d6ee..a38c3e95c 100644 --- a/tests/Config/CreatorTest.php +++ b/tests/Config/CreatorTest.php @@ -38,6 +38,7 @@ class CreatorTest extends TestCase xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns="https://getpsalm.org/schema/config" xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd" + findUnusedBaselineEntry="true" > diff --git a/tests/DocumentationTest.php b/tests/DocumentationTest.php index b15dc0bec..d79addf5a 100644 --- a/tests/DocumentationTest.php +++ b/tests/DocumentationTest.php @@ -15,6 +15,7 @@ use Psalm\Internal\Analyzer\ProjectAnalyzer; use Psalm\Internal\Provider\FakeFileProvider; use Psalm\Internal\Provider\Providers; use Psalm\Internal\RuntimeCaches; +use Psalm\Issue\UnusedBaselineEntry; use Psalm\Tests\Internal\Provider\FakeParserCacheProvider; use UnexpectedValueException; @@ -262,6 +263,7 @@ class DocumentationTest extends TestCase case 'RedundantIdentityWithTrue': case 'TraitMethodSignatureMismatch': case 'UncaughtThrowInGlobalScope': + case UnusedBaselineEntry::getIssueType(): continue 2; /** @todo reinstate this test when the issue is restored */ diff --git a/tests/Internal/Codebase/InternalCallMapHandlerTest.php b/tests/Internal/Codebase/InternalCallMapHandlerTest.php index fd675727a..742cc46c1 100644 --- a/tests/Internal/Codebase/InternalCallMapHandlerTest.php +++ b/tests/Internal/Codebase/InternalCallMapHandlerTest.php @@ -1395,7 +1395,6 @@ class InternalCallMapHandlerTest extends TestCase } } - /** @psalm-suppress UndefinedMethod */ public function assertEntryReturnType(ReflectionFunctionAbstract $function, string $entryReturnType): void { if (version_compare(PHP_VERSION, '8.1.0', '>=')) {