Fix pure annotations (#605)

Coming from https://github.com/ramsey/uuid/pull/603, this is an attempt
to fix the errors raised by the current phpstan settings.

I went through each of the errors raised by phpstan with the following
approach.

- If a method is part of an `@immutable` class, we can consider it pure,
  assuming it only affects internal variables.
- If a potentially pure method is calling a class's method that is only
  swapped during testing (and not during normal usage), then we can
  consider the calling method pure.
- If a class is marked deprecated, don't bother with attempting to mark
  it pure or immutable.
This commit is contained in:
Brandon Morrison
2025-06-24 20:28:52 -05:00
committed by Ben Ramsey
parent df575bdb79
commit aa18ce15d5
54 changed files with 217 additions and 21 deletions
+1 -1
View File
@@ -51,7 +51,7 @@ class DegradedUuidBuilder implements UuidBuilderInterface
*
* @return DegradedUuid The DegradedUuidBuild returns an instance of Ramsey\Uuid\DegradedUuid
*
* @pure
* @phpstan-impure
*/
public function build(CodecInterface $codec, string $bytes): UuidInterface
{
+8
View File
@@ -29,6 +29,8 @@ interface CodecInterface
* @param UuidInterface $uuid The UUID for which to create a hexadecimal string representation
*
* @return non-empty-string Hexadecimal string representation of a UUID
*
* @pure
*/
public function encode(UuidInterface $uuid): string;
@@ -38,6 +40,8 @@ interface CodecInterface
* @param UuidInterface $uuid The UUID for which to create a binary string representation
*
* @return non-empty-string Binary string representation of a UUID
*
* @pure
*/
public function encodeBinary(UuidInterface $uuid): string;
@@ -47,6 +51,8 @@ interface CodecInterface
* @param string $encodedUuid The hexadecimal string representation to convert into a UuidInterface instance
*
* @return UuidInterface An instance of a UUID decoded from a hexadecimal string representation
*
* @pure
*/
public function decode(string $encodedUuid): UuidInterface;
@@ -56,6 +62,8 @@ interface CodecInterface
* @param string $bytes The binary string representation to convert into a UuidInterface instance
*
* @return UuidInterface An instance of a UUID decoded from a binary string representation
*
* @pure
*/
public function decodeBytes(string $bytes): UuidInterface;
}
+3
View File
@@ -32,6 +32,7 @@ class GuidStringCodec extends StringCodec
{
public function encode(UuidInterface $uuid): string
{
/** @phpstan-ignore possiblyImpure.methodCall */
$hex = bin2hex($uuid->getFields()->getBytes());
/** @var non-empty-string */
@@ -52,8 +53,10 @@ class GuidStringCodec extends StringCodec
public function decode(string $encodedUuid): UuidInterface
{
/** @phpstan-ignore possiblyImpure.methodCall */
$bytes = $this->getBytes($encodedUuid);
/** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
return $this->getBuilder()->build($this, $this->swapBytes($bytes));
}
+5
View File
@@ -51,12 +51,15 @@ class OrderedTimeCodec extends StringCodec
public function encodeBinary(UuidInterface $uuid): string
{
if (
/** @phpstan-ignore possiblyImpure.methodCall */
!($uuid->getFields() instanceof Rfc4122FieldsInterface)
/** @phpstan-ignore possiblyImpure.methodCall */
|| $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME
) {
throw new InvalidArgumentException('Expected version 1 (time-based) UUID');
}
/** @phpstan-ignore possiblyImpure.methodCall */
$bytes = $uuid->getFields()->getBytes();
return $bytes[6] . $bytes[7] . $bytes[4] . $bytes[5]
@@ -85,7 +88,9 @@ class OrderedTimeCodec extends StringCodec
$uuid = parent::decodeBytes($rearrangedBytes);
if (
/** @phpstan-ignore possiblyImpure.methodCall */
!($uuid->getFields() instanceof Rfc4122FieldsInterface)
/** @phpstan-ignore possiblyImpure.methodCall */
|| $uuid->getFields()->getVersion() !== Uuid::UUID_TYPE_TIME
) {
throw new UnsupportedOperationException(
+2
View File
@@ -46,6 +46,7 @@ class StringCodec implements CodecInterface
public function encode(UuidInterface $uuid): string
{
/** @phpstan-ignore possiblyImpure.methodCall */
$hex = bin2hex($uuid->getFields()->getBytes());
/** @var non-empty-string */
@@ -75,6 +76,7 @@ class StringCodec implements CodecInterface
*/
public function decode(string $encodedUuid): UuidInterface
{
/** @phpstan-ignore possiblyImpure.methodCall */
return $this->builder->build($this, $this->getBytes($encodedUuid));
}
+6
View File
@@ -55,6 +55,7 @@ class TimestampFirstCombCodec extends StringCodec
*/
public function encode(UuidInterface $uuid): string
{
/** @phpstan-ignore possiblyImpure.methodCall */
$bytes = $this->swapBytes($uuid->getFields()->getBytes());
return sprintf(
@@ -83,18 +84,23 @@ class TimestampFirstCombCodec extends StringCodec
*/
public function decode(string $encodedUuid): UuidInterface
{
/** @phpstan-ignore possiblyImpure.methodCall */
$bytes = $this->getBytes($encodedUuid);
/** @phpstan-ignore possiblyImpure.methodCall */
return $this->getBuilder()->build($this, $this->swapBytes($bytes));
}
public function decodeBytes(string $bytes): UuidInterface
{
/** @phpstan-ignore possiblyImpure.methodCall */
return $this->getBuilder()->build($this, $this->swapBytes($bytes));
}
/**
* Swaps bytes according to the timestamp-first COMB rules
*
* @pure
*/
private function swapBytes(string $bytes): string
{
@@ -42,6 +42,7 @@ class GenericNumberConverter implements NumberConverterInterface
*/
public function toHex(string $number): string
{
/** @phpstan-ignore-next-line PHPStan complains that this is not a non-empty-string. */
return $this->calculator->toBase(new IntegerObject($number), 16);
}
}
+8 -4
View File
@@ -54,26 +54,29 @@ class GenericTimeConverter implements TimeConverterInterface
public function calculateTime(string $seconds, string $microseconds): Hexadecimal
{
/** @phpstan-ignore possiblyImpure.new */
$timestamp = new Time($seconds, $microseconds);
// Convert the seconds into a count of 100-nanosecond intervals.
$sec = $this->calculator->multiply(
$timestamp->getSeconds(),
new IntegerObject(self::SECOND_INTERVALS),
new IntegerObject(self::SECOND_INTERVALS), /** @phpstan-ignore possiblyImpure.new */
);
// Convert the microseconds into a count of 100-nanosecond intervals.
$usec = $this->calculator->multiply(
$timestamp->getMicroseconds(),
new IntegerObject(self::MICROSECOND_INTERVALS),
new IntegerObject(self::MICROSECOND_INTERVALS), /** @phpstan-ignore possiblyImpure.new */
);
// Combine the intervals of seconds and microseconds and add the count of 100-nanosecond intervals from the
// Gregorian calendar epoch to the Unix epoch. This gives us the correct count of 100-nanosecond intervals since
// the Gregorian calendar epoch for the given seconds and microseconds.
/** @var IntegerObject $uuidTime */
/** @phpstan-ignore possiblyImpure.new */
$uuidTime = $this->calculator->add($sec, $usec, new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS));
/** @phpstan-ignore-next-line phpstan considers CalculatorInterface::toHexidecimal, Hexadecimal:toString impure */
return new Hexadecimal(str_pad($this->calculator->toHexadecimal($uuidTime)->toString(), 16, '0', STR_PAD_LEFT));
}
@@ -83,7 +86,7 @@ class GenericTimeConverter implements TimeConverterInterface
// epoch. This gives us the number of 100-nanosecond intervals from the Unix epoch, which also includes the microtime.
$epochNanoseconds = $this->calculator->subtract(
$this->calculator->toInteger($uuidTimestamp),
new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS),
new IntegerObject(self::GREGORIAN_TO_UNIX_INTERVALS), /** @phpstan-ignore possiblyImpure.new */
);
// Convert the 100-nanosecond intervals into seconds and microseconds.
@@ -91,11 +94,12 @@ class GenericTimeConverter implements TimeConverterInterface
RoundingMode::HALF_UP,
6,
$epochNanoseconds,
new IntegerObject(self::SECOND_INTERVALS),
new IntegerObject(self::SECOND_INTERVALS), /** @phpstan-ignore possiblyImpure.new */
);
$split = explode('.', (string) $unixTimestamp, 2);
/** @phpstan-ignore possiblyImpure.new */
return new Time($split[0], $split[1] ?? 0);
}
}
+9 -3
View File
@@ -79,8 +79,8 @@ class PhpTimeConverter implements TimeConverterInterface
public function calculateTime(string $seconds, string $microseconds): Hexadecimal
{
$seconds = new IntegerObject($seconds);
$microseconds = new IntegerObject($microseconds);
$seconds = new IntegerObject($seconds); /** @phpstan-ignore possiblyImpure.new */
$microseconds = new IntegerObject($microseconds); /** @phpstan-ignore possiblyImpure.new */
// Calculate the count of 100-nanosecond intervals since the Gregorian calendar epoch
// for the given seconds and microseconds.
@@ -98,7 +98,10 @@ class PhpTimeConverter implements TimeConverterInterface
);
}
return new Hexadecimal(str_pad(dechex($uuidTime), 16, '0', STR_PAD_LEFT));
/** @phpstan-ignore possiblyImpure.new */
return new Hexadecimal(
str_pad(dechex($uuidTime), 16, '0', STR_PAD_LEFT)
);
}
public function convertTime(Hexadecimal $uuidTimestamp): Time
@@ -114,6 +117,7 @@ class PhpTimeConverter implements TimeConverterInterface
return $this->fallbackConverter->convertTime($uuidTimestamp);
}
/** @phpstan-ignore possiblyImpure.new */
return new Time($splitTime['sec'], $splitTime['usec']);
}
@@ -121,6 +125,8 @@ class PhpTimeConverter implements TimeConverterInterface
* @param float | int $time The time to split into seconds and microseconds
*
* @return string[]
*
* @pure
*/
private function splitTime(float | int $time): array
{
+17 -4
View File
@@ -42,23 +42,35 @@ class UnixTimeConverter implements TimeConverterInterface
public function calculateTime(string $seconds, string $microseconds): Hexadecimal
{
/** @phpstan-ignore possiblyImpure.new */
$timestamp = new Time($seconds, $microseconds);
// Convert the seconds into milliseconds.
$sec = $this->calculator->multiply($timestamp->getSeconds(), new IntegerObject(self::MILLISECONDS));
$sec = $this->calculator->multiply(
$timestamp->getSeconds(),
new IntegerObject(self::MILLISECONDS) /** @phpstan-ignore possiblyImpure.new */
);
// Convert the microseconds into milliseconds; the scale is zero because we need to discard the fractional part.
$usec = $this->calculator->divide(
RoundingMode::DOWN, // Always round down to stay in the previous millisecond.
0,
$timestamp->getMicroseconds(),
new IntegerObject(self::MILLISECONDS),
new IntegerObject(self::MILLISECONDS), /** @phpstan-ignore possiblyImpure.new */
);
/** @var IntegerObject $unixTime */
$unixTime = $this->calculator->add($sec, $usec);
return new Hexadecimal(str_pad($this->calculator->toHexadecimal($unixTime)->toString(), 12, '0', STR_PAD_LEFT));
/** @phpstan-ignore possiblyImpure.new */
return new Hexadecimal(
str_pad(
$this->calculator->toHexadecimal($unixTime)->toString(),
12,
'0',
STR_PAD_LEFT
)
);
}
public function convertTime(Hexadecimal $uuidTimestamp): Time
@@ -69,11 +81,12 @@ class UnixTimeConverter implements TimeConverterInterface
RoundingMode::HALF_UP,
6,
$milliseconds,
new IntegerObject(self::MILLISECONDS),
new IntegerObject(self::MILLISECONDS), /** @phpstan-ignore possiblyImpure.new */
);
$split = explode('.', (string) $unixTimestamp, 2);
/** @phpstan-ignore possiblyImpure.new */
return new Time($split[0], $split[1] ?? '0');
}
}
+2
View File
@@ -26,6 +26,8 @@ interface FieldsInterface extends Serializable
{
/**
* Returns the bytes that comprise the fields
*
* @pure
*/
public function getBytes(): string;
}
+3 -2
View File
@@ -35,13 +35,14 @@ class PeclUuidNameGenerator implements NameGeneratorInterface
public function generate(UuidInterface $ns, string $name, string $hashAlgorithm): string
{
$uuid = match ($hashAlgorithm) {
'md5' => uuid_generate_md5($ns->toString(), $name),
'sha1' => uuid_generate_sha1($ns->toString(), $name),
'md5' => uuid_generate_md5($ns->toString(), $name), /** @phpstan-ignore possiblyImpure.functionCall */
'sha1' => uuid_generate_sha1($ns->toString(), $name), /** @phpstan-ignore possiblyImpure.functionCall */
default => throw new NameException(
sprintf('Unable to hash namespace and name with algorithm \'%s\'', $hashAlgorithm),
),
};
/** @phpstan-ignore possiblyImpure.functionCall */
return (string) uuid_parse($uuid);
}
}
+5
View File
@@ -55,17 +55,22 @@ class GuidBuilder implements UuidBuilderInterface
public function build(CodecInterface $codec, string $bytes): UuidInterface
{
try {
/** @phpstan-ignore possiblyImpure.new */
return new Guid($this->buildFields($bytes), $this->numberConverter, $codec, $this->timeConverter);
} catch (Throwable $e) {
/** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e);
}
}
/**
* Proxy method to allow injecting a mock for testing
*
* @pure
*/
protected function buildFields(string $bytes): Fields
{
/** @phpstan-ignore possiblyImpure.new */
return new Fields($bytes);
}
}
+2 -4
View File
@@ -61,9 +61,6 @@ final class LazyUuidFromString implements UuidInterface
{
}
/**
* @pure
*/
public static function fromBytes(string $bytes): self
{
$base16Uuid = bin2hex($bytes);
@@ -217,7 +214,8 @@ final class LazyUuidFromString implements UuidInterface
public function getBytes(): string
{
/** @var non-empty-string */
/** @var non-empty-string
* @phpstan-ignore-next-line Avoiding pure function complaints */
return (string) hex2bin(str_replace('-', '', $this->uuid));
}
+13 -2
View File
@@ -49,9 +49,10 @@ final class BrickMathCalculator implements CalculatorInterface
$sum = BigInteger::of($augend->toString());
foreach ($addends as $addend) {
$sum = $sum->plus($addend->toString());
$sum = $sum->plus($addend->toString()); /** @phpstan-ignore possiblyImpure.methodCall */
}
/** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.new */
return new IntegerObject((string) $sum);
}
@@ -60,9 +61,10 @@ final class BrickMathCalculator implements CalculatorInterface
$difference = BigInteger::of($minuend->toString());
foreach ($subtrahends as $subtrahend) {
$difference = $difference->minus($subtrahend->toString());
$difference = $difference->minus($subtrahend->toString()); /** @phpstan-ignore possiblyImpure.methodCall */
}
/** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.new */
return new IntegerObject((string) $difference);
}
@@ -71,9 +73,11 @@ final class BrickMathCalculator implements CalculatorInterface
$product = BigInteger::of($multiplicand->toString());
foreach ($multipliers as $multiplier) {
/** @phpstan-ignore possiblyImpure.methodCall */
$product = $product->multipliedBy($multiplier->toString());
}
/** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.new */
return new IntegerObject((string) $product);
}
@@ -83,24 +87,29 @@ final class BrickMathCalculator implements CalculatorInterface
NumberInterface $dividend,
NumberInterface ...$divisors,
): NumberInterface {
/** @phpstan-ignore possiblyImpure.methodCall */
$brickRounding = $this->getBrickRoundingMode($roundingMode);
$quotient = BigDecimal::of($dividend->toString());
foreach ($divisors as $divisor) {
/** @phpstan-ignore possiblyImpure.methodCall */
$quotient = $quotient->dividedBy($divisor->toString(), $scale, $brickRounding);
}
if ($scale === 0) {
/** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall, possiblyImpure.new */
return new IntegerObject((string) $quotient->toBigInteger());
}
/** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.new */
return new Decimal((string) $quotient);
}
public function fromBase(string $value, int $base): IntegerObject
{
try {
/** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.new */
return new IntegerObject((string) BigInteger::fromBase($value, $base));
} catch (MathException | \InvalidArgumentException $exception) {
throw new InvalidArgumentException(
@@ -114,6 +123,7 @@ final class BrickMathCalculator implements CalculatorInterface
public function toBase(IntegerObject $value, int $base): string
{
try {
/** @phpstan-ignore possiblyImpure.methodCall */
return BigInteger::of($value->toString())->toBase($base);
} catch (MathException | \InvalidArgumentException $exception) {
throw new InvalidArgumentException(
@@ -126,6 +136,7 @@ final class BrickMathCalculator implements CalculatorInterface
public function toHexadecimal(IntegerObject $value): Hexadecimal
{
/** @phpstan-ignore possiblyImpure.new */
return new Hexadecimal($this->toBase($value, 16));
}
+16
View File
@@ -32,6 +32,8 @@ interface CalculatorInterface
* @param NumberInterface ...$addends The additional integers to a add to the augend
*
* @return NumberInterface The sum of all the parameters
*
* @pure
*/
public function add(NumberInterface $augend, NumberInterface ...$addends): NumberInterface;
@@ -42,6 +44,8 @@ interface CalculatorInterface
* @param NumberInterface ...$subtrahends The integers to subtract from the minuend
*
* @return NumberInterface The difference after subtracting all parameters
*
* @pure
*/
public function subtract(NumberInterface $minuend, NumberInterface ...$subtrahends): NumberInterface;
@@ -52,6 +56,8 @@ interface CalculatorInterface
* @param NumberInterface ...$multipliers The factors by which to multiply the multiplicand
*
* @return NumberInterface The product of multiplying all the provided parameters
*
* @pure
*/
public function multiply(NumberInterface $multiplicand, NumberInterface ...$multipliers): NumberInterface;
@@ -65,6 +71,8 @@ interface CalculatorInterface
* operations should take place (left-to-right)
*
* @return NumberInterface The quotient of dividing the provided parameters left-to-right
*
* @pure
*/
public function divide(
int $roundingMode,
@@ -80,6 +88,8 @@ interface CalculatorInterface
* @param int $base The base to convert from (i.e., 2, 16, 32, etc.)
*
* @return IntegerObject The base-10 integer value of the converted value
*
* @pure
*/
public function fromBase(string $value, int $base): IntegerObject;
@@ -90,16 +100,22 @@ interface CalculatorInterface
* @param int $base The base to convert to (i.e., 2, 16, 32, etc.)
*
* @return string The value represented in the specified base
*
* @pure
*/
public function toBase(IntegerObject $value, int $base): string;
/**
* Converts an Integer instance to a Hexadecimal instance
*
* @pure
*/
public function toHexadecimal(IntegerObject $value): Hexadecimal;
/**
* Converts a Hexadecimal instance to an Integer instance
*
* @pure
*/
public function toInteger(Hexadecimal $value): IntegerObject;
}
+1
View File
@@ -23,6 +23,7 @@ use Ramsey\Uuid\Uuid as BaseUuid;
* Nonstandard\Uuid is a UUID that doesn't conform to RFC 9562 (formerly RFC 4122)
*
* @immutable
* @pure
*/
final class Uuid extends BaseUuid
{
+5
View File
@@ -53,17 +53,22 @@ class UuidBuilder implements UuidBuilderInterface
public function build(CodecInterface $codec, string $bytes): UuidInterface
{
try {
/** @phpstan-ignore possiblyImpure.new */
return new Uuid($this->buildFields($bytes), $this->numberConverter, $codec, $this->timeConverter);
} catch (Throwable $e) {
/** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e);
}
}
/**
* Proxy method to allow injecting a mock for testing
*
* @pure
*/
protected function buildFields(string $bytes): Fields
{
/** @phpstan-ignore possiblyImpure.new */
return new Fields($bytes);
}
}
+3
View File
@@ -73,6 +73,9 @@ final class Fields implements FieldsInterface
}
}
/**
* @pure
*/
public function getBytes(): string
{
return $this->bytes;
+4
View File
@@ -114,6 +114,8 @@ interface FieldsInterface extends BaseFieldsInterface
* meaningful for this variant.
*
* @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
*
* @pure
*/
public function getVersion(): ?int;
@@ -121,6 +123,8 @@ interface FieldsInterface extends BaseFieldsInterface
* Returns true if these fields represent a nil UUID
*
* The nil UUID is a special form of UUID that is specified to have all 128 bits set to zero.
*
* @pure
*/
public function isNil(): bool;
}
+4
View File
@@ -23,11 +23,15 @@ trait MaxTrait
{
/**
* Returns the bytes that comprise the fields
*
* @pure
*/
abstract public function getBytes(): string;
/**
* Returns true if the byte string represents a max UUID
*
* @pure
*/
public function isMax(): bool
{
+2
View File
@@ -23,6 +23,8 @@ trait NilTrait
{
/**
* Returns the bytes that comprise the fields
*
* @pure
*/
abstract public function getBytes(): string;
+14
View File
@@ -70,39 +70,53 @@ class UuidBuilder implements UuidBuilderInterface
$fields = $this->buildFields($bytes);
if ($fields->isNil()) {
/** @phpstan-ignore possiblyImpure.new */
return new NilUuid($fields, $this->numberConverter, $codec, $this->timeConverter);
}
if ($fields->isMax()) {
/** @phpstan-ignore possiblyImpure.new */
return new MaxUuid($fields, $this->numberConverter, $codec, $this->timeConverter);
}
return match ($fields->getVersion()) {
/** @phpstan-ignore possiblyImpure.new */
Uuid::UUID_TYPE_TIME => new UuidV1($fields, $this->numberConverter, $codec, $this->timeConverter),
Uuid::UUID_TYPE_DCE_SECURITY
/** @phpstan-ignore possiblyImpure.new */
=> new UuidV2($fields, $this->numberConverter, $codec, $this->timeConverter),
/** @phpstan-ignore possiblyImpure.new */
Uuid::UUID_TYPE_HASH_MD5 => new UuidV3($fields, $this->numberConverter, $codec, $this->timeConverter),
/** @phpstan-ignore possiblyImpure.new */
Uuid::UUID_TYPE_RANDOM => new UuidV4($fields, $this->numberConverter, $codec, $this->timeConverter),
/** @phpstan-ignore possiblyImpure.new */
Uuid::UUID_TYPE_HASH_SHA1 => new UuidV5($fields, $this->numberConverter, $codec, $this->timeConverter),
Uuid::UUID_TYPE_REORDERED_TIME
/** @phpstan-ignore possiblyImpure.new */
=> new UuidV6($fields, $this->numberConverter, $codec, $this->timeConverter),
Uuid::UUID_TYPE_UNIX_TIME
/** @phpstan-ignore possiblyImpure.new */
=> new UuidV7($fields, $this->numberConverter, $codec, $this->unixTimeConverter),
/** @phpstan-ignore possiblyImpure.new */
Uuid::UUID_TYPE_CUSTOM => new UuidV8($fields, $this->numberConverter, $codec, $this->timeConverter),
default => throw new UnsupportedOperationException(
'The UUID version in the given fields is not supported by this UUID builder',
),
};
} catch (Throwable $e) {
/** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
throw new UnableToBuildUuidException($e->getMessage(), (int) $e->getCode(), $e);
}
}
/**
* Proxy method to allow injecting a mock for testing
*
* @pure
*/
protected function buildFields(string $bytes): FieldsInterface
{
/** @phpstan-ignore possiblyImpure.new */
return new Fields($bytes);
}
}
+2
View File
@@ -40,8 +40,10 @@ final class Validator implements ValidatorInterface
public function validate(string $uuid): bool
{
/** @phpstan-ignore possiblyImpure.functionCall */
$uuid = strtolower(str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid));
/** @phpstan-ignore possiblyImpure.functionCall */
return $uuid === Uuid::NIL || $uuid === Uuid::MAX || preg_match('/' . self::VALID_PATTERN . '/Dms', $uuid);
}
}
+2
View File
@@ -41,6 +41,8 @@ trait VersionTrait
* meaningful for this variant.
*
* @link https://www.rfc-editor.org/rfc/rfc9562#section-4.2 RFC 9562, 4.2. Version Field
*
* @pure
*/
abstract public function getVersion(): ?int;
+2
View File
@@ -46,6 +46,8 @@ final class Hexadecimal implements TypeInterface
/**
* @return non-empty-string
*
* @pure
*/
public function toString(): string
{
+2
View File
@@ -58,6 +58,8 @@ final class Integer implements NumberInterface
/**
* @return numeric-string
*
* @pure
*/
public function toString(): string
{
+6
View File
@@ -43,11 +43,17 @@ final class Time implements TypeInterface
$this->microseconds = new IntegerObject($microseconds);
}
/**
* @pure
*/
public function getSeconds(): IntegerObject
{
return $this->seconds;
}
/**
* @pure
*/
public function getMicroseconds(): IntegerObject
{
return $this->microseconds;
+6
View File
@@ -24,7 +24,13 @@ use Serializable;
*/
interface TypeInterface extends JsonSerializable, Serializable
{
/**
* @pure
*/
public function toString(): string;
/**
* @pure
*/
public function __toString(): string;
}
+16 -1
View File
@@ -453,6 +453,7 @@ class Uuid implements UuidInterface
*/
public static function fromBytes(string $bytes): UuidInterface
{
/** @phpstan-ignore impure.staticPropertyAccess */
if (!self::$factoryReplaced && strlen($bytes) === 16) {
$base16Uuid = bin2hex($bytes);
@@ -470,6 +471,7 @@ class Uuid implements UuidInterface
);
}
/** @phpstan-ignore possiblyImpure.methodCall */
return self::getFactory()->fromBytes($bytes);
}
@@ -487,12 +489,16 @@ class Uuid implements UuidInterface
public static function fromString(string $uuid): UuidInterface
{
$uuid = strtolower($uuid);
/** @phpstan-ignore impure.staticPropertyAccess, possiblyImpure.functionCall */
if (!self::$factoryReplaced && preg_match(LazyUuidFromString::VALID_REGEX, $uuid) === 1) {
/** @phpstan-ignore possiblyImpure.functionCall */
assert($uuid !== '');
/** @phpstan-ignore possiblyImpure.new */
return new LazyUuidFromString($uuid);
}
/** @phpstan-ignore possiblyImpure.methodCall */
return self::getFactory()->fromString($uuid);
}
@@ -527,10 +533,13 @@ class Uuid implements UuidInterface
*/
public static function fromHexadecimal(Hexadecimal $hex): UuidInterface
{
/** @phpstan-ignore possiblyImpure.methodCall */
$factory = self::getFactory();
if (method_exists($factory, 'fromHexadecimal')) {
/** @phpstan-ignore possiblyImpure.methodCall */
$uuid = $factory->fromHexadecimal($hex);
/** @phpstan-ignore possiblyImpure.functionCall */
assert($uuid instanceof UuidInterface);
return $uuid;
@@ -552,6 +561,7 @@ class Uuid implements UuidInterface
*/
public static function fromInteger(string $integer): UuidInterface
{
/** @phpstan-ignore possiblyImpure.methodCall */
return self::getFactory()->fromInteger($integer);
}
@@ -568,6 +578,7 @@ class Uuid implements UuidInterface
*/
public static function isValid(string $uuid): bool
{
/** @phpstan-ignore possiblyImpure.methodCall, possiblyImpure.methodCall */
return self::getFactory()->getValidator()->validate($uuid);
}
@@ -621,6 +632,7 @@ class Uuid implements UuidInterface
*/
public static function uuid3($ns, string $name): UuidInterface
{
/** @phpstan-ignore possiblyImpure.methodCall */
return self::getFactory()->uuid3($ns, $name);
}
@@ -646,6 +658,7 @@ class Uuid implements UuidInterface
*/
public static function uuid5($ns, string $name): UuidInterface
{
/** @phpstan-ignore possiblyImpure.methodCall */
return self::getFactory()->uuid5($ns, $name);
}
@@ -701,10 +714,12 @@ class Uuid implements UuidInterface
*/
public static function uuid8(string $bytes): UuidInterface
{
/** @phpstan-ignore possiblyImpure.methodCall */
$factory = self::getFactory();
if (method_exists($factory, 'uuid8')) {
/** @var UuidInterface */
/** @var UuidInterface
* @phpstan-ignore possiblyImpure.methodCall */
return $factory->uuid8($bytes);
}
+2
View File
@@ -396,6 +396,7 @@ class UuidFactory implements UuidFactoryInterface
*/
public function uuid8(string $bytes): UuidInterface
{
/** @phpstan-ignore possiblyImpure.methodCall */
return $this->uuidFromBytesAndVersion($bytes, Uuid::UUID_TYPE_CUSTOM);
}
@@ -439,6 +440,7 @@ class UuidFactory implements UuidFactoryInterface
$bytes = $this->nameGenerator->generate($ns, $name, $hashAlgorithm);
/** @phpstan-ignore possiblyImpure.methodCall */
return $this->uuidFromBytesAndVersion(substr($bytes, 0, 16), $version);
}
+6
View File
@@ -60,6 +60,8 @@ interface UuidInterface extends
* Returns the binary string representation of the UUID
*
* @return non-empty-string
*
* @pure
*/
public function getBytes(): string;
@@ -92,6 +94,8 @@ interface UuidInterface extends
* Returns the string standard representation of the UUID
*
* @return non-empty-string
*
* @pure
*/
public function toString(): string;
@@ -99,6 +103,8 @@ interface UuidInterface extends
* Casts the UUID to the string standard representation
*
* @return non-empty-string
*
* @pure
*/
public function __toString(): string;
}
+2
View File
@@ -41,8 +41,10 @@ final class GenericValidator implements ValidatorInterface
public function validate(string $uuid): bool
{
/** @phpstan-ignore possiblyImpure.functionCall */
$uuid = str_replace(['urn:', 'uuid:', 'URN:', 'UUID:', '{', '}'], '', $uuid);
/** @phpstan-ignore possiblyImpure.functionCall */
return $uuid === Uuid::NIL || preg_match('/' . self::VALID_PATTERN . '/Dms', $uuid);
}
}
+2
View File
@@ -34,6 +34,8 @@ interface ValidatorInterface
* @param string $uuid The string to validate as a UUID
*
* @return bool True if the string is a valid UUID, false otherwise
*
* @pure
*/
public function validate(string $uuid): bool;
}
+1
View File
@@ -58,6 +58,7 @@ class FallbackBuilderTest extends TestCase
'Could not find a suitable builder for the provided codec and fields'
);
/** @phpstan-ignore method.resultUnused */
$fallbackBuilder->build($codec, $bytes);
}
+1
View File
@@ -56,6 +56,7 @@ class GuidStringCodecTest extends TestCase
->method('getFields')
->willReturn($this->fields);
$codec = new GuidStringCodec($this->builder);
/** @phpstan-ignore method.resultUnused */
$codec->encode($this->uuid);
}
+3
View File
@@ -77,6 +77,7 @@ class OrderedTimeCodecTest extends TestCase
->method('getFields')
->willReturn($this->fields);
$codec = new OrderedTimeCodec($this->builder);
/** @phpstan-ignore method.resultUnused */
$codec->encode($this->uuid);
}
@@ -165,6 +166,7 @@ class OrderedTimeCodecTest extends TestCase
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Expected version 1 (time-based) UUID');
/** @phpstan-ignore method.resultUnused */
$codec->encodeBinary($uuid);
}
@@ -185,6 +187,7 @@ class OrderedTimeCodecTest extends TestCase
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Expected version 1 (time-based) UUID');
/** @phpstan-ignore method.resultUnused */
$codec->encodeBinary($uuid);
}
+2
View File
@@ -60,6 +60,7 @@ class StringCodecTest extends TestCase
->method('getFields')
->willReturn($this->fields);
$codec = new StringCodec($this->builder);
/** @phpstan-ignore method.resultUnused */
$codec->encode($this->uuid);
}
@@ -135,6 +136,7 @@ class StringCodecTest extends TestCase
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('$bytes string should contain 16 characters.');
/** @phpstan-ignore method.resultUnused */
$codec->decodeBytes($bytes);
}
@@ -17,6 +17,7 @@ class BigNumberConverterTest extends TestCase
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('"." is not a valid character in base 16');
/** @phpstan-ignore method.resultUnused */
$converter->fromHex('123.34');
}
@@ -30,6 +31,7 @@ class BigNumberConverterTest extends TestCase
. '0-9 and, optionally, a sign (+ or -)'
);
/** @phpstan-ignore method.resultUnused */
$converter->toHex('123.34');
}
@@ -56,6 +56,7 @@ class BigNumberTimeConverterTest extends TestCase
. '0-9 and, optionally, a sign (+ or -)'
);
/** @phpstan-ignore method.resultUnused */
$converter->calculateTime('12.34', '5678');
}
@@ -69,6 +70,7 @@ class BigNumberTimeConverterTest extends TestCase
. '0-9 and, optionally, a sign (+ or -)'
);
/** @phpstan-ignore method.resultUnused */
$converter->calculateTime('1234', '56.78');
}
}
@@ -52,6 +52,7 @@ class PhpTimeConverterTest extends TestCase
. '0-9 and, optionally, a sign (+ or -)'
);
/** @phpstan-ignore method.resultUnused */
$converter->calculateTime('12.34', '5678');
}
@@ -66,6 +67,7 @@ class PhpTimeConverterTest extends TestCase
. '0-9 and, optionally, a sign (+ or -)'
);
/** @phpstan-ignore method.resultUnused */
$converter->calculateTime('1234', '56.78');
}
@@ -75,6 +75,7 @@ class TimestampFirstCombCodecTest extends TestCase
'node' => '0800200c9a66',
]))
);
/** @phpstan-ignore method.resultUnused */
$this->codec->decode('0800200c-9a66-11e1-9b21-ff6f8cb0c57d');
}
@@ -78,6 +78,7 @@ class TimestampLastCombCodecTest extends TestCase
'node' => 'ff6f8cb0c57d',
]))
);
/** @phpstan-ignore method.resultUnused */
$this->codec->decode('0800200c-9a66-11e1-9b21-ff6f8cb0c57d');
}
@@ -79,6 +79,7 @@ class DefaultNameGeneratorTest extends TestCase
'Unable to hash namespace and name with algorithm \'aBadAlgorithm\''
);
/** @phpstan-ignore method.resultUnused */
$generator->generate($namespace, 'a test name', 'aBadAlgorithm');
}
}
@@ -99,6 +99,7 @@ class PeclUuidNameGeneratorTest extends TestCase
'Unable to hash namespace and name with algorithm \'aBadAlgorithm\''
);
/** @phpstan-ignore method.resultUnused */
$generator->generate($namespace, 'a test name', 'aBadAlgorithm');
}
}
+1
View File
@@ -28,6 +28,7 @@ class GuidBuilderTest extends TestCase
$this->expectException(UnableToBuildUuidException::class);
$this->expectExceptionMessage('exception thrown');
/** @phpstan-ignore method.resultUnused */
$builder->build($codec, 'foobar');
}
}
+1
View File
@@ -98,6 +98,7 @@ class BrickMathCalculatorTest extends TestCase
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('"o" is not a valid character in base 16');
/** @phpstan-ignore method.resultUnused */
$calculator->fromBase('foobar', 16);
}
+1
View File
@@ -28,6 +28,7 @@ class UuidBuilderTest extends TestCase
$this->expectException(UnableToBuildUuidException::class);
$this->expectExceptionMessage('exception thrown');
/** @phpstan-ignore method.resultUnused */
$builder->build($codec, 'foobar');
}
}
+2
View File
@@ -140,6 +140,7 @@ class UuidBuilderTest extends TestCase
'The byte string must be 16 bytes long; received 15 bytes'
);
/** @phpstan-ignore method.resultUnused */
$builder->build($codec, $bytes);
}
@@ -163,6 +164,7 @@ class UuidBuilderTest extends TestCase
'The UUID version in the given fields is not supported by this UUID builder'
);
/** @phpstan-ignore method.resultUnused */
$builder->build($codec, 'foobar');
}
}
+3
View File
@@ -861,6 +861,7 @@ class UuidTest extends TestCase
$this->expectException(UnsupportedOperationException::class);
$this->expectExceptionMessage('The provided factory does not support the uuid8() method');
/** @phpstan-ignore staticMethod.resultUnused */
Uuid::uuid8("\x00\x11\x22\x33\x44\x55\x66\x77\x88\x99\xaa\xbb\xcc\xdd\xee\xff");
}
@@ -1743,6 +1744,7 @@ class UuidTest extends TestCase
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Invalid UUID string:');
/** @phpstan-ignore staticMethod.resultUnused */
Uuid::uuid3('', '');
}
@@ -1765,6 +1767,7 @@ class UuidTest extends TestCase
$this->expectException(InvalidArgumentException::class);
$this->expectExceptionMessage('Invalid UUID string:');
/** @phpstan-ignore staticMethod.resultUnused */
Uuid::uuid5('', '');
}
+1
View File
@@ -38,6 +38,7 @@ final class GuidConversionBench
public function benchStringConversionOfGuid(): void
{
/** @phpstan-ignore method.resultUnused */
$this->uuid->toString();
}
}
@@ -34,6 +34,7 @@ final class NonLazyUuidConversionBench
public function benchStringConversionOfUuid(): void
{
/** @phpstan-ignore method.resultUnused */
$this->uuid->toString();
}
}
+2
View File
@@ -73,6 +73,7 @@ final class UuidGenerationBench
public function benchUuid3Generation(): void
{
/** @phpstan-ignore staticMethod.resultUnused */
Uuid::uuid3($this->namespace, 'name');
}
@@ -83,6 +84,7 @@ final class UuidGenerationBench
public function benchUuid5Generation(): void
{
/** @phpstan-ignore staticMethod.resultUnused */
Uuid::uuid5($this->namespace, 'name');
}
@@ -208,16 +208,19 @@ final class UuidStringConversionBench
public function benchStringConversionOfTinyUuid(): void
{
/** @phpstan-ignore method.resultUnused */
$this->tinyUuid->toString();
}
public function benchStringConversionOfHugeUuid(): void
{
/** @phpstan-ignore method.resultUnused */
$this->hugeUuid->toString();
}
public function benchStringConversionOfUuid(): void
{
/** @phpstan-ignore method.resultUnused */
$this->uuid->toString();
}
@@ -230,16 +233,19 @@ final class UuidStringConversionBench
public function benchBytesConversionOfTinyUuid(): void
{
/** @phpstan-ignore method.resultUnused */
$this->tinyUuid->getBytes();
}
public function benchBytesConversionOfHugeUuid(): void
{
/** @phpstan-ignore method.resultUnused */
$this->hugeUuid->getBytes();
}
public function benchBytesConversionOfUuid(): void
{
/** @phpstan-ignore method.resultUnused */
$this->uuid->getBytes();
}