CodeTestParser.php 1.9 KB

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