Test Failed
Push — master ( bc5b04...424213 )
by Hannes
03:21
created

ExampleFactory::__construct()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 8
Code Lines 3

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 1
eloc 3
nc 1
nop 3
dl 0
loc 8
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\Parser\Annotation;
11
use hanneskod\readmetester\Parser\Definition;
12
13
/**
14
 * Create Examples objects from Definitions
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 Example[]
47
     */
48
    public function createExamples(Definition ...$defs): array
49
    {
50
        $examples = [];
51
        $context = null;
52
53
        foreach ($defs as $index => $def) {
54
            $name = '';
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
                    $name = $annotation->getArgument() ?: (string)($index + 1);
71
                    continue;
72
                }
73
74
                if ($annotation->isNamed(Annotations::ANNOTATION_INCLUDE)) {
75
                    $toInclude = $annotation->getArgument();
76
77
                    if (!isset($examples[$toInclude])) {
78
                        throw new \RuntimeException(
79
                            "Example '$toInclude' does not exist and can not be included in definition $name"
80
                        );
81
                    }
82
83
                    $code = $code->prepend($examples[$toInclude]->getCodeBlock());
84
                    continue;
85
                }
86
87
                if ($expectation = $this->expectationFactory->createExpectation($annotation)) {
88
                    if ($expectation instanceof ExpectationInterface) {
89
                        $expectations[] = $expectation;
90
                        continue;
91
                    }
92
                }
93
94
                if ($annotation->isNamed(Annotations::ANNOTATION_CONTEXT)) {
95
                    $context = $code;
96
                    continue;
97
                }
98
99
                if (!$this->ignoreUnknownAnnotations) {
100
                    throw new \RuntimeException("Unknown annotation @{$annotation->getName()}");
101
                }
102
            }
103
104
            if (isset($examples[$name])) {
105
                throw new \RuntimeException("Example '$name' already exists in definition " . ($index + 1));
106
            }
107
108
            if (!$this->filter->isValid($name)) {
109
                $ignoreExample = true;
110
            }
111
112
            if (!$name) {
113
                $name = (string)($index + 1);
114
            }
115
116
            $examples[$name] = $ignoreExample
117
                ? new IgnoredExample($name, $code, $expectations)
118
                : new Example($name, $code, $expectations);
119
        }
120
121
        return $examples;
122
    }
123
}
124