Skip to content

Feature/new rectors 1#5

Closed
bbrala wants to merge 17 commits into
feature/digest-rectorsfrom
feature/new-rectors-1
Closed

Feature/new rectors 1#5
bbrala wants to merge 17 commits into
feature/digest-rectorsfrom
feature/new-rectors-1

Conversation

@bbrala

@bbrala bbrala commented May 27, 2026

Copy link
Copy Markdown
Owner

This pull request introduces several new deprecation-handling rectors and improves the accuracy, traceability, and documentation of deprecation coverage in the codebase. The most significant changes are the addition of new rector rules for Drupal 11 deprecations, the introduction of an auto-generated coverage registry for PHPStan deprecation messages, and enhancements to the documentation and configuration files to ensure traceability and easier maintenance.

New deprecation-handling rectors and coverage improvements:

New Rector Rules and Coverage:

  • Added ViewsConfigUpdaterClassResolverToServiceRector to rewrite deprecated \Drupal::classResolver(\Drupal\views\ViewsConfigUpdater::class) calls to the new service-based approach, with BC wrappers for compatibility.
  • Added EntityFormModeEmptyDescriptionToNullRector to migrate empty string descriptions in EntityFormMode::create() to NULL, as required by newer Drupal versions. [1] [2]
  • Added DrupalGetHeadersAssocArrayRector to convert deprecated $headers argument formats in UiHelperTrait::drupalGet() to the associative array format, with live tests and change record references. [1] [2] [3]
  • Added ReplaceHideShowWithPrintedRector to replace deprecated hide()/show() calls with direct assignment to $element['#printed'].
  • Added ReplaceExpectDeprecationRector to migrate deprecated test methods to their PHPUnit 11+ equivalents, with BC wrappers.

Deprecation Message Coverage and Registry:

  • Introduced an auto-generated config/coverage-registry.php file, which maps each rector to the normalized PHPStan deprecation messages it covers, ensuring traceability and easier integration with tools like upgrade_status.
  • Updated the SKILL documentation to detail how to capture, normalize, and register PHPStan deprecation messages for each rector, and how to handle cases where no deprecation message is emitted. [1] [2]

Documentation and Configuration Enhancements:

Change Record and Related Issue References:

  • Updated and expanded references to Drupal.org issues and change records in the deprecation configuration files for improved traceability and context. This includes more precise attributions for each rule, distinguishing between change records and related issues. [1] [2] [3] [4] [5] [6] [7] [8] [9]

General Configuration Updates:

  • Registered new rector classes in the relevant drupal-11 deprecation configuration files to ensure they are applied as part of the automated upgrade process. [1] [2]

These changes collectively improve the project's ability to keep up with Drupal core deprecations, provide better traceability for coverage, and ensure that automated upgrades are robust and well-documented.## Description
Explain the technical implementation of the work done.

To Test

  • Add steps to test this feature

Drupal.org issue

Provide a link to the issue from https://www.drupal.org/project/rector/issues. If no issue exists, please create one and link to this PR.

bbrala added 17 commits May 28, 2026 10:51
Rewrites statement-level calls to the deprecated global hide() and show()
functions to direct $element['#printed'] = TRUE/FALSE assignment.

The functions are deprecated in drupal:11.4.0 and removed in drupal:13.0.0.
Expression-context uses (where the return value is captured) are skipped
because the original returns the element while the rewrite would not.

Live-tested against fpa, saml_sp, vertical_tabs_config, and
field_group_background_image — 4 modules, 10 calls transformed cleanly.

See https://www.drupal.org/node/2258355
See https://www.drupal.org/node/3261271 (change record)
Migrates removed Drupal/PHPUnit test framework methods to their
PHPUnit 11+ replacements:

- $this->expectDeprecation()         (PHPUnit no-arg form) → removed
- $this->expectDeprecation($msg)     (Drupal trait form)   → expectUserDeprecationMessage($msg)
- $this->expectDeprecationMessage($msg)        → expectUserDeprecationMessage($msg)
- $this->expectDeprecationMessageMatches($p)   → expectUserDeprecationMessageMatches($p)

Renames are BC-wrapped via DeprecationHelper::backwardsCompatibleCall()
so tests keep passing on both pre-11.4 (old methods) and 11.4+ (new
methods). The 0-arg PHPUnit form is unconditionally removed because
real-world contrib uses the 1-arg Drupal-trait form.

Live-tested against honeypot, key, entity_usage, and node_revision_delete.

ExpectDeprecationTrait is deprecated in drupal:11.4.0 and removed
in drupal:12.0.0.

See https://www.drupal.org/node/3550268
See https://www.drupal.org/node/3545276 (change record)
…e #3571874

Four BC class aliases in Drupal\block_content\Access were deprecated in
drupal:11.3.0 and removed in drupal:12.0.0. Add config-only RenameClassRector
entries mapping each to its canonical Drupal\Core\Access home:

- AccessGroupAnd
- DependentAccessInterface
- RefinableDependentAccessInterface
- RefinableDependentAccessTrait

See https://www.drupal.org/node/3571874 and
https://www.drupal.org/node/3527501 (change record).
Introduce a rector → PHPStan-deprecation-message map so a future
upgrade_status PR can replace its hardcoded $rector_covered array
with a generated, version-aware registry.

Source of truth lives on the code, not in a sidecar file:

- Custom rector classes: public const PHPSTAN_MESSAGES = [...].
- Config-only registrations: // PHPSTAN_MESSAGES <Rector>: comment
  block above the ruleWithConfiguration() call.

Tooling:

- scripts/normalize-phpstan-message.php applies the three transforms
  upgrade_status's DeprecationAnalyzer::categorizeMessage() applies
  before isRectorCovered() (whitespace collapse, ": in" → ". Deprecated
  in", strip leading \\Drupal). Same transforms run on stored
  messages so the registry is comparison-ready.

- scripts/generate-coverage-registry.php walks src/ + config/, reads
  both shapes, normalizes, writes config/coverage-registry.php
  (rector short name → list of normalized messages).

Worked example added to ReplaceExpectDeprecationRector (captured via
synthetic probe against installed 11.4-dev). 3571874 config-only block
gets a TODO marker rather than a synthesized guess, since the aliases
are already gone from 11.4-dev core and a live capture requires a
11.3.x test env.

rector-live-test SKILL.md gets a new step 5 wiring the capture into
the existing live-test flow: while the contrib module is still
installed and the pre-transform file on disk, run PHPStan, normalize
the message, store on the class or in the config comment block, then
regenerate the registry.
…#3520946

Replaces $block->setConfigurationValue('items_per_page', 'none') with NULL
for Views block plugins. The string 'none' was deprecated in drupal:11.2.0
and removed in drupal:12.0.0; NULL is the canonical value for inheriting
the items-per-page setting from the view.

See https://www.drupal.org/node/3520946
See https://www.drupal.org/node/3522240 (change record)
Replaces deprecated DrupalTestCaseTrait::getDrupalRoot() instance calls with
direct $this->root property access. The method was deprecated in drupal:11.4.0
and removed in drupal:13.0.0. The rule targets subclasses of BrowserTestBase,
KernelTestBase, and UnitTestCase, which all inherit the $root property via
DrupalTestCaseTrait. Static calls and BuildTestBase (which overrides the method
with a non-deprecated implementation) are intentionally left untouched.

See https://www.drupal.org/node/3589047
See https://www.drupal.org/node/3574112 (change record)
…ctor

Captures the three real PHPStan deprecation messages this rector covers — one
per base test class (BrowserTestBase, KernelTestBase, UnitTestCase). The
BrowserTestBase variant was verified against automatic_updates 4.1.x; the
KernelTestBase variant against project_browser 2.1.x. The UnitTestCase variant
mirrors the deterministic PHPStan format.

Regenerates config/coverage-registry.php for upgrade_status consumption.
…538660

Replaces DRUPAL_DISABLED/OPTIONAL/REQUIRED with CommentPreviewMode enum cases
in CommentTestBase::setCommentPreview() calls. Passing an int to this method
was deprecated in drupal:11.3.0 and is removed in drupal:13.0.0; the new
CommentPreviewMode enum only exists on Drupal >= 11.3.0, so the replacement
is BC-wrapped via AbstractDrupalCoreRector + DeprecationHelper.

The type guard targets Drupal\Tests\comment\Functional\CommentTestBase
(the actual owner of setCommentPreview, not the NodeTypeInterface the
upstream digest incorrectly pointed at). A minimal CommentTestBase stub is
added so PHPStan can resolve the receiver type during rector tests.

A TODO PHPSTAN_MESSAGES comment is included because PHPStan emits no
deprecation for this call: setCommentPreview() itself is not @deprecated
(the trigger_error fires at runtime when an int is passed), and phpstan
does not flag file-scope const usage for DRUPAL_DISABLED/OPTIONAL/REQUIRED.

See https://www.drupal.org/node/3538660
See https://www.drupal.org/node/3538678 (change record)
Rewrites deprecated UiHelperTrait::drupalGet() $headers patterns:
- ['Header-Name: value'] → ['Header-Name' => 'value']
- ['Header-Name' => NULL] → ['Header-Name' => '']

Deprecated in drupal:11.1.0, removed in drupal:12.0.0. The associative
format has always been the documented contract; no new Drupal API is
required, so no BC wrapping is needed.

Type guard: Drupal\Tests\BrowserTestBase (UiHelperTrait fires the
deprecation; KernelTestBase uses HttpKernelUiHelperTrait, which does not).

Validated against pager_serializer 8.x-1.x (Functional/Views/StyleSerializerTest.php).
…sue #3448457

Rewrites EntityFormMode::create([..., 'description' => '', ...]) to use
NULL instead of an empty string. Setting the description property of an
EntityFormMode to '' was deprecated in drupal:11.2.0 and must be NULL in
drupal:12.0.0.

Matches both the short class name (use-imported) and the fully-qualified
\Drupal\Core\Entity\Entity\EntityFormMode::create() form via an isName()
static-call guard. Sibling classes (EntityViewMode), non-empty
descriptions, already-migrated NULL values, and other array keys are all
left untouched.

The replacement is plain PHP, so no BC wrapping is needed.

The deprecated pattern is genuinely rare in contrib (16 modules call
EntityFormMode::create() but none with 'description' => ''); validated
via synthetic probe.
…r issue #3529274

Rewrites \Drupal::classResolver(\Drupal\views\ViewsConfigUpdater::class)
to \Drupal::service(\Drupal\views\ViewsConfigUpdater::class). In
drupal:11.3.0 ViewsConfigUpdater was registered as a service;
classResolver() returns a fresh instance on each call, so state set via
setDeprecationsEnabled(FALSE) was lost across hook invocations.

The new call only resolves on Drupal >= 11.3.0 (the service isn't
registered on older versions), so the replacement is BC-wrapped via
DeprecationHelper::backwardsCompatibleCall().

Three layered isName guards ensure only the targeted call shape is
touched: receiver must be \Drupal, method must be classResolver, and the
single argument must be \Drupal\views\ViewsConfigUpdater::class. The
argument guard correctly disambiguates against module subclasses
sharing the short name (validated against entity_hierarchy, which uses
\Drupal\entity_hierarchy\Update\ViewsConfigUpdater and is correctly
skipped).

Live-tested against tripal.
@bbrala bbrala force-pushed the feature/new-rectors-1 branch from bf7d2a8 to 15e96d3 Compare May 28, 2026 08:53
@bbrala bbrala closed this May 28, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant