Modernize codebase for PHP 8 (#100)

This commit is contained in:
Alexander M. Turek
2024-05-08 10:12:09 +02:00
committed by GitHub
parent 1f855459d4
commit d1ac84aef7
17 changed files with 173 additions and 327 deletions

14
.github/workflows/coding-standards.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
name: "Coding Standards"
on:
pull_request:
branches:
- "*.x"
push:
branches:
- "*.x"
jobs:
coding-standards:
name: "Coding Standards"
uses: "doctrine/.github/.github/workflows/coding-standards.yml@5.0.1"

View File

@@ -1,4 +1,3 @@
name: "Continuous Integration"
on:
@@ -9,125 +8,11 @@ on:
branches:
- "*.x"
env:
fail-fast: true
jobs:
unit-tests:
name: "Unit tests"
runs-on: "ubuntu-20.04"
strategy:
matrix:
php-version:
- "7.2"
- "7.3"
- "7.4"
- "8.0"
- "8.1"
steps:
- name: "Checkout code"
uses: "actions/checkout@v4"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
php-version: "${{ matrix.php-version }}"
tools: "cs2pr"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v3"
with:
dependency-versions: "highest"
- name: "Test fixes"
run: "vendor/bin/phpunit --coverage-text"
static-analysis-phpstan:
name: "Static Analysis with PHPStan"
runs-on: "ubuntu-20.04"
strategy:
matrix:
php-version:
- "7.4"
steps:
- name: "Checkout code"
uses: "actions/checkout@v4"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
php-version: "${{ matrix.php-version }}"
extensions: "mbstring"
tools: "cs2pr"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v3"
with:
dependency-versions: "highest"
- name: "Run a static analysis with phpstan/phpstan"
run: "vendor/bin/phpstan analyse --error-format=checkstyle | cs2pr"
static-analysis-psalm:
name: "Static Analysis with Psalm"
runs-on: "ubuntu-20.04"
strategy:
matrix:
php-version:
- "7.4"
steps:
- name: "Checkout code"
uses: "actions/checkout@v4"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
php-version: "${{ matrix.php-version }}"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v3"
with:
dependency-versions: "highest"
- name: "Run a static analysis with vimeo/psalm"
run: "vendor/bin/psalm --show-info=false --stats --output-format=github --threads=4"
coding-standards:
name: "Coding Standards"
runs-on: "ubuntu-20.04"
strategy:
matrix:
php-version:
- "7.4"
steps:
- name: "Checkout"
uses: "actions/checkout@v4"
- name: "Install PHP"
uses: "shivammathur/setup-php@v2"
with:
coverage: "none"
php-version: "${{ matrix.php-version }}"
tools: "cs2pr"
- name: "Install dependencies with Composer"
uses: "ramsey/composer-install@v3"
with:
dependency-versions: "highest"
# Remove -q when updating to phpcs v4
- name: "Run squizlabs/php_codesniffer"
run: "vendor/bin/phpcs -q --no-colors --report=checkstyle | cs2pr"
phpunit:
name: "PHPUnit"
uses: "doctrine/.github/.github/workflows/continuous-integration.yml@5.0.1"
with:
php-versions: '["8.1", "8.2", "8.3"]'
secrets:
CODECOV_TOKEN: "${{ secrets.CODECOV_TOKEN }}"

14
.github/workflows/static-analysis.yml vendored Normal file
View File

@@ -0,0 +1,14 @@
name: "Static Analysis"
on:
pull_request:
branches:
- "*.x"
push:
branches:
- "*.x"
jobs:
static-analysis:
name: "Static Analysis"
uses: "doctrine/.github/.github/workflows/static-analysis.yml@5.0.1"

4
.gitignore vendored
View File

@@ -1,4 +1,4 @@
/.phpunit.result.cache
/.phpunit.cache
/.phpcs-cache
vendor/
/vendor
/composer.lock

View File

@@ -6,13 +6,13 @@
"license": "MIT",
"type": "library",
"require": {
"php": "^7.2 || ^8.0"
"php": "^8.1"
},
"require-dev": {
"doctrine/coding-standard": "^9.0",
"phpstan/phpstan": "^1.0",
"phpunit/phpunit": "^8.5 || ^9.6",
"vimeo/psalm": "^4.11"
"doctrine/coding-standard": "^12",
"phpstan/phpstan": "^1.10",
"phpunit/phpunit": "^10.5",
"vimeo/psalm": "^5.24"
},
"authors": [
{

View File

@@ -154,7 +154,7 @@ SQL,
Usage:
<pre>
<?php highlight_string(
'<?php' . "\n" . '$formatted = (new SqlFormatter())->format($sql);' . "\n" . '?>'
'<?php' . "\n" . '$formatted = (new SqlFormatter())->format($sql);' . "\n" . '?>',
); ?>
</pre>
</div>
@@ -195,7 +195,7 @@ SQL,
<pre><?= $sql; ?></pre>
</td>
<td><pre><?= htmlentities((new SqlFormatter(
new NullHighlighter()
new NullHighlighter(),
))->format($sql)); ?></pre></td>
</tr>
<?php endforeach ?>
@@ -208,7 +208,7 @@ SQL,
Usage:
<pre>
<?php highlight_string(
'<?php' . "\n" . '$highlighted = (new SqlFormatter())->highlight($sql);' . "\n" . '?>'
'<?php' . "\n" . '$highlighted = (new SqlFormatter())->highlight($sql);' . "\n" . '?>',
); ?>
</pre>
</div>
@@ -234,7 +234,7 @@ SQL,
Usage:
<pre>
<?php highlight_string(
'<?php' . "\n" . '$compressed = (new SqlFormatter())->compress($sql);' . "\n" . '?>'
'<?php' . "\n" . '$compressed = (new SqlFormatter())->compress($sql);' . "\n" . '?>',
); ?>
</pre>
</div>

View File

@@ -7,11 +7,14 @@
<arg name="basepath" value="."/>
<arg name="extensions" value="php"/>
<arg name="parallel" value="80"/>
<arg name="cache" value=".phpcs-cache"/>
<arg name="colors" />
<!-- Show progress of the run -->
<arg value="p"/>
<!-- Ignore warnings, show progress of the run and show sniff names -->
<arg value="nps"/>
<config name="php_version" value="80100"/>
<rule ref="Doctrine"/>
@@ -19,13 +22,6 @@
<file>src</file>
<file>tests</file>
<!-- Disable the rules that will require PHP 7.4 -->
<rule ref="SlevomatCodingStandard.TypeHints.PropertyTypeHint">
<properties>
<property name="enableNativeTypeHint" value="false"/>
</properties>
</rule>
<rule ref="Generic.Files.InlineHTML">
<exclude-pattern>examples/*.php</exclude-pattern>
<exclude-pattern>tests/performance.php</exclude-pattern>

View File

@@ -1,24 +1,24 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.0/phpunit.xsd"
xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/10.5/phpunit.xsd"
bootstrap="vendor/autoload.php"
executionOrder="depends,defects"
forceCoversAnnotation="true"
beStrictAboutCoversAnnotation="true"
beStrictAboutOutputDuringTests="true"
beStrictAboutTodoAnnotatedTests="true"
colors="true"
verbose="true">
cacheDirectory=".phpunit.cache"
requireCoverageMetadata="true"
beStrictAboutCoverageMetadata="true"
>
<testsuites>
<testsuite name="default">
<directory suffix="Test.php">tests</directory>
</testsuite>
</testsuites>
<filter>
<whitelist processUncoveredFilesFromWhitelist="true">
<source>
<include>
<directory suffix=".php">src</directory>
</whitelist>
</filter>
</include>
</source>
</phpunit>

View File

@@ -2,6 +2,8 @@
<psalm
errorLevel="5"
resolveFromConfigFile="true"
findUnusedBaselineEntry="true"
findUnusedCode="false"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="https://getpsalm.org/schema/config"
xsi:schemaLocation="https://getpsalm.org/schema/config vendor/vimeo/psalm/config.xsd"

View File

@@ -13,11 +13,9 @@ final class CliHighlighter implements Highlighter
public const HIGHLIGHT_FUNCTIONS = 'functions';
/** @var array<string, string> */
private $escapeSequences;
private array $escapeSequences;
/**
* @param array<string, string> $escapeSequences
*/
/** @param array<string, string> $escapeSequences */
public function __construct(array $escapeSequences = [])
{
$this->escapeSequences = $escapeSequences + [
@@ -48,7 +46,7 @@ final class CliHighlighter implements Highlighter
return $prefix . $value . "\x1b[0m";
}
private function prefix(int $type): ?string
private function prefix(int $type): string|null
{
if (! isset(self::TOKEN_TYPE_TO_HIGHLIGHT[$type])) {
return null;
@@ -64,7 +62,7 @@ final class CliHighlighter implements Highlighter
PHP_EOL,
$this->escapeSequences[self::HIGHLIGHT_ERROR],
$value,
"\x1b[0m"
"\x1b[0m",
);
}

View File

@@ -6,21 +6,15 @@ namespace Doctrine\SqlFormatter;
final class Cursor
{
/** @var int */
private $position = -1;
private int $position = -1;
/** @var Token[] */
private $tokens;
/**
* @param Token[] $tokens
*/
public function __construct(array $tokens)
{
$this->tokens = $tokens;
/** @param Token[] $tokens */
public function __construct(
private readonly array $tokens,
) {
}
public function next(?int $exceptTokenType = null): ?Token
public function next(int|null $exceptTokenType = null): Token|null
{
while ($token = $this->tokens[++$this->position] ?? null) {
if ($exceptTokenType !== null && $token->isOfType($exceptTokenType)) {
@@ -33,7 +27,7 @@ final class Cursor
return null;
}
public function previous(?int $exceptTokenType = null): ?Token
public function previous(int|null $exceptTokenType = null): Token|null
{
while ($token = $this->tokens[--$this->position] ?? null) {
if ($exceptTokenType !== null && $token->isOfType($exceptTokenType)) {

View File

@@ -16,21 +16,17 @@ final class HtmlHighlighter implements Highlighter
{
public const HIGHLIGHT_PRE = 'pre';
/**
* This flag tells us if queries need to be enclosed in <pre> tags
*
* @var bool
*/
private $usePre;
/** @var array<string, string> */
private $htmlAttributes;
private readonly array $htmlAttributes;
/**
* @param array<string, string> $htmlAttributes
* @param bool $usePre This flag tells us if queries need to be enclosed in <pre> tags
*/
public function __construct(array $htmlAttributes = [], bool $usePre = true)
{
public function __construct(
array $htmlAttributes = [],
private readonly bool $usePre = true,
) {
$this->htmlAttributes = $htmlAttributes + [
self::HIGHLIGHT_QUOTE => 'style="color: blue;"',
self::HIGHLIGHT_BACKTICK_QUOTE => 'style="color: purple;"',
@@ -43,7 +39,6 @@ final class HtmlHighlighter implements Highlighter
self::HIGHLIGHT_VARIABLE => 'style="color: orange;"',
self::HIGHLIGHT_PRE => 'style="color: black; background-color: white;"',
];
$this->usePre = $usePre;
}
public function highlightToken(int $type, string $value): string
@@ -62,7 +57,7 @@ final class HtmlHighlighter implements Highlighter
return '<span ' . $attributes . '>' . $value . '</span>';
}
public function attributes(int $type): ?string
public function attributes(int $type): string|null
{
if (! isset(self::TOKEN_TYPE_TO_HIGHLIGHT[$type])) {
return null;
@@ -77,7 +72,7 @@ final class HtmlHighlighter implements Highlighter
'%s<span %s>%s</span>',
PHP_EOL,
$this->htmlAttributes[self::HIGHLIGHT_ERROR],
$value
$value,
);
}

View File

@@ -28,13 +28,10 @@ use const PHP_SAPI;
final class SqlFormatter
{
/** @var Highlighter */
private $highlighter;
private readonly Highlighter $highlighter;
private readonly Tokenizer $tokenizer;
/** @var Tokenizer */
private $tokenizer;
public function __construct(?Highlighter $highlighter = null)
public function __construct(Highlighter|null $highlighter = null)
{
$this->tokenizer = new Tokenizer();
$this->highlighter = $highlighter ?? (PHP_SAPI === 'cli' ? new CliHighlighter() : new HtmlHighlighter());
@@ -73,7 +70,7 @@ final class SqlFormatter
while ($token = $cursor->next(Token::TOKEN_TYPE_WHITESPACE)) {
$highlighted = $this->highlighter->highlightToken(
$token->type(),
$token->value()
$token->value(),
);
// If we are increasing the special indent level now
@@ -175,7 +172,7 @@ final class SqlFormatter
Token::TOKEN_TYPE_RESERVED_TOPLEVEL,
Token::TOKEN_TYPE_RESERVED_NEWLINE,
Token::TOKEN_TYPE_COMMENT,
Token::TOKEN_TYPE_BLOCK_COMMENT
Token::TOKEN_TYPE_BLOCK_COMMENT,
)
) {
break;
@@ -334,7 +331,7 @@ final class SqlFormatter
Token::TOKEN_TYPE_QUOTE,
Token::TOKEN_TYPE_BACKTICK_QUOTE,
Token::TOKEN_TYPE_WORD,
Token::TOKEN_TYPE_NUMBER
Token::TOKEN_TYPE_NUMBER,
)
) {
continue;
@@ -347,7 +344,7 @@ final class SqlFormatter
if (array_search('block', $indentTypes) !== false) {
$return = rtrim($return, ' ');
$return .= $this->highlighter->highlightErrorMessage(
'WARNING: unclosed parentheses or section'
'WARNING: unclosed parentheses or section',
);
}
@@ -373,7 +370,7 @@ final class SqlFormatter
while ($token = $cursor->next()) {
$return .= $this->highlighter->highlightToken(
$token->type(),
$token->value()
$token->value(),
);
}
@@ -405,7 +402,7 @@ final class SqlFormatter
$token->isOfType(
Token::TOKEN_TYPE_RESERVED,
Token::TOKEN_TYPE_RESERVED_NEWLINE,
Token::TOKEN_TYPE_RESERVED_TOPLEVEL
Token::TOKEN_TYPE_RESERVED_TOPLEVEL,
)
) {
$newValue = preg_replace('/\s+/', ' ', $token->value());

View File

@@ -5,7 +5,7 @@ declare(strict_types=1);
namespace Doctrine\SqlFormatter;
use function in_array;
use function strpos;
use function str_contains;
final class Token
{
@@ -28,16 +28,10 @@ final class Token
public const TOKEN_TYPE = 0;
public const TOKEN_VALUE = 1;
/** @var int */
private $type;
/** @var string */
private $value;
public function __construct(int $type, string $value)
{
$this->type = $type;
$this->value = $value;
public function __construct(
private readonly int $type,
private readonly string $value,
) {
}
public function value(): string
@@ -57,9 +51,9 @@ final class Token
public function hasExtraWhitespace(): bool
{
return strpos($this->value(), ' ') !== false ||
strpos($this->value(), "\n") !== false ||
strpos($this->value(), "\t") !== false;
return str_contains($this->value(), ' ') ||
str_contains($this->value(), "\n") ||
str_contains($this->value(), "\t");
}
public function withValue(string $value): self

View File

@@ -18,17 +18,15 @@ use function strpos;
use function strtoupper;
use function substr;
/**
* @internal
*/
/** @internal */
final class Tokenizer
{
/**
* Reserved words (for syntax highlighting)
*
* @var string[]
* @var list<string>
*/
private $reserved = [
private array $reserved = [
'ACCESSIBLE',
'ACTION',
'AFTER',
@@ -314,9 +312,9 @@ final class Tokenizer
* For SQL formatting
* These keywords will all be on their own line
*
* @var string[]
* @var list<string>
*/
private $reservedToplevel = [
private array $reservedToplevel = [
'WITH',
'SELECT',
'FROM',
@@ -345,8 +343,8 @@ final class Tokenizer
'WINDOW',
];
/** @var string[] */
private $reservedNewline = [
/** @var list<string> */
private array $reservedNewline = [
'LEFT OUTER JOIN',
'RIGHT OUTER JOIN',
'LEFT JOIN',
@@ -360,8 +358,8 @@ final class Tokenizer
'EXCLUDE',
];
/** @var string[] */
private $functions = [
/** @var list<string> */
private array $functions = [
'ABS',
'ACOS',
'ADDDATE',
@@ -687,27 +685,18 @@ final class Tokenizer
// Regular expressions for tokenizing
/** @var string */
private $regexBoundaries;
/** @var string */
private $regexReserved;
/** @var string */
private $regexReservedNewline;
/** @var string */
private $regexReservedToplevel;
/** @var string */
private $regexFunction;
private readonly string $regexBoundaries;
private readonly string $regexReserved;
private readonly string $regexReservedNewline;
private readonly string $regexReservedToplevel;
private readonly string $regexFunction;
/**
* Punctuation that can be used as a boundary between other tokens
*
* @var string[]
* @var list<string>
*/
private $boundaries = [
private array $boundaries = [
',',
';',
'::', // PostgreSQL cast operator
@@ -737,7 +726,7 @@ final class Tokenizer
public function __construct()
{
// Sort reserved word list from longest word to shortest, 3x faster than usort
$reservedMap = array_combine($this->reserved, array_map('strlen', $this->reserved));
$reservedMap = array_combine($this->reserved, array_map(strlen(...), $this->reserved));
assert($reservedMap !== false);
arsort($reservedMap);
$this->reserved = array_keys($reservedMap);
@@ -745,19 +734,19 @@ final class Tokenizer
// Set up regular expressions
$this->regexBoundaries = '(' . implode(
'|',
$this->quoteRegex($this->boundaries)
$this->quoteRegex($this->boundaries),
) . ')';
$this->regexReserved = '(' . implode(
'|',
$this->quoteRegex($this->reserved)
$this->quoteRegex($this->reserved),
) . ')';
$this->regexReservedToplevel = str_replace(' ', '\\s+', '(' . implode(
'|',
$this->quoteRegex($this->reservedToplevel)
$this->quoteRegex($this->reservedToplevel),
) . ')');
$this->regexReservedNewline = str_replace(' ', '\\s+', '(' . implode(
'|',
$this->quoteRegex($this->reservedNewline)
$this->quoteRegex($this->reservedNewline),
) . ')');
$this->regexFunction = '(' . implode('|', $this->quoteRegex($this->functions)) . ')';
@@ -816,7 +805,7 @@ final class Tokenizer
*
* @return Token An associative array containing the type and value of the token.
*/
private function createNextToken(string $string, ?Token $previous = null): Token
private function createNextToken(string $string, Token|null $previous = null): Token
{
$matches = [];
// Whitespace
@@ -854,7 +843,7 @@ final class Tokenizer
($string[0] === '`' || $string[0] === '['
? Token::TOKEN_TYPE_BACKTICK_QUOTE
: Token::TOKEN_TYPE_QUOTE),
$this->getQuotedString($string)
$this->getQuotedString($string),
);
}
@@ -884,7 +873,7 @@ final class Tokenizer
preg_match(
'/^([0-9]+(\.[0-9]+)?|0x[0-9a-fA-F]+|0b[01]+)($|\s|"\'`|' . $this->regexBoundaries . ')/',
$string,
$matches
$matches,
)
) {
return new Token(Token::TOKEN_TYPE_NUMBER, $matches[1]);
@@ -904,12 +893,12 @@ final class Tokenizer
preg_match(
'/^(' . $this->regexReservedToplevel . ')($|\s|' . $this->regexBoundaries . ')/',
$upper,
$matches
$matches,
)
) {
return new Token(
Token::TOKEN_TYPE_RESERVED_TOPLEVEL,
substr($upper, 0, strlen($matches[1]))
substr($upper, 0, strlen($matches[1])),
);
}
@@ -918,12 +907,12 @@ final class Tokenizer
preg_match(
'/^(' . $this->regexReservedNewline . ')($|\s|' . $this->regexBoundaries . ')/',
$upper,
$matches
$matches,
)
) {
return new Token(
Token::TOKEN_TYPE_RESERVED_NEWLINE,
substr($upper, 0, strlen($matches[1]))
substr($upper, 0, strlen($matches[1])),
);
}
@@ -932,12 +921,12 @@ final class Tokenizer
preg_match(
'/^(' . $this->regexReserved . ')($|\s|' . $this->regexBoundaries . ')/',
$upper,
$matches
$matches,
)
) {
return new Token(
Token::TOKEN_TYPE_RESERVED,
substr($upper, 0, strlen($matches[1]))
substr($upper, 0, strlen($matches[1])),
);
}
}
@@ -949,7 +938,7 @@ final class Tokenizer
if (preg_match('/^(' . $this->regexFunction . '[(]|\s|[)])/', $upper, $matches)) {
return new Token(
Token::TOKEN_TYPE_RESERVED,
substr($upper, 0, strlen($matches[1]) - 1)
substr($upper, 0, strlen($matches[1]) - 1),
);
}
@@ -968,9 +957,10 @@ final class Tokenizer
*/
private function quoteRegex(array $strings): array
{
return array_map(static function (string $string): string {
return preg_quote($string, '/');
}, $strings);
return array_map(
static fn (string $string): string => preg_quote($string, '/'),
$strings,
);
}
private function getQuotedString(string $string): string
@@ -989,7 +979,7 @@ final class Tokenizer
(("[^"\\\\]*(?:\\\\.[^"\\\\]*)*("|$))+)|
((\'[^\'\\\\]*(?:\\\\.[^\'\\\\]*)*(\'|$))+))/sx',
$string,
$matches
$matches,
)
) {
$ret = $matches[1];

View File

@@ -9,6 +9,8 @@ use Doctrine\SqlFormatter\HtmlHighlighter;
use Doctrine\SqlFormatter\NullHighlighter;
use Doctrine\SqlFormatter\SqlFormatter;
use Generator;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DataProvider;
use PHPUnit\Framework\TestCase;
use UnexpectedValueException;
@@ -21,48 +23,33 @@ use function pack;
use function sprintf;
use function trim;
/**
* @covers \Doctrine\SqlFormatter\SqlFormatter
*/
#[CoversClass(SqlFormatter::class)]
final class SqlFormatterTest extends TestCase
{
/** @var string[] */
private $sqlData;
/** @var SqlFormatter */
private $formatter;
/** @var HtmlHighlighter */
private $highlighter;
private SqlFormatter $formatter;
protected function setUp(): void
{
// Force SqlFormatter to run in non-CLI mode for tests
$this->highlighter = new HtmlHighlighter();
$highlighter = new HtmlHighlighter();
$this->formatter = new SqlFormatter($this->highlighter);
$this->formatter = new SqlFormatter($highlighter);
}
/**
* @dataProvider formatHighlightData
*/
#[DataProvider('formatHighlightData')]
public function testFormatHighlight(string $sql, string $html): void
{
$this->assertEquals(trim($html), trim($this->formatter->format($sql)));
}
/**
* @dataProvider formatData
*/
#[DataProvider('formatData')]
public function testFormat(string $sql, string $html): void
{
$formatter = new SqlFormatter(new NullHighlighter());
$this->assertEquals(trim($html), trim($formatter->format($sql)));
}
/**
* @dataProvider highlightData
*/
#[DataProvider('highlightData')]
public function testHighlight(string $sql, string $html): void
{
$this->assertEquals(trim($html), trim($this->formatter->highlight($sql)));
@@ -87,18 +74,14 @@ final class SqlFormatterTest extends TestCase
$this->assertEquals(trim($html), trim($this->formatter->highlight($sql)));
}
/**
* @dataProvider highlightCliData
*/
#[DataProvider('highlightCliData')]
public function testCliHighlight(string $sql, string $html): void
{
$formatter = new SqlFormatter(new CliHighlighter());
$this->assertEquals(trim($html), trim($formatter->format($sql)));
}
/**
* @dataProvider compressData
*/
#[DataProvider('compressData')]
public function testCompress(string $sql, string $html): void
{
$this->assertEquals(trim($html), trim($this->formatter->compress($sql)));
@@ -118,21 +101,19 @@ final class SqlFormatterTest extends TestCase
$this->assertEquals($actual, $expected);
}
/**
* @return Generator<mixed[]>
*/
private function fileDataProvider(string $file): Generator
/** @return Generator<mixed[]> */
private static function fileDataProvider(string $file): Generator
{
$contents = file_get_contents(__DIR__ . '/' . $file);
assert($contents !== false);
$formatHighlightData = explode("\n---\n", $contents);
$sqlData = $this->sqlData();
$sqlData = self::sqlData();
if (count($formatHighlightData) !== count($sqlData)) {
throw new UnexpectedValueException(sprintf(
'"%s" (%d sections) and sql.sql (%d sections) should have the same number of sections',
$file,
count($formatHighlightData),
count($sqlData)
count($sqlData),
));
}
@@ -141,57 +122,42 @@ final class SqlFormatterTest extends TestCase
}
}
/**
* @return Generator<mixed[]>
*/
public function formatHighlightData(): Generator
/** @return Generator<mixed[]> */
public static function formatHighlightData(): Generator
{
return $this->fileDataProvider('format-highlight.html');
return self::fileDataProvider('format-highlight.html');
}
/**
* @return Generator<mixed[]>
*/
public function highlightCliData(): Generator
/** @return Generator<mixed[]> */
public static function highlightCliData(): Generator
{
return $this->fileDataProvider('clihighlight.html');
return self::fileDataProvider('clihighlight.html');
}
/**
* @return Generator<mixed[]>
*/
public function formatData(): Generator
/** @return Generator<mixed[]> */
public static function formatData(): Generator
{
return $this->fileDataProvider('format.html');
return self::fileDataProvider('format.html');
}
/**
* @return Generator<mixed[]>
*/
public function compressData(): Generator
/** @return Generator<mixed[]> */
public static function compressData(): Generator
{
return $this->fileDataProvider('compress.html');
return self::fileDataProvider('compress.html');
}
/**
* @return Generator<mixed[]>
*/
public function highlightData(): Generator
/** @return Generator<mixed[]> */
public static function highlightData(): Generator
{
return $this->fileDataProvider('highlight.html');
return self::fileDataProvider('highlight.html');
}
/**
* @return mixed[]
*/
public function sqlData(): array
/** @return mixed[] */
private static function sqlData(): array
{
if (! $this->sqlData) {
$contents = file_get_contents(__DIR__ . '/sql.sql');
assert($contents !== false);
$this->sqlData = explode("\n---\n", $contents);
}
$contents = file_get_contents(__DIR__ . '/sql.sql');
assert($contents !== false);
return $this->sqlData;
return explode("\n---\n", $contents);
}
}

View File

@@ -5,13 +5,14 @@ declare(strict_types=1);
namespace Doctrine\SqlFormatter\Tests;
use Doctrine\SqlFormatter\Tokenizer;
use PHPUnit\Framework\Attributes\CoversClass;
use PHPUnit\Framework\Attributes\DoesNotPerformAssertions;
use PHPUnit\Framework\TestCase;
#[CoversClass(Tokenizer::class)]
final class TokenizerTest extends TestCase
{
/**
* @doesNotPerformAssertions
*/
#[DoesNotPerformAssertions]
public function testThereAreNoRegressions(): void
{
(new Tokenizer())->tokenize('*/');