From f704787a0a32d8cfdb846420139f6bd86e31ed94 Mon Sep 17 00:00:00 2001
From: Andreas Hennings <andreas@dqxtech.net>
Date: Wed, 7 May 2025 14:00:46 +0200
Subject: [PATCH 01/17] Drop 'public ' for parameters passed to parent
 constructor.

---
 core/lib/Drupal/Core/Hook/Attribute/FormAlter.php | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
index 158010463d2a..c245c3369c3e 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
@@ -44,9 +44,9 @@ class FormAlter extends Hook {
    */
   public function __construct(
     string $form_id = '',
-    public string $method = '',
-    public ?string $module = NULL,
-    public ?OrderInterface $order = NULL,
+    string $method = '',
+    ?string $module = NULL,
+    ?OrderInterface $order = NULL,
   ) {
     parent::__construct($form_id, $method, $module, $order);
   }
-- 
GitLab


From 83ec149fa09f307563924cd5a44c5cc79706e554 Mon Sep 17 00:00:00 2001
From: Andreas Hennings <andreas@dqxtech.net>
Date: Wed, 7 May 2025 14:03:17 +0200
Subject: [PATCH 02/17] Don't use constants for inheritance, call parent
 constructor instead.

---
 .../Drupal/Core/Hook/Attribute/FormAlter.php  | 13 ++-----
 core/lib/Drupal/Core/Hook/Attribute/Hook.php  | 26 ++------------
 .../Drupal/Core/Hook/Attribute/Preprocess.php | 36 ++++++++++++++-----
 3 files changed, 32 insertions(+), 43 deletions(-)

diff --git a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
index c245c3369c3e..3820af5e201d 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
@@ -14,16 +14,6 @@
 #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
 class FormAlter extends Hook {
 
-  /**
-   * {@inheritdoc}
-   */
-  public const string PREFIX = 'form';
-
-  /**
-   * {@inheritdoc}
-   */
-  public const string SUFFIX = 'alter';
-
   /**
    * Constructs a FormAlter attribute object.
    *
@@ -48,7 +38,8 @@ public function __construct(
     ?string $module = NULL,
     ?OrderInterface $order = NULL,
   ) {
-    parent::__construct($form_id, $method, $module, $order);
+    $hook = ($form_id === NULL) ? 'form_alter' : 'form_' . $form_id . '_alter';
+    parent::__construct($hook, $method, $module, $order);
   }
 
 }
diff --git a/core/lib/Drupal/Core/Hook/Attribute/Hook.php b/core/lib/Drupal/Core/Hook/Attribute/Hook.php
index 34dbc8ebf916..0084e651180d 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/Hook.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/Hook.php
@@ -97,28 +97,11 @@
 #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
 class Hook implements HookAttributeInterface {
 
-  /**
-   * The hook prefix such as `form`.
-   *
-   * @var string
-   */
-  public const string PREFIX = '';
-
-  /**
-   * The hook suffix such as `alter`.
-   *
-   * @var string
-   */
-  public const string SUFFIX = '';
-
   /**
    * Constructs a Hook attribute object.
    *
    * @param string $hook
    *   The short hook name, without the 'hook_' prefix.
-   *   $hook is only optional when Hook is extended and a PREFIX or SUFFIX is
-   *   defined. When using the [#Hook] attribute directly $hook is required.
-   *   See Drupal\Core\Hook\Attribute\Preprocess.
    * @param string $method
    *   (optional) The method name. If this attribute is on a method, this
    *   parameter is not required. If this attribute is on a class and this
@@ -132,15 +115,10 @@ class Hook implements HookAttributeInterface {
    *   (optional) Set the order of the implementation.
    */
   public function __construct(
-    public string $hook = '',
+    public string $hook,
     public string $method = '',
     public ?string $module = NULL,
     public ?OrderInterface $order = NULL,
-  ) {
-    $this->hook = implode('_', array_filter([static::PREFIX, $hook, static::SUFFIX]));
-    if ($this->hook === '') {
-      throw new \LogicException('The Hook attribute or an attribute extending the Hook attribute must provide the $hook parameter, a PREFIX or a SUFFIX.');
-    }
-  }
+  ) {}
 
 }
diff --git a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
index 47642859a20b..b89319d07b03 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
@@ -4,20 +4,40 @@
 
 namespace Drupal\Core\Hook\Attribute;
 
+use Drupal\Core\Hook\Order\OrderInterface;
+
 /**
  * Attribute for defining a class method as a preprocess function.
- *
- * Pass no arguments for hook_preprocess `#[Preprocess]`.
- * For `hook_preprocess_HOOK` pass the `HOOK` without the `hook_preprocess`
- * portion `#[Preprocess('HOOK')]`.
- *
- * See \Drupal\Core\Hook\Attribute\Hook for additional information.
  */
 #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
 class Preprocess extends Hook {
+
   /**
-   * {@inheritdoc}
+   * Constructor.
+   *
+   * @param string|null $theme_hook
+   *   (optional) Name of a theme hook, or NULL for a generic preprocess that
+   *   applies to all theme hooks.
+   * @param string $method
+   *   (optional) The method name. If this attribute is on a method, this
+   *   parameter is not required. If this attribute is on a class and this
+   *   parameter is omitted, the class must have an __invoke() method, which is
+   *   taken as the hook implementation.
+   * @param string|null $module
+   *   (optional) The module this implementation is for. This allows one module
+   *   to implement a hook on behalf of another module. Defaults to the module
+   *   the implementation is in.
+   * @param \Drupal\Core\Hook\Order\OrderInterface|null $order
+   *   (optional) Set the order of the implementation.
    */
-  public const string PREFIX = 'preprocess';
+  public function __construct(
+    ?string $theme_hook = NULL,
+    string $method = '',
+    ?string $module = NULL,
+    ?OrderInterface $order = NULL,
+  ) {
+    $hook = ($theme_hook === NULL) ? 'preprocess' : 'preprocess_' . $theme_hook;
+    parent::__construct($hook, $method, $module, $order);
+  }
 
 }
-- 
GitLab


From 7b47d578fd295d7e8609e5ebb06c11bb9c46f20b Mon Sep 17 00:00:00 2001
From: Andreas Hennings <andreas@dqxtech.net>
Date: Wed, 7 May 2025 18:55:17 +0200
Subject: [PATCH 03/17] Use null as empty value for $form_id.

---
 core/lib/Drupal/Core/Hook/Attribute/FormAlter.php | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

diff --git a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
index 3820af5e201d..a6943be39cb2 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
@@ -17,9 +17,8 @@ class FormAlter extends Hook {
   /**
    * Constructs a FormAlter attribute object.
    *
-   * @param string $form_id
-   *   (optional) The ID of the form that this implementation alters.
-   *   If this is left blank then `form_alter` is the hook that is registered.
+   * @param string|null $form_id
+   *   (optional) The ID of the target form, or NULL to target all forms.
    * @param string $method
    *   (optional) The method name. If this attribute is on a method, this
    *   parameter is not required. If this attribute is on a class and this
@@ -33,7 +32,7 @@ class FormAlter extends Hook {
    *   (optional) Set the order of the implementation.
    */
   public function __construct(
-    string $form_id = '',
+    ?string $form_id = NULL,
     string $method = '',
     ?string $module = NULL,
     ?OrderInterface $order = NULL,
-- 
GitLab


From 513bae8d37581f927aeb462980ee9c3c9ca0de4d Mon Sep 17 00:00:00 2001
From: Andreas Hennings <andreas@dqxtech.net>
Date: Thu, 8 May 2025 18:22:09 +0200
Subject: [PATCH 04/17] Refine the class doc on 'Preprocess' attribute class.

---
 core/lib/Drupal/Core/Hook/Attribute/Preprocess.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
index b89319d07b03..7236e6188f7c 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
@@ -7,7 +7,7 @@
 use Drupal\Core\Hook\Order\OrderInterface;
 
 /**
- * Attribute for defining a class method as a preprocess function.
+ * Attribute to register a class method as a theme preprocess function.
  */
 #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
 class Preprocess extends Hook {
-- 
GitLab


From 695a84546ee6266836df6bb5f4ab6ca351c57049 Mon Sep 17 00:00:00 2001
From: Andreas Hennings <andreas@dqxtech.net>
Date: Thu, 8 May 2025 18:22:54 +0200
Subject: [PATCH 05/17] Fix and enhance @see docs.

---
 core/lib/Drupal/Core/Hook/Attribute/FormAlter.php  | 4 +++-
 core/lib/Drupal/Core/Hook/Attribute/Preprocess.php | 3 +++
 2 files changed, 6 insertions(+), 1 deletion(-)

diff --git a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
index a6943be39cb2..6d4f949c792b 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
@@ -9,7 +9,9 @@
 /**
  * Hook attribute for FormAlter.
  *
- * @see hook_form_alter().
+ * @see hook_form_alter()
+ * @see hook_form_BASE_FORM_ID_alter()
+ * @see hook_form_FORM_ID_alter()
  */
 #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
 class FormAlter extends Hook {
diff --git a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
index 7236e6188f7c..5c6c7f09bd5c 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
@@ -8,6 +8,9 @@
 
 /**
  * Attribute to register a class method as a theme preprocess function.
+ *
+ * @see hook_preprocess()
+ * @see hook_preprocess_HOOK()
  */
 #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
 class Preprocess extends Hook {
-- 
GitLab


From 677dedefc6f6af4e2ea9d2cc7f4101d0b7649e21 Mon Sep 17 00:00:00 2001
From: Ghost Of Drupal Past <drupal@negyesi.net>
Date: Mon, 12 May 2025 03:31:35 +0200
Subject: [PATCH 06/17] move to HookPattern

---
 .../Drupal/Core/Hook/Attribute/FormAlter.php  |  3 ++
 .../Core/Hook/Attribute/HookPattern.php       | 47 +++++++++++++++++++
 .../Drupal/Core/Hook/Attribute/Preprocess.php |  2 +
 3 files changed, 52 insertions(+)
 create mode 100644 core/lib/Drupal/Core/Hook/Attribute/HookPattern.php

diff --git a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
index 6d4f949c792b..bd6cd1c95db3 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
@@ -13,6 +13,9 @@
  * @see hook_form_BASE_FORM_ID_alter()
  * @see hook_form_FORM_ID_alter()
  */
+#[HookPattern('form_alter')]
+#[HookPattern('form_FORM_ID_alter')]
+#[HookPattern('form_BASE_FORM_ID_alter')]
 #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
 class FormAlter extends Hook {
 
diff --git a/core/lib/Drupal/Core/Hook/Attribute/HookPattern.php b/core/lib/Drupal/Core/Hook/Attribute/HookPattern.php
new file mode 100644
index 000000000000..b99a27beaacc
--- /dev/null
+++ b/core/lib/Drupal/Core/Hook/Attribute/HookPattern.php
@@ -0,0 +1,47 @@
+<?php
+
+declare(strict_types=1);
+
+namespace Drupal\Core\Hook\Attribute;
+
+/**
+ * Declare which hook this class provides shorthand for.
+ *
+ * This attribute is used on classes extending \Drupal\Core\Hook\Attribute\Hook
+ * to facilitate association of implementations with the hook documentation.
+ * For example, the \Drupal\Core\Hook\Attribute\FormAlter attribute class
+ * has these attributes:
+ *
+ * @code
+ * #[HookPattern('form_alter')]
+ * #[HookPattern('form_FORM_ID_alter')]
+ * #[HookPattern('form_BASE_FORM_ID_alter')]
+ * @endcode
+ *
+ * This allows a tool like api module to link a method marked with the
+ * FormAlter attribute to the documentation on function hook_form_alter().
+ *
+ * This attribute is never instantiated, it is solely used for documentation.
+ *
+ * @see \Drupal\Core\Hook\Attribute\FormAlter
+ * @see \Drupal\Core\Hook\Attribute\Preprocess
+ */
+#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
+class HookPattern {
+
+  /**
+   * Construct a HookPattern attribute.
+   *
+   * This attribute is never instantiated, it is solely used for documentation.
+   *
+   * @param string $hookPattern
+   *   The hook pattern, e.g.: "form_alter" or "form_FORM_ID_alter".
+   *   Use only string literals and avoid any other constant expression
+   *   because while PHP can evaluate them, the automated tools this attribute
+   *   targets not necessarily can.
+   */
+  public function __construct(
+    protected readonly string $hookPattern,
+  ) {}
+
+}
diff --git a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
index 5c6c7f09bd5c..41a96df8689e 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
@@ -12,6 +12,8 @@
  * @see hook_preprocess()
  * @see hook_preprocess_HOOK()
  */
+#[HookPattern('preprocess')]
+#[HookPattern('preprocess_HOOK')]
 #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
 class Preprocess extends Hook {
 
-- 
GitLab


From 023e473637876d7ef116434880c7a2e4270f1ef8 Mon Sep 17 00:00:00 2001
From: Ghost Of Drupal Past <drupal@negyesi.net>
Date: Mon, 12 May 2025 11:19:35 +0200
Subject: [PATCH 07/17] mention base id

---
 core/lib/Drupal/Core/Hook/Attribute/FormAlter.php | 3 ++-
 1 file changed, 2 insertions(+), 1 deletion(-)

diff --git a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
index bd6cd1c95db3..48ae24c3bf66 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
@@ -23,7 +23,8 @@ class FormAlter extends Hook {
    * Constructs a FormAlter attribute object.
    *
    * @param string|null $form_id
-   *   (optional) The ID of the target form, or NULL to target all forms.
+   *   (optional) The ID or the base ID of the target form, or NULL to target
+   *   all forms.
    * @param string $method
    *   (optional) The method name. If this attribute is on a method, this
    *   parameter is not required. If this attribute is on a class and this
-- 
GitLab


From 68c0d50e82a42c96a13d77d528713969a4323de6 Mon Sep 17 00:00:00 2001
From: Ghost Of Drupal Past <drupal@negyesi.net>
Date: Mon, 12 May 2025 15:43:20 +0200
Subject: [PATCH 08/17] rename, use callable

---
 .../Drupal/Core/Hook/Attribute/FormAlter.php  | 13 ++++-----
 .../{HookPattern.php => HookDocumentedAt.php} | 27 ++++++++++---------
 .../Drupal/Core/Hook/Attribute/Preprocess.php | 10 +++----
 3 files changed, 24 insertions(+), 26 deletions(-)
 rename core/lib/Drupal/Core/Hook/Attribute/{HookPattern.php => HookDocumentedAt.php} (55%)

diff --git a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
index 48ae24c3bf66..babfa63c152b 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
@@ -8,14 +8,10 @@
 
 /**
  * Hook attribute for FormAlter.
- *
- * @see hook_form_alter()
- * @see hook_form_BASE_FORM_ID_alter()
- * @see hook_form_FORM_ID_alter()
  */
-#[HookPattern('form_alter')]
-#[HookPattern('form_FORM_ID_alter')]
-#[HookPattern('form_BASE_FORM_ID_alter')]
+#[HookDocumentedAt('hook_form_alter')]
+#[HookDocumentedAt('hook_form_FORM_ID_alter')]
+#[HookDocumentedAt('hook_form_BASE_FORM_ID_alter')]
 #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
 class FormAlter extends Hook {
 
@@ -24,7 +20,8 @@ class FormAlter extends Hook {
    *
    * @param string|null $form_id
    *   (optional) The ID or the base ID of the target form, or NULL to target
-   *   all forms.
+   *   all forms. For documentation purposes, always make this the first
+   *   parameter, without using form_id: and use a string literal.
    * @param string $method
    *   (optional) The method name. If this attribute is on a method, this
    *   parameter is not required. If this attribute is on a class and this
diff --git a/core/lib/Drupal/Core/Hook/Attribute/HookPattern.php b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentedAt.php
similarity index 55%
rename from core/lib/Drupal/Core/Hook/Attribute/HookPattern.php
rename to core/lib/Drupal/Core/Hook/Attribute/HookDocumentedAt.php
index b99a27beaacc..a767a9e5ce52 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/HookPattern.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentedAt.php
@@ -9,17 +9,18 @@
  *
  * This attribute is used on classes extending \Drupal\Core\Hook\Attribute\Hook
  * to facilitate association of implementations with the hook documentation.
- * For example, the \Drupal\Core\Hook\Attribute\FormAlter attribute class
+ * For example, the \Drupal\Core\Hook\Attribute\Preprocess attribute class
  * has these attributes:
  *
  * @code
- * #[HookPattern('form_alter')]
- * #[HookPattern('form_FORM_ID_alter')]
- * #[HookPattern('form_BASE_FORM_ID_alter')]
+ * #[HookDocumentedAt('hook_preprocess')]
+ * #[HookDocumentedAt('hook_preprocess_HOOK')]
  * @endcode
  *
  * This allows a tool like api module to link a method marked with the
- * FormAlter attribute to the documentation on function hook_form_alter().
+ * FormAlter attribute to the documentation on function hook_preprocess()
+ * or hook_preprocess_HOOK. The two can be told apart depending on whether
+ * the first argument of Preprocess is a string or a named argument.
  *
  * This attribute is never instantiated, it is solely used for documentation.
  *
@@ -27,21 +28,23 @@
  * @see \Drupal\Core\Hook\Attribute\Preprocess
  */
 #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
-class HookPattern {
+class HookDocumentedAt {
 
   /**
-   * Construct a HookPattern attribute.
+   * Construct a HookDocumentedAt attribute.
    *
    * This attribute is never instantiated, it is solely used for documentation.
    *
-   * @param string $hookPattern
-   *   The hook pattern, e.g.: "form_alter" or "form_FORM_ID_alter".
+   * @param callable $hookDocumentedAt
+   *   The name of the function, e.g.: "hook_form_alter" or
+   *   "hook_form_FORM_ID_alter" where the documentation for this function
+   *   lives.
    *   Use only string literals and avoid any other constant expression
    *   because while PHP can evaluate them, the automated tools this attribute
    *   targets not necessarily can.
+   *
+   * @phpstan-param callable-string $hookDocumentedAt
    */
-  public function __construct(
-    protected readonly string $hookPattern,
-  ) {}
+  public function __construct(callable $hookDocumentedAt) {}
 
 }
diff --git a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
index 41a96df8689e..4140ff53b4d2 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
@@ -8,12 +8,9 @@
 
 /**
  * Attribute to register a class method as a theme preprocess function.
- *
- * @see hook_preprocess()
- * @see hook_preprocess_HOOK()
  */
-#[HookPattern('preprocess')]
-#[HookPattern('preprocess_HOOK')]
+#[HookDocumentedAt('hook_preprocess')]
+#[HookDocumentedAt('hook_preprocess_HOOK')]
 #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
 class Preprocess extends Hook {
 
@@ -22,7 +19,8 @@ class Preprocess extends Hook {
    *
    * @param string|null $theme_hook
    *   (optional) Name of a theme hook, or NULL for a generic preprocess that
-   *   applies to all theme hooks.
+   *   applies to all theme hooks. For documentation purposes, always make this
+   *   the first parameter, do not use theme_hook: and use a string literal.
    * @param string $method
    *   (optional) The method name. If this attribute is on a method, this
    *   parameter is not required. If this attribute is on a class and this
-- 
GitLab


From 6179d39d8e06621147216fead0546881edd0db3a Mon Sep 17 00:00:00 2001
From: ghost of drupal past
 <48724-GhostOfDrupalPast@users.noreply.drupalcode.org>
Date: Mon, 12 May 2025 14:00:56 +0000
Subject: [PATCH 09/17] Apply 2 suggestion(s) to 1 file(s)

Co-authored-by: Andreas Hennings <11336-donquixote@users.noreply.drupalcode.org>
---
 core/lib/Drupal/Core/Hook/Attribute/HookDocumentedAt.php | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentedAt.php b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentedAt.php
index a767a9e5ce52..f49d5d1c2fed 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentedAt.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentedAt.php
@@ -18,7 +18,7 @@
  * @endcode
  *
  * This allows a tool like api module to link a method marked with the
- * FormAlter attribute to the documentation on function hook_preprocess()
+ * #[Preprocess] attribute to the documentation on function hook_preprocess()
  * or hook_preprocess_HOOK. The two can be told apart depending on whether
  * the first argument of Preprocess is a string or a named argument.
  *
@@ -37,7 +37,7 @@ class HookDocumentedAt {
    *
    * @param callable $hookDocumentedAt
    *   The name of the function, e.g.: "hook_form_alter" or
-   *   "hook_form_FORM_ID_alter" where the documentation for this function
+   *   "hook_form_FORM_ID_alter" where the documentation for this hook
    *   lives.
    *   Use only string literals and avoid any other constant expression
    *   because while PHP can evaluate them, the automated tools this attribute
-- 
GitLab


From 185c4fe021747493dc88fb37b76bf3c6679512f4 Mon Sep 17 00:00:00 2001
From: Ghost Of Drupal Past <drupal@negyesi.net>
Date: Mon, 12 May 2025 19:09:56 +0200
Subject: [PATCH 10/17] fixes

---
 .../Core/Hook/Attribute/HookDocumentedAt.php      | 15 +++++++++------
 .../lib/Drupal/Core/Hook/Attribute/Preprocess.php |  2 +-
 2 files changed, 10 insertions(+), 7 deletions(-)

diff --git a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentedAt.php b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentedAt.php
index f49d5d1c2fed..977df5dc9179 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentedAt.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentedAt.php
@@ -17,10 +17,11 @@
  * #[HookDocumentedAt('hook_preprocess_HOOK')]
  * @endcode
  *
- * This allows a tool like api module to link a method marked with the
- * #[Preprocess] attribute to the documentation on function hook_preprocess()
- * or hook_preprocess_HOOK. The two can be told apart depending on whether
- * the first argument of Preprocess is a string or a named argument.
+ * This allows a tool like https://drupal.org/project/api module to link a
+ * method marked with the #[Preprocess] attribute to the documentation on
+ * function hook_preprocess() or hook_preprocess_HOOK. The two can be told
+ * apart depending on whether the first argument of Preprocess is a string
+ * or a named argument.
  *
  * This attribute is never instantiated, it is solely used for documentation.
  *
@@ -31,9 +32,11 @@
 class HookDocumentedAt {
 
   /**
-   * Construct a HookDocumentedAt attribute.
+   * Constructs a HookDocumentedAt attribute.
    *
-   * This attribute is never instantiated, it is solely used for documentation.
+   * This attribute is solely used for automated tools parsing for
+   * documentation purposes like https://drupal.org/project/api and
+   * instantiating it is likely to cause a fatal error by design.
    *
    * @param callable $hookDocumentedAt
    *   The name of the function, e.g.: "hook_form_alter" or
diff --git a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
index 4140ff53b4d2..d7e80a043f7b 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
@@ -15,7 +15,7 @@
 class Preprocess extends Hook {
 
   /**
-   * Constructor.
+   * Constructs a Preprocess attribute.
    *
    * @param string|null $theme_hook
    *   (optional) Name of a theme hook, or NULL for a generic preprocess that
-- 
GitLab


From 830d583cad25c3dae900557f56194c2371ca1e59 Mon Sep 17 00:00:00 2001
From: Ghost Of Drupal Past <drupal@negyesi.net>
Date: Wed, 14 May 2025 07:18:21 +0200
Subject: [PATCH 11/17] hookdocumentation

---
 core/lib/Drupal/Core/Hook/Attribute/FormAlter.php           | 6 +++---
 .../{HookDocumentedAt.php => HookDocumentation.php}         | 6 +++---
 core/lib/Drupal/Core/Hook/Attribute/Preprocess.php          | 4 ++--
 3 files changed, 8 insertions(+), 8 deletions(-)
 rename core/lib/Drupal/Core/Hook/Attribute/{HookDocumentedAt.php => HookDocumentation.php} (93%)

diff --git a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
index babfa63c152b..03f84c386840 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
@@ -9,9 +9,9 @@
 /**
  * Hook attribute for FormAlter.
  */
-#[HookDocumentedAt('hook_form_alter')]
-#[HookDocumentedAt('hook_form_FORM_ID_alter')]
-#[HookDocumentedAt('hook_form_BASE_FORM_ID_alter')]
+#[HookDocumentation('hook_form_alter')]
+#[HookDocumentation('hook_form_FORM_ID_alter')]
+#[HookDocumentation('hook_form_BASE_FORM_ID_alter')]
 #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
 class FormAlter extends Hook {
 
diff --git a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentedAt.php b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
similarity index 93%
rename from core/lib/Drupal/Core/Hook/Attribute/HookDocumentedAt.php
rename to core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
index 977df5dc9179..555219b1d0f2 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentedAt.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
@@ -13,8 +13,8 @@
  * has these attributes:
  *
  * @code
- * #[HookDocumentedAt('hook_preprocess')]
- * #[HookDocumentedAt('hook_preprocess_HOOK')]
+ * #[HookDocumentation('hook_preprocess')]
+ * #[HookDocumentation('hook_preprocess_HOOK')]
  * @endcode
  *
  * This allows a tool like https://drupal.org/project/api module to link a
@@ -29,7 +29,7 @@
  * @see \Drupal\Core\Hook\Attribute\Preprocess
  */
 #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
-class HookDocumentedAt {
+class HookDocumentation {
 
   /**
    * Constructs a HookDocumentedAt attribute.
diff --git a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
index d7e80a043f7b..a2fdded6a3c6 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
@@ -9,8 +9,8 @@
 /**
  * Attribute to register a class method as a theme preprocess function.
  */
-#[HookDocumentedAt('hook_preprocess')]
-#[HookDocumentedAt('hook_preprocess_HOOK')]
+#[HookDocumentation('hook_preprocess')]
+#[HookDocumentation('hook_preprocess_HOOK')]
 #[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
 class Preprocess extends Hook {
 
-- 
GitLab


From 256efc8125a47960eed04bcaa7adca52c63539c5 Mon Sep 17 00:00:00 2001
From: Ghost Of Drupal Past <drupal@negyesi.net>
Date: Wed, 14 May 2025 19:27:08 +0200
Subject: [PATCH 12/17] better wording for the first parameter

---
 core/lib/Drupal/Core/Hook/Attribute/FormAlter.php  | 4 ++--
 core/lib/Drupal/Core/Hook/Attribute/Preprocess.php | 5 +++--
 2 files changed, 5 insertions(+), 4 deletions(-)

diff --git a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
index 03f84c386840..6233b01a6f22 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
@@ -20,8 +20,8 @@ class FormAlter extends Hook {
    *
    * @param string|null $form_id
    *   (optional) The ID or the base ID of the target form, or NULL to target
-   *   all forms. For documentation purposes, always make this the first
-   *   parameter, without using form_id: and use a string literal.
+   *   all forms. To better support documentation parsers, do not use named
+   *   argument syntax for this parameter and always pass a string literal.
    * @param string $method
    *   (optional) The method name. If this attribute is on a method, this
    *   parameter is not required. If this attribute is on a class and this
diff --git a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
index a2fdded6a3c6..d8ab2e9fb221 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
@@ -19,8 +19,9 @@ class Preprocess extends Hook {
    *
    * @param string|null $theme_hook
    *   (optional) Name of a theme hook, or NULL for a generic preprocess that
-   *   applies to all theme hooks. For documentation purposes, always make this
-   *   the first parameter, do not use theme_hook: and use a string literal.
+   *   applies to all theme hooks. To better support documentation parsers, do
+   *   not use named argument syntax for this parameter and always pass a
+   *   string literal.
    * @param string $method
    *   (optional) The method name. If this attribute is on a method, this
    *   parameter is not required. If this attribute is on a class and this
-- 
GitLab


From a32c7035f83a46d0643aa34ca9f4326af3c53917 Mon Sep 17 00:00:00 2001
From: Derek Wright <git@dwwright.net>
Date: Wed, 14 May 2025 08:07:50 -1000
Subject: [PATCH 13/17] Docs nits on HookDocumentation attribute

---
 .../Core/Hook/Attribute/HookDocumentation.php | 20 +++++++++----------
 1 file changed, 10 insertions(+), 10 deletions(-)

diff --git a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
index 555219b1d0f2..dd94b77ea4c0 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
@@ -19,9 +19,9 @@
  *
  * This allows a tool like https://drupal.org/project/api module to link a
  * method marked with the #[Preprocess] attribute to the documentation on
- * function hook_preprocess() or hook_preprocess_HOOK. The two can be told
- * apart depending on whether the first argument of Preprocess is a string
- * or a named argument.
+ * function hook_preprocess() or hook_preprocess_HOOK(). The two can be told
+ * apart depending on whether the first argument of #[Preprocess] is a string or
+ * a named argument.
  *
  * This attribute is never instantiated, it is solely used for documentation.
  *
@@ -32,19 +32,19 @@
 class HookDocumentation {
 
   /**
-   * Constructs a HookDocumentedAt attribute.
+   * Constructs a HookDocumentation attribute.
    *
-   * This attribute is solely used for automated tools parsing for
-   * documentation purposes like https://drupal.org/project/api and
-   * instantiating it is likely to cause a fatal error by design.
+   * This attribute is solely used for automated tools parsing for documentation
+   * purposes like https://drupal.org/project/api and to support
+   * IDEs. Instantiating it is likely to cause a fatal error by design.
    *
    * @param callable $hookDocumentedAt
    *   The name of the function, e.g.: "hook_form_alter" or
    *   "hook_form_FORM_ID_alter" where the documentation for this hook
    *   lives.
-   *   Use only string literals and avoid any other constant expression
-   *   because while PHP can evaluate them, the automated tools this attribute
-   *   targets not necessarily can.
+   *   Use only string literals and avoid any other constant expression.
+   *   While PHP can evaluate them, the automated tools this attribute
+   *   exists to support can not necessarily do so.
    *
    * @phpstan-param callable-string $hookDocumentedAt
    */
-- 
GitLab


From 2a2b4283b824b4ff9f6975f8064cdfcf0ece1b35 Mon Sep 17 00:00:00 2001
From: Derek Wright <git@dwwright.net>
Date: Wed, 14 May 2025 08:08:53 -1000
Subject: [PATCH 14/17] s/$hookDocumentedAt/$documentation/ as the param for
 HookDocumentation constructor

---
 core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
index dd94b77ea4c0..b7e6102978a8 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
@@ -38,7 +38,7 @@ class HookDocumentation {
    * purposes like https://drupal.org/project/api and to support
    * IDEs. Instantiating it is likely to cause a fatal error by design.
    *
-   * @param callable $hookDocumentedAt
+   * @param callable $documentation
    *   The name of the function, e.g.: "hook_form_alter" or
    *   "hook_form_FORM_ID_alter" where the documentation for this hook
    *   lives.
@@ -46,8 +46,8 @@ class HookDocumentation {
    *   While PHP can evaluate them, the automated tools this attribute
    *   exists to support can not necessarily do so.
    *
-   * @phpstan-param callable-string $hookDocumentedAt
+   * @phpstan-param callable-string $documentation
    */
-  public function __construct(callable $hookDocumentedAt) {}
+  public function __construct(callable $documentation) {}
 
 }
-- 
GitLab


From dcfc1ee9cfff2228cb00e97014f6a16be8ed4a15 Mon Sep 17 00:00:00 2001
From: Derek Wright <git@dwwright.net>
Date: Wed, 14 May 2025 08:11:19 -1000
Subject: [PATCH 15/17] Better 1-liner at the top of HookDocumentation

---
 core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
index b7e6102978a8..b646265a1ea6 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
@@ -5,7 +5,7 @@
 namespace Drupal\Core\Hook\Attribute;
 
 /**
- * Declare which hook this class provides shorthand for.
+ * Declares which hook a class provides shorthand for.
  *
  * This attribute is used on classes extending \Drupal\Core\Hook\Attribute\Hook
  * to facilitate association of implementations with the hook documentation.
-- 
GitLab


From f632feb0bf5238454253822108447b2802e3bb4f Mon Sep 17 00:00:00 2001
From: Derek Wright <git@dwwright.net>
Date: Wed, 14 May 2025 08:48:15 -1000
Subject: [PATCH 16/17] Merge constructor and attribute docs in
 HookDocumentation

---
 core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php | 8 +++-----
 1 file changed, 3 insertions(+), 5 deletions(-)

diff --git a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
index b646265a1ea6..6a8203e7d649 100644
--- a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
+++ b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
@@ -23,7 +23,9 @@
  * apart depending on whether the first argument of #[Preprocess] is a string or
  * a named argument.
  *
- * This attribute is never instantiated, it is solely used for documentation.
+ * This attribute is solely used for automated tools parsing for documentation
+ * purposes and to support IDEs. Instantiating it is likely to cause a fatal
+ * error by design.
  *
  * @see \Drupal\Core\Hook\Attribute\FormAlter
  * @see \Drupal\Core\Hook\Attribute\Preprocess
@@ -34,10 +36,6 @@ class HookDocumentation {
   /**
    * Constructs a HookDocumentation attribute.
    *
-   * This attribute is solely used for automated tools parsing for documentation
-   * purposes like https://drupal.org/project/api and to support
-   * IDEs. Instantiating it is likely to cause a fatal error by design.
-   *
    * @param callable $documentation
    *   The name of the function, e.g.: "hook_form_alter" or
    *   "hook_form_FORM_ID_alter" where the documentation for this hook
-- 
GitLab


From a7e254e17c485ede1407b8d4c095f788b6577e70 Mon Sep 17 00:00:00 2001
From: nicxvan <nic@nlightened.net>
Date: Wed, 14 May 2025 22:38:52 -0400
Subject: [PATCH 17/17] Remove Preprocess and FormAlter

---
 .../Drupal/Core/Hook/Attribute/FormAlter.php  | 47 -----------------
 .../Core/Hook/Attribute/HookDocumentation.php | 51 -------------------
 .../Drupal/Core/Hook/Attribute/Preprocess.php | 47 -----------------
 .../comment/src/Hook/CommentThemeHooks.php    |  4 +-
 .../Hook/CommentEmptyTitleTestThemeHooks.php  |  4 +-
 .../contact/src/Hook/ContactFormHooks.php     |  6 +--
 .../src/Hook/ContextualThemeHooks.php         |  4 +-
 .../locale/src/Hook/LocaleThemeHooks.php      |  4 +-
 core/modules/node/src/Hook/NodeThemeHooks.php |  4 +-
 .../ModuleTestOopPreprocessThemeHooks.php     |  6 +--
 .../src/Hook/ThemeTestThemeHooks.php          |  4 +-
 11 files changed, 18 insertions(+), 163 deletions(-)
 delete mode 100644 core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
 delete mode 100644 core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
 delete mode 100644 core/lib/Drupal/Core/Hook/Attribute/Preprocess.php

diff --git a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php b/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
deleted file mode 100644
index 6233b01a6f22..000000000000
--- a/core/lib/Drupal/Core/Hook/Attribute/FormAlter.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\Core\Hook\Attribute;
-
-use Drupal\Core\Hook\Order\OrderInterface;
-
-/**
- * Hook attribute for FormAlter.
- */
-#[HookDocumentation('hook_form_alter')]
-#[HookDocumentation('hook_form_FORM_ID_alter')]
-#[HookDocumentation('hook_form_BASE_FORM_ID_alter')]
-#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
-class FormAlter extends Hook {
-
-  /**
-   * Constructs a FormAlter attribute object.
-   *
-   * @param string|null $form_id
-   *   (optional) The ID or the base ID of the target form, or NULL to target
-   *   all forms. To better support documentation parsers, do not use named
-   *   argument syntax for this parameter and always pass a string literal.
-   * @param string $method
-   *   (optional) The method name. If this attribute is on a method, this
-   *   parameter is not required. If this attribute is on a class and this
-   *   parameter is omitted, the class must have an __invoke() method, which is
-   *   taken as the hook implementation.
-   * @param string|null $module
-   *   (optional) The module this implementation is for. This allows one module
-   *   to implement a hook on behalf of another module. Defaults to the module
-   *   the implementation is in.
-   * @param \Drupal\Core\Hook\Order\OrderInterface|null $order
-   *   (optional) Set the order of the implementation.
-   */
-  public function __construct(
-    ?string $form_id = NULL,
-    string $method = '',
-    ?string $module = NULL,
-    ?OrderInterface $order = NULL,
-  ) {
-    $hook = ($form_id === NULL) ? 'form_alter' : 'form_' . $form_id . '_alter';
-    parent::__construct($hook, $method, $module, $order);
-  }
-
-}
diff --git a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php b/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
deleted file mode 100644
index 6a8203e7d649..000000000000
--- a/core/lib/Drupal/Core/Hook/Attribute/HookDocumentation.php
+++ /dev/null
@@ -1,51 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\Core\Hook\Attribute;
-
-/**
- * Declares which hook a class provides shorthand for.
- *
- * This attribute is used on classes extending \Drupal\Core\Hook\Attribute\Hook
- * to facilitate association of implementations with the hook documentation.
- * For example, the \Drupal\Core\Hook\Attribute\Preprocess attribute class
- * has these attributes:
- *
- * @code
- * #[HookDocumentation('hook_preprocess')]
- * #[HookDocumentation('hook_preprocess_HOOK')]
- * @endcode
- *
- * This allows a tool like https://drupal.org/project/api module to link a
- * method marked with the #[Preprocess] attribute to the documentation on
- * function hook_preprocess() or hook_preprocess_HOOK(). The two can be told
- * apart depending on whether the first argument of #[Preprocess] is a string or
- * a named argument.
- *
- * This attribute is solely used for automated tools parsing for documentation
- * purposes and to support IDEs. Instantiating it is likely to cause a fatal
- * error by design.
- *
- * @see \Drupal\Core\Hook\Attribute\FormAlter
- * @see \Drupal\Core\Hook\Attribute\Preprocess
- */
-#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::IS_REPEATABLE)]
-class HookDocumentation {
-
-  /**
-   * Constructs a HookDocumentation attribute.
-   *
-   * @param callable $documentation
-   *   The name of the function, e.g.: "hook_form_alter" or
-   *   "hook_form_FORM_ID_alter" where the documentation for this hook
-   *   lives.
-   *   Use only string literals and avoid any other constant expression.
-   *   While PHP can evaluate them, the automated tools this attribute
-   *   exists to support can not necessarily do so.
-   *
-   * @phpstan-param callable-string $documentation
-   */
-  public function __construct(callable $documentation) {}
-
-}
diff --git a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php b/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
deleted file mode 100644
index d8ab2e9fb221..000000000000
--- a/core/lib/Drupal/Core/Hook/Attribute/Preprocess.php
+++ /dev/null
@@ -1,47 +0,0 @@
-<?php
-
-declare(strict_types=1);
-
-namespace Drupal\Core\Hook\Attribute;
-
-use Drupal\Core\Hook\Order\OrderInterface;
-
-/**
- * Attribute to register a class method as a theme preprocess function.
- */
-#[HookDocumentation('hook_preprocess')]
-#[HookDocumentation('hook_preprocess_HOOK')]
-#[\Attribute(\Attribute::TARGET_CLASS | \Attribute::TARGET_METHOD | \Attribute::IS_REPEATABLE)]
-class Preprocess extends Hook {
-
-  /**
-   * Constructs a Preprocess attribute.
-   *
-   * @param string|null $theme_hook
-   *   (optional) Name of a theme hook, or NULL for a generic preprocess that
-   *   applies to all theme hooks. To better support documentation parsers, do
-   *   not use named argument syntax for this parameter and always pass a
-   *   string literal.
-   * @param string $method
-   *   (optional) The method name. If this attribute is on a method, this
-   *   parameter is not required. If this attribute is on a class and this
-   *   parameter is omitted, the class must have an __invoke() method, which is
-   *   taken as the hook implementation.
-   * @param string|null $module
-   *   (optional) The module this implementation is for. This allows one module
-   *   to implement a hook on behalf of another module. Defaults to the module
-   *   the implementation is in.
-   * @param \Drupal\Core\Hook\Order\OrderInterface|null $order
-   *   (optional) Set the order of the implementation.
-   */
-  public function __construct(
-    ?string $theme_hook = NULL,
-    string $method = '',
-    ?string $module = NULL,
-    ?OrderInterface $order = NULL,
-  ) {
-    $hook = ($theme_hook === NULL) ? 'preprocess' : 'preprocess_' . $theme_hook;
-    parent::__construct($hook, $method, $module, $order);
-  }
-
-}
diff --git a/core/modules/comment/src/Hook/CommentThemeHooks.php b/core/modules/comment/src/Hook/CommentThemeHooks.php
index e789af6dab10..c137d586d416 100644
--- a/core/modules/comment/src/Hook/CommentThemeHooks.php
+++ b/core/modules/comment/src/Hook/CommentThemeHooks.php
@@ -2,7 +2,7 @@
 
 namespace Drupal\comment\Hook;
 
-use Drupal\Core\Hook\Attribute\Preprocess;
+use Drupal\Core\Hook\Attribute\Hook;
 
 /**
  * Hook implementations for comment.
@@ -12,7 +12,7 @@ class CommentThemeHooks {
   /**
    * Implements hook_preprocess_HOOK() for block templates.
    */
-  #[Preprocess('block')]
+  #[Hook('preprocess_block')]
   public function preprocessBlock(&$variables): void {
     if ($variables['configuration']['provider'] == 'comment') {
       $variables['attributes']['role'] = 'navigation';
diff --git a/core/modules/comment/tests/modules/comment_empty_title_test/src/Hook/CommentEmptyTitleTestThemeHooks.php b/core/modules/comment/tests/modules/comment_empty_title_test/src/Hook/CommentEmptyTitleTestThemeHooks.php
index db1ffae5a6d0..01a40394b409 100644
--- a/core/modules/comment/tests/modules/comment_empty_title_test/src/Hook/CommentEmptyTitleTestThemeHooks.php
+++ b/core/modules/comment/tests/modules/comment_empty_title_test/src/Hook/CommentEmptyTitleTestThemeHooks.php
@@ -4,7 +4,7 @@
 
 namespace Drupal\comment_empty_title_test\Hook;
 
-use Drupal\Core\Hook\Attribute\Preprocess;
+use Drupal\Core\Hook\Attribute\Hook;
 
 /**
  * Hook implementations for comment_empty_title_test.
@@ -14,7 +14,7 @@ class CommentEmptyTitleTestThemeHooks {
   /**
    * Implements hook_preprocess_comment().
    */
-  #[Preprocess('comment')]
+  #[Hook('preprocess_comment')]
   public function preprocessComment(&$variables): void {
     $variables['title'] = '';
   }
diff --git a/core/modules/contact/src/Hook/ContactFormHooks.php b/core/modules/contact/src/Hook/ContactFormHooks.php
index ad8223c3ec62..b31b929bddf2 100644
--- a/core/modules/contact/src/Hook/ContactFormHooks.php
+++ b/core/modules/contact/src/Hook/ContactFormHooks.php
@@ -4,7 +4,7 @@
 
 use Drupal\Core\Config\ConfigFactoryInterface;
 use Drupal\Core\Form\FormStateInterface;
-use Drupal\Core\Hook\Attribute\FormAlter;
+use Drupal\Core\Hook\Attribute\Hook;
 use Drupal\Core\Session\AccountInterface;
 use Drupal\Core\StringTranslation\StringTranslationTrait;
 use Drupal\user\UserDataInterface;
@@ -29,7 +29,7 @@ public function __construct(
    *
    * @see \Drupal\user\ProfileForm::form()
    */
-  #[FormAlter('user_form')]
+  #[Hook('form_user_form_alter')]
   public function formUserFormAlter(&$form, FormStateInterface $form_state) : void {
     $form['contact'] = [
       '#type' => 'details',
@@ -55,7 +55,7 @@ public function formUserFormAlter(&$form, FormStateInterface $form_state) : void
    *
    * Adds the default personal contact setting on the user settings page.
    */
-  #[FormAlter('user_admin_settings')]
+  #[Hook('form_user_admin_settings_alter')]
   public function formUserAdminSettingsAlter(&$form, FormStateInterface $form_state) : void {
     $form['contact'] = [
       '#type' => 'details',
diff --git a/core/modules/contextual/src/Hook/ContextualThemeHooks.php b/core/modules/contextual/src/Hook/ContextualThemeHooks.php
index 760a42c97854..7d873196b431 100644
--- a/core/modules/contextual/src/Hook/ContextualThemeHooks.php
+++ b/core/modules/contextual/src/Hook/ContextualThemeHooks.php
@@ -2,7 +2,7 @@
 
 namespace Drupal\contextual\Hook;
 
-use Drupal\Core\Hook\Attribute\Preprocess;
+use Drupal\Core\Hook\Attribute\Hook;
 use Drupal\Core\Session\AccountInterface;
 
 /**
@@ -21,7 +21,7 @@ public function __construct(
    * @see contextual_page_attachments()
    * @see \Drupal\contextual\ContextualController::render()
    */
-  #[Preprocess]
+  #[Hook('preprocess')]
   public function preprocess(&$variables, $hook, $info): void {
     // Determine the primary theme function argument.
     if (!empty($info['variables'])) {
diff --git a/core/modules/locale/src/Hook/LocaleThemeHooks.php b/core/modules/locale/src/Hook/LocaleThemeHooks.php
index d1e438f50ace..4ef5ca0b4989 100644
--- a/core/modules/locale/src/Hook/LocaleThemeHooks.php
+++ b/core/modules/locale/src/Hook/LocaleThemeHooks.php
@@ -2,7 +2,7 @@
 
 namespace Drupal\locale\Hook;
 
-use Drupal\Core\Hook\Attribute\Preprocess;
+use Drupal\Core\Hook\Attribute\Hook;
 use Drupal\Core\Language\LanguageInterface;
 use Drupal\Core\Language\LanguageManagerInterface;
 
@@ -18,7 +18,7 @@ public function __construct(
   /**
    * Implements hook_preprocess_HOOK() for node templates.
    */
-  #[Preprocess('node')]
+  #[Hook('preprocess_node')]
   public function preprocessNode(&$variables): void {
     /** @var \Drupal\node\NodeInterface $node */
     $node = $variables['node'];
diff --git a/core/modules/node/src/Hook/NodeThemeHooks.php b/core/modules/node/src/Hook/NodeThemeHooks.php
index 7ee443c458f8..7ed0ef91f5fd 100644
--- a/core/modules/node/src/Hook/NodeThemeHooks.php
+++ b/core/modules/node/src/Hook/NodeThemeHooks.php
@@ -4,7 +4,7 @@
 
 namespace Drupal\node\Hook;
 
-use Drupal\Core\Hook\Attribute\Preprocess;
+use Drupal\Core\Hook\Attribute\Hook;
 
 /**
  * Hook implementations for the node module.
@@ -14,7 +14,7 @@ class NodeThemeHooks {
   /**
    * Implements hook_preprocess_HOOK() for node field templates.
    */
-  #[Preprocess('field__node')]
+  #[Hook('preprocess_field__node')]
   public function preprocessFieldNode(&$variables): void {
     // Set a variable 'is_inline' in cases where inline markup is required,
     // without any block elements such as <div>.
diff --git a/core/modules/system/tests/modules/module_test_oop_preprocess/src/Hook/ModuleTestOopPreprocessThemeHooks.php b/core/modules/system/tests/modules/module_test_oop_preprocess/src/Hook/ModuleTestOopPreprocessThemeHooks.php
index 1cbb9e6b422b..db923382a21b 100644
--- a/core/modules/system/tests/modules/module_test_oop_preprocess/src/Hook/ModuleTestOopPreprocessThemeHooks.php
+++ b/core/modules/system/tests/modules/module_test_oop_preprocess/src/Hook/ModuleTestOopPreprocessThemeHooks.php
@@ -4,19 +4,19 @@
 
 namespace Drupal\module_test_oop_preprocess\Hook;
 
-use Drupal\Core\Hook\Attribute\Preprocess;
+use Drupal\Core\Hook\Attribute\Hook;
 
 /**
  * Hook implementations for module_test_oop_preprocess.
  */
 class ModuleTestOopPreprocessThemeHooks {
 
-  #[Preprocess]
+  #[Hook('preprocess')]
   public function rootPreprocess($arg): mixed {
     return $arg;
   }
 
-  #[Preprocess('test')]
+  #[Hook('preprocess_test')]
   public function preprocessTest($arg): mixed {
     return $arg;
   }
diff --git a/core/modules/system/tests/modules/theme_test/src/Hook/ThemeTestThemeHooks.php b/core/modules/system/tests/modules/theme_test/src/Hook/ThemeTestThemeHooks.php
index fc48756de51a..7bfc10ef0ef9 100644
--- a/core/modules/system/tests/modules/theme_test/src/Hook/ThemeTestThemeHooks.php
+++ b/core/modules/system/tests/modules/theme_test/src/Hook/ThemeTestThemeHooks.php
@@ -4,7 +4,7 @@
 
 namespace Drupal\theme_test\Hook;
 
-use Drupal\Core\Hook\Attribute\Preprocess;
+use Drupal\Core\Hook\Attribute\Hook;
 
 /**
  * Hook implementations for theme_test.
@@ -14,7 +14,7 @@ class ThemeTestThemeHooks {
   /**
    * Implements hook_preprocess_HOOK().
    */
-  #[Preprocess('theme_test_preprocess_suggestions__monkey')]
+  #[Hook('preprocess_theme_test_preprocess_suggestions__monkey')]
   public function preprocessTestSuggestions(&$variables): void {
     $variables['foo'] = 'Monkey';
   }
-- 
GitLab