Skip to content

Commit

Permalink
PhpDocBlock metadata.
Browse files Browse the repository at this point in the history
  • Loading branch information
LastDragon-ru committed Aug 13, 2024
1 parent 9b3fa40 commit 770e9ea
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 0 deletions.
69 changes: 69 additions & 0 deletions packages/documentator/src/Processor/Metadata/PhpDocBlock.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,69 @@
<?php declare(strict_types = 1);

namespace LastDragon_ru\LaraASP\Documentator\Processor\Metadata;

use LastDragon_ru\LaraASP\Documentator\Markdown\Document;
use LastDragon_ru\LaraASP\Documentator\Processor\Contracts\Metadata;
use LastDragon_ru\LaraASP\Documentator\Processor\FileSystem\File;
use LastDragon_ru\LaraASP\Documentator\Utils\PhpDoc;
use Override;
use PhpParser\NameContext;
use PhpParser\Node\Name;

use function preg_replace_callback;
use function trim;

use const PREG_UNMATCHED_AS_NULL;

/**
* @implements Metadata<?Document>
*/
class PhpDocBlock implements Metadata {
public function __construct(
protected readonly PhpClass $class,
) {
// empty
}

/**
* @inheritDoc
*/
#[Override]
public function __invoke(File $file): mixed {
// Class?
$class = $file->getMetadata($this->class);

if (!$class) {
return null;
}

// Parse
$content = (new PhpDoc($class->class->getDocComment()?->getText()))->getText();
$content = $this->preprocess($class->context, $content);
$content = trim($content);

if (!$content) {
return new Document('', $file->getPath());
}

// Create
return new Document($content, $file->getPath());
}

private function preprocess(NameContext $context, string $string): string {
return (string) preg_replace_callback(
pattern : '/\{@(?:see|link)\s+(?P<class>[^}\s\/:]+)(?:::(?P<method>[^(]+\(\)))?\s?\}/imu',
callback: static function (array $matches) use ($context): string {
$class = (string) $context->getResolvedClassName(new Name($matches['class']));
$method = $matches['method'] ?? null;
$result = $method
? "`{$class}::{$method}`"
: "`{$class}`";

return $result;
},
subject : $string,
flags : PREG_UNMATCHED_AS_NULL,
);
}
}
75 changes: 75 additions & 0 deletions packages/documentator/src/Processor/Metadata/PhpDocBlockTest.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,75 @@
<?php declare(strict_types = 1);

namespace LastDragon_ru\LaraASP\Documentator\Processor\Metadata;

use LastDragon_ru\LaraASP\Core\Utils\Path;
use LastDragon_ru\LaraASP\Documentator\Processor\FileSystem\File;
use LastDragon_ru\LaraASP\Documentator\Testing\Package\TestCase;
use Override;
use PHPUnit\Framework\Attributes\CoversClass;

/**
* @internal
*/
#[CoversClass(PhpDocBlock::class)]
final class PhpDocBlockTest extends TestCase {
public function testInvoke(): void {
$content = <<<'PHP'
<?php declare(strict_types = 1);
namespace LastDragon_ru\LaraASP\Documentator\Processor\Metadata;
use stdClass;
use LastDragon_ru\LaraASP\Documentator\Processor\Metadata\PhpClass;
/**
* Description.
*
* Summary {@see stdClass} and {@see PhpClass}.
*/
class A {
// empty
}
PHP;
$file = new File(
Path::normalize(self::getTempFile($content)->getPathname()),
false,
);
$factory = new PhpDocBlock(new PhpClass());
$metadata = $factory($file);

self::assertNotNull($metadata);
self::assertEquals(
<<<'MARKDOWN'
Description.
Summary `stdClass` and `LastDragon_ru\LaraASP\Documentator\Processor\Metadata\PhpClass`.
MARKDOWN,
(string) $metadata,
);
}

public function testInvokeEmpty(): void {
$file = new File(Path::normalize(__FILE__), false);
$factory = new PhpDocBlock(new PhpClass());
$metadata = $factory($file);

self::assertNotNull($metadata);
self::assertTrue($metadata->isEmpty());
}

public function testInvokeNotPhp(): void {
$file = new File(Path::normalize(__FILE__), false);
$factory = new PhpDocBlock(
new class() extends PhpClass {
#[Override]
public function __invoke(File $file): mixed {
return null;
}
},
);
$metadata = $factory($file);

self::assertNull($metadata);
}
}

0 comments on commit 770e9ea

Please sign in to comment.