From 8b5bc09cbe4dd75b049b32df9802c7103148a3a1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?C=C3=B4me=20Chilliet?= Date: Fri, 13 Mar 2026 10:20:10 +0100 Subject: [PATCH] feat: Add a psalm plugin to forbid static properties and variables MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Côme Chilliet --- build/psalm/StaticVarsChecker.php | 54 +++++++++++++++++++++++++++++++ build/psalm/StaticVarsTest.php | 23 +++++++++++++ psalm.xml | 1 + 3 files changed, 78 insertions(+) create mode 100644 build/psalm/StaticVarsChecker.php create mode 100644 build/psalm/StaticVarsTest.php diff --git a/build/psalm/StaticVarsChecker.php b/build/psalm/StaticVarsChecker.php new file mode 100644 index 00000000000..24d08b45aa8 --- /dev/null +++ b/build/psalm/StaticVarsChecker.php @@ -0,0 +1,54 @@ +getStmt(); + $statementsSource = $event->getStatementsSource(); + + foreach ($classLike->stmts as $stmt) { + if ($stmt instanceof Property) { + if ($stmt->isStatic()) { + IssueBuffer::maybeAdd( + // ImpureStaticProperty is close enough, all static properties are impure to my eyes + new \Psalm\Issue\ImpureStaticProperty( + 'Static property should not be used as they do not follow requests lifecycle', + new CodeLocation($statementsSource, $stmt), + ) + ); + } + } + } + } + + public static function afterStatementAnalysis(AfterStatementAnalysisEvent $event): ?bool { + $stmt = $event->getStmt(); + if ($stmt instanceof PhpParser\Node\Stmt\Static_) { + IssueBuffer::maybeAdd( + // Same logic + new \Psalm\Issue\ImpureStaticVariable( + 'Static var should not be used as they do not follow requests lifecycle and are hard to reset', + new CodeLocation($event->getStatementsSource(), $stmt), + ) + ); + } + return null; + } +} diff --git a/build/psalm/StaticVarsTest.php b/build/psalm/StaticVarsTest.php new file mode 100644 index 00000000000..f40ac56ff51 --- /dev/null +++ b/build/psalm/StaticVarsTest.php @@ -0,0 +1,23 @@ + +