From 102230b6adcc06cec132efb1cd3ea2c5d3ab77d1 Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Thu, 9 Apr 2026 10:18:42 -0500 Subject: [PATCH 1/5] Add stubs for legacy hook BC attributes LegacyHook, LegacyRequirementsHook, and LegacyModuleImplementsAlter were added across different Drupal minor versions and LegacyHook is being removed in Drupal 12. Without stubs, PHPStan reports "class not found" errors against Drupal versions where these attributes don't exist, and "unused ignore" errors against versions where they do. Providing stubs makes these classes always available to PHPStan regardless of the installed Drupal version. Closes #945 Co-Authored-By: Claude Sonnet 4.6 --- .../Core/Hook/Attribute/LegacyHook.stub | 8 +++++ .../LegacyModuleImplementsAlter.stub | 8 +++++ .../Attribute/LegacyRequirementsHook.stub | 8 +++++ .../src/Type/LegacyHookAttributeStubsTest.php | 33 +++++++++++++++++++ .../Type/data/legacy-hook-attribute-stubs.php | 20 +++++++++++ 5 files changed, 77 insertions(+) create mode 100644 stubs/Drupal/Core/Hook/Attribute/LegacyHook.stub create mode 100644 stubs/Drupal/Core/Hook/Attribute/LegacyModuleImplementsAlter.stub create mode 100644 stubs/Drupal/Core/Hook/Attribute/LegacyRequirementsHook.stub create mode 100644 tests/src/Type/LegacyHookAttributeStubsTest.php create mode 100644 tests/src/Type/data/legacy-hook-attribute-stubs.php diff --git a/stubs/Drupal/Core/Hook/Attribute/LegacyHook.stub b/stubs/Drupal/Core/Hook/Attribute/LegacyHook.stub new file mode 100644 index 00000000..1298b4a0 --- /dev/null +++ b/stubs/Drupal/Core/Hook/Attribute/LegacyHook.stub @@ -0,0 +1,8 @@ +assertFileAsserts($assertType, $file, ...$args); + } +} diff --git a/tests/src/Type/data/legacy-hook-attribute-stubs.php b/tests/src/Type/data/legacy-hook-attribute-stubs.php new file mode 100644 index 00000000..495c02fa --- /dev/null +++ b/tests/src/Type/data/legacy-hook-attribute-stubs.php @@ -0,0 +1,20 @@ + Date: Thu, 9 Apr 2026 10:28:31 -0500 Subject: [PATCH 2/5] Remove ineffective TypeInferenceTestCase test The test would pass even without the stubs because the fixture classes in tests/fixtures/drupal/ are always present, and TypeInferenceTestCase does not surface unknown class errors. StubTest already validates stub well-formedness; integration coverage comes from the build_integration CI jobs running against real Drupal installations. Co-Authored-By: Claude Sonnet 4.6 --- .../src/Type/LegacyHookAttributeStubsTest.php | 33 ------------------- .../Type/data/legacy-hook-attribute-stubs.php | 20 ----------- 2 files changed, 53 deletions(-) delete mode 100644 tests/src/Type/LegacyHookAttributeStubsTest.php delete mode 100644 tests/src/Type/data/legacy-hook-attribute-stubs.php diff --git a/tests/src/Type/LegacyHookAttributeStubsTest.php b/tests/src/Type/LegacyHookAttributeStubsTest.php deleted file mode 100644 index 763e87ef..00000000 --- a/tests/src/Type/LegacyHookAttributeStubsTest.php +++ /dev/null @@ -1,33 +0,0 @@ -assertFileAsserts($assertType, $file, ...$args); - } -} diff --git a/tests/src/Type/data/legacy-hook-attribute-stubs.php b/tests/src/Type/data/legacy-hook-attribute-stubs.php deleted file mode 100644 index 495c02fa..00000000 --- a/tests/src/Type/data/legacy-hook-attribute-stubs.php +++ /dev/null @@ -1,20 +0,0 @@ - Date: Thu, 9 Apr 2026 10:30:34 -0500 Subject: [PATCH 3/5] Add integration test for legacy hook attribute stubs Adds a fixture PHP file using LegacyHook, LegacyRequirementsHook, and LegacyModuleImplementsAlter, and scans it in both build_integration jobs across all Drupal version matrix entries. Against Drupal 10.4 these classes don't exist in the installed package, so this verifies the stubs make them available regardless of Drupal version. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/php.yml | 8 ++++++ .../integration/legacy-hook-attributes.php | 28 +++++++++++++++++++ 2 files changed, 36 insertions(+) create mode 100644 tests/fixtures/integration/legacy-hook-attributes.php diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index d01fb00d..2a74ed6a 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -128,6 +128,10 @@ jobs: run: | cd ~/drupal ./vendor/bin/phpstan analyze web/core/install.php --debug + - name: "Test legacy hook attribute stubs" + run: | + cd ~/drupal + ./vendor/bin/phpstan analyze $GITHUB_WORKSPACE/tests/fixtures/integration/legacy-hook-attributes.php --no-progress - name: "Test BrowserTestBase is autoloaded" run: | cd ~/drupal @@ -200,6 +204,10 @@ jobs: run: | cd ~/drupal ./vendor/bin/phpstan analyze web/core/install.php --debug + - name: "Test legacy hook attribute stubs" + run: | + cd ~/drupal + ./vendor/bin/phpstan analyze $GITHUB_WORKSPACE/tests/fixtures/integration/legacy-hook-attributes.php --no-progress - name: "Test no crash" run: | cd ~/drupal diff --git a/tests/fixtures/integration/legacy-hook-attributes.php b/tests/fixtures/integration/legacy-hook-attributes.php new file mode 100644 index 00000000..5d08b521 --- /dev/null +++ b/tests/fixtures/integration/legacy-hook-attributes.php @@ -0,0 +1,28 @@ + Date: Thu, 9 Apr 2026 11:10:06 -0500 Subject: [PATCH 4/5] Fix legacy hook attribute stubs integration test file path Copy the fixture into the Drupal directory before analysing rather than passing an absolute workspace path to PHPStan, which failed to resolve it. Co-Authored-By: Claude Sonnet 4.6 --- .github/workflows/php.yml | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/.github/workflows/php.yml b/.github/workflows/php.yml index 2a74ed6a..f2021d6b 100644 --- a/.github/workflows/php.yml +++ b/.github/workflows/php.yml @@ -130,8 +130,9 @@ jobs: ./vendor/bin/phpstan analyze web/core/install.php --debug - name: "Test legacy hook attribute stubs" run: | + cp $GITHUB_WORKSPACE/tests/fixtures/integration/legacy-hook-attributes.php ~/drupal/legacy-hook-attributes.php cd ~/drupal - ./vendor/bin/phpstan analyze $GITHUB_WORKSPACE/tests/fixtures/integration/legacy-hook-attributes.php --no-progress + ./vendor/bin/phpstan analyze legacy-hook-attributes.php --no-progress - name: "Test BrowserTestBase is autoloaded" run: | cd ~/drupal @@ -206,8 +207,9 @@ jobs: ./vendor/bin/phpstan analyze web/core/install.php --debug - name: "Test legacy hook attribute stubs" run: | + cp $GITHUB_WORKSPACE/tests/fixtures/integration/legacy-hook-attributes.php ~/drupal/legacy-hook-attributes.php cd ~/drupal - ./vendor/bin/phpstan analyze $GITHUB_WORKSPACE/tests/fixtures/integration/legacy-hook-attributes.php --no-progress + ./vendor/bin/phpstan analyze legacy-hook-attributes.php --no-progress - name: "Test no crash" run: | cd ~/drupal From b8049bed65daf1a4ab4ead90c66a5baec69c90fe Mon Sep 17 00:00:00 2001 From: Matt Glaman Date: Thu, 9 Apr 2026 11:36:52 -0500 Subject: [PATCH 5/5] Replace stubs with ignoreErrors for legacy hook attributes MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit PHPStan stubs only override type information for existing classes; they cannot make missing classes available for attribute validation. The integration tests confirmed this — attribute class errors still fired on Drupal 10.4 where the classes don't exist. Instead, add ignoreErrors entries with reportUnmatched: false so the suppression is silent on Drupal versions where the classes do exist, avoiding the "unused ignore" problem the issue describes. Co-Authored-By: Claude Sonnet 4.6 --- extension.neon | 10 ++++++++++ stubs/Drupal/Core/Hook/Attribute/LegacyHook.stub | 8 -------- .../Hook/Attribute/LegacyModuleImplementsAlter.stub | 8 -------- .../Core/Hook/Attribute/LegacyRequirementsHook.stub | 8 -------- 4 files changed, 10 insertions(+), 24 deletions(-) delete mode 100644 stubs/Drupal/Core/Hook/Attribute/LegacyHook.stub delete mode 100644 stubs/Drupal/Core/Hook/Attribute/LegacyModuleImplementsAlter.stub delete mode 100644 stubs/Drupal/Core/Hook/Attribute/LegacyRequirementsHook.stub diff --git a/extension.neon b/extension.neon index 098118de..53f9518f 100644 --- a/extension.neon +++ b/extension.neon @@ -1,6 +1,16 @@ parameters: bootstrapFiles: - drupal-autoloader.php + ignoreErrors: + - + message: '#^Attribute class Drupal\\Core\\Hook\\Attribute\\LegacyHook does not exist\.$#' + reportUnmatched: false + - + message: '#^Attribute class Drupal\\Core\\Hook\\Attribute\\LegacyRequirementsHook does not exist\.$#' + reportUnmatched: false + - + message: '#^Attribute class Drupal\\Core\\Hook\\Attribute\\LegacyModuleImplementsAlter does not exist\.$#' + reportUnmatched: false excludePaths: - '*.api.php' - '*/tests/fixtures/*.php' diff --git a/stubs/Drupal/Core/Hook/Attribute/LegacyHook.stub b/stubs/Drupal/Core/Hook/Attribute/LegacyHook.stub deleted file mode 100644 index 1298b4a0..00000000 --- a/stubs/Drupal/Core/Hook/Attribute/LegacyHook.stub +++ /dev/null @@ -1,8 +0,0 @@ -