1
0
mirror of https://github.com/danog/psalm.git synced 2025-01-22 13:51:54 +01:00

Added better stubs for DateTimeImmutable, highlighting how the constructor is **NOT** immutable

`DateTimeImmutable` is **almost** immutable: `DateTimeImmutable::__construct()` is in fact not a pure
method, since `new DateTimeImmutable('now')` produces a different value at each instantiation (by design).

This change makes sure that `DateTimeImmutable` loses its `@psalm-immutable` class-level marker,
preventing downstream misuse of the constructor inside otherwise referentially transparent code.

Note: only pure methods are stubbed here: all other methods declared by `DateTimeImmutable` (parent interface)
are NOT present here, and are either inferred from runtime reflection, or `CallMap*.php` definitions.

Methods are sorted in the order defined by reflection on PHP 8.1.8, at the time of writing this ( https://3v4l.org/3TGg8 ).

Following simplistic snippet was used to infer the current signature:

```php
<?php

$c = new \ReflectionClass(\DateTimeImmutable::class);

$methods = array_map(function ($m) {
    return $m->getName()
        . '(' . implode(',', array_map(function ($p) {
            return $p->getType()
                . ' $' . $p->getName()
                . ($p->isOptional() ? ' = ' . var_export($p->getDefaultValue(), true) : '');
        }, $m->getParameters())) . ')' . ($m->getReturnType() ? (': ' . $m->getReturnType()) : '');
}, $c->getMethods());

$properties = array_map(function ($m) {
    return $m->getName();
}, $c->getProperties());

var_dump($methods, $properties);
```
This commit is contained in:
Marco Pivetta 2022-07-31 18:02:30 +02:00
parent 6998fabb2b
commit b4b2bc66c7

View File

@ -1,11 +1,106 @@
<?php
/**
* @psalm-immutable
*/
class DateTimeImmutable implements DateTimeInterface
{
public function __construct(string $datetime = "now", DateTimeZone $timezone = null) {}
/**
* @psalm-pure
* @return static|false
*/
public static function createFromFormat(string $format, string $datetime, ?DateTimeZone $timezone = null) {}
/**
* @psalm-pure
* @param string $format
* @return string
*/
public function format($format) {}
/**
* @psalm-pure
* @return DateTimeZone
*/
public function getTimezone() {}
/**
* @psalm-pure
* @return int
*/
public function getOffset() {}
/**
* @psalm-pure
* @return int
*/
public function getTimestamp() {}
/**
* @psalm-pure
* @param bool $absolute
* @return DateInterval
*/
public function diff(DateTimeInterface $targetObject, $absolute = false) {}
/**
* @psalm-pure
* @return static
*/
public function modify(string $modifier) {}
/**
* @psalm-pure
* @return static
*/
public function add(DateInterval $interval) {}
/**
* @psalm-pure
* @return static
*/
public function sub(DateInterval $interval) {}
/**
* @psalm-pure
* @return static|false
*/
public function setTimezone(DateTimeZone $timezone) {}
/**
* @psalm-pure
* @return static|false
*/
public function setTime(int $hour, int $minute, int $second = 0, int $microsecond = 0) {}
/**
* @psalm-pure
* @return static|false
*/
public function setDate(int $year, int $month, int $day) {}
/**
* @psalm-pure
* @return static|false
*/
public function setISODate(int $year, int $week, int $dayOfWeek = 1) {}
/**
* @psalm-pure
* @return static|false
*/
public function setTimestamp(int $unixtimestamp) {}
/**
* @psalm-pure
* @return static
*/
public static function createFromMutable(DateTime $object) {}
/**
* @psalm-pure
* @return self
*/
public static function createFromInterface(DateTimeInterface $object) {}
}
/**