Browse Source

fix: Tokens::overrideRange() block cache pruning (#8240)

Michael Voříšek 4 months ago
parent
commit
c982d2c7e0
2 changed files with 39 additions and 7 deletions
  1. 9 7
      src/Tokenizer/Tokens.php
  2. 30 0
      tests/Tokenizer/TokensTest.php

+ 9 - 7
src/Tokenizer/Tokens.php

@@ -351,15 +351,17 @@ class Tokens extends \SplFixedArray
             )));
         }
 
+        if (isset($this[$index])) {
+            if (isset($this->blockStartCache[$index])) {
+                unset($this->blockEndCache[$this->blockStartCache[$index]], $this->blockStartCache[$index]);
+            }
+            if (isset($this->blockEndCache[$index])) {
+                unset($this->blockStartCache[$this->blockEndCache[$index]], $this->blockEndCache[$index]);
+            }
+        }
+
         if (!isset($this[$index]) || !$this[$index]->equals($newval)) {
             if (isset($this[$index])) {
-                if (isset($this->blockStartCache[$index])) {
-                    unset($this->blockEndCache[$this->blockStartCache[$index]], $this->blockStartCache[$index]);
-                }
-                if (isset($this->blockEndCache[$index])) {
-                    unset($this->blockStartCache[$this->blockEndCache[$index]], $this->blockEndCache[$index]);
-                }
-
                 $this->unregisterFoundToken($this[$index]);
             }
 

+ 30 - 0
tests/Tokenizer/TokensTest.php

@@ -1776,6 +1776,36 @@ $bar;',
         $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, 5);
     }
 
+    public function testBlockEdgeCachingOffsetSetPruneEvenIfTokenEquals(): void
+    {
+        $tokens = Tokens::fromArray([
+            new Token([T_OPEN_TAG, '<?php ']),
+            new Token([T_VARIABLE, '$a']),
+            new Token('='),
+            new Token([T_WHITESPACE, ' ']),
+            new Token([CT::T_ARRAY_SQUARE_BRACE_OPEN, '[']),
+            new Token([T_WHITESPACE, ' ']),
+            new Token([CT::T_ARRAY_SQUARE_BRACE_CLOSE, ']']),
+            new Token(';'),
+        ]);
+
+        self::assertSame(6, $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, 4));
+        self::assertSame(4, $tokens->findBlockStart(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, 6));
+
+        $tokens->overrideRange(3, 6, [
+            new Token([CT::T_ARRAY_SQUARE_BRACE_OPEN, '[']),
+            $tokens[4],
+            new Token([CT::T_ARRAY_SQUARE_BRACE_CLOSE, ']']),
+            $tokens[6],
+        ]);
+
+        self::assertSame(5, $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, 4));
+        self::assertSame(4, $tokens->findBlockStart(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, 5));
+
+        self::assertSame(6, $tokens->findBlockEnd(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, 3));
+        self::assertSame(3, $tokens->findBlockStart(Tokens::BLOCK_TYPE_ARRAY_SQUARE_BRACE, 6));
+    }
+
     public function testBlockEdgeCachingClearAt(): void
     {
         $tokens = $this->getBlockEdgeCachingTestTokens();