From fe308f32cf043315ac765595dfce891cb94ec371 Mon Sep 17 00:00:00 2001 From: Marco Pivetta Date: Sat, 7 Sep 2019 15:11:16 +0200 Subject: [PATCH] Memoizing `DocBlock#requirements()` so that repeated calls do not lead to overhead Parsing requirements on docblocks seems to be repeated multiple times, so we need to prevent this from being performed more than necessary. The regular expressions around this are quite complex, and therefore there is a performance impact (~2% total runtime on an IO-free test suite). --- src/Annotation/DocBlock.php | 24 ++++++++++++++++++++++-- 1 file changed, 22 insertions(+), 2 deletions(-) diff --git a/src/Annotation/DocBlock.php b/src/Annotation/DocBlock.php index 65e1837d10e..e699a18bd43 100644 --- a/src/Annotation/DocBlock.php +++ b/src/Annotation/DocBlock.php @@ -23,7 +23,7 @@ * @internal This class is part of PHPUnit internals, an not intended * for downstream usage * - * @psalm-immutable + * @psalm-mutation-free */ final class DocBlock { @@ -52,6 +52,20 @@ final class DocBlock /** @var array> pre-parsed annotations indexed by name and occurrence index */ private $symbolAnnotations; + /** + * @var array|null + * + * @psalm-var null|(array{ + * __OFFSET: array&array{__FILE: string}, + * setting?: array, + * extension_versions?: array + * }&array< + * string, + * string|array{version: string, operator: string}|array{constraint: string}|array + * >) + */ + private $parsedRequirements; + /** @var int */ private $startLine; @@ -137,9 +151,15 @@ private function __construct( * string, * string|array{version: string, operator: string}|array{constraint: string}|array * > + * + * @throws Warning if the requirements version constraint is not well-formed */ public function requirements(): array { + if ($this->parsedRequirements !== null) { + return $this->parsedRequirements; + } + $offset = $this->startLine; $requires = []; $recordedSettings = []; @@ -212,7 +232,7 @@ public function requirements(): array $offset++; } - return \array_merge( + return $this->parsedRequirements = \array_merge( $requires, ['__OFFSET' => $recordedOffsets], \array_filter([