![]() Server : Apache System : Linux server2.corals.io 4.18.0-348.2.1.el8_5.x86_64 #1 SMP Mon Nov 15 09:17:08 EST 2021 x86_64 User : corals ( 1002) PHP Version : 7.4.33 Disable Function : exec,passthru,shell_exec,system Directory : /home/corals/old/vendor/codeception/codeception/src/Codeception/Lib/ |
<?php declare(strict_types=1); namespace Codeception\Lib; use Codeception\Exception\TestParseException; use Codeception\Scenario; use Codeception\Step\Action; use Codeception\Step\Comment; use Codeception\Test\Metadata; use Exception; use ParseError; class Parser { protected string $code; public function __construct(protected Scenario $scenario, protected Metadata $metadata) { } public function prepareToRun(string $code): void { $this->parseFeature($code); $this->parseScenarioOptions($code); } public function parseFeature(string $code): void { $matches = []; $code = $this->stripComments($code); $res = preg_match("#\\\$I->wantTo\\(\\s*?['\"](.*?)['\"]\\s*?\\);#", $code, $matches); if ($res) { $this->scenario->setFeature($matches[1]); return; } $res = preg_match("#\\\$I->wantToTest\\(['\"](.*?)['\"]\\);#", $code, $matches); if ($res) { $this->scenario->setFeature("test " . $matches[1]); } } public function parseScenarioOptions(string $code): void { $this->metadata->setParamsFromAnnotations($this->matchComments($code)); } public function parseSteps(string $code): void { // parse per line $friends = []; $lines = explode("\n", $code); $isFriend = false; foreach ($lines as $line) { // friends if (preg_match("#\\\$I->haveFriend\\((.*?)\\);#", $line, $matches)) { $friends[] = trim($matches[1], '\'"'); } // friend's section start if (preg_match("#\\\$(.*?)->does\\(#", $line, $matches)) { $friend = $matches[1]; if (!in_array($friend, $friends)) { continue; } $isFriend = true; $this->addCommentStep("\n----- {$friend} does -----"); continue; } // actions if (preg_match("#\\\$I->(.*)\\((.*?)\\);#", $line, $matches)) { $this->addStep($matches); } // friend's section ends if ($isFriend && str_contains($line, '}')) { $this->addCommentStep("-------- back to me\n"); $isFriend = false; } } } protected function addStep(array $matches): void { [$m, $action, $params] = $matches; if (in_array($action, ['wantTo', 'wantToTest'])) { return; } $this->scenario->addStep(new Action($action, explode(',', $params))); } protected function addCommentStep(string $comment): void { $this->scenario->addStep(new Comment($comment, [])); } public static function load(string $file): void { try { self::includeFile($file); } catch (ParseError $e) { throw new TestParseException($file, $e->getMessage(), $e->getLine()); } catch (Exception) { // file is valid otherwise } } /** * @return string[] */ public static function getClassesFromFile(string $file): array { $sourceCode = file_get_contents($file); $classes = []; $tokens = token_get_all($sourceCode, TOKEN_PARSE); $tokenCount = count($tokens); $namespace = ''; for ($i = 0; $i < $tokenCount; ++$i) { if ($tokens[$i][0] === T_NAMESPACE) { $namespace = ''; for ($j = $i + 1; $j < $tokenCount; ++$j) { if ($tokens[$j] === '{' || $tokens[$j] === ';') { break; } if ($tokens[$j][0] === T_STRING || $tokens[$j][0] === T_NAME_QUALIFIED) { $namespace .= $tokens[$j][1] . '\\'; } } } if ($tokens[$i][0] === T_CLASS) { // class at the beginning of file if (!isset($tokens[$i - 2])) { $classes[] = $namespace . $tokens[$i + 2][1]; continue; } // new class if ($tokens[$i - 2][0] === T_NEW) { continue; } // :: class if ($tokens[$i - 1][0] === T_WHITESPACE && $tokens[$i - 2][0] === T_DOUBLE_COLON) { continue; } // ::class if ($tokens[$i - 1][0] === T_DOUBLE_COLON) { continue; } // class{ if (isset($tokens[$i + 1]) && ($tokens[$i + 1] === '{')) { continue; } // class { if (isset($tokens[$i + 2]) && $tokens[$i + 1][0] === T_WHITESPACE && $tokens[$i + 2] === '{') { continue; } $classes[] = $namespace . $tokens[$i + 2][1]; } } $tokens = null; gc_mem_caches(); return $classes; } /* * Include in different scope to prevent included file from affecting $file variable */ private static function includeFile(string $file): void { include_once $file; } protected function stripComments(string $code): string { $code = preg_replace('#//.*?$#m', '', $code); // remove inline comments return preg_replace('#/*\*.*?\*/#ms', '', $code); // remove block comment } protected function matchComments(string $code): string { $matches = []; $comments = ''; $hasLineComment = preg_match_all('#//(.*?)$#m', $code, $matches); if ($hasLineComment) { foreach ($matches[1] as $line) { $comments .= $line . "\n"; } } $hasBlockComment = preg_match('#/*\*(.*?)\*/#ms', $code, $matches); if ($hasBlockComment) { $comments .= $matches[1] . "\n"; } return $comments; } }