packages/sql-semantics/tests/Unit/Core/Analysis/TriviaReaderTest.php

1<?php
2
3declare(strict_types=1);
4
5namespace Tests\Unit\Core\Analysis;
6
7use PHPUnit\Framework\Attributes\CoversClass;
8use PHPUnit\Framework\Attributes\Small;
9use PHPUnit\Framework\Attributes\UsesClass;
10use PHPUnit\Framework\TestCase;
11use SqlParser\Lexer\Token;
12use SqlParser\Parser\Node;
13use SqlSemantics\Core\Analysis\SourceComments;
14use SqlSemantics\Core\Analysis\TriviaReader;
15
16#[CoversClass(TriviaReader::class)]
17#[UsesClass(SourceComments::class)]
18#[Small]
19final class TriviaReaderTest extends TestCase
20{
21    public function testReadSeparatesLeadingTrailingAndTokenCommentsAndSkipsTokensThatSpellNothing(): void
22    {
23        $select = new Token(1, 'SELECT', 'SELECT', 11, '/* lead */ ');
24        $one = new Token(2, 'NUM', '1', 26, ' /* value */ ');
25        $end = new Token(0, 'END_OF_INPUT', '', 33, " -- after\n");
26        $tree = new Node('root', 0, [new Node('stmt', 0, [$select, new Node('expr', 0, [$one])]), $end], "-- more\n");
27        $comments = (new TriviaReader())->read($tree);
28        self::assertSame(['/* lead */'], $comments->leading);
29        self::assertSame(['/* value */'], $comments->before($one));
30        self::assertSame([], $comments->before($select));
31        self::assertSame([], $comments->before($end));
32        self::assertSame(['-- after', '-- more'], $comments->trailing);
33    }
34
35    public function testReadStartsEachTreeOutsideAnExecutableComment(): void
36    {
37        $reader = new TriviaReader(executableVersion: 80000);
38        $opened = new Node('root', 0, [new Token(1, 'SELECT', 'SELECT', 0), new Token(2, 'NUM', '1', 16, ' /*!50700 ')]);
39        $reader->read($opened);
40        $plain = new Node('root', 0, [new Token(1, 'SELECT', 'SELECT', 0), new Token(2, 'NUM', '1', 14, ' /* a */ ')]);
41        self::assertSame(['/* a */'], $reader->read($plain)->before($plain->tokens()[1]));
42    }
43
44    public function testCommentsSplitsBlockAndLineCommentsWithoutTheirWhitespace(): void
45    {
46        $reader = new TriviaReader();
47        self::assertSame([], $reader->comments(''));
48        self::assertSame([], $reader->comments(" \n\t"));
49        self::assertSame(['/* a */', '-- b', '#c', '/* d'], $reader->comments("  /* a */\n-- b \r\n#c\n /* d"));
50        self::assertSame(['/* a /* b */'], $reader->comments('/* a /* b */'));
51    }
52
53    public function testCommentsNestsBlockCommentsWhenTheLanguageDoes(): void
54    {
55        self::assertSame(['/* a /* b */ c */', '-- d'], (new TriviaReader(nestedBlocks: true))->comments("/* a /* b */ c */ -- d\n"));
56    }
57
58    public function testCommentsKeepsExecutableCommentDelimitersApartAndOrdinaryVersionCommentsWhole(): void
59    {
60        $reader = new TriviaReader(executableVersion: 80000);
61        self::assertSame(['/*!50700'], $reader->comments(' /*!50700 '));
62        self::assertSame(['/* inner */', '*/'], $reader->comments(' /* inner */ */ '));
63        self::assertSame(['/*!99999 skipped */', '/*!'], $reader->comments(' /*!99999 skipped */ /*! '));
64        self::assertSame(['*/'], $reader->comments(' */ '));
65        self::assertSame(['/* a /*! b */ c */'], $reader->comments('/* a /*! b */ c */'));
66    }
67
68
69    public function testCommentEndFindsTheEndOfEachCommentKind(): void
70    {
71        $reader = new TriviaReader();
72        self::assertSame(4, $reader->commentEnd("-- a\nb", 0));
73        self::assertSame(2, $reader->commentEnd('#a', 0));
74        self::assertSame(8, $reader->commentEnd(' /* a */ ', 1));
75    }
76
77    public function testBlockEndStepsOverPairsOnlyInLanguagesWithExecutableComments(): void
78    {
79        self::assertSame(5, (new TriviaReader())->blockEnd('/*/*/ x */', 0));
80        self::assertSame(10, (new TriviaReader(executableVersion: 80000))->blockEnd('/*/*/ x */', 0));
81        self::assertSame(10, (new TriviaReader(nestedBlocks: true))->blockEnd('/* /* */*/', 0));
82        self::assertSame(7, (new TriviaReader())->blockEnd('/* open', 0));
83    }
84}
85