GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.

TypeSystem::getBinaryOperation()   C
last analyzed

Complexity

Conditions 7
Paths 4

Size

Total Lines 23
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
dl 0
loc 23
rs 6.7272
c 0
b 0
f 0
cc 7
eloc 14
nc 4
nop 3
1
<?php
2
3
namespace Pinq\Analysis;
4
5
use Pinq\Analysis\BinaryOperations\BinaryOperation;
6
use Pinq\Analysis\TypeOperations\TypeOperation;
7
use Pinq\Expressions\Operators;
8
9
/**
10
 * Base class of the type system.
11
 *
12
 * @author Elliot Levin <[email protected]>
13
 */
14
abstract class TypeSystem implements ITypeSystem
15
{
16
    /**
17
     * @var INativeType[]
18
     */
19
    protected $nativeTypes = [];
20
21
    /**
22
     * @var IObjectType[]
23
     */
24
    protected $objectTypes = [];
25
26
    /**
27
     * @var ICompositeType[]
28
     */
29
    protected $compositeTypes = [];
30
31
    /**
32
     * @var IType[]
33
     */
34
    protected $customTypes = [];
35
36
    /**
37
     * @var IFunction[]
38
     */
39
    protected $functions = [];
40
41
    /**
42
     * @var IBinaryOperation[]
43
     */
44
    protected $binaryOperations = [];
45
46
    public function __construct()
47
    {
48
        foreach ($this->buildNativeTypes() as $nativeType) {
49
            $this->nativeTypes[$nativeType->getTypeOfType()] = $nativeType;
50
        }
51
52
        foreach ($this->buildBinaryOperations() as $binaryOperation) {
53
            $this->binaryOperations[] = $binaryOperation;
54
        }
55
    }
56
57
    /**
58
     * Performs all necessary normalization to the class name.
59
     *
60
     * @param string $name
61
     *
62
     * @return string
63
     */
64
    protected function normalizeClassName($name)
65
    {
66
        return $name;
67
    }
68
69
    /**
70
     * Performs all necessary normalization the function name.
71
     *
72
     * @param string $name
73
     *
74
     * @return string
75
     */
76
    protected function normalizeFunctionName($name)
77
    {
78
        return $name;
79
    }
80
81
    protected function buildTypeOperations($type, array $operatorTypeMap = [])
82
    {
83
        return array_map(
84
                function ($returnType) use ($type) {
85
                    return new TypeOperation($this, $type, $returnType);
86
                },
87
                $operatorTypeMap
88
        );
89
    }
90
91
    /**
92
     * @return INativeType[]
93
     */
94
    abstract protected function nativeTypes();
95
96
    /**
97
     * @return INativeType[]
98
     */
99
    protected function buildNativeTypes()
100
    {
101
        return $this->nativeTypes();
102
    }
103
104
    /**
105
     * @return array[]
106
     */
107
    abstract protected function binaryOperations();
108
109
    /**
110
     * @return IBinaryOperation[]
111
     */
112
    protected function buildBinaryOperations()
113
    {
114
        $binaryOperations = [];
115
        foreach ($this->binaryOperations() as $operator) {
116
            $binaryOperations[] = new BinaryOperation($this, $operator[0], $operator[1], $operator[2], $operator['return']);
117
        }
118
119
        return $binaryOperations;
120
    }
121
122
    public function getType($typeIdentifier)
123
    {
124
        if (TypeId::isObject($typeIdentifier)) {
125
            return $this->getObjectType(TypeId::getClassTypeFromId($typeIdentifier));
126
        } elseif (TypeId::isComposite($typeIdentifier)) {
127
            return $this->getCompositeType(
128
                    array_map([$this, __FUNCTION__], TypeId::getComposedTypeIdsFromId($typeIdentifier))
129
            );
130
        } else {
131
            return $this->getNativeType($typeIdentifier);
132
        }
133
    }
134
135
    public function getNativeType($nativeType)
136
    {
137
        if (!isset($this->nativeTypes[$nativeType])) {
138
            throw new TypeException('Cannot get native type \'%s\': type is not supported', $nativeType);
139
        }
140
141
        return $this->nativeTypes[$nativeType];
142
    }
143
144
    /**
145
     * @param string $typeId
146
     * @param string $classType
147
     *
148
     * @return IObjectType
149
     */
150
    abstract protected function buildObjectType($typeId, $classType);
151
152
    public function getObjectType($classType)
153
    {
154
        $normalizedClassType = $this->normalizeClassName($classType);
155
        $typeId = TypeId::getObject($normalizedClassType);
156
        if (!isset($this->objectTypes[$typeId])) {
157
            $this->objectTypes[$typeId] = $this->buildObjectType($typeId, $normalizedClassType);
158
        }
159
160
        return $this->objectTypes[$typeId];
161
    }
162
163
    /**
164
     * @param string  $typeId
165
     * @param IType[] $types
166
     *
167
     * @return ICompositeType
168
     */
169
    abstract protected function buildCompositeType($typeId, array $types);
170
171
    public function getCompositeType(array $types)
172
    {
173
        $types = $this->flattenComposedTypes($types);
174
175
        //Remove any redundant types: (\Iterator and \Traversable) becomes \Iterator
176
        /** @var $types IType[] */
177
        foreach ($types as $outer => $outerType) {
178
            foreach ($types as $inner => $innerType) {
179
                if ($outer !== $inner && $innerType->isParentTypeOf($outerType)) {
180
                    unset($types[$inner]);
181
                }
182
            }
183
        }
184
185
        if (count($types) === 0) {
186
            return $this->getNativeType(INativeType::TYPE_MIXED);
187
        } elseif (count($types) === 1) {
188
            return reset($types);
0 ignored issues
show
Comprehensibility Best Practice introduced by
The expression reset($types); of type Pinq\Analysis\IType|false adds false to the return on line 188 which is incompatible with the return type declared by the interface Pinq\Analysis\ITypeSystem::getCompositeType of type Pinq\Analysis\IType. It seems like you forgot to handle an error condition.
Loading history...
189
        }
190
191
        ksort($types, SORT_STRING);
192
        $typeId = TypeId::getComposite(array_keys($types));
193
        if (!isset($this->compositeTypes[$typeId])) {
194
            $this->compositeTypes[$typeId] = $this->buildCompositeType($typeId, $types);
195
        }
196
197
        return $this->compositeTypes[$typeId];
198
    }
199
200
    /**
201
     * Flattens all the composed types.
202
     *
203
     * @param IType[] $types
204
     *
205
     * @return IType[]
206
     */
207
    protected function flattenComposedTypes(array $types)
208
    {
209
        $composedTypes = [];
210
        foreach ($types as $type) {
211
            if ($type instanceof ICompositeType) {
212
                $composedTypes += $this->flattenComposedTypes($type->getComposedTypes());
213
            } else {
214
                $composedTypes[$type->getIdentifier()] = $type;
215
            }
216
        }
217
218
        return $composedTypes;
219
    }
220
221
    /**
222
     * @param string $name
223
     *
224
     * @return IFunction
225
     */
226
    abstract protected function buildFunction($name);
227
228
    public function getFunction($name)
229
    {
230
        $normalizedName = $this->normalizeFunctionName($name);
231
        if (!isset($this->functions[$normalizedName])) {
232
            $this->functions[$normalizedName] = $this->buildFunction($normalizedName);
233
        }
234
235
        return $this->functions[$normalizedName];
236
    }
237
238
    public function getBinaryOperation(IType $leftOperandType, $operator, IType $rightOperandType)
239
    {
240
        foreach ($this->binaryOperations as $binaryOperation) {
241
            $leftOperand = $binaryOperation->getLeftOperandType();
242
            $rightOperand = $binaryOperation->getRightOperandType();
243
244
            if ($binaryOperation->getOperator() === $operator) {
245
                if (($leftOperand->isParentTypeOf($leftOperandType) && $rightOperand->isParentTypeOf($rightOperandType))
246
                        //Binary operators are symmetrical: test for flipped operands
247
                        || ($leftOperand->isParentTypeOf($rightOperandType)
248
                                && $rightOperand->isParentTypeOf($leftOperandType))
249
                ) {
250
                    return $binaryOperation;
251
                }
252
            }
253
        }
254
255
        throw new TypeException(
256
                'Cannot get binary operation: operation for \'%s\' %s \'%s\' is not supported',
257
                $leftOperandType->getIdentifier(),
258
                $operator,
259
                $rightOperandType->getIdentifier());
260
    }
261
}
262