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', '>=')) {