CodeTestParser.php 1.9 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667
  1. <?php declare(strict_types=1);
  2. namespace PhpParser;
  3. class CodeTestParser {
  4. public function parseTest($code, $chunksPerTest) {
  5. $code = canonicalize($code);
  6. // evaluate @@{expr}@@ expressions
  7. $code = preg_replace_callback(
  8. '/@@\{(.*?)\}@@/',
  9. function ($matches) {
  10. return eval('return ' . $matches[1] . ';');
  11. },
  12. $code
  13. );
  14. // parse sections
  15. $parts = preg_split("/\n-----(?:\n|$)/", $code);
  16. // first part is the name
  17. $name = array_shift($parts);
  18. // multiple sections possible with always two forming a pair
  19. $chunks = array_chunk($parts, $chunksPerTest);
  20. $tests = [];
  21. foreach ($chunks as $i => $chunk) {
  22. $lastPart = array_pop($chunk);
  23. list($lastPart, $mode) = $this->extractMode($lastPart);
  24. $tests[] = [$mode, array_merge($chunk, [$lastPart])];
  25. }
  26. return [$name, $tests];
  27. }
  28. public function reconstructTest($name, array $tests) {
  29. $result = $name;
  30. foreach ($tests as list($mode, $parts)) {
  31. $lastPart = array_pop($parts);
  32. foreach ($parts as $part) {
  33. $result .= "\n-----\n$part";
  34. }
  35. $result .= "\n-----\n";
  36. if (null !== $mode) {
  37. $result .= "!!$mode\n";
  38. }
  39. $result .= $lastPart;
  40. }
  41. return $result . "\n";
  42. }
  43. private function extractMode(string $expected): array {
  44. $firstNewLine = strpos($expected, "\n");
  45. if (false === $firstNewLine) {
  46. $firstNewLine = strlen($expected);
  47. }
  48. $firstLine = substr($expected, 0, $firstNewLine);
  49. if (0 !== strpos($firstLine, '!!')) {
  50. return [$expected, null];
  51. }
  52. $expected = (string) substr($expected, $firstNewLine + 1);
  53. return [$expected, substr($firstLine, 2)];
  54. }
  55. }