Skip to content

Report invalid DateInterval constructor arguments at analysis time#5587

Merged
staabm merged 7 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-v8z1qut
May 5, 2026
Merged

Report invalid DateInterval constructor arguments at analysis time#5587
staabm merged 7 commits intophpstan:2.1.xfrom
phpstan-bot:create-pull-request/patch-v8z1qut

Conversation

@phpstan-bot
Copy link
Copy Markdown
Collaborator

@phpstan-bot phpstan-bot commented May 3, 2026

Summary

PHPStan did not report errors when DateInterval was constructed with an invalid duration string (e.g. new DateInterval('1M') instead of new DateInterval('P1M')). While there was already a DateIntervalConstructorThrowTypeExtension that refined the throw type, there was no rule to actually report the error to the user.

Fixes phpstan/phpstan#14442

see https://3v4l.org/MBaPe#veol

Comment thread src/Rules/DateTimeZoneInstantiationRule.php Outdated
@VincentLanglet VincentLanglet changed the title Report invalid DateInterval and DateTimeZone constructor arguments at analysis time Report invalid DateInterval constructor arguments at analysis time May 3, 2026
Comment thread tests/PHPStan/Rules/DateIntervalInstantiationRuleTest.php
@staabm staabm force-pushed the create-pull-request/patch-v8z1qut branch from 070b036 to c0929f9 Compare May 3, 2026 11:16
/**
* @implements Rule<Node\Expr\New_>
*/
#[RegisteredRule(level: 5)]
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

should it be bleeding edge only?

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done. The DateIntervalInstantiationRule is now bleeding edge only:

  • Removed #[RegisteredRule(level: 5)] from the rule class
  • Added checkDateIntervalConstructor feature toggle (default false in config.neon, true in bleedingEdge.neon)
  • Added the toggle to the parameters schema
  • Registered the rule as a service in config.level5.neon with a conditionalTags entry gated on the feature toggle

All tests pass and make phpstan reports no errors.

staabm and others added 4 commits May 5, 2026 19:29
…s at analysis time

- Add DateIntervalInstantiationRule that validates constant duration strings
  passed to the DateInterval constructor and reports errors for invalid ones
- Add DateTimeZoneInstantiationRule that validates constant timezone strings
  passed to the DateTimeZone constructor and reports errors for invalid ones
- Both rules follow the same pattern as the existing DateTimeInstantiationRule:
  extract constant strings, attempt construction, report exceptions as errors
- Both registered at level 5, matching DateTimeInstantiationRule
The DateTimeZone validation rule is less valuable than the DateInterval
case since DateInterval durations are more commonly known at analysis time.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
On PHP < 8.1, DateInterval::__construct() prefixes the exception
message with "DateInterval::__construct(): ", while PHP 8.1+ uses
a shorter format. Gate the existing test with RequiresPhp(>= 8.1.0)
and add a separate testLegacyPhp method for older PHP versions.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@staabm staabm force-pushed the create-pull-request/patch-v8z1qut branch from c2c3f59 to a71fa23 Compare May 5, 2026 17:29
Comment on lines +53 to +54
// normalize PHP7 errors to PHP8 format
str_replace('DateInterval::__construct(): ', '', $e->getMessage()),
Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

The same difference exist for other instantiation but we don't normalize the errors.
https://3v4l.org/Yt4EU#v7.4.33

I think we should be consistent for now.

Copy link
Copy Markdown
Collaborator Author

Choose a reason for hiding this comment

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

Done. Removed the str_replace normalization from DateIntervalInstantiationRule so error messages are passed through as-is from PHP's DateInterval constructor — consistent with how other rules handle version-specific error messages. Test expectations now use a $prefix variable based on PHP_VERSION_ID to handle the DateInterval::__construct(): prefix present on PHP < 8.1.

Be consistent with other rules by not normalizing PHP exception
messages. Split test expectations by PHP version instead.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
@VincentLanglet
Copy link
Copy Markdown
Contributor

I didn't realize the bot will handle my review @staabm (#5587 (comment))

Please confirm you're ok with it before merging thanks.

@staabm staabm merged commit ab0b1ae into phpstan:2.1.x May 5, 2026
660 checks passed
@staabm staabm deleted the create-pull-request/patch-v8z1qut branch May 5, 2026 18:29
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.

3 participants