Make WordPress Core


Ignore:
Timestamp:
07/30/2026 04:45:34 AM (3 months ago)
Author:
westonruter
Message:

Build/Test Tools: Verify hook docblocks statically.

Add PHPStan extensions that read the docblock documenting each hook where the hook is fired. The value apply_filters() returns is typed from the first @param that docblock documents rather than mixed; core's /** This filter is documented in <file> */ convention is resolved, so a hook documented elsewhere is analyzed against its canonical docblock, including a dynamic canonical name such as "{$type}_template_hierarchy"; and two rules require every hook invocation to be documented, and to pass as many arguments as its documentation describes.

These conventions were previously enforced by review alone. A reference comment could name a file that no longer documents the hook, and a call site could pass fewer arguments than documented, which raises an ArgumentCountError in a callback registered for the documented count, or more, which drops the extra argument and leaves the documentation wrong. Both are now reported where they occur. The hook issues this surfaced in core were fixed in preceding commits.

The generated src/wp-includes/build tree is excluded from analysis, as its sources live in the Gutenberg plugin.

Developed in ​https://github.com/WordPress/wordpress-develop/pull/12022.
Follow-up to r61699, r62292, r62893, r62894, r62925, r62926, r62927, r62928, r62930, r62931, r62932, r62933, r62934, r62935.

Props westonruter, szepeviktor, khokansardar.
See #64898.
Fixes #65376.

File:
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/tests/phpstan/base.neon

    r62657 r62939  
    1212                tags:
    1313                        - phpstan.parser.richParserNodeVisitor
     14
     15        # Attaches the docblock documenting a hook to the hook's call, so that the return
     16        # type extension and the rules below can all read it.
     17        -
     18                class: WordPress\PHPStan\HookDocsVisitor
     19                tags:
     20                        - phpstan.parser.richParserNodeVisitor
     21
     22        # Resolves a hook call's documentation, whether written at the call or inherited
     23        # through the "This filter is documented in <file>" convention.
     24        -
     25                class: WordPress\PHPStan\HookDocBlock
     26
     27        # Types the return value of apply_filters() (and variants) from the `@param` type
     28        # documented for the value being filtered. Adapted from szepeviktor/phpstan-wordpress.
     29        -
     30                class: WordPress\PHPStan\ApplyFiltersDynamicFunctionReturnTypeExtension
     31                tags:
     32                        - phpstan.broker.dynamicFunctionReturnTypeExtension
     33
     34        # Enforces that every hook invocation is preceded by a documenting docblock or
     35        # a valid "This filter is documented in <file>" reference comment.
     36        -
     37                class: WordPress\PHPStan\HookDocumentationRule
     38                tags:
     39                        - phpstan.rules.rule
     40
     41        # Enforces that a hook invocation passes as many arguments as its documentation
     42        # (inline or referenced) describes.
     43        -
     44                class: WordPress\PHPStan\HookParamCountRule
     45                tags:
     46                        - phpstan.rules.rule
     47
     48        # Docblocks inherited from another file, and the sources above that read them,
     49        # are invisible to PHPStan's dependency graph, so both are folded into the result
     50        # cache key. Without this, editing a canonical hook docblock leaves the cached
     51        # results of every call site inheriting it in place.
     52        -
     53                class: WordPress\PHPStan\HookDocsResultCacheMetaExtension
     54                tags:
     55                        - phpstan.resultCacheMetaExtension
    1456
    1557parameters:
    … …  
    100142                - ../../src/xmlrpc.php
    101143                - GlobalDocBlockVisitor.php
     144                - HookDocsVisitor.php
     145                - HookDocBlock.php
     146                - ApplyFiltersDynamicFunctionReturnTypeExtension.php
     147                - HookDocumentationRule.php
     148                - HookParamCountRule.php
     149                - HookDocsResultCacheMetaExtension.php
    102150        bootstrapFiles:
    103151                - bootstrap.php
    … …  
    120168                        # These files are autogenerated by tools/gutenberg/copy.js.
    121169                        - ../../src/wp-includes/blocks
     170                        # Generated output from the Gutenberg plugin's wp-build templates.
     171                        - ../../src/wp-includes/build
    122172                        # Third-party libraries.
    123173                        - ../../src/wp-admin/includes/class-ftp-pure.php
Note: See TracChangeset for help on using the changeset viewer.