Skip to content

Commit

Permalink
Add a configuration to skip DocBlock Custom Annotations detection (#336
Browse files Browse the repository at this point in the history
…) (#337)
  • Loading branch information
LuigiCardamone authored Jan 20, 2023
1 parent a9e6e0d commit fbe1290
Show file tree
Hide file tree
Showing 7 changed files with 68 additions and 4 deletions.
5 changes: 5 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -123,6 +123,11 @@ return static function (Config $config): void {
->add($mvcClassSet, ...$rules);
};
```
PHPArkitect can detect violations also on DocBlocks custom annotations (like `@Assert\NotBlank` or `@Serializer\Expose`).
If you want to disable this feature you can add this simple configuration:
```php
$config->skipParsingCustomAnnotations();
```

# Available rules

Expand Down
4 changes: 2 additions & 2 deletions src/Analyzer/FileParserFactory.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@

class FileParserFactory
{
public static function createFileParser(TargetPhpVersion $targetPhpVersion): FileParser
public static function createFileParser(TargetPhpVersion $targetPhpVersion, bool $parseCustomAnnotations = true): FileParser
{
return new FileParser(
new NodeTraverser(),
new FileVisitor(ClassDescriptionBuilder::create()),
new NameResolver(),
new NameResolver(null, ['parseCustomAnnotations' => $parseCustomAnnotations]),
$targetPhpVersion
);
}
Expand Down
7 changes: 6 additions & 1 deletion src/Analyzer/NameResolver.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ class NameResolver extends NodeVisitorAbstract
/** @var bool Whether to replace resolved nodes in place, or to add resolvedNode attributes */
protected $replaceNodes;

/** @var bool Whether to parse DocBlock Custom Annotations */
protected $parseCustomAnnotations;

/**
* Constructs a name resolution visitor.
*
Expand All @@ -40,6 +43,7 @@ class NameResolver extends NodeVisitorAbstract
* * replaceNodes (default true): Resolved names are replaced in-place. Otherwise, a
* resolvedName attribute is added. (Names that cannot be statically resolved receive a
* namespacedName attribute, as usual.)
* * parseCustomAnnotations (default true): Whether to parse DocBlock Custom Annotations.
*
* @param ErrorHandler|null $errorHandler Error handler
* @param array $options Options
Expand All @@ -49,6 +53,7 @@ public function __construct(ErrorHandler $errorHandler = null, array $options =
$this->nameContext = new NameContext($errorHandler ?? new ErrorHandler\Throwing());
$this->preserveOriginalNames = $options['preserveOriginalNames'] ?? false;
$this->replaceNodes = $options['replaceNodes'] ?? true;
$this->parseCustomAnnotations = $options['parseCustomAnnotations'] ?? true;
}

/**
Expand Down Expand Up @@ -148,7 +153,7 @@ public function enterNode(Node $node)
break;
}

if (!($node->type instanceof FullyQualified)) {
if ($this->parseCustomAnnotations && !($node->type instanceof FullyQualified)) {
foreach ($phpDocNode->getTags() as $tagValue) {
if ('@' === $tagValue->name[0] && false === strpos($tagValue->name, '@var')) {
$customTag = str_replace('@', '', $tagValue->name);
Expand Down
15 changes: 15 additions & 0 deletions src/CLI/Config.php
Original file line number Diff line number Diff line change
Expand Up @@ -13,11 +13,14 @@ class Config
private $classSetRules;
/** @var bool */
private $runOnlyARule;
/** @var bool */
private $parseCustomAnnotations;

public function __construct()
{
$this->classSetRules = [];
$this->runOnlyARule = false;
$this->parseCustomAnnotations = true;
}

public function add(ClassSet $classSet, ArchRule ...$rules): self
Expand Down Expand Up @@ -46,4 +49,16 @@ public function getClassSetRules(): array
{
return $this->classSetRules;
}

public function skipParsingCustomAnnotations(): self
{
$this->parseCustomAnnotations = false;

return $this;
}

public function isParseCustomAnnotationsEnabled(): bool
{
return $this->parseCustomAnnotations;
}
}
2 changes: 1 addition & 1 deletion src/CLI/Runner.php
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ public function __construct(bool $stopOnFailure = false)
public function run(Config $config, Progress $progress, TargetPhpVersion $targetPhpVersion): void
{
/** @var FileParser $fileParser */
$fileParser = FileParserFactory::createFileParser($targetPhpVersion);
$fileParser = FileParserFactory::createFileParser($targetPhpVersion, $config->isParseCustomAnnotationsEnabled());

/** @var ClassSetRules $classSetRule */
foreach ($config->getClassSetRules() as $classSetRule) {
Expand Down
30 changes: 30 additions & 0 deletions tests/Unit/Analyzer/FileVisitorTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -767,4 +767,34 @@ public function getRequest(): Request //the violations is reported here

$this->assertCount(0, $violations);
}

public function test_it_skip_custom_annotations_in_docblocks_if_the_option_parse_custom_annotation_is_false(): void
{
$code = <<< 'EOF'
<?php
namespace MyProject\AppBundle\Application;
use Symfony\Component\Validator\Constraints as Assert;
class ApplicationLevelDto
{
/**
* @Assert\NotBlank
*/
public $foo;
}
EOF;

/** @var FileParser $fp */
$fp = FileParserFactory::createFileParser(TargetPhpVersion::create('8.1'), false);
$fp->parse($code, 'relativePathName');

$cd = $fp->getClassDescriptions();

$violations = new Violations();

$dependsOnlyOnTheseNamespaces = new DependsOnlyOnTheseNamespaces('MyProject\AppBundle\Application');
$dependsOnlyOnTheseNamespaces->evaluate($cd[0], $violations, 'we want to add this rule for our software');

$this->assertCount(0, $violations);
}
}
9 changes: 9 additions & 0 deletions tests/Unit/CLI/ConfigTest.php
Original file line number Diff line number Diff line change
Expand Up @@ -55,4 +55,13 @@ public function test_it_should_create_config_with_only_one_rule_to_run(): void
$classSetRulesExpected[] = ClassSetRules::create($classSet, ...[$rule2]);
$this->assertEquals($classSetRulesExpected, $config->getClassSetRules());
}

public function test_it_should_allow_to_change_the_default_value_for_parsing_custom_annotations(): void
{
$config = new Config();
$this->assertTrue($config->isParseCustomAnnotationsEnabled());

$config->skipParsingCustomAnnotations();
$this->assertFalse($config->isParseCustomAnnotationsEnabled());
}
}

0 comments on commit fbe1290

Please sign in to comment.