Passed
Push — develop ( 6ae3da...c93a2f )
by Paul
02:03
created

AnnotationParser   A

Complexity

Total Complexity 16

Size/Duplication

Total Lines 114
Duplicated Lines 0 %

Importance

Changes 0
Metric Value
dl 0
loc 114
rs 10
c 0
b 0
f 0
wmc 16

3 Methods

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