RemoveAliasManagerCacheMethodCallsRector: unconditional removal of setCacheKey()/writeCache() breaks BC before 11.3
## Problem `RemoveAliasManagerCacheMethodCallsRector` (Drupal 11.3 set) removes calls to `AliasManager::setCacheKey()` and `AliasManager::writeCache()` **unconditionally** — it matches the whole `Expression` statement and returns `NodeVisitor::REMOVE_NODE`, with no version guard and no backwards-compatibility wrapper. As reported by @berdir: > note that just removing `setCacheKey()` is not correct, that breaks before 11.3, it needs to be conditional. This is correct. The transform is only safe on Drupal >= 11.3. ## Why unconditional removal is wrong These methods only became no-ops **at** 11.3, at the same time the deprecation landed — not earlier: - [Change record 3496369](https://www.drupal.org/node/3496369): *"The method `::setCacheKey()` on AliasManager becomes a no-op and is deprecated for removal."* The methods previously performed real work — the per-page path-alias preload cache that had existed since 2009. - [Change record 3532412](https://www.drupal.org/node/3532412): *"From Drupal 11.3 this cache has been removed entirely from the AliasManager class"*, replaced by a Fiber-based bulk-lookup strategy. So on Drupal <= 11.2 the calls do real caching work; on 11.3+ they are no-ops; on 13.0 the methods are removed. For a module that supports both < 11.3 and >= 11.3, deleting the call outright silently drops the alias preload caching on the older supported versions. (The impact is a lost performance optimization, not a correctness break, but it is still a BC change the rector should not make silently.) ## Real-world call site The only known caller outside core appears to be the Redirect module: https://git.drupalcode.org/project/redirect/-/merge_requests/196/diffs#be8ef21e311f164f95ac2b3c97142ccfc779b3d0_110_110 ## Proposed fix Route the rector through the project's BC infrastructure (`AbstractDrupalCoreRector`) so it is version-gated and can emit a conditional wrapper: - **When BC support is enabled** (target spans < 11.3), emit a `DeprecationHelper::backwardsCompatibleCall()` with a **no-op current callable** and the original call as the deprecated callable: ```php \Drupal\Component\Utility\DeprecationHelper::backwardsCompatibleCall( \Drupal::VERSION, '11.3.0', static fn () => null, // 11.3+: no-op fn () => $this->aliasManager->setCacheKey($path), // <= 11.2: real caching ); ``` Verified against core source: `backwardsCompatibleCall()` takes two required `callable` params and just invokes one based on the version compare; a `fn () => null` current callable is valid and its `mixed` return is discarded in statement context. No deprecation notice fires, because `setCacheKey()`/`writeCache()` are only invoked on the branch where they are not yet deprecated. - **When BC support is disabled** (or the minimum supported core is already >= 11.3), keep the current clean removal. Note: the shared `AbstractDrupalCoreRector::createBcCallOnExpr()` helper cannot produce this shape — it assumes the "new" branch is a replacement `Expr`, whereas here the new branch is empty (whole-statement deletion). So the wrapper node needs to be built in the rector itself, keeping the `Expression`-level node match.
issue