Skip to content

Commit

Permalink
[FEATURE] Introduce modifiers "final" and "abstract" for classes (#14)
Browse files Browse the repository at this point in the history
* [FEATURE] Introduce modifiers "final" and "abstract" for classes

* [TASK] Ignore rector rule

The suggested change would make the method much longer and harder to read.

* [TASK] Only use document context for debug information

using the block context causes an exception due to a bug in the guides
  • Loading branch information
linawolf authored Nov 26, 2023
1 parent 598c70e commit cd9c713
Show file tree
Hide file tree
Showing 17 changed files with 150 additions and 10 deletions.
2 changes: 2 additions & 0 deletions rector.php
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@

use Rector\Config\RectorConfig;
use Rector\Core\ValueObject\PhpVersion;
use Rector\EarlyReturn\Rector\If_\ChangeAndIfToEarlyReturnRector;
use Rector\PHPUnit\CodeQuality\Rector\Class_\PreferPHPUnitThisCallRector;
use Rector\PHPUnit\Set\PHPUnitLevelSetList;
use Rector\PHPUnit\Set\PHPUnitSetList;
Expand All @@ -30,5 +31,6 @@
]);
$config->skip([
PreferPHPUnitThisCallRector::class,
ChangeAndIfToEarlyReturnRector::class
]);
};
2 changes: 2 additions & 0 deletions resources/config/php-domain.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@
use T3Docs\GuidesPhpDomain\Directives\Php\ConstDirective;
use T3Docs\GuidesPhpDomain\Directives\Php\StaticMethodDirective;
use T3Docs\GuidesPhpDomain\Directives\Php\GlobalDirective;
use T3Docs\GuidesPhpDomain\PhpDomain\ModifierService;
use function Symfony\Component\DependencyInjection\Loader\Configurator\service;

use T3Docs\GuidesPhpDomain\Directives\Php\EnumDirective;
Expand Down Expand Up @@ -41,6 +42,7 @@
->set(StaticMethodDirective::class)
->set(FullyQualifiedNameService::class)
->set(MethodNameService::class)
->set(ModifierService::class)
->set(NamespaceRepository::class)

->set(InterfaceTextRole::class)
Expand Down
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
<dl class="php {{ node.type }}">
<dt class="sig sig-object php"
id="{{ node.id }}">
{% for modifier in node.modifiers -%}
{{- renderNode(modifier) }}{{ ' ' -}}
{%- endfor -%}
<em class="property"><span class="pre">{{ node.type }}</span> </em>
{{ renderNode(node.name) }}
</dt>
Expand Down
17 changes: 15 additions & 2 deletions src/Directives/Php/ClassDirective.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,17 +12,26 @@
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\PhpClassNode;
use T3Docs\GuidesPhpDomain\Nodes\PhpInterfaceNode;
use T3Docs\GuidesPhpDomain\Nodes\PhpModifierNode;
use T3Docs\GuidesPhpDomain\PhpDomain\FullyQualifiedNameService;
use T3Docs\GuidesPhpDomain\PhpDomain\ModifierService;

final class ClassDirective extends SubDirective
{
/**
* @var string[]
*/
private array $allowedModifiers = ['abstract', 'final'];
public function __construct(
Rule $startingRule,
GenericLinkProvider $genericLinkProvider,
private readonly FullyQualifiedNameService $fullyQualifiedNameService,
private readonly AnchorReducer $anchorReducer,
private readonly LoggerInterface $logger,
private readonly ModifierService $modifierService,
) {
parent::__construct($startingRule);
$genericLinkProvider->addGenericLink($this->getName(), $this->getName());
Expand All @@ -40,16 +49,20 @@ protected function processSub(
): Node|null {
$name = trim($directive->getData());
$fqn = $this->fullyQualifiedNameService->getFullyQualifiedName($name, true);

$id = $this->anchorReducer->reduceAnchor($fqn->toString());
$modifiers = $this->modifierService->getModifiersFromDirectiveOptions($directive, $this->allowedModifiers);

if ($directive->hasOption('abstract') && $directive->hasOption('final')) {
$this->logger->warning('A PHP class cannot be abstract and final at the same time.', $blockContext->getDocumentParserContext()->getLoggerInformation());
}

return new PhpClassNode(
$id,
$fqn,
$collectionNode->getChildren(),
null,
[],
[],
$modifiers,
);
}
}
1 change: 0 additions & 1 deletion src/Directives/Php/InterfaceDirective.php
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,6 @@ protected function processSub(
$collectionNode->getChildren(),
null,
[],
[],
);
}
}
2 changes: 1 addition & 1 deletion src/Nodes/PhpClassNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ final class PhpClassNode extends PhpComponentNode
private const TYPE = 'class';
/**
* @param list<PhpMemberNode> $members
* @param list<string> $modifiers
* @param list<PhpModifierNode> $modifiers
* @param list<Node> $value
*/
public function __construct(
Expand Down
4 changes: 2 additions & 2 deletions src/Nodes/PhpComponentNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ abstract class PhpComponentNode extends CompoundNode implements LinkTargetNode
{
/**
* @param list<PhpMemberNode> $members
* @param list<string> $modifiers
* @param list<PhpModifierNode> $modifiers
* @param list<Node> $value
*/
public function __construct(
Expand Down Expand Up @@ -88,7 +88,7 @@ public function getType(): string
}

/**
* @return list<string>
* @return list<PhpModifierNode>
*/
public function getModifiers(): array
{
Expand Down
2 changes: 1 addition & 1 deletion src/Nodes/PhpEnumNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ final class PhpEnumNode extends PhpComponentNode

/**
* @param list<PhpMemberNode> $members
* @param list<string> $modifiers
* @param list<PhpModifierNode> $modifiers
* @param list<Node> $value
*/
public function __construct(
Expand Down
4 changes: 1 addition & 3 deletions src/Nodes/PhpInterfaceNode.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,6 @@ final class PhpInterfaceNode extends PhpComponentNode
private const TYPE = 'interface';
/**
* @param list<PhpMemberNode> $members
* @param list<string> $modifiers
* @param list<Node> $value
*/
public function __construct(
Expand All @@ -20,8 +19,7 @@ public function __construct(
array $value = [],
PhpNamespaceNode|null $namespace = null,
array $members = [],
array $modifiers = [],
) {
parent::__construct($id, self::TYPE, $name, $value, $namespace, $members, $modifiers);
parent::__construct($id, self::TYPE, $name, $value, $namespace, $members);
}
}
33 changes: 33 additions & 0 deletions src/PhpDomain/ModifierService.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,33 @@
<?php

declare(strict_types=1);

namespace T3Docs\GuidesPhpDomain\PhpDomain;

use phpDocumentor\Guides\ReferenceResolvers\AnchorReducer;
use phpDocumentor\Guides\RestructuredText\Parser\BlockContext;
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\PhpModifierNode;

final class ModifierService
{
/**
* @param list<string> $allowedModifiers
* @return list<PhpModifierNode>
*/
public function getModifiersFromDirectiveOptions(Directive $directive, array $allowedModifiers): array
{
$modifiers = [];

foreach ($allowedModifiers as $allowedModifier) {
if ($directive->hasOption($allowedModifier)) {
$modifiers[] = new PhpModifierNode($allowedModifier);
}
}
return $modifiers;
}

}
21 changes: 21 additions & 0 deletions tests/integration/class-abstract/expected/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!-- content start -->
<div class="section" id="abstract-class">
<h1>abstract class</h1>

<dl class="php class">
<dt class="sig sig-object php"
id="typo3-cms-core-abstracttest">
<span class="sig-name modifier"><span class="pre">abstract</span></span>
<em class="property"><span class="pre">class</span> </em>
<span class="sig-prename descclassname"><span class="pre">\TYPO3\CMS\Core\</span></span>
<span class="sig-name descname"><span class="pre">AbstractTest</span></span>

</dt>
<dd>
<p>Lorem Ipsum Dolor!</p>
</dd>
</dl>

</div>

<!-- content end -->
8 changes: 8 additions & 0 deletions tests/integration/class-abstract/input/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
==============
abstract class
==============

.. php:class:: TYPO3\CMS\Core\AbstractTest
:abstract:

Lorem Ipsum Dolor!
22 changes: 22 additions & 0 deletions tests/integration/class-final-abstract/expected/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
<!-- content start -->
<div class="section" id="abstract-final-class-causes-warning">
<h1>abstract final class causes warning</h1>

<dl class="php class">
<dt class="sig sig-object php"
id="typo3-cms-core-test">
<span class="sig-name modifier"><span class="pre">abstract</span></span>
<span class="sig-name modifier"><span class="pre">final</span></span>
<em class="property"><span class="pre">class</span> </em>
<span class="sig-prename descclassname"><span class="pre">\TYPO3\CMS\Core\</span></span>
<span class="sig-name descname"><span class="pre">Test</span></span>

</dt>
<dd>
<p>Lorem Ipsum Dolor!</p>
</dd>
</dl>

</div>

<!-- content end -->
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
app.WARNING: A PHP class cannot be abstract and final at the same time.
9 changes: 9 additions & 0 deletions tests/integration/class-final-abstract/input/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
===================================
abstract final class causes warning
===================================

.. php:class:: TYPO3\CMS\Core\Test
:abstract:
:final:

Lorem Ipsum Dolor!
21 changes: 21 additions & 0 deletions tests/integration/class-final/expected/index.html
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
<!-- content start -->
<div class="section" id="final-class">
<h1>final class</h1>

<dl class="php class">
<dt class="sig sig-object php"
id="typo3-cms-core-test">
<span class="sig-name modifier"><span class="pre">final</span></span>
<em class="property"><span class="pre">class</span> </em>
<span class="sig-prename descclassname"><span class="pre">\TYPO3\CMS\Core\</span></span>
<span class="sig-name descname"><span class="pre">Test</span></span>

</dt>
<dd>
<p>Lorem Ipsum Dolor!</p>
</dd>
</dl>

</div>

<!-- content end -->
8 changes: 8 additions & 0 deletions tests/integration/class-final/input/index.rst
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
===========
final class
===========

.. php:class:: TYPO3\CMS\Core\Test
:final:

Lorem Ipsum Dolor!

0 comments on commit cd9c713

Please sign in to comment.