Skip to content

Add a dynamic return type extension for wp_parse_args() (2.x) - #310

Merged
szepeviktor merged 3 commits into
szepeviktor:2.xfrom
swissspidy:fix/wp-parse-args-for-v2
Sep 8, 2026
Merged

szepeviktor merged 3 commits into
szepeviktor:2.xfrom
swissspidy:fix/wp-parse-args-for-v2

Conversation

@swissspidy

@swissspidy swissspidy commented Sep 8, 2026

Copy link
Copy Markdown
Contributor

This ports #309 to the 2.x branch. I mistakenly opened #309 against master, which is the 1.x line for PHPStan 1, so the extension never reached the PHPStan 2 release line. Apologies for the mix-up.

The extension itself is unchanged. What differs from #309:

  • The test data file uses the hyphenated naming of this branch.
  • Two assertions depend on PHPStan internals that changed during 2.x, so they live in tests/data/wp-parse-args-phpstan-2.1.39.php and only run on PHPStan ^2.1.39, like the existing slashit gate. PHPStan 2.1.1 changed how
    unions of array shapes are normalized, and PHPStan 2.1.39 changed the keys of get_object_vars() from string to array-key.
  • The WPCS bump from Add a dynamic return type extension for wp_parse_args() #309 is included as a separate commit. It resolves to szepeviktor/phpcs-psr-12-neutron-hybrid-ruleset v1.2.0, which carries the same pin, and the lowest-deps setup matches what already passes on master.

claude and others added 2 commits September 8, 2026 09:47
Port of the extension merged into the 1.x line (master) to the 2.x line
for PHPStan 2. The extension itself is unchanged; the type assertions
that depend on PHPStan 2 internals are kept in a separate data file
gated on PHPStan 2.1.39, in line with the existing slashit gate:

- PHPStan 2.1.1 normalizes unions of array shapes differently.
- PHPStan 2.1.39 types the keys of get_object_vars() as array-key.

Co-authored-by: Pascal Birchler <pascal.birchler@gmail.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BdixSnMLgw1cC5m1ZSP5Kd
Co-authored-by: Pascal Birchler <pascal.birchler@gmail.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BdixSnMLgw1cC5m1ZSP5Kd
Copilot AI lite review requested due to automatic review settings September 8, 2026 10:00
@greptile-apps

greptile-apps Bot commented Sep 8, 2026

Copy link
Copy Markdown

Greptile Summary

This PR adds a PHPStan 2.x dynamic return-type extension for wp_parse_args() and registers it with the extension.

  • Infers array shapes after applying defaults while preserving argument precedence.
  • Handles arrays and safely modeled objects, falling back to the declared return type for uncertain inputs.
  • Normalizes PHP 8 named arguments and avoids namespace shadowing in synthetic built-in calls.
  • Adds version-gated type-inference fixtures and updates PHP 7.4 syntax-test exclusions.
  • Updates the WordPress Coding Standards development dependency.

Confidence Score: 5/5

The PR appears safe to merge, with the prior named-argument issue fully addressed and no new actionable defects identified.

Named calls are now normalized before positional indexing, and tests cover both named-argument orders. The additional namespace-resolution and version-gating changes use safe fallbacks and match established repository patterns.

Important Files Changed

Filename Overview
src/WpParseArgsDynamicFunctionReturnTypeExtension.php Adds conservative wp_parse_args() return-type inference, including normalized named arguments and fully qualified synthetic built-in calls.
extension.neon Registers the new dynamic function return-type extension with PHPStan.
tests/DynamicReturnTypeExtensionTest.php Loads the new fixtures with appropriate PHP and PHPStan version gates.
tests/data/wp-parse-args.php Covers array shapes, precedence, empty and invalid defaults, string fallback, class scope, and namespace shadowing.
tests/data/wp-parse-args-named-args.php Verifies named arguments are normalized correctly regardless of their source order.
tests/data/wp-parse-args-phpstan-2.1.39.php Covers inference whose expected representation depends on PHPStan 2.1.39 or later.
.travis.yml Prevents PHP 7.4 syntax checks from parsing the PHP 8-only named-argument fixture.
composer.json Updates the development WPCS constraint while retaining the compatibility alias.

Flowchart

%%{init: {'theme': 'neutral'}}%%
flowchart TD
    A[wp_parse_args call] --> B[Normalize arguments]
    B --> C{Normalization succeeded<br/>and no unpacking?}
    C -- No --> F[Use declared return type]
    C -- Yes --> D{args is an array or<br/>safe object conversion?}
    D -- No --> F
    D -- Yes --> E{defaults supplied as array?}
    E -- No --> G[Return parsed args type]
    E -- Yes --> H[Infer array_merge of defaults and args]
    H --> I{Defaults definitely non-empty?}
    I -- Yes --> J[Return merged type]
    I -- No --> K[Union merged and original args types]
Loading

Reviews (2): Last reviewed commit: "Address review feedback for wp_parse_arg..." | Re-trigger Greptile

Comment thread src/WpParseArgsDynamicFunctionReturnTypeExtension.php Outdated

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🟡 Changes recommended

The new extension builds synthetic calls using unqualified built-in function names, which can resolve in the caller’s namespace and yield incorrect inferred types.

Once you've addressed the issues Copilot identified, you can request another Copilot review.

Pull request overview

This PR ports the wp_parse_args() dynamic return type extension and its test coverage to the PHPStan 2.x (2.x branch) release line, ensuring callers get precise array-shape inference instead of a generic array<mixed> return type.

Changes:

  • Add WpParseArgsDynamicFunctionReturnTypeExtension to infer merged array-shape return types for wp_parse_args().
  • Add new type-inference test fixtures for wp_parse_args(), including a PHPStan-version-gated fixture for behavior that changed in PHPStan 2.1.x.
  • Register the new extension in extension.neon and bump the WPCS dev dependency pin.
File summaries
File Description
tests/DynamicReturnTypeExtensionTest.php Adds PHPStan-version-gated inclusion of an additional wp_parse_args() assert fixture and includes the base fixture.
tests/data/wp-parse-args.php Adds core wp_parse_args() type assertion coverage (array-shapes, defaults precedence, ignored defaults, query string/object cases).
tests/data/wp-parse-args-phpstan-2.1.39.php Adds PHPStan-2.1.39-gated assertions for behaviors affected by PHPStan internal type normalization changes.
src/WpParseArgsDynamicFunctionReturnTypeExtension.php Implements the dynamic return type extension for wp_parse_args().
extension.neon Registers the new dynamic return type extension service.
composer.json Updates the WPCS alias pin from 3.1.0 to 3.4.1 (aliased as 2.3.0).
Review details

Suppressed comments (1)

src/WpParseArgsDynamicFunctionReturnTypeExtension.php:101

  • The synthetic get_object_vars() call is created with an unqualified name, so it can be resolved against the caller’s namespace instead of the global built-in. Use a fully-qualified name to ensure the correct function is analysed.
            return new FuncCall(new Name('get_object_vars'), [new Arg($argsExpr)]);
  • Files reviewed: 6/6 changed files
  • Comments generated: 1
  • Review effort level: Lite

💡 Add a code-review agent skill or configure MCP servers for context-aware, tailored reviews. Learn more in the docs.

Comment thread src/WpParseArgsDynamicFunctionReturnTypeExtension.php Outdated
- Normalize the arguments of wp_parse_args() through NormalizedArguments,
  so named arguments in any order are matched up with the right parameter.
- Resolve the synthetic array_merge() and get_object_vars() calls with
  fully qualified names, so a function of the same name in the caller's
  namespace cannot shadow the built-in ones.
- Cover both cases in the tests. The named arguments file is excluded from
  the PHP 7.4 syntax lint like the existing hook-callback-named-args.php.

Co-authored-by: Pascal Birchler <pascal.birchler@gmail.com>
Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
Claude-Session: https://claude.ai/code/session_01BdixSnMLgw1cC5m1ZSP5Kd
@szepeviktor

Copy link
Copy Markdown
Owner

This PR is nice and long.
Let me see the agencies compensating for my food cost -> immediate merge.

@szepeviktor
szepeviktor merged commit 88b27c9 into szepeviktor:2.x Sep 8, 2026
1 of 2 checks passed
@swissspidy
swissspidy deleted the fix/wp-parse-args-for-v2 branch September 8, 2026 11:05
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.

4 participants