AnnotationParser::parse()   C
last analyzed

Complexity

Conditions 12
Paths 12

Size

Total Lines 38
Code Lines 33

Duplication

Lines 0
Ratio 0 %

Importance

Changes 1
Bugs 0 Features 0
Metric Value
cc 12
eloc 33
c 1
b 0
f 0
nc 12
nop 2
dl 0
loc 38
rs 6.9666

How to fix   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
/**
4
 * This file is part of PhpUnitGen.
5
 *
6
 * (c) 2017-2018 Paul Thébaud <[email protected]>
7
 *
8
 * For the full copyright and license information, please view the LICENSE.md
9
 * file that was distributed with this source code.
10
 */
11
12
namespace PhpUnitGen\Annotation;
13
14
use PhpUnitGen\Exception\AnnotationParseException;
15
use PhpUnitGen\Model\PropertyInterface\DocumentationInterface;
16
17
/**
18
 * Class AnnotationParser.
19
 *
20
 * @author     Paul Thébaud <[email protected]>.
21
 * @copyright  2017-2018 Paul Thébaud <[email protected]>.
22
 * @license    https://opensource.org/licenses/MIT The MIT license.
23
 * @link       https://github.com/paul-thebaud/phpunit-generator
24
 * @since      Class available since Release 2.0.0.
25
 */
26
class AnnotationParser
27
{
28
    /**
29
     * @var AnnotationLexer $annotationLexer The annotation lexer to use.
30
     */
31
    private $annotationLexer;
32
33
    /**
34
     * @var TokenConsumer $tokenConsumer The token consumer to use.
35
     */
36
    private $tokenConsumer;
37
38
    /**
39
     * @var AnnotationRegister $annotationRegister The annotation register to use.
40
     */
41
    private $annotationRegister;
42
43
    /**
44
     * AnnotationParser constructor.
45
     *
46
     * @param AnnotationLexer    $annotationLexer    The lexer to use.
47
     * @param TokenConsumer      $tokenConsumer      The token consumer to use.
48
     * @param AnnotationRegister $annotationRegister The annotation register to use.
49
     */
50
    public function __construct(
51
        AnnotationLexer $annotationLexer,
52
        TokenConsumer $tokenConsumer,
53
        AnnotationRegister $annotationRegister
54
    ) {
55
        $this->annotationLexer    = $annotationLexer;
56
        $this->tokenConsumer      = $tokenConsumer;
57
        $this->annotationRegister = $annotationRegister;
58
    }
59
60
    /**
61
     * Parse a documentation to add annotations to parent.
62
     *
63
     * @param DocumentationInterface $parent        The parent that has this documentation.
64
     * @param string                 $documentation The documentation string to parse.
65
     *
66
     * @throws AnnotationParseException If there is an error during parsing process.
67
     */
68
    public function invoke(DocumentationInterface $parent, string $documentation): void
69
    {
70
        try {
71
            $this->tokenConsumer->initialize();
72
73
            $this->annotationLexer->setInput($documentation);
74
            $this->annotationLexer->moveNext();
75
            $this->annotationLexer->moveNext();
76
77
            while ($this->annotationLexer->token) {
78
                $this->parse(
79
                    $this->annotationLexer->token['type'],
80
                    $this->annotationLexer->token['value']
81
                );
82
                $this->annotationLexer->moveNext();
83
                $this->annotationLexer->moveNext();
84
            }
85
86
            $this->tokenConsumer->finalize();
87
88
            $this->annotationRegister->invoke($parent, $this->tokenConsumer->getParsedAnnotations());
89
        } catch (AnnotationParseException $exception) {
90
            throw new AnnotationParseException($exception->getMessage());
91
        }
92
    }
93
94
    /**
95
     * Parse a token with a value and type, and consume it depending on type.
96
     *
97
     * @param int    $type  The token type (an integer from the Lexer class constant).
98
     * @param string $value The token value.
99
     *
100
     * @throws AnnotationParseException If the token type is invalid.
101
     */
102
    private function parse(int $type, string $value): void
103
    {
104
        switch ($type) {
105
            case AnnotationLexer::T_ANNOTATION:
106
                $this->tokenConsumer->consumeAnnotationToken($value);
107
                break;
108
            case AnnotationLexer::T_O_PARENTHESIS:
109
                $this->tokenConsumer->consumeOpeningParenthesisToken();
110
                $this->tokenConsumer->addTokenToContent($value);
111
                break;
112
            case AnnotationLexer::T_C_PARENTHESIS:
113
                $this->tokenConsumer->addTokenToContent($value);
114
                $this->tokenConsumer->consumeClosingParenthesisToken();
115
                break;
116
            case AnnotationLexer::T_SINGLE_QUOTE:
117
            case AnnotationLexer::T_DOUBLE_QUOTE:
118
                $this->tokenConsumer->addTokenToContent($value);
119
                $this->tokenConsumer->consumeQuoteToken($type);
120
                break;
121
            case AnnotationLexer::T_ASTERISK:
122
                if ($this->tokenConsumer->hasOpenedString()) {
123
                    // We are in a string, save this token value.
124
                    $this->tokenConsumer->addTokenToContent($value);
125
                }
126
                break;
127
            case AnnotationLexer::T_LINE_BREAK:
128
                $this->tokenConsumer->addTokenToContent($value);
129
                $this->tokenConsumer->increaseLine();
130
                break;
131
            case AnnotationLexer::T_BACKSLASH:
132
            case AnnotationLexer::T_WHITESPACE:
133
            case AnnotationLexer::T_OTHER:
134
                $this->tokenConsumer->addTokenToContent($value);
135
                break;
136
            default:
137
                throw new AnnotationParseException(sprintf('A token of value "%s" has an invalid type', $value));
138
        }
139
        $this->tokenConsumer->afterConsume($type);
140
    }
141
}
142