Test Failed
Push — master ( a380eb...a52ae2 )
by Hannes
01:59
created

ExampleFactory::readExample()   A

Complexity

Conditions 3
Paths 3

Size

Total Lines 9
Code Lines 4

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 3
eloc 4
nc 3
nop 2
dl 0
loc 9
rs 10
c 0
b 0
f 0
1
<?php
2
3
declare(strict_types = 1);
4
5
namespace hanneskod\readmetester\Example;
6
7
use hanneskod\readmetester\Annotations;
8
use hanneskod\readmetester\Expectation\ExpectationFactory;
9
use hanneskod\readmetester\Expectation\ExpectationInterface;
10
use hanneskod\readmetester\Name\AnonymousName;
11
use hanneskod\readmetester\Name\ExampleName;
12
use hanneskod\readmetester\Name\NameInterface;
13
use hanneskod\readmetester\Parser\Annotation;
14
use hanneskod\readmetester\Parser\Definition;
15
16
class ExampleFactory
17
{
18
    /**
19
     * @var ExpectationFactory
20
     */
21
    private $expectationFactory;
22
23
    /**
24
     * @var FilterInterface
25
     */
26
    private $filter;
27
28
    /**
29
     * @var bool
30
     */
31
    private $ignoreUnknownAnnotations;
32
33
    public function __construct(
34
        ExpectationFactory $expectationFactory,
35
        FilterInterface $filter,
36
        bool $ignoreUnknownAnnotations = false
37
    ) {
38
        $this->expectationFactory = $expectationFactory;
39
        $this->filter = $filter;
40
        $this->ignoreUnknownAnnotations = $ignoreUnknownAnnotations;
41
    }
42
43
    /**
44
     * Create examples from definitions
45
     *
46
     * @return ExampleInterface[]
47
     */
48
    public function createExamples(Definition ...$defs): array
49
    {
50
        $examples = [];
51
        $context = null;
52
53
        foreach ($defs as $index => $def) {
54
            $name = new AnonymousName('');
55
            $code = $def->getCodeBlock();
56
            $expectations = [];
57
            $ignoreExample = false;
58
59
            if ($context) {
60
                $code = $code->prepend($context);
0 ignored issues
show
Bug introduced by
$context of type void is incompatible with the type hanneskod\readmetester\Parser\CodeBlock expected by parameter $codeBlock of hanneskod\readmetester\Parser\CodeBlock::prepend(). ( Ignorable by Annotation )

If this is a false-positive, you can also ignore this issue in your code via the ignore-type  annotation

60
                $code = $code->prepend(/** @scrutinizer ignore-type */ $context);
Loading history...
61
            }
62
63
            foreach ($def->getAnnotations() as $annotation) {
64
                if ($annotation->isNamed(Annotations::ANNOTATION_IGNORE)) {
65
                    $ignoreExample = true;
66
                    continue;
67
                }
68
69
                if ($annotation->isNamed(Annotations::ANNOTATION_EXAMPLE)) {
70
                    if ($annotation->getArgument()) {
71
                        $name = new ExampleName($annotation->getArgument(), $name->getNamespaceName());
72
                    }
73
                    continue;
74
                }
75
76
                if ($annotation->isNamed(Annotations::ANNOTATION_INCLUDE)) {
77
                    $toInclude = $this->readExample($examples, new ExampleName($annotation->getArgument(), ''));
78
79
                    if (is_null($toInclude)) {
80
                        throw new \RuntimeException(
81
                            "Example '{$annotation->getArgument()}' can not be included in {$name->getShortName()}"
82
                        );
83
                    }
84
85
                    $code = $code->prepend($toInclude->getCodeBlock());
86
                    continue;
87
                }
88
89
                if ($expectation = $this->expectationFactory->createExpectation($annotation)) {
90
                    if ($expectation instanceof ExpectationInterface) {
91
                        $expectations[] = $expectation;
92
                        continue;
93
                    }
94
                }
95
96
                if ($annotation->isNamed(Annotations::ANNOTATION_CONTEXT)) {
97
                    $context = $code;
98
                    continue;
99
                }
100
101
                if (!$this->ignoreUnknownAnnotations) {
102
                    throw new \RuntimeException("Unknown annotation @{$annotation->getName()}");
103
                }
104
            }
105
106
            if ($this->readExample($examples, $name)) {
107
                throw new \RuntimeException("Example '{$name->getShortName()}' already exists");
108
            }
109
110
            if (!$this->filter->isValid($name->getCompleteName())) {
111
                $ignoreExample = true;
112
            }
113
114
            $examples[] = $ignoreExample
115
                ? new IgnoredExample($name, $code, $expectations)
116
                : new Example($name, $code, $expectations);
117
        }
118
119
        return $examples;
120
    }
121
122
    private function readExample(array $examples, NameInterface $name): ?ExampleInterface
123
    {
124
        foreach ($examples as $example) {
125
            if ($example->getName()->equals($name)) {
126
                return $example;
127
            }
128
        }
129
130
        return null;
131
    }
132
}
133