Browse Source

minor #6250 Tokens - optimize cache clear (SpacePossum)

This PR was merged into the master branch.

Discussion
----------

Tokens - optimize cache clear

replaces https://github.com/FriendsOfPHP/PHP-CS-Fixer/pull/6176

Commits
-------

5800ffccf Tokens - optimize cache clear
SpacePossum 3 years ago
parent
commit
b0a9fcac80
2 changed files with 72 additions and 1 deletions
  1. 6 1
      src/Tokenizer/Tokens.php
  2. 66 0
      tests/Tokenizer/TokensTest.php

+ 6 - 1
src/Tokenizer/Tokens.php

@@ -340,10 +340,15 @@ class Tokens extends \SplFixedArray
 
         for ($count = $index; $index < $limit; ++$index) {
             if (!$this->isEmptyAt($index)) {
-                $this[$count++] = $this[$index]; // @phpstan-ignore-line as we know that index exists
+                // use directly for speed, skip the register of token kinds found etc.
+                parent::offsetSet($count++, $this[$index]);
             }
         }
 
+        // we are moving the tokens, we need to clear the indices Cache
+        $this->blockStartCache = [];
+        $this->blockEndCache = [];
+
         $this->setSize($count);
     }
 

+ 66 - 0
tests/Tokenizer/TokensTest.php

@@ -16,6 +16,7 @@ namespace PhpCsFixer\Tests\Tokenizer;
 
 use PhpCsFixer\Tests\Test\Assert\AssertTokensTrait;
 use PhpCsFixer\Tests\TestCase;
+use PhpCsFixer\Tokenizer\CT;
 use PhpCsFixer\Tokenizer\Token;
 use PhpCsFixer\Tokenizer\Tokens;
 
@@ -1531,6 +1532,71 @@ EOF
         ];
     }
 
+    public function testBlockEdgeCachingOffsetSet(): void
+    {
+        $tokens = $this->getBlockEdgeCachingTestTokens();
+
+        $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, 5);
+        static::assertSame(9, $endIndex);
+
+        $tokens->offsetSet(5, new Token('('));
+        $tokens->offsetSet(9, new Token('('));
+
+        $this->expectException(\InvalidArgumentException::class);
+        $this->expectExceptionMessage('Invalid param $startIndex - not a proper block "start".');
+
+        $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, 5);
+    }
+
+    public function testBlockEdgeCachingClearAt(): void
+    {
+        $tokens = $this->getBlockEdgeCachingTestTokens();
+
+        $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, 5);
+        static::assertSame(9, $endIndex);
+
+        $tokens->clearAt(7); // note: offsetUnset doesn't work here
+        $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, 5);
+        static::assertSame(9, $endIndex);
+
+        $tokens->clearEmptyTokens();
+        $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, 5);
+        static::assertSame(8, $endIndex);
+    }
+
+    public function testBlockEdgeCachingInsertSlices(): void
+    {
+        $tokens = $this->getBlockEdgeCachingTestTokens();
+
+        $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, 5);
+        static::assertSame(9, $endIndex);
+
+        $tokens->insertSlices([6 => [new Token([T_COMMENT, '/* A */'])], new Token([T_COMMENT, '/* B */'])]);
+
+        $endIndex = $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, 5);
+        static::assertSame(11, $endIndex);
+    }
+
+    private function getBlockEdgeCachingTestTokens(): Tokens
+    {
+        Tokens::clearCache();
+
+        return Tokens::fromArray([
+            new Token([T_OPEN_TAG, '<?php ']),
+            new Token([T_VARIABLE, '$a']),
+            new Token([T_WHITESPACE, ' ']),
+            new Token('='),
+            new Token([T_WHITESPACE, ' ']),
+            new Token([CT::T_ARRAY_SQUARE_BRACE_OPEN, '[']),
+            new Token([T_WHITESPACE, ' ']),
+            new Token([T_COMMENT, '/* foo */']),
+            new Token([T_WHITESPACE, ' ']),
+            new Token([CT::T_ARRAY_SQUARE_BRACE_CLOSE, ']']),
+            new Token(';'),
+            new Token([T_WHITESPACE, "\n"]),
+        ]);
+    }
+
     private static function assertFindBlockEnd(int $expectedIndex, string $source, int $type, int $searchIndex): void
     {
         Tokens::clearCache();