diff --git a/phpstan-baseline.neon b/phpstan-baseline.neon index da3ffe9..85dad07 100644 --- a/phpstan-baseline.neon +++ b/phpstan-baseline.neon @@ -2,7 +2,7 @@ parameters: ignoreErrors: - message: "#^Function phpDocumentor\\\\Guides\\\\DependencyInjection\\\\template not found\\.$#" - count: 10 + count: 11 path: src/DependencyInjection/GuidesPhpDomainExtension.php - diff --git a/resources/config/php-domain.php b/resources/config/php-domain.php index b353875..47335d0 100644 --- a/resources/config/php-domain.php +++ b/resources/config/php-domain.php @@ -7,6 +7,7 @@ use phpDocumentor\Guides\RestructuredText\Parser\Productions\DirectiveContentRule; use Symfony\Component\DependencyInjection\Loader\Configurator\ContainerConfigurator; +use T3Docs\GuidesPhpDomain\Directives\Php\CaseDirective; use T3Docs\GuidesPhpDomain\Directives\Php\ClassDirective; use T3Docs\GuidesPhpDomain\Directives\Php\ConstDirective; use T3Docs\GuidesPhpDomain\Directives\Php\ExceptionDirective; @@ -35,7 +36,7 @@ ->bind('$startingRule', service(DirectiveContentRule::class)) ->instanceof(BaseDirective::class) ->tag('phpdoc.guides.directive') - ->set(ClassDirective::class) + ->set(CaseDirective::class) ->set(ClassDirective::class) ->set(ConstDirective::class) ->set(EnumDirective::class) diff --git a/resources/template/html/body/directive/php/case.html.twig b/resources/template/html/body/directive/php/case.html.twig new file mode 100644 index 0000000..2b53930 --- /dev/null +++ b/resources/template/html/body/directive/php/case.html.twig @@ -0,0 +1,7 @@ +
+
+ case + {{ renderNode(node.memberName) }} : {% if node.backedValue -%}{{ node.backedValue }} {% endif -%} +
+
{{ renderNode(node.value) }}
+
diff --git a/resources/template/html/body/directive/php/component.html.twig b/resources/template/html/body/directive/php/component.html.twig index 5e5bbb4..147b7bf 100644 --- a/resources/template/html/body/directive/php/component.html.twig +++ b/resources/template/html/body/directive/php/component.html.twig @@ -5,7 +5,7 @@ {{- renderNode(modifier) }}{{ ' ' -}} {%- endfor -%} {{ node.type }} - {{ renderNode(node.name) }} + {{ renderNode(node.name) }} {%- if node.type == 'enum' and node.phpType -%} : {{ node.phpType }} {% endif -%}
{{ renderNode(node.value) }} diff --git a/src/DependencyInjection/GuidesPhpDomainExtension.php b/src/DependencyInjection/GuidesPhpDomainExtension.php index 4529808..3d1ba23 100644 --- a/src/DependencyInjection/GuidesPhpDomainExtension.php +++ b/src/DependencyInjection/GuidesPhpDomainExtension.php @@ -12,8 +12,10 @@ use T3Docs\GuidesPhpDomain\Nodes\FullyQualifiedNameNode; use T3Docs\GuidesPhpDomain\Nodes\MemberNameNode; use T3Docs\GuidesPhpDomain\Nodes\MethodNameNode; +use T3Docs\GuidesPhpDomain\Nodes\PhpCaseNode; use T3Docs\GuidesPhpDomain\Nodes\PhpComponentNode; use T3Docs\GuidesPhpDomain\Nodes\PhpConstNode; +use T3Docs\GuidesPhpDomain\Nodes\PhpEnumNode; use T3Docs\GuidesPhpDomain\Nodes\PhpGlobalNode; use T3Docs\GuidesPhpDomain\Nodes\PhpMethodNode; use T3Docs\GuidesPhpDomain\Nodes\PhpModifierNode; @@ -44,6 +46,7 @@ public function prepend(ContainerBuilder $container): void 'base_template_paths' => [dirname(__DIR__, 2) . '/resources/template/html'], 'templates' => [ template(FullyQualifiedNameNode::class, 'body/directive/php/fullyQualifiedName.html.twig'), + template(PhpCaseNode::class, 'body/directive/php/case.html.twig'), template(PhpComponentNode::class, 'body/directive/php/component.html.twig'), template(PhpConstNode::class, 'body/directive/php/const.html.twig'), template(PhpGlobalNode::class, 'body/directive/php/global.html.twig'), diff --git a/src/Directives/Php/CaseDirective.php b/src/Directives/Php/CaseDirective.php new file mode 100644 index 0000000..81c3c20 --- /dev/null +++ b/src/Directives/Php/CaseDirective.php @@ -0,0 +1,57 @@ +addGenericLink($this->getName(), $this->getName()); + } + + public function getName(): string + { + return 'php:case'; + } + + protected function processSub( + BlockContext $blockContext, + CollectionNode $collectionNode, + Directive $directive, + ): Node|null { + $name = new MemberNameNode(trim($directive->getData())); + $id = $this->anchorReducer->reduceAnchor($name->toString()); + + $value = null; + if ($directive->hasOption('value')) { + $value = $directive->getOption('value')->toString(); + } + + return new PhpCaseNode( + $id, + $name, + $collectionNode->getChildren(), + $value, + ); + } +} diff --git a/src/Directives/Php/EnumDirective.php b/src/Directives/Php/EnumDirective.php index 3060e29..e2998e8 100644 --- a/src/Directives/Php/EnumDirective.php +++ b/src/Directives/Php/EnumDirective.php @@ -12,6 +12,7 @@ use phpDocumentor\Guides\RestructuredText\Parser\Directive; use phpDocumentor\Guides\RestructuredText\Parser\Productions\Rule; use phpDocumentor\Guides\RestructuredText\TextRoles\GenericLinkProvider; +use Psr\Log\LoggerInterface; use T3Docs\GuidesPhpDomain\Nodes\PhpEnumNode; use T3Docs\GuidesPhpDomain\PhpDomain\FullyQualifiedNameService; @@ -22,6 +23,7 @@ public function __construct( GenericLinkProvider $genericLinkProvider, private readonly FullyQualifiedNameService $fullyQualifiedNameService, private readonly AnchorReducer $anchorReducer, + private readonly LoggerInterface $logger, ) { parent::__construct($startingRule); $genericLinkProvider->addGenericLink($this->getName(), $this->getName()); @@ -38,10 +40,25 @@ protected function processSub( Directive $directive, ): Node|null { $name = trim($directive->getData()); - $fqn = $this->fullyQualifiedNameService->getFullyQualifiedName($name, true); + $type = null; + + if (str_contains($name, ':')) { + [$name, $type] = explode(':', $name, 2); + $type = trim($type); + $this->logger->warning('Passing the type of a backed enum directly with the name is deprecated. Use option :type: instead.', $blockContext->getDocumentParserContext()->getLoggerInformation()); + } + + $fqn = $this->fullyQualifiedNameService->getFullyQualifiedName(trim($name), true); $id = $this->anchorReducer->reduceAnchor($fqn->toString()); + if ($directive->hasOption('type')) { + if ($type != null) { + $this->logger->warning('The type of the backed enum was set twice. The type from the option will be prefered.', $blockContext->getDocumentParserContext()->getLoggerInformation()); + } + $type = $directive->getOption('type')->toString(); + } + return new PhpEnumNode( $id, $fqn, @@ -49,6 +66,7 @@ protected function processSub( null, [], [], + $type, ); } } diff --git a/src/Nodes/PhpCaseNode.php b/src/Nodes/PhpCaseNode.php new file mode 100644 index 0000000..333d9b4 --- /dev/null +++ b/src/Nodes/PhpCaseNode.php @@ -0,0 +1,34 @@ +toString(), $value); + } + + public function getMemberName(): MemberNameNode + { + return $this->memberName; + } + + public function getBackedValue(): ?string + { + return $this->backedValue; + } +} diff --git a/src/Nodes/PhpEnumNode.php b/src/Nodes/PhpEnumNode.php index 54088f9..e17e7c1 100644 --- a/src/Nodes/PhpEnumNode.php +++ b/src/Nodes/PhpEnumNode.php @@ -22,7 +22,13 @@ public function __construct( PhpNamespaceNode|null $namespace = null, array $members = [], array $modifiers = [], + private readonly ?string $phpType = null, ) { parent::__construct($id, self::TYPE, $name, $value, $namespace, $members, $modifiers); } + + public function getPhpType(): ?string + { + return $this->phpType; + } } diff --git a/tests/integration/enum-backed-with-cases/expected/index.html b/tests/integration/enum-backed-with-cases/expected/index.html new file mode 100644 index 0000000..8a04bf1 --- /dev/null +++ b/tests/integration/enum-backed-with-cases/expected/index.html @@ -0,0 +1,33 @@ + +
+

PHP Enum with Const

+ +
+
+ enum + RedSuit + : string
+
+

In playing cards, a suit is one of the categories into which the +cards of a deck are divided.

+
+ case + Hearts + : 'H'
+

Hearts is one of the four suits in playing cards.

+
+
+
+ case + Diamonds + : 'D'
+

Diamonds is one of the four suits in playing cards.

+
+ +
+
+ +
+ + diff --git a/tests/integration/enum-backed-with-cases/input/index.rst b/tests/integration/enum-backed-with-cases/input/index.rst new file mode 100644 index 0000000..936c0bc --- /dev/null +++ b/tests/integration/enum-backed-with-cases/input/index.rst @@ -0,0 +1,19 @@ +=================== +PHP Enum with Const +=================== + +.. php:enum:: RedSuit + :type: string + + In playing cards, a suit is one of the categories into which the + cards of a deck are divided. + + .. php:case:: Hearts + :value: 'H' + + Hearts is one of the four suits in playing cards. + + .. php:case:: Diamonds + :value: 'D' + + Diamonds is one of the four suits in playing cards. diff --git a/tests/integration/enum-with-cases/expected/index.html b/tests/integration/enum-with-cases/expected/index.html new file mode 100644 index 0000000..54fbf8c --- /dev/null +++ b/tests/integration/enum-with-cases/expected/index.html @@ -0,0 +1,48 @@ + +
+

PHP Enum with Const

+ +
+
+ enum + Suit + +
+
+

In playing cards, a suit is one of the categories into which the +cards of a deck are divided.

+
+ case + Hearts + :
+

Hearts is one of the four suits in playing cards.

+
+
+
+ case + Diamonds + :
+

Diamonds is one of the four suits in playing cards.

+
+
+
+ case + Clubs + :
+

Clubs is one of the four suits in playing cards.

+
+
+
+ case + Spades + :
+

Spades is one of the four suits in playing cards.

+
+ +
+
+ +
+ + diff --git a/tests/integration/enum-with-cases/input/index.rst b/tests/integration/enum-with-cases/input/index.rst new file mode 100644 index 0000000..f907797 --- /dev/null +++ b/tests/integration/enum-with-cases/input/index.rst @@ -0,0 +1,24 @@ +=================== +PHP Enum with Const +=================== + +.. php:enum:: Suit + + In playing cards, a suit is one of the categories into which the + cards of a deck are divided. + + .. php:case:: Hearts + + Hearts is one of the four suits in playing cards. + + .. php:case:: Diamonds + + Diamonds is one of the four suits in playing cards. + + .. php:case:: Clubs + + Clubs is one of the four suits in playing cards. + + .. php:case:: Spades + + Spades is one of the four suits in playing cards. diff --git a/tests/integration/enum-with-warnings/expected/index.html b/tests/integration/enum-with-warnings/expected/index.html new file mode 100644 index 0000000..3dd0ee0 --- /dev/null +++ b/tests/integration/enum-with-warnings/expected/index.html @@ -0,0 +1,58 @@ + +
+

PHP Enum with Warnings

+ +
+
+ enum + RedSuit + : string
+
+

In playing cards, a suit is one of the categories into which the +cards of a deck are divided.

+
+ case + Hearts + : 'H'
+

Hearts is one of the four suits in playing cards.

+
+
+
+ case + Diamonds + : 'D'
+

Diamonds is one of the four suits in playing cards.

+
+ +
+
+ +
+
+ enum + BlackSuit + : string
+
+
+
+ case + Clubs : 'C' + :
+

Clubs is one of the four suits in playing cards.

+
+
+
+ case + Spades : 'S' + :
+

Spades is one of the four suits in playing cards.

+
+ +
+
+ +
+ + diff --git a/tests/integration/enum-with-warnings/expected/logs/warning.log b/tests/integration/enum-with-warnings/expected/logs/warning.log new file mode 100644 index 0000000..d9db898 --- /dev/null +++ b/tests/integration/enum-with-warnings/expected/logs/warning.log @@ -0,0 +1,3 @@ +app.WARNING: Passing the type of a backed enum directly with the name is deprecated. Use option :type: instead. {"rst-file":"index.rst"} [] +app.WARNING: The type of the backed enum was set twice. The type from the option will be prefered. {"rst-file":"index.rst"} [] +app.WARNING: Passing the type of a backed enum directly with the name is deprecated. Use option :type: instead. {"rst-file":"index.rst"} [] diff --git a/tests/integration/enum-with-warnings/input/index.rst b/tests/integration/enum-with-warnings/input/index.rst new file mode 100644 index 0000000..c0911bf --- /dev/null +++ b/tests/integration/enum-with-warnings/input/index.rst @@ -0,0 +1,30 @@ +====================== +PHP Enum with Warnings +====================== + +.. php:enum:: RedSuit : string + :type: string + + In playing cards, a suit is one of the categories into which the + cards of a deck are divided. + + .. php:case:: Hearts + :value: 'H' + + Hearts is one of the four suits in playing cards. + + .. php:case:: Diamonds + :value: 'D' + + Diamonds is one of the four suits in playing cards. + + +.. php:enum:: BlackSuit : string + + .. php:case:: Clubs : 'C' + + Clubs is one of the four suits in playing cards. + + .. php:case:: Spades : 'S' + + Spades is one of the four suits in playing cards.