parseStaticValueVersionSpecific()   F
last analyzed

Complexity

Conditions 86
Paths 38

Size

Total Lines 181
Code Lines 156

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
eloc 156
dl 0
loc 181
rs 3.3333
c 0
b 0
f 0
cc 86
nc 38
nop 1

How to fix   Long Method    Complexity   

Long Method

Small methods make your code easier to understand, in particular if combined with a good name. Besides, if your method is small, finding a good name is usually much easier.

For example, if you find yourself adding comments to a method's body, this is usually a good sign to extract the commented part to a new method, and use the comment as a starting point when coming up with a good name for this new method.

Commonly applied refactorings include:

1
<?php
2
/**
3
 * This file is part of PDepend.
4
 *
5
 * PHP Version 5
6
 *
7
 * Copyright (c) 2008-2017 Manuel Pichler <[email protected]>.
8
 * All rights reserved.
9
 *
10
 * Redistribution and use in source and binary forms, with or without
11
 * modification, are permitted provided that the following conditions
12
 * are met:
13
 *
14
 *   * Redistributions of source code must retain the above copyright
15
 *     notice, this list of conditions and the following disclaimer.
16
 *
17
 *   * Redistributions in binary form must reproduce the above copyright
18
 *     notice, this list of conditions and the following disclaimer in
19
 *     the documentation and/or other materials provided with the
20
 *     distribution.
21
 *
22
 *   * Neither the name of Manuel Pichler nor the names of his
23
 *     contributors may be used to endorse or promote products derived
24
 *     from this software without specific prior written permission.
25
 *
26
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
27
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
28
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
29
 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
30
 * COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
31
 * INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
32
 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
33
 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
34
 * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
35
 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
36
 * ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
37
 * POSSIBILITY OF SUCH DAMAGE.
38
 *
39
 * @copyright 2008-2017 Manuel Pichler. All rights reserved.
40
 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
41
 *
42
 * @since 2.3
43
 */
44
45
namespace PDepend\Source\Language\PHP;
46
47
use PDepend\Source\AST\ASTArguments;
48
use PDepend\Source\AST\ASTConstant;
49
use PDepend\Source\AST\ASTNamedArgument;
50
use PDepend\Source\AST\ASTNode;
51
use PDepend\Source\AST\ASTValue;
52
use PDepend\Source\Parser\UnexpectedTokenException;
53
use PDepend\Source\Tokenizer\FullTokenizer;
54
use PDepend\Source\Tokenizer\Tokenizer;
55
use PDepend\Source\Tokenizer\Tokens;
56
57
/**
58
 * Concrete parser implementation that supports features up to PHP version 5.6.
59
 *
60
 * @copyright 2008-2017 Manuel Pichler. All rights reserved.
61
 * @license http://www.opensource.org/licenses/bsd-license.php BSD License
62
 *
63
 * @since 2.3
64
 */
65
abstract class PHPParserVersion56 extends PHPParserVersion55
66
{
67
    /**
68
     * Parses additional static values that are valid in the supported php version.
69
     *
70
     * @throws UnexpectedTokenException
71
     *
72
     * @return ASTValue|null
73
     */
74
    protected function parseStaticValueVersionSpecific(ASTValue $value)
75
    {
76
        $expressions = array();
77
78
        while (($tokenType = $this->tokenizer->peek()) != Tokenizer::T_EOF) {
79
            switch ($tokenType) {
80
                case Tokens::T_COMMA:
81
                case Tokens::T_CLOSE_TAG:
82
                case Tokens::T_COLON:
83
                case Tokens::T_DOUBLE_ARROW:
84
                case Tokens::T_END_HEREDOC:
85
                case Tokens::T_PARENTHESIS_CLOSE:
86
                case Tokens::T_SEMICOLON:
87
                case Tokens::T_SQUARED_BRACKET_CLOSE:
88
                    break 2;
89
                case Tokens::T_SELF:
90
                case Tokens::T_STRING:
91
                case Tokens::T_PARENT:
92
                case Tokens::T_STATIC:
93
                case Tokens::T_DOLLAR:
94
                case Tokens::T_VARIABLE:
95
                case Tokens::T_BACKSLASH:
96
                case Tokens::T_NAMESPACE:
97
                    $expressions[] = $this->parseVariableOrConstantOrPrimaryPrefix();
98
                    break;
99
                case ($this->isArrayStartDelimiter()):
100
                    $expressions[] = $this->doParseArray(true);
101
                    break;
102
                case Tokens::T_NULL:
103
                case Tokens::T_TRUE:
104
                case Tokens::T_FALSE:
105
                case Tokens::T_LNUMBER:
106
                case Tokens::T_DNUMBER:
107
                case Tokens::T_BACKTICK:
108
                case Tokens::T_DOUBLE_QUOTE:
109
                case Tokens::T_CONSTANT_ENCAPSED_STRING:
110
                    $expressions[] = $this->parseLiteralOrString();
111
                    break;
112
                case Tokens::T_QUESTION_MARK:
113
                    $expressions[] = $this->parseConditionalExpression();
114
                    break;
115
                case Tokens::T_BOOLEAN_AND:
116
                    $expressions[] = $this->parseBooleanAndExpression();
117
                    break;
118
                case Tokens::T_BOOLEAN_OR:
119
                    $expressions[] = $this->parseBooleanOrExpression();
120
                    break;
121
                case Tokens::T_LOGICAL_AND:
122
                    $expressions[] = $this->parseLogicalAndExpression();
123
                    break;
124
                case Tokens::T_LOGICAL_OR:
125
                    $expressions[] = $this->parseLogicalOrExpression();
126
                    break;
127
                case Tokens::T_LOGICAL_XOR:
128
                    $expressions[] = $this->parseLogicalXorExpression();
129
                    break;
130
                case Tokens::T_PARENTHESIS_OPEN:
131
                    $expressions[] = $this->parseParenthesisExpressionOrPrimaryPrefix();
132
                    break;
133
                case Tokens::T_START_HEREDOC:
134
                    $expressions[] = $this->parseHeredoc();
135
                    break;
136
                case Tokens::T_SL:
137
                    $expressions[] = $this->parseShiftLeftExpression();
138
                    break;
139
                case Tokens::T_SR:
140
                    $expressions[] = $this->parseShiftRightExpression();
141
                    break;
142
                case Tokens::T_ELLIPSIS:
143
                    $this->checkEllipsisInExpressionSupport();
144
                    // no break
145
                case Tokens::T_STRING_VARNAME: // TODO: Implement this
146
                case Tokens::T_PLUS: // TODO: Make this a arithmetic expression
147
                case Tokens::T_MINUS:
148
                case Tokens::T_MUL:
149
                case Tokens::T_DIV:
150
                case Tokens::T_MOD:
151
                case Tokens::T_POW:
152
                case Tokens::T_IS_EQUAL: // TODO: Implement compare expressions
153
                case Tokens::T_IS_NOT_EQUAL:
154
                case Tokens::T_IS_IDENTICAL:
155
                case Tokens::T_IS_NOT_IDENTICAL:
156
                case Tokens::T_BITWISE_OR:
157
                case Tokens::T_BITWISE_AND:
158
                case Tokens::T_BITWISE_NOT:
159
                case Tokens::T_BITWISE_XOR:
160
                case Tokens::T_IS_GREATER_OR_EQUAL:
161
                case Tokens::T_IS_SMALLER_OR_EQUAL:
162
                case Tokens::T_ANGLE_BRACKET_OPEN:
163
                case Tokens::T_ANGLE_BRACKET_CLOSE:
164
                case Tokens::T_EMPTY:
165
                case Tokens::T_CONCAT:
166
                    $token = $this->consumeToken($tokenType);
167
168
                    $expr = $this->builder->buildAstExpression($token->image);
169
                    $expr->configureLinesAndColumns(
170
                        $token->startLine,
171
                        $token->endLine,
172
                        $token->startColumn,
173
                        $token->endColumn
174
                    );
175
176
                    $expressions[] = $expr;
177
                    break;
178
                case Tokens::T_EQUAL:
179
                case Tokens::T_OR_EQUAL:
180
                case Tokens::T_SL_EQUAL:
181
                case Tokens::T_SR_EQUAL:
182
                case Tokens::T_AND_EQUAL:
183
                case Tokens::T_DIV_EQUAL:
184
                case Tokens::T_MOD_EQUAL:
185
                case Tokens::T_MUL_EQUAL:
186
                case Tokens::T_XOR_EQUAL:
187
                case Tokens::T_PLUS_EQUAL:
188
                case Tokens::T_MINUS_EQUAL:
189
                case Tokens::T_CONCAT_EQUAL:
190
                case Tokens::T_COALESCE_EQUAL:
191
                    $expressions[] = $this->parseAssignmentExpression(
192
                        array_pop($expressions)
193
                    );
194
                    break;
195
                case Tokens::T_DIR:
196
                case Tokens::T_FILE:
197
                case Tokens::T_LINE:
198
                case Tokens::T_NS_C:
199
                case Tokens::T_FUNC_C:
200
                case Tokens::T_CLASS_C:
201
                case Tokens::T_METHOD_C:
202
                    $expressions[] = $this->parseConstant();
203
                    break;
204
                // TODO: Handle comments here
205
                case Tokens::T_COMMENT:
206
                case Tokens::T_DOC_COMMENT:
207
                    $this->consumeToken($tokenType);
208
                    break;
209
                case Tokens::T_AT:
210
                case Tokens::T_EXCLAMATION_MARK:
211
                    $token = $this->consumeToken($tokenType);
212
213
                    $expr = $this->builder->buildAstUnaryExpression($token->image);
214
                    $expr->configureLinesAndColumns(
215
                        $token->startLine,
216
                        $token->endLine,
217
                        $token->startColumn,
218
                        $token->endColumn
219
                    );
220
221
                    $expressions[] = $expr;
222
                    break;
223
                default:
224
                    throw $this->getUnexpectedNextTokenException();
225
            }
226
        }
227
228
        $expressions = $this->reduce($expressions);
229
230
        $count = count($expressions);
231
        if ($count == 0) {
232
            return null;
233
        } elseif ($count == 1) {
234
            // @todo ASTValue must be a valid node.
235
            $value->setValue($expressions[0]);
236
237
            return $value;
238
        }
239
240
        $expr = $this->builder->buildAstExpression();
241
        foreach ($expressions as $node) {
242
            $expr->addChild($node);
243
        }
244
        $expr->configureLinesAndColumns(
245
            $expressions[0]->getStartLine(),
246
            $expressions[$count - 1]->getEndLine(),
247
            $expressions[0]->getStartColumn(),
248
            $expressions[$count - 1]->getEndColumn()
249
        );
250
251
        // @todo ASTValue must be a valid node.
252
        $value->setValue($expr);
253
254
        return $value;
255
    }
256
257
    /**
258
     * Parses use declarations that are valid in the supported php version.
259
     *
260
     * @return void
261
     */
262
    protected function parseUseDeclarations()
263
    {
264
        // Consume use keyword
265
        $this->consumeToken(Tokens::T_USE);
266
        $this->consumeComments();
267
268
        // Consume const and function tokens
269
        $nextToken = $this->tokenizer->peek();
270
        switch ($nextToken) {
271
            case Tokens::T_CONST:
272
            case Tokens::T_FUNCTION:
273
                $this->consumeToken($nextToken);
274
        }
275
276
        // Parse all use declarations
277
        $this->parseUseDeclaration();
278
        $this->consumeComments();
279
280
        // Consume closing semicolon
281
        $this->consumeToken(Tokens::T_SEMICOLON);
282
283
        // Reset any previous state
284
        $this->reset();
285
    }
286
287
    /**
288
     * This method will be called when the base parser cannot handle an expression
289
     * in the base version. In this method you can implement version specific
290
     * expressions.
291
     *
292
     * @throws UnexpectedTokenException
293
     *
294
     * @return ASTNode
295
     *
296
     * @since 2.2
297
     */
298
    protected function parseOptionalExpressionForVersion()
299
    {
300
        if ($expression = $this->parseExpressionVersion56()) {
301
            return $expression;
302
        }
303
        return parent::parseOptionalExpressionForVersion();
304
    }
305
306
    /**
307
     * In this method we implement parsing of PHP 5.6 specific expressions.
308
     *
309
     * @return ASTNode|null
310
     *
311
     * @since 2.3
312
     */
313
    protected function parseExpressionVersion56()
314
    {
315
        $this->consumeComments();
316
        $nextTokenType = $this->tokenizer->peek();
317
318
        switch ($nextTokenType) {
319
            case Tokens::T_POW:
320
                $token = $this->consumeToken($nextTokenType);
321
322
                $expr = $this->builder->buildAstExpression($token->image);
323
                $expr->configureLinesAndColumns(
324
                    $token->startLine,
325
                    $token->endLine,
326
                    $token->startColumn,
327
                    $token->endColumn
328
                );
329
330
                return $expr;
331
        }
332
333
        return null;
334
    }
335
336
    /**
337
     * @return ASTConstant|ASTNamedArgument
338
     */
339
    protected function parseConstantArgument(ASTConstant $constant, ASTArguments $arguments)
0 ignored issues
show
Unused Code introduced by
The parameter $arguments is not used and could be removed. ( Ignorable by Annotation )

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

339
    protected function parseConstantArgument(ASTConstant $constant, /** @scrutinizer ignore-unused */ ASTArguments $arguments)

This check looks for parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
340
    {
341
        return $constant;
342
    }
343
344
    /**
345
     * @return ASTArguments
346
     */
347
    protected function parseArgumentList(ASTArguments $arguments)
348
    {
349
        while (true) {
350
            $this->consumeComments();
351
352
            if (Tokens::T_ELLIPSIS === $this->tokenizer->peek()) {
353
                $this->consumeToken(Tokens::T_ELLIPSIS);
354
            }
355
356
            $expr = $this->parseArgumentExpression();
357
358
            if ($expr instanceof ASTConstant) {
359
                $expr = $this->parseConstantArgument($expr, $arguments);
360
            }
361
362
            if (!$expr || !$this->addChildToList($arguments, $expr)) {
363
                break;
364
            }
365
        }
366
367
        return $arguments;
368
    }
369
370
    /**
371
     * @return ASTNode|null
372
     */
373
    protected function parseArgumentExpression()
374
    {
375
        return $this->parseOptionalExpression();
376
    }
377
378
    /**
379
     * Parses the value of a php constant. By default this can be only static
380
     * values that were allowed in the oldest supported PHP version.
381
     *
382
     * @return ASTValue
383
     */
384
    protected function parseConstantDeclaratorValue()
385
    {
386
        if ($this->isFollowedByStaticValueOrStaticArray()) {
387
            return $this->parseVariableDefaultValue();
388
        }
389
390
        // Else it would be provided as ASTLiteral or expressions object.
391
        $value = new ASTValue();
392
        $value->setValue($this->parseOptionalExpression());
393
394
        return $value;
395
    }
396
397
    /**
398
     * Determines if the following expression can be stored as a static value.
399
     *
400
     * @return bool
401
     */
402
    protected function isFollowedByStaticValueOrStaticArray()
403
    {
404
        // If we can't anticipate, we should assume it can be a dynamic value
405
        if (!($this->tokenizer instanceof FullTokenizer)) {
406
            return false;
407
        }
408
409
        for ($i = 0; $type = $this->tokenizer->peekAt($i); $i++) {
410
            switch ($type) {
411
                case Tokens::T_COMMENT:
412
                case Tokens::T_DOC_COMMENT:
413
                case Tokens::T_ARRAY:
414
                case Tokens::T_SQUARED_BRACKET_OPEN:
415
                case Tokens::T_SQUARED_BRACKET_CLOSE:
416
                case Tokens::T_PARENTHESIS_OPEN:
417
                case Tokens::T_PARENTHESIS_CLOSE:
418
                case Tokens::T_COMMA:
419
                case Tokens::T_DOUBLE_ARROW:
420
                case Tokens::T_NULL:
421
                case Tokens::T_TRUE:
422
                case Tokens::T_FALSE:
423
                case Tokens::T_LNUMBER:
424
                case Tokens::T_DNUMBER:
425
                case Tokens::T_STRING:
426
                case Tokens::T_EQUAL:
427
                case Tokens::T_START_HEREDOC:
428
                case Tokens::T_END_HEREDOC:
429
                case Tokens::T_ENCAPSED_AND_WHITESPACE:
430
                    break;
431
432
                case Tokens::T_SEMICOLON:
433
                case Tokenizer::T_EOF:
434
                    return true;
435
436
                default:
437
                    return false;
438
            }
439
        }
440
441
        return false;
442
    }
443
}
444