Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Internal call implementation #904

Merged
merged 4 commits into from
Jun 10, 2022
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions docs/concepts.md
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,10 @@ uncovered dependencies are encountered.
You can use the `--report-uncovered` option to let you know about any uncovered
dependencies in the report that is generated by Deptrac.

### @internal and @deptrac-internal annotation

You can mark your classes with `@internal` or `@deptrac-internal` annotation. If you do so, the marked class cannot be referenced by any class outside its layer. This will supersede any ruleset configuration you might have defined. This way, you don't have to define 2 separate layers to distinguish between layers external API and its private implementation.

## Violations

If we have 2 layers (*Models*, *Controller*) and one layer is using the other,
Expand Down
3 changes: 3 additions & 0 deletions src/Analyser/AstMapExtractor.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
use Qossmic\Deptrac\Ast\AstMap\AstMap;
use Qossmic\Deptrac\InputCollector\InputCollectorInterface;

/**
* @internal
*/
class AstMapExtractor
{
private InputCollectorInterface $inputCollector;
Expand Down
13 changes: 13 additions & 0 deletions src/Analyser/EventHandler/AllowDependencyHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -5,12 +5,16 @@
namespace Qossmic\Deptrac\Analyser\EventHandler;

use Qossmic\Deptrac\Analyser\Event\ProcessEvent;
use Qossmic\Deptrac\Ast\AstMap\ClassLike\ClassLikeReference;
use Qossmic\Deptrac\Layer\Exception\CircularReferenceException;
use Qossmic\Deptrac\Layer\LayerProvider;
use Qossmic\Deptrac\Result\Allowed;
use Qossmic\Deptrac\Result\Error;
use function in_array;

/**
* @internal
*/
class AllowDependencyHandler
{
private LayerProvider $layerProvider;
Expand Down Expand Up @@ -40,6 +44,15 @@ public function __invoke(ProcessEvent $event): void
return;
}

if ($dependerLayer !== $dependentLayer) {
$dependentReference = $event->getDependentReference();
if (($dependentReference instanceof ClassLikeReference)
&& $dependentReference->isInternal()
) {
return;
}
}

$ruleset->add(new Allowed($dependency, $dependerLayer, $dependentLayer));

$event->stopPropagation();
Expand Down
3 changes: 3 additions & 0 deletions src/Analyser/EventHandler/MatchingLayersHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,9 @@

use Qossmic\Deptrac\Analyser\Event\ProcessEvent;

/**
* @internal
*/
class MatchingLayersHandler
{
public function __invoke(ProcessEvent $event): void
Expand Down
2 changes: 2 additions & 0 deletions src/Analyser/EventHandler/SkippedViolationHelper.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,8 @@

/**
* @psalm-immutable
*
* @internal
*/
final class SkippedViolationHelper
{
Expand Down
3 changes: 3 additions & 0 deletions src/Analyser/EventHandler/UncoveredDependentHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
use Qossmic\Deptrac\Ast\AstMap\ClassLike\ClassLikeToken;
use Qossmic\Deptrac\Result\Uncovered;

/**
* @internal
*/
class UncoveredDependentHandler
{
private bool $ignoreUncoveredInternalClasses;
Expand Down
3 changes: 3 additions & 0 deletions src/Analyser/EventHandler/ViolationHandler.php
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@
use Qossmic\Deptrac\Result\Violation;
use function sprintf;

/**
* @internal
*/
class ViolationHandler
{
private SkippedViolationHelper $skippedViolationHelper;
Expand Down
10 changes: 9 additions & 1 deletion src/Ast/AstMap/ClassLike/ClassLikeReference.php
Original file line number Diff line number Diff line change
Expand Up @@ -25,16 +25,19 @@ class ClassLikeReference implements TokenReferenceInterface
/** @var AstInherit[] */
private array $inherits;

private bool $isInternal;

/**
* @param AstInherit[] $inherits
* @param DependencyToken[] $dependencies
*/
public function __construct(ClassLikeToken $classLikeName, ClassLikeType $classLikeType = null, array $inherits = [], array $dependencies = [])
public function __construct(ClassLikeToken $classLikeName, ClassLikeType $classLikeType = null, array $inherits = [], array $dependencies = [], bool $isInternal = false)
{
$this->classLikeName = $classLikeName;
$this->classLikeType = $classLikeType ?? ClassLikeType::classLike();
$this->dependencies = $dependencies;
$this->inherits = $inherits;
$this->isInternal = $isInternal;
}

public function withFileReference(FileReference $astFileReference): self
Expand Down Expand Up @@ -75,4 +78,9 @@ public function getInherits(): array
{
return $this->inherits;
}

public function isInternal(): bool
{
return $this->isInternal;
}
}
29 changes: 19 additions & 10 deletions src/Ast/AstMap/ClassLike/ClassLikeReferenceBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -16,47 +16,50 @@ final class ClassLikeReferenceBuilder extends ReferenceBuilder
/** @var AstInherit[] */
private array $inherits = [];

private bool $isInternal;

/**
* @param string[] $tokenTemplates
*/
protected function __construct(array $tokenTemplates, string $filepath, ClassLikeToken $classLikeToken, ClassLikeType $classLikeType)
protected function __construct(array $tokenTemplates, string $filepath, ClassLikeToken $classLikeToken, ClassLikeType $classLikeType, bool $isInternal)
{
parent::__construct($tokenTemplates, $filepath);

$this->classLikeToken = $classLikeToken;
$this->classLikeType = $classLikeType;
$this->isInternal = $isInternal;
}

/**
* @param string[] $classTemplates
*/
public static function createClassLike(string $filepath, string $classLikeName, array $classTemplates): self
public static function createClassLike(string $filepath, string $classLikeName, array $classTemplates, bool $isInternal): self
{
return new self($classTemplates, $filepath, ClassLikeToken::fromFQCN($classLikeName), ClassLikeType::classLike());
return new self($classTemplates, $filepath, ClassLikeToken::fromFQCN($classLikeName), ClassLikeType::classLike(), $isInternal);
}

/**
* @param string[] $classTemplates
*/
public static function createClass(string $filepath, string $classLikeName, array $classTemplates): self
public static function createClass(string $filepath, string $classLikeName, array $classTemplates, bool $isInternal): self
{
return new self($classTemplates, $filepath, ClassLikeToken::fromFQCN($classLikeName), ClassLikeType::class());
return new self($classTemplates, $filepath, ClassLikeToken::fromFQCN($classLikeName), ClassLikeType::class(), $isInternal);
}

/**
* @param string[] $classTemplates
*/
public static function createTrait(string $filepath, string $classLikeName, array $classTemplates): self
public static function createTrait(string $filepath, string $classLikeName, array $classTemplates, bool $isInternal): self
{
return new self($classTemplates, $filepath, ClassLikeToken::fromFQCN($classLikeName), ClassLikeType::trait());
return new self($classTemplates, $filepath, ClassLikeToken::fromFQCN($classLikeName), ClassLikeType::trait(), $isInternal);
}

/**
* @param string[] $classTemplates
*/
public static function createInterface(string $filepath, string $classLikeName, array $classTemplates): self
public static function createInterface(string $filepath, string $classLikeName, array $classTemplates, bool $isInternal): self
{
return new self($classTemplates, $filepath, ClassLikeToken::fromFQCN($classLikeName), ClassLikeType::interface());
return new self($classTemplates, $filepath, ClassLikeToken::fromFQCN($classLikeName), ClassLikeType::interface(), $isInternal);
}

/** @internal */
Expand All @@ -66,7 +69,8 @@ public function build(): ClassLikeReference
$this->classLikeToken,
$this->classLikeType,
$this->inherits,
$this->dependencies
$this->dependencies,
$this->isInternal
);
}

Expand Down Expand Up @@ -99,4 +103,9 @@ public function trait(string $classLikeName, int $occursAtLine): self

return $this;
}

public function isInternal(): bool
{
return $this->isInternal;
}
}
16 changes: 8 additions & 8 deletions src/Ast/AstMap/File/FileReferenceBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -38,9 +38,9 @@ public function useStatement(string $classLikeName, int $occursAtLine): self
/**
* @param string[] $templateTypes
*/
public function newClass(string $classLikeName, array $templateTypes = []): ClassLikeReferenceBuilder
public function newClass(string $classLikeName, array $templateTypes, bool $isInternal): ClassLikeReferenceBuilder
{
$classReference = ClassLikeReferenceBuilder::createClass($this->filepath, $classLikeName, $templateTypes);
$classReference = ClassLikeReferenceBuilder::createClass($this->filepath, $classLikeName, $templateTypes, $isInternal);
$this->classReferences[] = $classReference;

return $classReference;
Expand All @@ -49,9 +49,9 @@ public function newClass(string $classLikeName, array $templateTypes = []): Clas
/**
* @param string[] $templateTypes
*/
public function newTrait(string $classLikeName, array $templateTypes = []): ClassLikeReferenceBuilder
public function newTrait(string $classLikeName, array $templateTypes, bool $isInternal): ClassLikeReferenceBuilder
{
$classReference = ClassLikeReferenceBuilder::createTrait($this->filepath, $classLikeName, $templateTypes);
$classReference = ClassLikeReferenceBuilder::createTrait($this->filepath, $classLikeName, $templateTypes, $isInternal);
$this->classReferences[] = $classReference;

return $classReference;
Expand All @@ -60,9 +60,9 @@ public function newTrait(string $classLikeName, array $templateTypes = []): Clas
/**
* @param string[] $templateTypes
*/
public function newClassLike(string $classLikeName, array $templateTypes = []): ClassLikeReferenceBuilder
public function newClassLike(string $classLikeName, array $templateTypes, bool $isInternal): ClassLikeReferenceBuilder
{
$classReference = ClassLikeReferenceBuilder::createClassLike($this->filepath, $classLikeName, $templateTypes);
$classReference = ClassLikeReferenceBuilder::createClassLike($this->filepath, $classLikeName, $templateTypes, $isInternal);
$this->classReferences[] = $classReference;

return $classReference;
Expand All @@ -71,9 +71,9 @@ public function newClassLike(string $classLikeName, array $templateTypes = []):
/**
* @param string[] $templateTypes
*/
public function newInterface(string $classLikeName, array $templateTypes = []): ClassLikeReferenceBuilder
public function newInterface(string $classLikeName, array $templateTypes, bool $isInternal): ClassLikeReferenceBuilder
{
$classReference = ClassLikeReferenceBuilder::createInterface($this->filepath, $classLikeName, $templateTypes);
$classReference = ClassLikeReferenceBuilder::createInterface($this->filepath, $classLikeName, $templateTypes, $isInternal);
$this->classReferences[] = $classReference;

return $classReference;
Expand Down
16 changes: 12 additions & 4 deletions src/Ast/Parser/NikicPhpParser/FileReferenceVisitor.php
Original file line number Diff line number Diff line change
Expand Up @@ -246,8 +246,16 @@ public function leaveNode(Node $node)

private function enterClassLike(string $name, ClassLike $node): void
{
$isInternal = false;
$docComment = $node->getDocComment();
if (null !== $docComment) {
$tokens = new TokenIterator($this->lexer->tokenize($docComment->getText()));
$docNode = $this->docParser->parse($tokens);
$isInternal = [] !== array_merge($docNode->getTagsByName('@internal'), $docNode->getTagsByName('@deptrac-internal'));
}

if ($node instanceof Interface_) {
$this->currentReference = $this->fileReferenceBuilder->newInterface($name, $this->templatesFromDocs($node));
$this->currentReference = $this->fileReferenceBuilder->newInterface($name, $this->templatesFromDocs($node), $isInternal);

foreach ($node->extends as $extend) {
$this->currentReference->implements($extend->toCodeString(), $extend->getLine());
Expand All @@ -257,7 +265,7 @@ private function enterClassLike(string $name, ClassLike $node): void
}

if ($node instanceof Class_) {
$this->currentReference = $this->fileReferenceBuilder->newClass($name, $this->templatesFromDocs($node));
$this->currentReference = $this->fileReferenceBuilder->newClass($name, $this->templatesFromDocs($node), $isInternal);
if ($node->extends instanceof Name) {
$this->currentReference->extends($node->extends->toCodeString(), $node->extends->getLine());
}
Expand All @@ -270,12 +278,12 @@ private function enterClassLike(string $name, ClassLike $node): void
}

if ($node instanceof Trait_) {
$this->currentReference = $this->fileReferenceBuilder->newTrait($name, $this->templatesFromDocs($node));
$this->currentReference = $this->fileReferenceBuilder->newTrait($name, $this->templatesFromDocs($node), $isInternal);

return;
}

$this->currentReference = $this->fileReferenceBuilder->newClassLike($name, $this->templatesFromDocs($node));
$this->currentReference = $this->fileReferenceBuilder->newClassLike($name, $this->templatesFromDocs($node), $isInternal);
}

private function enterFunction(string $name, Node\Stmt\Function_ $node): void
Expand Down
3 changes: 3 additions & 0 deletions src/File/Exception/CouldNotReadFileException.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
use Qossmic\Deptrac\Exception\ExceptionInterface;
use RuntimeException;

/**
* @internal
*/
final class CouldNotReadFileException extends RuntimeException implements ExceptionInterface
{
public static function fromFilename(string $filename): self
Expand Down
3 changes: 3 additions & 0 deletions src/File/Exception/FileCannotBeParsedAsYamlException.php
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,9 @@
use RuntimeException;
use Symfony\Component\Yaml\Exception\ParseException;

/**
* @internal
*/
final class FileCannotBeParsedAsYamlException extends RuntimeException implements ExceptionInterface
{
public static function fromFilenameAndException(string $filename, ParseException $exception): self
Expand Down
3 changes: 3 additions & 0 deletions src/File/Exception/ParsedYamlIsNotAnArrayException.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
use Qossmic\Deptrac\Exception\ExceptionInterface;
use RuntimeException;

/**
* @internal
*/
final class ParsedYamlIsNotAnArrayException extends RuntimeException implements ExceptionInterface
{
public static function fromFilename(string $filename): self
Expand Down
3 changes: 3 additions & 0 deletions src/File/YmlFileLoader.php
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,9 @@
use Symfony\Component\Yaml\Exception\ParseException;
use Symfony\Component\Yaml\Yaml;

/**
* @internal
*/
class YmlFileLoader
{
/**
Expand Down
3 changes: 3 additions & 0 deletions src/InputCollector/FileInputCollector.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
use Symfony\Component\Filesystem\Path;
use Symfony\Component\Finder\Finder;

/**
* @internal
*/
final class FileInputCollector implements InputCollectorInterface
{
/**
Expand Down
3 changes: 3 additions & 0 deletions src/OutputFormatter/BaselineOutputFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
use function ksort;
use function sort;

/**
* @internal
*/
final class BaselineOutputFormatter implements OutputFormatterInterface
{
private const DEFAULT_PATH = './deptrac.baseline.yaml';
Expand Down
3 changes: 3 additions & 0 deletions src/OutputFormatter/CodeclimateOutputFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,9 @@
use function sprintf;
use const JSON_PRETTY_PRINT;

/**
* @internal
*/
final class CodeclimateOutputFormatter implements OutputFormatterInterface
{
/**
Expand Down
3 changes: 3 additions & 0 deletions src/OutputFormatter/ConsoleOutputFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,9 @@
use Qossmic\Deptrac\Result\Violation;
use function count;

/**
* @internal
*/
final class ConsoleOutputFormatter implements OutputFormatterInterface
{
public static function getName(): string
Expand Down
3 changes: 3 additions & 0 deletions src/OutputFormatter/GraphVizOutputDisplayFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
use Qossmic\Deptrac\Configuration\OutputFormatterInput;
use Qossmic\Deptrac\Console\Output;

/**
* @internal
*/
final class GraphVizOutputDisplayFormatter extends GraphVizOutputFormatter
{
/** @var positive-int */
Expand Down
3 changes: 3 additions & 0 deletions src/OutputFormatter/GraphVizOutputDotFormatter.php
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,9 @@
use Qossmic\Deptrac\Configuration\OutputFormatterInput;
use Qossmic\Deptrac\Console\Output;

/**
* @internal
*/
final class GraphVizOutputDotFormatter extends GraphVizOutputFormatter
{
public static function getName(): string
Expand Down
Loading