ok
Direktori : /home2/selectio/public_html/fms-worksuite/vendor/phpmyadmin/sql-parser/src/Tools/ |
Current File : /home2/selectio/public_html/fms-worksuite/vendor/phpmyadmin/sql-parser/src/Tools/TestGenerator.php |
<?php declare(strict_types=1); namespace PhpMyAdmin\SqlParser\Tools; use Exception; use PhpMyAdmin\SqlParser\Context; use PhpMyAdmin\SqlParser\Exceptions\LexerException; use PhpMyAdmin\SqlParser\Exceptions\ParserException; use PhpMyAdmin\SqlParser\Lexer; use PhpMyAdmin\SqlParser\Parser; use PhpMyAdmin\SqlParser\Token; use function dirname; use function file_exists; use function file_get_contents; use function file_put_contents; use function in_array; use function is_dir; use function json_decode; use function json_encode; use function mkdir; use function print_r; use function scandir; use function sprintf; use function str_contains; use function str_ends_with; use function str_replace; use function strpos; use function substr; use const JSON_PRESERVE_ZERO_FRACTION; use const JSON_PRETTY_PRINT; use const JSON_UNESCAPED_SLASHES; use const JSON_UNESCAPED_UNICODE; /** * Used for test generation. */ class TestGenerator { /** * Generates a test's data. * * @param string $query the query to be analyzed * @param string $type test's type (may be `lexer` or `parser`) * * @return array<string, string|Lexer|Parser|array<string, array<int, array<int, int|string|Token>>>|null> */ public static function generate($query, $type = 'parser') { /** * Lexer used for tokenizing the query. */ $lexer = new Lexer($query); /** * Parsed used for analyzing the query. * A new instance of parser is generated only if the test requires. * * @var Parser */ $parser = $type === 'parser' ? new Parser($lexer->list) : null; /** * Lexer's errors. * * @var array<int, array<int, int|string>> */ $lexerErrors = []; /** * Parser's errors. * * @var array<int, array<int, int|string|Token>> */ $parserErrors = []; // Both the lexer and the parser construct exception for errors. // Usually, exceptions contain a full stack trace and other details that // are not required. // The code below extracts only the relevant information. // Extracting lexer's errors. if (! empty($lexer->errors)) { /** @var LexerException $err */ foreach ($lexer->errors as $err) { $lexerErrors[] = [ $err->getMessage(), $err->ch, $err->pos, $err->getCode(), ]; } $lexer->errors = []; } // Extracting parser's errors. if (! empty($parser->errors)) { /** @var ParserException $err */ foreach ($parser->errors as $err) { $parserErrors[] = [ $err->getMessage(), $err->token, $err->getCode(), ]; } $parser->errors = []; } return [ 'query' => $query, 'lexer' => $lexer, 'parser' => $parser, 'errors' => [ 'lexer' => $lexerErrors, 'parser' => $parserErrors, ], ]; } /** * Builds a test. * * Reads the input file, generates the data and writes it back. * * @param string $type the type of this test * @param string $input the input file * @param string $output the output file * @param string $debug the debug file * @param bool $ansi activate quotes ANSI mode * * @return void */ public static function build($type, $input, $output, $debug = null, $ansi = false) { // Support query types: `lexer` / `parser`. if (! in_array($type, ['lexer', 'parser'])) { throw new Exception('Unknown test type (expected `lexer` or `parser`).'); } /** * The query that is used to generate the test. * * @var string */ $query = file_get_contents($input); // There is no point in generating a test without a query. if (empty($query)) { throw new Exception('No input query specified.'); } if ($ansi === true) { // set ANSI_QUOTES for ansi tests Context::setMode(Context::SQL_MODE_ANSI_QUOTES); } $mariaDbPos = strpos($input, '_mariadb_'); if ($mariaDbPos !== false) {// Keep in sync with TestCase.php // set context $mariaDbVersion = (int) substr($input, $mariaDbPos + 9, 6); Context::load('MariaDb' . $mariaDbVersion); } else { // Load the default context to be sure there is no side effects Context::load(''); } $test = static::generate($query, $type); // unset mode, reset to default every time, to be sure Context::setMode(); $serializer = new CustomJsonSerializer(); // Writing test's data. $encoded = $serializer->serialize($test); $encoded = (string) json_encode( json_decode($encoded), JSON_PRETTY_PRINT | JSON_UNESCAPED_UNICODE | JSON_PRESERVE_ZERO_FRACTION | JSON_UNESCAPED_SLASHES ); // Remove the project path from .out file, it changes for each dev $projectFolder = dirname(__DIR__, 2);// Jump to root $encoded = str_replace($projectFolder, '<project-root>', $encoded); file_put_contents($output, $encoded); // Dumping test's data in human readable format too (if required). if (empty($debug)) { return; } file_put_contents($debug, print_r($test, true)); } /** * Generates recursively all tests preserving the directory structure. * * @param string $input the input directory * @param string $output the output directory * @param mixed|null $debug * * @return void */ public static function buildAll($input, $output, $debug = null) { $files = scandir($input); foreach ($files as $file) { // Skipping current and parent directories. if (($file === '.') || ($file === '..')) { continue; } // Appending the filename to directories. $inputFile = $input . '/' . $file; $outputFile = $output . '/' . $file; $debugFile = $debug !== null ? $debug . '/' . $file : null; if (is_dir($inputFile)) { // Creating required directories to maintain the structure. // Ignoring errors if the folder structure exists already. if (! is_dir($outputFile)) { mkdir($outputFile); } if (($debug !== null) && (! is_dir($debugFile))) { mkdir($debugFile); } // Generating tests recursively. static::buildAll($inputFile, $outputFile, $debugFile); } elseif (str_ends_with($inputFile, '.in')) { // Generating file names by replacing `.in` with `.out` and // `.debug`. $outputFile = substr($outputFile, 0, -3) . '.out'; if ($debug !== null) { $debugFile = substr($debugFile, 0, -3) . '.debug'; } // Building the test. if (! file_exists($outputFile)) { echo sprintf("Building test for %s...\n", $inputFile); static::build( str_contains($inputFile, 'lex') ? 'lexer' : 'parser', $inputFile, $outputFile, $debugFile, str_contains($inputFile, 'ansi') ); } else { echo sprintf("Test for %s already built!\n", $inputFile); } } } } }