Completed
Push — master ( 296743...12eab9 )
by Kirill
36:17
created

validateListInverseRedefinition()   A

Complexity

Conditions 3
Paths 4

Size

Total Lines 9

Duplication

Lines 9
Ratio 100 %

Code Coverage

Tests 6
CRAP Score 3

Importance

Changes 0
Metric Value
dl 9
loc 9
ccs 6
cts 6
cp 1
rs 9.9666
c 0
b 0
f 0
cc 3
nc 4
nop 2
crap 3
1
<?php
2
/**
3
 * This file is part of Railt package.
4
 *
5
 * For the full copyright and license information, please view the LICENSE
6
 * file that was distributed with this source code.
7
 */
8
declare(strict_types=1);
9
10
namespace Railt\SDL\Reflection\Validation\Inheritance;
11
12
use Railt\SDL\Contracts\Behavior\AllowsTypeIndication;
13
use Railt\SDL\Contracts\Definitions\TypeDefinition;
14
use Railt\SDL\Contracts\Dependent\DependentDefinition;
15
use Railt\SDL\Exceptions\TypeConflictException;
16
17
/**
18
 * Validation of arguments and fields inheritance.
19
 */
20
class WrapperValidator extends BaseInheritanceValidator
21
{
22
    /**
23
     * @param AllowsTypeIndication|TypeDefinition $child
24
     * @param AllowsTypeIndication|TypeDefinition $parent
25
     * @return bool
26
     */
27 270
    public function match(TypeDefinition $child, TypeDefinition $parent): bool
28
    {
29 270
        return $child instanceof AllowsTypeIndication &&
30 270
            $parent instanceof AllowsTypeIndication;
31
    }
32
33
    /**
34
     * @param AllowsTypeIndication|TypeDefinition $child
35
     * @param AllowsTypeIndication|TypeDefinition $parent
36
     * @return void
37
     * @throws \Railt\SDL\Exceptions\TypeConflictException
38
     * @throws \OutOfBoundsException
39
     */
40 270
    public function validate(TypeDefinition $child, TypeDefinition $parent): void
41
    {
42
        /**
43
         * We check that the List type is redefined by the List type
44
         */
45 270
        $this->validateListType($child, $parent);
0 ignored issues
show
Documentation introduced by
$child is of type object<Railt\SDL\Contrac...nitions\TypeDefinition>, but the function expects a object<Railt\SDL\Contrac...r\AllowsTypeIndication>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
$parent is of type object<Railt\SDL\Contrac...nitions\TypeDefinition>, but the function expects a object<Railt\SDL\Contrac...r\AllowsTypeIndication>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
46
47
        /**
48
         * We check that the Nullable/NonNull reference is correctly
49
         * overridden by another Nullable/NonNull signature.
50
         */
51 238
        if ($this->isPostCondition($child)) {
0 ignored issues
show
Documentation introduced by
$child is of type object<Railt\SDL\Contrac...nitions\TypeDefinition>, but the function expects a object<Railt\SDL\Contrac...r\AllowsTypeIndication>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
52 238
            $this->validatePostconditionalInheritance($child, $parent);
0 ignored issues
show
Documentation introduced by
$child is of type object<Railt\SDL\Contrac...nitions\TypeDefinition>, but the function expects a object<Railt\SDL\Contrac...r\AllowsTypeIndication>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
$parent is of type object<Railt\SDL\Contrac...nitions\TypeDefinition>, but the function expects a object<Railt\SDL\Contrac...r\AllowsTypeIndication>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
53
        } else {
54 56
            $this->validatePreconditionalInheritance($child, $parent);
0 ignored issues
show
Documentation introduced by
$child is of type object<Railt\SDL\Contrac...nitions\TypeDefinition>, but the function expects a object<Railt\SDL\Contrac...r\AllowsTypeIndication>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
Documentation introduced by
$parent is of type object<Railt\SDL\Contrac...nitions\TypeDefinition>, but the function expects a object<Railt\SDL\Contrac...r\AllowsTypeIndication>.

It seems like the type of the argument is not accepted by the function/method which you are calling.

In some cases, in particular if PHP’s automatic type-juggling kicks in this might be fine. In other cases, however this might be a bug.

We suggest to add an explicit type cast like in the following example:

function acceptsInteger($int) { }

$x = '123'; // string "123"

// Instead of
acceptsInteger($x);

// we recommend to use
acceptsInteger((integer) $x);
Loading history...
55
        }
56 230
    }
57
58
    /**
59
     * @param AllowsTypeIndication $child
60
     * @param AllowsTypeIndication $parent
61
     * @return void
62
     * @throws TypeConflictException
63
     */
64 270
    private function validateListType(AllowsTypeIndication $child, AllowsTypeIndication $parent): void
65
    {
66 270
        $this->validateListDirectRedefinition($child, $parent);
67 254
        $this->validateListInverseRedefinition($child, $parent);
68 238
    }
69
70
    /**
71
     * Checks the following situations:
72
     * <code>
73
     *  - [Type]   overriden by Type
74
     *  - [Type]   overriden by Type!
75
     *  - [Type]!  overriden by Type
76
     *  - [Type]!  overriden by Type!
77
     *  - [Type!]  overriden by Type
78
     *  - [Type!]  overriden by Type!
79
     *  - [Type!]! overriden by Type
80
     *  - [Type!]! overriden by Type!
81
     * </code>
82
     *
83
     * @param AllowsTypeIndication $child
84
     * @param AllowsTypeIndication $parent
85
     * @return void
86
     * @throws TypeConflictException
87
     */
88 270 View Code Duplication
    private function validateListDirectRedefinition(AllowsTypeIndication $child, AllowsTypeIndication $parent): void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
89
    {
90 270
        $isBrokenDirectRedefinition = $parent->isList() && ! $child->isList();
91
92 270
        if ($isBrokenDirectRedefinition) {
93 16
            $error = \sprintf('The %s cannot be overridden by non-list, but %s given', $parent, $child);
94 16
            throw new TypeConflictException($error, $this->getCallStack());
95
        }
96 254
    }
97
98
    /**
99
     * Checks the following situations:
100
     * <code>
101
     *  - Type  overriden by [Type]
102
     *  - Type! overriden by [Type]
103
     *  - Type  overriden by [Type]!
104
     *  - Type! overriden by [Type]!
105
     *  - Type  overriden by [Type!]
106
     *  - Type! overriden by [Type!]
107
     *  - Type  overriden by [Type!]!
108
     *  - Type! overriden by [Type!]!
109
     * </code>
110
     *
111
     * @param AllowsTypeIndication $child
112
     * @param AllowsTypeIndication $parent
113
     * @return void
114
     * @throws TypeConflictException
115
     */
116 254 View Code Duplication
    private function validateListInverseRedefinition(AllowsTypeIndication $child, AllowsTypeIndication $parent): void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
117
    {
118 254
        $isBrokenInverseRedefinition = ! $parent->isList() && $child->isList();
119
120 254
        if ($isBrokenInverseRedefinition) {
121 16
            $error = \sprintf('The %s cannot be overridden by list, but %s given', $parent, $child);
122 16
            throw new TypeConflictException($error, $this->getCallStack());
123
        }
124 238
    }
125
126
    /**
127
     * @param AllowsTypeIndication|DependentDefinition $child
128
     * @param AllowsTypeIndication|DependentDefinition $parent
129
     * @return void
130
     * @throws TypeConflictException
131
     */
132 238 View Code Duplication
    private function validatePostconditionalInheritance(AllowsTypeIndication $child, AllowsTypeIndication $parent): void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
133
    {
134 238
        $invalidWrapperInheritance = $parent->isNonNull() && ! $child->isNonNull();
135
136 238
        $invalidListWrapperInheritance = $this->isSameWrapperList($child, $parent) &&
137 238
            $parent->isListOfNonNulls() && ! $child->isListOfNonNulls();
138
139 238
        if ($invalidWrapperInheritance || $invalidListWrapperInheritance) {
140 8
            $error = '%s postcondition of %s can not be weakened by %s of %s';
141 8
            $error = \sprintf($error, $parent, $parent->getParent(), $child, $child->getParent());
142
143 8
            throw new TypeConflictException($error, $this->getCallStack());
144
        }
145 230
    }
146
147
    /**
148
     * @param AllowsTypeIndication|DependentDefinition $child
149
     * @param AllowsTypeIndication|DependentDefinition $parent
150
     * @return void
151
     * @throws \Railt\SDL\Exceptions\TypeConflictException
152
     */
153 56 View Code Duplication
    private function validatePreconditionalInheritance(AllowsTypeIndication $child, AllowsTypeIndication $parent): void
0 ignored issues
show
Duplication introduced by
This method seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
154
    {
155 56
        $invalidWrapperInheritance = ! $parent->isNonNull() && $child->isNonNull();
156
157 56
        $invalidListWrapperInheritance = $this->isSameWrapperList($child, $parent) &&
158 56
            ! $parent->isListOfNonNulls() && $child->isListOfNonNulls();
159
160 56
        if ($invalidWrapperInheritance || $invalidListWrapperInheritance) {
161
            $error = '%s precondition of %s can not be strengthened by %s of %s';
162
            $error = \sprintf($error, $parent, $parent->getParent(), $child, $child->getParent());
163
164
            throw new TypeConflictException($error, $this->getCallStack());
165
        }
166 56
    }
167
168
    /**
169
     * @param AllowsTypeIndication $child
170
     * @param AllowsTypeIndication $parent
171
     * @return bool
172
     */
173 238
    private function isSameWrapperList(AllowsTypeIndication $child, AllowsTypeIndication $parent): bool
174
    {
175 238
        return $child->isList() === $parent->isList();
176
    }
177
}
178