Skip to content

Instantly share code, notes, and snippets.

@Hywan
Last active March 4, 2017 15:04
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Hywan/b8bd387def5e3cc13e024c4f924e8c3c to your computer and use it in GitHub Desktop.
Save Hywan/b8bd387def5e3cc13e024c4f924e8c3c to your computer and use it in GitHub Desktop.
Address RFC 52 from Hoa
<?php
require 'vendor/autoload.php';
use Hoa\File;
use League\CommonMark;
const DIRECTORY_TO_SCAN = '../Acl';
const NAMESPACE_TO_SCAN = 'Hoa\\\Acl\\\\';
const DOCUMENTATION_SECTION = 'Examples';
require DIRECTORY_TO_SCAN . '/vendor/autoload.php';
$finder = new File\Finder();
$finder
->files()
->name('/\.php$/')
->in(DIRECTORY_TO_SCAN)
->notIn('/^\.git|vendor|Test$/');
$classes = get_declared_classes();
foreach ($finder as $file) {
require_once $file->getPathName();
}
$reflectedClasses = [];
foreach (array_diff(get_declared_classes(), $classes) as $class) {
if (0 === preg_match('/^' . NAMESPACE_TO_SCAN . '/', $class)) {
continue;
}
$reflectedClasses[] = new ReflectionClass($class);
}
unset($classes);
$markdown = new CommonMark\DocParser(CommonMark\Environment::createCommonMarkEnvironment());
$testSuites = [];
foreach ($reflectedClasses as $reflectedClass) {
$testSuite = sprintf(
'<?php' . "\n\n" .
'namespace Hoa\Foo\Test\Documentation;' . "\n\n" .
'use Hoa\Test;' . "\n\n" .
'class %s extends Test\Integration\Suite' . "\n" .
'{',
$reflectedClass->getShortName()
);
$anyTestCase = false;
foreach ($reflectedClass->getMethods() as $reflectedMethod) {
$comment = $reflectedMethod->getDocComment();
if (false === $comment) {
continue;
}
$comment = extractFromComment($comment);
$examples = collectExamples($markdown->parse($comment)->walker());
if (empty($examples)) {
continue;
}
$anyTestCase = true;
$testCaseIndex = 0;
foreach ($examples as $example) {
$testSuite .= sprintf(
"\n" .
' public function case_%s_example_%d()' . "\n" .
' {' . "\n" .
'%s' . "\n" .
' }' . "\n",
$reflectedMethod->getName(),
$testCaseIndex,
compileExampleToTestCaseBody($example)
);
$testCaseIndex++;
}
}
$testSuite .= '}';
if (true === $anyTestCase) {
$testSuites[$reflectedClass->getName()] = $testSuite;
}
}
var_dump($testSuites);
function extractFromComment(string $comment): string
{
return preg_replace(
',^(/\*\*|\h*\*/?\h*),m',
'',
$comment
);
}
function collectExamples(CommonMark\Node\NodeWalker $walker): array
{
while ($event = $walker->next()) {
$node = $event->getNode();
if (false === $event->isEntering() ||
!($node instanceof CommonMark\Block\Element\Heading) ||
1 !== $node->getLevel() ||
DOCUMENTATION_SECTION !== $node->getStringContent()) {
continue;
}
$examples = [];
while ($childEvent = $walker->next()) {
$childNode = $childEvent->getNode();
if ($childNode instanceof CommonMark\Block\Element\Heading &&
DOCUMENTATION_SECTION !== $childNode->getStringContent()) {
break;
}
if (false === $event->isEntering() ||
!($childNode instanceof CommonMark\Block\Element\FencedCode)) {
continue;
}
$hash = spl_object_hash($childNode);
if (isset($examples[$hash])) {
continue;
}
$codeBlock = new CodeBlock();
$codeBlock->type = $childNode->getInfo();
$codeBlock->code = trim($childNode->getStringContent());
$examples[$hash] = $codeBlock;
}
return $examples;
}
return [];
}
function compileExampleToTestCaseBody(CodeBlock $example): string
{
return sprintf(
' $this' . "\n" .
' ->do(function () {' . "\n" .
' %s' . "\n" .
' });' . "\n",
preg_replace(
'/^\h+$/m',
'',
str_replace("\n", "\n" . ' ', $example->code)
)
);
}
class CodeBlock
{
public $type = null;
public $code = null;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment