Skip to content

Commit

Permalink
Merge pull request #26 from MontealegreLuis/enums
Browse files Browse the repository at this point in the history
Add support for enumerations
  • Loading branch information
MontealegreLuis authored Jun 20, 2022
2 parents 1ba30a0 + 5be1314 commit 8ac47c5
Show file tree
Hide file tree
Showing 77 changed files with 1,277 additions and 482 deletions.
5 changes: 3 additions & 2 deletions containers/tests/Dockerfile
Original file line number Diff line number Diff line change
@@ -1,10 +1,11 @@
FROM php:8.1.1-cli-alpine3.15

RUN apk add --update --no-cache autoconf g++ pkgconfig imagemagick imagemagick-dev make ttf-freefont graphviz \
RUN apk add --update --no-cache autoconf g++ pkgconfig imagemagick imagemagick-dev make ttf-freefont graphviz git \
&& printf "\n" | pecl install imagick \
&& echo "extension=imagick.so" >> /usr/local/etc/php/php.ini \
&& printf "\n" | pecl install xdebug \
&& echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)" > /usr/local/etc/php/conf.d/xdebug.ini
&& echo "zend_extension=$(find /usr/local/lib/php/extensions/ -name xdebug.so)" > /usr/local/etc/php/conf.d/xdebug.ini \
&& git config --global --add safe.directory /usr/src/phuml

RUN mkdir -p /usr/src/phuml

Expand Down
12 changes: 9 additions & 3 deletions docs/format.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,10 +10,16 @@ currentMenu: format
* Static methods and functions are shown underlined
* Abstract classes, abstract methods and interfaces names are shown in *italics*

## Traits and Attributes
## Traits, Attributes, and Enums

[Traits](https://www.php.net/manual/en/language.oop5.traits.php) and class [attributes](https://www.php.net/manual/en/language.attributes.overview.php)(annotations) will be shown with a [UML stereotype](https://www.uml-diagrams.org/stereotype.html).
Traits will be shown with the `<<trait>>` stereotype above its name, and attributes (annotations) will be shown with the `<<attribute>>` stereotype above its name.
[Traits](https://www.php.net/manual/en/language.oop5.traits.php), class [attributes](https://www.php.net/manual/en/language.attributes.overview.php)(annotations), and [enumerations](https://www.php.net/manual/en/language.enumerations.php) will be shown with a [UML stereotype](https://www.uml-diagrams.org/stereotype.html) above its name.
Traits will be shown with the `<<trait>>` stereotype, attributes (annotations) will be shown with the `<<attribute>>` stereotype, and enumerations will be shown with the `<<enum>>` stereotype.

## Enumerations

Case definitions in enumerations will be shown without a visibility modifier (`+`, `-`, `#`) and to differentiate them from constants, cases won't be in italics.

If an enum defines constants, they will be shown above its cases.

## Relationships

Expand Down
20 changes: 5 additions & 15 deletions src/Code/ClassDefinition.php
Original file line number Diff line number Diff line change
Expand Up @@ -20,11 +20,12 @@
/**
* It represents a class definition
*/
final class ClassDefinition extends Definition implements HasProperties, HasConstants, CanBeAbstract, UseTraits
final class ClassDefinition extends Definition implements HasProperties, HasConstants, CanBeAbstract, UseTraits, ImplementsInterfaces
{
use WithProperties;
use WithConstants;
use WithTraits;
use WithInterfaces;

/**
* @param Method[] $methods
Expand All @@ -39,13 +40,14 @@ public function __construct(
array $constants = [],
private readonly ?Name $parent = null,
array $properties = [],
private readonly array $interfaces = [],
array $interfaces = [],
array $traits = [],
private readonly bool $isAttribute = false
) {
parent::__construct($name, $methods);
$this->constants = $constants;
$this->properties = $properties;
$this->interfaces = $interfaces;
$this->traits = $traits;
}

Expand All @@ -54,7 +56,7 @@ public function __construct(
* classes via the constructor
*
* @return Parameter[]
* @see \PhUml\Graphviz\Builders\AssociationsBuilder::fromProperties() for more details
* @see \PhUml\Graphviz\Builders\EdgesBuilder::fromProperties() for more details
*/
public function constructorParameters(): array
{
Expand Down Expand Up @@ -91,18 +93,6 @@ public function countTypedPropertiesByVisibility(Visibility $visibility): int
));
}

/**
* It is used by the `ClassGraphBuilder` to create the edges to represent implementation
* associations
*
* @return Name[]
* @see \PhUml\Graphviz\Builders\ClassGraphBuilder::extractFrom() for more details
*/
public function interfaces(): array
{
return $this->interfaces;
}

/**
* It is used by the `ClassGraphBuilder` to create the edge to represent inheritance
*
Expand Down
51 changes: 51 additions & 0 deletions src/Code/EnumDefinition.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
<?php declare(strict_types=1);
/**
* This source file is subject to the license that is bundled with this package in the file LICENSE.
*/

namespace PhUml\Code;

use PhUml\Code\Methods\Method;
use PhUml\Code\Properties\Constant;
use PhUml\Code\Properties\EnumCase;
use PhUml\Code\Properties\HasConstants;
use PhUml\Code\Properties\WithConstants;

final class EnumDefinition extends Definition implements HasConstants, UseTraits, ImplementsInterfaces
{
use WithConstants;
use WithTraits;
use WithInterfaces;

/**
* @param Method[] $methods
* @param EnumCase[] $cases
* @param Constant[] $constants
* @param Name[] $interfaces
* @param Name[] $traits
*/
public function __construct(
Name $name,
private readonly array $cases,
array $methods = [],
array $constants = [],
array $interfaces = [],
array $traits = [],
) {
parent::__construct($name, $methods);
$this->constants = $constants;
$this->traits = $traits;
$this->interfaces = $interfaces;
}

public function hasProperties(): bool
{
return $this->cases !== [] || $this->constants !== [];
}

/** @return EnumCase[] */
public function cases(): array
{
return $this->cases;
}
}
12 changes: 12 additions & 0 deletions src/Code/ImplementsInterfaces.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
<?php declare(strict_types=1);
/**
* This source file is subject to the license that is bundled with this package in the file LICENSE.
*/

namespace PhUml\Code;

interface ImplementsInterfaces
{
/** @return Name[] */
public function interfaces(): array;
}
20 changes: 20 additions & 0 deletions src/Code/Properties/EnumCase.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
<?php declare(strict_types=1);
/**
* This source file is subject to the license that is bundled with this package in the file LICENSE.
*/

namespace PhUml\Code\Properties;

use Stringable;

final class EnumCase implements Stringable
{
public function __construct(private readonly string $name)
{
}

public function __toString(): string
{
return $this->name;
}
}
4 changes: 2 additions & 2 deletions src/Code/Variables/HasType.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,8 +26,8 @@ public function hasTypeDeclaration(): bool;
/**
* It is used by the `EdgesBuilder` class to mark an association as resolved
*
* @see \PhUml\Graphviz\Builders\EdgesBuilder::needAssociation() for more details
* @see \PhUml\Graphviz\Builders\EdgesBuilder::markAssociationResolvedFor() for more details
* @see \PhUml\Graphviz\Builders\DirectedEdgesBuilder::needAssociation() for more details
* @see \PhUml\Graphviz\Builders\DirectedEdgesBuilder::markAssociationResolvedFor() for more details
*/
public function type(): TypeDeclaration;
}
18 changes: 18 additions & 0 deletions src/Code/WithInterfaces.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
<?php declare(strict_types=1);
/**
* This source file is subject to the license that is bundled with this package in the file LICENSE.
*/

namespace PhUml\Code;

trait WithInterfaces
{
/** @var Name[] */
private readonly array $interfaces;

/** @return Name[] */
public function interfaces(): array
{
return $this->interfaces;
}
}
27 changes: 0 additions & 27 deletions src/Graphviz/Builders/AssociationsBuilder.php

This file was deleted.

6 changes: 3 additions & 3 deletions src/Graphviz/Builders/ClassGraphBuilder.php
Original file line number Diff line number Diff line change
Expand Up @@ -26,12 +26,12 @@ final class ClassGraphBuilder
/** @var HasDotRepresentation[] */
private array $dotElements;

private readonly AssociationsBuilder $associationsBuilder;
private readonly EdgesBuilder $associationsBuilder;

public function __construct(AssociationsBuilder $associationsBuilder = null)
public function __construct(EdgesBuilder $associationsBuilder)
{
$this->dotElements = [];
$this->associationsBuilder = $associationsBuilder ?? new NoAssociationsBuilder();
$this->associationsBuilder = $associationsBuilder;
}

/**
Expand Down
88 changes: 88 additions & 0 deletions src/Graphviz/Builders/DirectedEdgesBuilder.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,88 @@
<?php declare(strict_types=1);
/**
* This source file is subject to the license that is bundled with this package in the file LICENSE.
*/

namespace PhUml\Graphviz\Builders;

use PhUml\Code\ClassDefinition;
use PhUml\Code\Codebase;
use PhUml\Code\Name;
use PhUml\Code\Variables\HasType;
use PhUml\Graphviz\Edge;

/**
* It creates directed edges by inspecting a class
*
* 1. It creates edges by inspecting the properties of a class
* 2. It creates edges by inspecting the parameters of the constructor of a class
*/
final class DirectedEdgesBuilder implements EdgesBuilder
{
/** @var bool[] */
private array $edges = [];

/**
* It creates an edge if the property
*
* - Has type information, and it's not a PHP's built-in type
* - The association hasn't already been resolved
*
* @return Edge[]
*/
public function fromProperties(ClassDefinition $class, Codebase $codebase): array
{
return $this->buildEdgesFor($class, $class->properties(), $codebase);
}

/**
* It creates an edge if the constructor parameter
*
* - Has type information, and it's not a PHP's built-in type
* - The association hasn't already been resolved
*
* @return Edge[]
*/
public function fromConstructor(ClassDefinition $class, Codebase $codebase): array
{
return $this->buildEdgesFor($class, $class->constructorParameters(), $codebase);
}

/**
* @param HasType[] $variables
* @return Edge[]
*/
private function buildEdgesFor(ClassDefinition $class, array $variables, Codebase $codebase): array
{
$edges = [];
foreach ($variables as $variable) {
$key = EdgeKey::from($class->name(), $variable->type());
if ($this->isAssociationResolved($key)) {
continue;
}

$this->markAssociationResolvedFor($key);
$edges[] = $this->addAssociations($class, $variable, $codebase);
}
return array_merge(...$edges);
}

/** @return Edge[] */
private function addAssociations(ClassDefinition $class, HasType $property, Codebase $codebase): array
{
return array_map(
static fn (Name $reference): Edge => Edge::association($codebase->get($reference), $class),
$property->references()
);
}

private function isAssociationResolved(EdgeKey $key): bool
{
return array_key_exists((string) $key, $this->edges) && $this->edges[(string) $key];
}

private function markAssociationResolvedFor(EdgeKey $key): void
{
$this->edges[(string) $key] = true;
}
}
30 changes: 30 additions & 0 deletions src/Graphviz/Builders/EdgeKey.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php declare(strict_types=1);
/**
* This source file is subject to the license that is bundled with this package in the file LICENSE.
*/

namespace PhUml\Graphviz\Builders;

use PhUml\Code\Name;
use PhUml\Code\Variables\TypeDeclaration;
use Stringable;

final class EdgeKey implements Stringable
{
private readonly string $key;

public static function from(Name $name, TypeDeclaration $type): EdgeKey
{
return new EdgeKey($name . $type);
}

private function __construct(string $key)
{
$this->key = $key;
}

public function __toString(): string
{
return $this->key;
}
}
Loading

0 comments on commit 8ac47c5

Please sign in to comment.